假设我有以下类:
class Caller {
public void createSomething() {
new Something();
}
}
将执行这一行:
static void main() {
Class<?> clazz = Caller.class;
}
导致JVM加载类Something
还是类加载延迟到方法createSomething()
被调用?
只在需要该类信息时才加载该类。
public class SomethingCaller {
public static Something something = null; // (1) does not cause class loading
public static Class<?> somethingClass = Something.class; // (2) causes class loading
public void doSomething() {
new Something(); // (3) causes class loading
}
}
行(2)&(3)会导致类被加载。class对象包含只能来自类定义的信息(第(2)行),因此需要加载类。对构造函数(3)的调用显然需要类定义。对于类上的任何其他方法也是如此。
然而,第(1)行并不导致类被加载,因为您实际上不需要任何信息,它只是一个对象的引用。
编辑:在你改变的问题中,你问是否引用Something.class加载类。是的。但是,在main()执行之前,它不会加载类。使用以下代码:
public class SomethingTest {
public static void main(String[] args) {
new SomethingCaller();
}
}
public class SomethingCaller {
public void doSomething() {
Class<?> somethingClass = Something.class;
}
}
public class Something {}
这段代码不会导致加载something .类。然而,如果我调用doSomething(),类就会被加载。为了测试这一点,创建上面的类,编译它们并删除Something.class文件。上面的代码不会因为ClassNotFoundException而崩溃。
是的,当包含File.class
引用的类被加载时,这将导致类加载。不这样做的唯一方法是通过反射引用类。然后你可以控制何时加载
如果您有如此严格的性能要求,您应该考虑编写一个自定义ClassLoader对象。这将允许您在不再需要时从内存中转储类。
您将需要检查loadClass
, findClass
和defineClass
方法在ClassLoader
类中,重载加载和查找并在实现中使用defineClass。在谷歌上搜索一下编写自定义类加载器,你会发现很多这样做的示例代码,但基本上你要把类的结果缓存在一个Map(类名到类)中,然后提供一些回调机制,在不需要的时候从缓存中删除加载的类。
好运。