代码之家  ›  专栏  ›  技术社区  ›  LatencyFighter

如何通过引导类加载器以编程方式加载另一个类?

  •  4
  • LatencyFighter  · 技术社区  · 7 年前

    我知道有一个“引导类加载器”从jre/lib(rt.jar等)加载所有类。为了从另一个非java包中加载额外的类,我是否有可能掌握这个“引导类加载器”?

    我说的是 独自创立 类路径,与此答案中描述的常规类路径非常不同: How should I load Jars dynamically at runtime?

    2 回复  |  直到 7 年前
        1
  •  8
  •   Holger    7 年前

    引导类加载器表示为 null ,例如呼叫时 Class.getClassLoader() . 这可以直接馈送到 Class.forName(String,boolean,ClassLoader) :

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

    因此,您可以尝试使用 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 . 已有Q&关于创建这样一个 查找 对象用于其他目的,例如。 this one . 不过,这种反射黑客并不能保证在未来的版本中正常工作。

    对于Java代理,还可以选择将类文件转储到临时Jar文件中 add it to the bootstrap class path 从编程的角度来说,如果它不介意这涉及到I/O。

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

        2
  •  0
  •   michid    3 年前

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

        ClassLoader bootClassLoader = new ClassLoader(null){};
    

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