4

我知道有一个“引导类加载器”从 jre/lib(rt.jar 等)加载所有类。是否可以使用这个“引导类加载器”以便从另一个非 java 包加载附加类?

我说的是引导类路径,它与这个答案中描述的常规类路径非常不同:我应该如何在运行时动态加载 Jars?

4

2 回答 2

8

引导类加载器表示为null,例如在调用时Class.getClassLoader()。这可以直接喂给Class.forName(String,boolean,ClassLoader)

如果参数loader为空,则通过引导类加载器加载该类。

因此,您可以尝试通过引导加载程序显式加载一个类,Class.forName(className,true,null)或者使用解析相对于另一个类的上下文的类,Class.forName(className,true,context.getClassLoader())而无需对引导加载程序进行特殊处理。


如果你想定义一个运行时类,就好像被引导加载程序加载一样,没有标准的解决方案。有一种方法sun.misc.Unsafe.defineClass(String, byte, int, int, ClassLoader, ProtectionDomain)允许在特定的类加载器中定义一个类,这是一个专有的 API,将来可能会消失。

从 Java 9 开始,有java.lang.invoke.MethodHandles.Lookup.defineClass(byte[])一个标准方法在另一个类的上下文中定义一个类,但它需要非标准方法,例如具有访问覆盖的反射来获取Lookup对引导加载的类具有适当访问权限的对象,例如java.lang.Object. Lookup已经存在关于为其他目的创建这样一个对象的问答,例如这个。但是,不能保证此类反射黑客在未来的版本中有效。

对于 Java 代理,如果不介意这涉及 I/O ,还可以选择将类文件转储到临时 Jar 文件中并以编程方式将其添加到引导类路径中。

还有一个问题需要注意。当您希望其他引导加载的类找到您的类时,您必须在第一次尝试访问该类之前添加它,因为 JVM 的解析器会记住结果,即使它因错误而失败。

于 2018-02-08T17:27:41.380 回答
0

通过引导类加载器加载类的一种有点迂回的方法是定义自己的类加载器,如下所示:

    ClassLoader bootClassLoader = new ClassLoader(null){};

这个类加载器没有父类,因此它加载类的唯一位置是固有的引导类加载器。

于 2021-09-24T13:50:29.127 回答