【问题标题】:What classloader does Play use when compiling classes with the JDT compiler?使用 JDT 编译器编译类时,Play 使用什么类加载器?
【发布时间】:2011-12-17 03:14:14
【问题描述】:

我正在尝试编写一个在运行时将 jar 文件添加到 Play 类路径的 Play 插件。当调用onLoad 时,它需要加载一组jar,以便JDT 编译器可以使用它们来解析应用程序类中的依赖关系。这些 jar 文件不在标准的 lib/ 目录中,因此在 Play 启动时不会加载到系统类路径中。

其实加载jar文件是没有问题的,我会把我需要的每个jar文件指定为一个URL,然后将它们传递给URLClassLoader的一个实例。

经过大量研究后,我假设 Play 使用的类加载器位于 Play.classloader 中,我最初的计划是创建自己的扩展 Play.ApplicationClassloader 的类加载器。这个类加载器将使用 URLClassLoader 的实例来查找类,然后再委托给Play.ApplicationClassloader 中的标准功能。然后我打算用我的新实例替换 Play 类加载器:

Play.classloader = new MyExtensionClassLoader();

我遇到的问题是 JDT 编译器似乎没有使用 Play.classloader 实例来加载它的类。

所以我有两个问题:

如果 JDT 编译器不使用 Play.classloader 实例,它实际使用的是什么类路径?

更一般地说,有人对我如何在运行时将 jar 加载到 Play 中以便 JDT 编译器可以使用它有任何建议吗?

【问题讨论】:

    标签: java playframework


    【解决方案1】:

    我认为这行不通。

    Play 有自己的类加载器,它首先检查一个类是否是“托管播放应用程序类”(使用 JDT 编译器运行时编译的类),然后它回退到默认 jvm-one 的父类加载器。 .

    所以所有 playframework-core 类和其他库(如 Hibernate-classes)都作为常规类从默认的 jvm-classloader 加载。

    希望你能理解我:)

    -死

    【讨论】:

    • 经过更多调查:魔法发生在 ApplicationCompiler 中的 'private NameEnvironmentAnswer findType(final String name)' 中,它通过 'Play.classloader.getClassDefinition(name)' 加载类的字节,而后者又使用 getResourceAsStream (name)(这是默认的类加载器方法)。
    • 确实有道理。如前所述,我已经用我自己的实例替换了Play.classloader 中的ApplicationClassloader 实例。我知道它会被应用程序类调用,但 JDT 编译器似乎不使用该类加载器。
    • 我曾假设通过替换Play.classloaderApplicationCompiler.compile() ... findType() 将使用我的新实例来加载类。但事实并非如此。我曾希望在本节中与findType() 挂钩:'// 所以这是一个标准类 byte[] bytes = Play.classloader.getClassDefinition(name);'位于ApplicationCompiler 的第 184-185 行。
    【解决方案2】:

    我认为您的问题是您无法修改哪个 java.lang.Classloader 是 ApplicationClassloader 的父类加载器。

    如果您查看构造函数,您会发现它总是选择从中加载 ApplicationClassloader.class 的类加载器。

    如果您可以将父类加载器作为参数发送到 ApplicationClassloader 的构造函数,那么您可以这样做:

    创建新的 ClassloaderA 扩展 java.lang.Classloader 并使用 parent-classloader 作为 JVM-default。然后在 ClassloaderA 中,覆盖 findClass 和 getResourceAsStream 以在查看父级之前查看您的 jar 文件。那么你可以给 Play.classloader 一个新的 ApplicationClassloader 实例,并将 ClassloaderA 的实例作为其父类加载器。

    我认为这将使 Classloader-hirarchy 正确..

    【讨论】:

    • 几个问题。 1/ 如何获得 JVM-default 类加载器? (Thread.currentThread().getContextClassLoader()?) 2/ 如何创建ApplicationClassloader 的新实例,以便ClassloaderA 是它的父类加载器?
    • 为了回答我自己的问题,因为做任何其他事情都只是懒惰,1/我如何获得 JVM 默认类加载器.....它可以在系统属性中定义“ java.system.class.loader" 所以在启动时可以指定 -D java.system.class.loader=MyCustomClassLoader
    • 当我说“默认类加载器”时,我指的是初始类加载器,它在我们开始对它进行 trixing 之前加载第一个类(或所有类)。所有类对象都引用了它从中加载的类加载器实例,因此 Integer.class.getClassloader() 返回我正在谈论的类加载器实例
    猜你喜欢
    • 1970-01-01
    • 2011-08-14
    • 1970-01-01
    • 2021-12-29
    • 1970-01-01
    • 2010-12-11
    • 2014-03-02
    • 1970-01-01
    • 2010-12-18
    相关资源
    最近更新 更多