I am currently looking into how Java bytecode works. I created this simple test class:
class Main {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
With javap -c Main.class I can get its bytecode:
class Main {
Main();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #13 // String Hello, World!
5: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}
The first instruction that should be executed (according to my understanding) should be the getstatic instruction in the main function. This leads to the System class and others like Console being loaded.
During the <clinit> method of Console:
static {};
Code:
0: ldc #2 // class java/io/Console
2: invokevirtual #203 // Method java/lang/Class.desiredAssertionStatus:()Z
...
a invokevirtual method is executed to call the desiredAssertionStatus function on the class Class. One can already see a difference between this invokevirtual instruction and the one above: javap appends the class name before the method name because the function is found in the class Class and not in Console.
So finally my question is: What is going on here? According to the JVM 19 specification for invokevirtual the method should be invoked on the object that was on the stack. In this case Console but this class doesn't have the requested method nor is it a subclass of Class. What does the JVM intend to do here/how do JVM implementations like Hotspot go about doing this.
Do they just put the method onto the Console class for the duration of the instruction or somehow inject the class Class into Console or maybe there is something completely different going on here that I am missing?
Anyways thank you for taking your time to read my question!
I hope you have/had a wonderful day :)
I thought about doing the following things:
Adding the method to the
Consoleclass for the duration of the instruction. This doesn't work because the method requires fields from the classClass.Actually just calling the method on an instance of
Classwhich is created on the fly but I think these seems weird.This might be a very special case because I think that it has something to do with
Consoletrying to interact with itsClassLoader. If this is a special case and there aren't many occurrences of this happening: Maybe the JVM just does some under the hood magic like assigning each class an instance ofClassafter loading which is then used for just this. Also seems weird to me.