I do not understand why the following code isn't this a causing a Stack overflow equivalent for Heap (OutOfMemoryError or something) since it is some kind of infinite recursion (is it not?). Does the static initialization provide a guard against something like this and throws NullPointerException instead?
Edit: I do not believe I was understood:
public static void main(String[] args) calls a static method from StaticClass. Before this method, doSmth(), is called StaticClass needs to be loaded first. When a class is loaded, all the static code is ran; in the StaticClass class, objClass is a static field attributed with the value of a new ObjClass() and thus shouldn't be null (to throw NullPointerException). Obviously new ObjClass() can not be instantiated because in order to do this you need to load the StaticClass and this already happens when StaticClass is loading (thus the analogy with infinite recursion, or probably deadlock analogy). The problem is the JVM says the objClass is null instead of saying it couldn't initialize new ObjClass() because some kind of recurrent call.
In a normal case, NullPointerException is thrown because of the caller. But in this case, you can change only the callee (remove the line with the comment at the end, in the ObjClass constructor) and then you won't receive NullPointerException.
package pack;
public class ObjClass
{
public ObjClass() {
StaticClass.doSmth();//if removed, no NullPointerException
}
public String getSomething() {
return "get";
}
public static void main(String[] args) {
StaticClass.loadStaticClass();
}
}
class StaticClass {
private static ObjClass objClass = new ObjClass();
static void loadStaticClass() {
}
static void doSmth() {
System.out.println(objClass.getSomething());
}
}
which gives:
Exception in thread "main" java.lang.ExceptionInInitializerError
at pack.ObjClass.main(ObjClass.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.lang.NullPointerException
at pack.ObjClass$StaticClass.doSmth(ObjClass.java:39)
at pack.ObjClass.<init>(ObjClass.java:20)
at pack.ObjClass$StaticClass.<clinit>(ObjClass.java:34)
... 6 more