Search code examples
javaclassloaderclassloading

order of classloader in java during compile time and run time


I've created below class with qualified name java.lang.String in java.

package java.lang;

public class String {
    public int getValue() {
        return 42;
   }
}

In Main Class, I have added the below code.

public class Main {

    public static void main(String[] args) {
        String s = new String();
        System.out.println(s.getValue());
    }
}

The code compile just fine. When I run the code, it fails with below error.

 Exception in thread "main" java.lang.NoSuchMethodError:    java.lang.String.getValue()I
at com.Main.main(Main.java:12)

I got to understand the java.lang.String is loaded by bootstrap classloader at runtime from rt.jar file.

So, I think the order of class loading should be different during compile time and runtime. Can you please give the order of class loading during compile time and runtime.


Solution

  • First of all, this test won't work in Java 9 or later. Attempting to compile the String class will give this error:

    java/lang/String.java:1: error: package exists in another module: java.base
    package java.lang;
    ^
    

    On Java 8, I get the behavior you see. Assuming that the tweaked String class is in the same source tree, the Main class compiles, but it gives an exception when you try to run it.

    This appears to have been reported as bug 4929425. The resolution was this was a documentation bug, and they clarified the documentation for the javac command ... though maybe not enough.

    Anyhow, there is a difference, and it is a subtle one.

    The java command simply searches in the following order:

    • bootstrap classpath
    • extension directories
    • classpath

    The javac command first searches the source directory. If it finds a source file there, it looks for a corresponding class file in the same location and (if necessary) compiles or recompiles it. If no source file is found, then it searches the classpaths for a class file as described above for java.

    Note that it takes very careful reading of the javac manual entry to tease this out. It is easy to miss. (https://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html#searching)

    (IMO, they could make the manual page clearer. However, this inconsistency only makes a difference if you are attempting to override some class on the bootstrap classpath or in extension directory. And you are doing it in the wrong way. Basically, this is an edge case. The problem with clearly documenting obscure edge cases is that you can end up making the documentation more confusing for the normal case.)