我最近看到了JRebel的在线演示,其中他们解释了他们的产品的作用,他们提到的其中一个幻灯片中他们没有使用类加载器(见下面的截图)。
我有一些项目,我使用类加载器在运行时动态加载类,例如依赖注入(如我开发的Maker Factory框架)。我认为在Java中加载类的唯一方法是使用类加载器。
答案 0 :(得分:6)
他们不使用任何 new 类加载器;他们扩展了默认值。
http://zeroturnaround.com/software/jrebel/learn/faq/#how_does_jrebel_work
答案 1 :(得分:3)
他们提到他们不使用类加载器。
每个类都使用ClassLoader(基元除外)。但是,库不需要创建额外的ClassLoader。
即使是" Hello World"程序将有两个类加载器(一个用于boostrapping)
我认为在Java中加载类的唯一方法是使用类加载器。
确实如此,但你可以强制现有的类加载器加载你的类,这个类是黑客但可能更容易使用。
(更正)如果您使用null
作为ClassLoader,则Unsafe.defineClass()将默认为调用者的ClassLoader。
答案 2 :(得分:3)
所以这个问题的答案可能是:第一次没有使用类加载器就无法动态加载Java类。但是可以通过检测类加载器来部分重新加载类。
基于Dave Newton的回答链接,从JRebel faq中提取重要内容:
他们使用Instrumentation API来检测Container / Server类加载器,这样他们就可以动态地监视和控制加载过程。他们将扫描类路径以搜索与加载的类对应的.class文件,并使用文件时间戳来检测对其的更改。当检测到更改时,它们将通过检测的类加载器传播该更改。它将保留类的现有实例,但不会重新运行构造函数,这意味着新添加的字段不会被初始化。
答案 3 :(得分:3)
免责声明:我参与了JRebel开发
从技术上讲,可以绕过带有一些Unsafe魔法的类加载器,JVM在创建运行时匿名类时使用lambdas(在Java 8中)。
然而,JRebel实际上与现有的类加载器集成在一起并且不会创建新的类加载器 - 这就是幻灯片的意思。当必须重新加载类时,JRebel不会删除现有的类加载器。相反,它在现有的类加载器中加载和版本化类。
答案 4 :(得分:1)
实际上,加载类的唯一方法是通过类加载器。
JRebel人可能会说不要使用类加载器来重新定义类。可以通过其他方式重新定义类,例如通过JVMTI。
答案 5 :(得分:0)
您当然可以自己将类文件读入内存。但是要在您的代码中使用该类,您仍然需要使用ClassLoader#defineClass。
通常,程序中使用的任何类都必须由类加载器定义,否则getClass().getClassLoader()
应该返回什么?
答案 6 :(得分:0)
为了完整起见,我想提到Java 9中引入的新方法Lookup.defineClass()。它可以动态定义新类,而不会给类加载器带来麻烦。该方法的用法非常简单:您只需传递一个字节数组,即可立即获得一个LOSER_ID
对象。但是它有一个局限性:该类必须与调用者类位于同一包中。