ClassLoader : possible configure to use lazy and not static resolution?

冷暖自知 提交于 2019-12-13 04:17:23

问题


I read JLS Chapter 12. Execution so it says about resolution

Resolution is the process of checking symbolic references from Test to other classes and interfaces, by loading the other classes and interfaces that are mentioned and checking that the references are correct.

The resolution step is optional at the time of initial linkage. An implementation may resolve symbolic references from a class or interface that is being linked very early, even to the point of resolving all symbolic references from the classes and interfaces that are further referenced, recursively. ...

An implementation may instead choose to resolve a symbolic reference only when it is actively used; consistent use of this strategy for all symbolic references would represent the "laziest" form of resolution. In this case, if Test had several symbolic references to another class, then the references might be resolved one at a time, as they are used, or perhaps not at all, if these references were never used during execution of the program.

For example, an implementation may choose to resolve each symbolic reference in a class or interface individually, only when it is used (lazy or late resolution), or to resolve them all at once while the class is being verified (static resolution). This means that the resolution process may continue, in some implementations, after a class or interface has been initialized.

So my question is whether I can select to choose/force to use lazy intialization? Maybe it requires writing a custom class loader? Or maybe ClassNotFoundException in class loader at start up might be ignored?

I have a conditional creation of an Object in main which should never actually happen and that corresponding class is missing from jar. But NoClassDefFound is thrown even before main starts execution.


回答1:


The NoClassDefFoundError error:

Thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found.

The error not related to instantiating an instance of the class in question. So for your example, it may be enough, if the "outer" class defines a field for that type. Your class, that contains the main, can't be loaded, because it depends on a type that is not available on the classpath at runtime.

If in doubt, look through your import statements and remove the import*) for the class that you want to load dynamically. Then try to get rid of the error markers without adding an import for that class again.

*) - I assume, that this dynamically loaded class is in a different package and you need an import for it.




回答2:


You can't with Oracle's JVM.

According to the Documentation the class loader cannot defer the loading of a class. And the order and timinig of linking is implementation-specific. AFAIK most JVMs chose to link as early as possible, some even at compile time (see Excelsior JET for an example of this).




回答3:


Consider this

class Test2 {
}

public class Test1 {
    static Test2 test2;

    public static void main(String[] args) {
        System.out.println("Test1");
        test2 = new Test2();
    }
}

I compiled it, remove Test2.class and ran java -cp . Test1 Output

    Test1
    Exception in thread "main" java.lang.NoClassDefFoundError: Test2
        at Test1.main(Test1.java:9)
    Caused by: java.lang.ClassNotFoundException: Test2
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
......

In my view this means that JVM dependency resolution is lazy by default. JVM did not notice that Test2.class was missing until its first usage.



来源:https://stackoverflow.com/questions/13929324/classloader-possible-configure-to-use-lazy-and-not-static-resolution

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!