Байт-код 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функция. Это приводит кSystemclass и другим нравится быть загруженными.

В течение<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после загрузки, который затем используется именно для этого. Мне тоже кажется странным.

0 ответов

Другие вопросы по тегам