Байт-код Java: вызывает виртуальную ссылку на метод для ссылки на объект с другим классом
В настоящее время я изучаю, как работает байт-код Java. Я создал этот простой тестовый класс:
class Main {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
Сjavap -c Main.class
Я могу получить его байт-код:
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
}
Первая инструкция, которая должна быть выполнена (согласно моему пониманию), должна бытьgetstatic
инструкция вmain
функция. Это приводит кSystem
class и другим нравится быть загруженными.
В течение<clinit>
метод :
static {};
Code:
0: ldc #2 // class java/io/Console
2: invokevirtual #203 // Method java/lang/Class.desiredAssertionStatus:()Z
...
выполняется метод для вызоваdesiredAssertionStatus
функция на классе. Уже можно увидеть разницу между этой инструкцией и приведенной выше:javap
добавляет имя класса перед именем метода, потому что функция находится в классе, а не в .
Итак, наконец, мой вопрос: что здесь происходит? Согласно спецификации JVM 19 для
invokevirtual
метод должен быть вызван для объекта, который был в стеке. В этом случае, но этот класс не имеет запрошенного метода и не является подклассом . Что здесь собирается делать JVM/как это делают реализации JVM, такие как Hotspot. Они просто помещают метод в класс на время инструкции или каким-то образом внедряют класс, или, может быть, здесь происходит что-то совершенно другое, что я упускаю?
В любом случае спасибо, что нашли время, чтобы прочитать мой вопрос!
Я надеюсь, что у вас был / был замечательный день :)
Я думал о том, чтобы сделать следующие вещи:
Добавление метода в класс на время выполнения инструкции. Это не работает, потому что для метода требуются поля из класса.
На самом деле просто вызов метода для экземпляра, который создается на лету, но я думаю, что это кажется странным.
Это может быть очень особенным случаем, потому что я думаю, что это как-то связано с
Console
пытается взаимодействовать со своимClassLoader
. Если это особый случай, и таких случаев не так много: может быть, JVM просто выполняет какую-то скрытую магию, например, назначает каждому классу экземплярClass
после загрузки, который затем используется именно для этого. Мне тоже кажется странным.