如何以编程方式通过 bootstrap classloader 加载另一个 class?

How to load another class via bootstrap classloader programmatically?

我知道有一个 "bootstrap classloader" 从 jre/lib(rt.jar 等)加载所有 classes。是否有可能得到这个 "bootstrap classloader" 以便从另一个非 java 包加载额外的 class?

我说的是 bootstrap class 路径,它与此答案中描述的常规 class 路径非常不同: How should I load Jars dynamically at runtime?

bootstrap class 加载程序表示为 null,例如调用 Class.getClassLoader() 时。这可以直接提供给 Class.forName(String,boolean,ClassLoader):

If the parameter loader is null, the class is loaded through the bootstrap class loader.

因此,您可以尝试使用 Class.forName(className,true,null) 通过 bootstrap 加载器显式加载 class 或解析相对于另一个 class 的 class'使用 Class.forName(className,true,context.getClassLoader()) 的上下文,而不必特例 bootstrap 加载器。


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

从 Java 9 开始,有 java.lang.invoke.MethodHandles.Lookup.defineClass(byte[]), a standard method define a class within another class’ context, but it requires non-standard ways, e.g. Reflection with access override to get a Lookup object with the appropriate access right to a bootstrap loaded class, e.g. java.lang.Object. There are already existing Q&A about creating such a Lookup object for other purposes, e.g. 。但是,不能保证此类 Reflection hack 在未来的版本中有效。

对于 Java 代理,如果不介意,还可以选择将 class 文件转储到临时 Jar 文件并以编程方式 add it to the bootstrap class path这涉及 I/O.

还有一个问题需要注意。当你想让其他 bootstrap 加载的 classes 找到你的 class 时,你必须在第一次尝试访问那个 class 之前添加它,因为 JVM 的解析器会记住结果,即使它因错误而失败。

通过 bootstrap class 加载程序加载 classes 的一种有点迂回的方法是定义您自己的 class 加载程序,如下所示:

    ClassLoader bootClassLoader = new ClassLoader(null){};

此 class 加载器没有父级,因此它将加载 classes 的唯一位置是固有的 bootstrap class 加载器。