My understanding of classloading was that a class gets loaded when it is first needed (to put it in a very simple way). Running the following sample with -verbose:class and a modified version of the Iterators class that prints a message when its clinit is called I observed something that I can not really explain though:
public class IteratorsTest
{
public static void main(String[] args)
{
com.google.common.collect.Iterators.forArray(1, 2, 3);
}
}
The (cleaned-up) output is the following:
[Loaded com.google.common.collect.Iterators from file:...]
[Loaded com.google.common.collect.Iterators$1 from file:...]
---------> Iterators <clinit>
Why is Iterators$1 loaded before clinit is called? It is only defined in the clinit, isn't it?
static final UnmodifiableListIterator<Object> EMPTY_LIST_ITERATOR =
new UnmodifiableListIterator<Object>() {
...
}
Which results in the following byte code:
static <clinit>()V
L0
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "---------> Iterators clinit --------------"**
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L1
NEW com/google/common/collect/Iterators$1
DUP
INVOKESPECIAL com/google/common/collect/Iterators$1.<init> ()V
L2
PUTSTATIC com/google/common/collect/Iterators.EMPTY_LIST_ITERATOR : Lcom/google/common/collect/UnmodifiableListIterator;
And to confuse me even more I have one more sample (too complex to post here) where the same line of code as in the main above leads to the following output:
[Loaded com.google.common.collect.Iterators from file:...]
---------> Iterators <clinit>
[Loaded com.google.common.collect.Iterators$1 from file:...]
This is actually what I would have expected from the simple test program as well.
I tried to find the answer here https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html , but that didn't really help.
- What could be the reason for sometimes the clinit being executed first and sometimes the anonymous class being loaded first?
- Is there a way to trace when the JVM invokes the clinit of the classes? something similar to -verbose:class or -XX:+TraceClassLoading, etc?