JVM何时加载类?

假设我有以下课程:

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)行将导致类被加载。 Something.class对象包含只能来自类定义的信息(第(2)行),因此您需要加载该类。 对构造函数(3)的调用显然需要类定义。 类似于课堂上的任何其他方法。

但是,line(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.class。 但是,如果我调用doSomething(),则会加载该类。 要测试它,请创建上面的类,编译它们并删除Something.class文件。 上面的代码不会因ClassNotFoundException而崩溃。

是的,这将导致在加载包含File.class引用的类时加载类。 不这样做的唯一方法是通过reflection引用一个类。 然后你可以控制何时加载它。

如果您有严格的性能要求,则应考虑编写自定义的ClassLoader对象。 这将允许您可以在不再需要时从内存中转储类。

您将要查看defineClass类中的loadClassfindClass和可能的defineClass方法,覆盖加载并在实现中查找和使用defineClass。 编写自定义类加载器的谷歌搜索会显示大量示例代码来执行此操作,但基本上您要将类结果缓存到Map(类名称为Class),然后提供一些回调机制以从缓存中删除加载的类当他们不需要时。

祝你好运。