java JVM 何时加载类?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7560721/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 20:30:08  来源:igfitidea点击:

When does the JVM load classes?

javareflectionjvmclassloader

提问by Garrett Hall

Assume I have the following class:

假设我有以下课程:

class Caller {
  public void createSomething() {
    new Something();
  }
}

Would executing this line:

会执行这一行:

static void main() {
   Class<?> clazz = Caller.class;
}

cause the JVM to load the class Somethingor is the class loading deferred until the method createSomething()is called?

导致 JVM 加载类Something还是类加载推迟到createSomething()调用方法?

回答by Matthew Farwell

A class is loaded only when you require information about that class.

仅当您需要有关该类的信息时才加载该类。

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
    }
}

The lines (2) & (3) would cause the class to be loaded. The Something.class object contains information (line (2)) which could only come from the class definition, so you need to load the class. The call to the constructor (3) obviously requires the class definition. Similarly for any other method on the class.

第 (2) 行和 (3) 行将导致加载类。Some.class 对象包含只能来自类定义的信息(第 (2) 行),因此您需要加载该类。对构造函数 (3) 的调用显然需要类定义。类上的任何其他方法也是如此。

However, line (1) doesn't cause the class to be loaded, because you don't actually need any information, it's just a reference to an object.

但是,第 (1) 行不会导致加载类,因为您实际上不需要任何信息,它只是对对象的引用。

EDIT: In your changed question, you ask whether referring to Something.class loads the class. Yes it does. It does not load the class until main() is executed though. Using the following code:

编辑:在您更改的问题中,您询问是否引用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 {}

This code does not cause the Something.class to be loaded. However, if I call doSomething(), the class is loaded. To test this, create the above classes, compile them and delete the Something.class file. The above code does not crash with a ClassNotFoundException.

此代码不会导致加载Something.class。但是,如果我调用 doSomething(),则会加载该类。要对此进行测试,请创建上述类,编译它们并删除Something.class 文件。上面的代码不会因 ClassNotFoundException 而崩溃。

回答by Sean Owen

Yes, that will cause the class to load when the class containing the File.classreference is loaded. The only way to not do this is to reference a class by reflection. Then you can control when it's loaded.

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

回答by Eric Lindauer

If you have performance requirements this strict, you should consider writing a custom ClassLoader object. This would let you can dump classes from memory when they aren't needed any more.

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

You'll want to check out the loadClass, findClassand probably the defineClassmethods in the ClassLoaderclass, overriding load and find and using defineClass in the implementation. A google search on writing custom class loaders will reveal lots of sample code to do this, but basically you are going to cache the class results in a Map (class name to Class), then provide some callback mechanism to remove loaded classes from your cache when they aren't needed.

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

good luck.

祝你好运。