0

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.

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, I understand what you mean here. But what I can do about it?
If you can't use an interface, that is known at runtime, then you'll have to store the instance as an Object type and reflect the fields and methods.
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).

1 Comment

What Andreas_D said is very true: You can hack your way around the problem, but not in the way you asked for.
1

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.

1 Comment

Yes, you are right. I have done experiment about this code, also separating in different packages, putting in jar, and get Test1 always before the exception/error. But in my real code exception is printed first and not println in main.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.