Подтвердить что ты не робот

Понимание выхода javap для пула констант

При запуске javap в очень простом приложении HelloWorld у меня есть путаница в выходе вокруг константного пула.

Тестовый код

public class TestClass {
    public static void main(String[] args) {
        System.out.println("hello world");
    }
}

Javap -c -verbose output (snipped)

// Header + consts 1..22 snipped
const #22 = String      #23;    //  hello world
const #23 = Asciz       hello world;

public static void main(java.lang.String[]);
  Signature: ([Ljava/lang/String;)V
  Code:
   Stack=2, Locals=1, Args_size=1
   0:   getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #22; //String hello world
   5:   invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:   return
  // Debug info snipped
}

Хорошо, поэтому на строке 3 мы видим, что константа "hello world" накладывается на стек через # 22, но const # 23, похоже, сохраняет фактическое значение. Наверное, я немного смущен тем, что означает # (число), когда оно отображается в правой части распечатки.

Страница пользователя Oracle/Sun для javap оставляет желать лучшего.

4b9b3361

Ответ 1

Все ваши имена class, interface, field и константы string входят в пул констант java .

В соответствии с VM Spec (http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html):

Константа_pool - это таблица структур (§4.4), представляющих различные строковые константы, класс и интерфейс имена, имена полей и другие константы, на которые ссылаются структуру ClassFile и ее подструктур. Формат каждого указана запись в таблице константа_pool по его первому байту "тег". Стол константной_индексирован с 1 to constant_pool_count-1.

Итак, с точки зрения постоянного пула что-то вроде ниже можно увидеть как:

const #22 = String      #23;    //  hello world
const #23 = Asciz       hello world;

Значение в # 22 (индекс 22) имеет тип string и его значение имеет нулевое завершение c string (Asciz) hello world имеет индекс 23.

Ответ 2

Пул констант Java хранит два разных типа записей при сохранении строки. Во-первых, он хранит строковый литерал как кодированные данные UTF-8 (здесь константа № 23). Во-вторых, в нем также хранится запись строки (# 22), указывающая, что содержимое константы № 23 должно использоваться для построения String. Я думаю, причина в том, что JVM связывает с каждым классом "пул постоянной среды выполнения", состоящий из динамической реализации данных констант. Для строк это может быть ссылка на интернированный объект String, содержащий заданные символы. У постоянных данных UTF-8 есть другие варианты использования, помимо строковых литералов (например, имена полей и классов), поэтому это дополнительное косвенное отношение кажется разумным способом отделить проблемы.

Ответ 3

Пул № 22 - объект java.lang.String. Запись № 23 - это массив символов, используемых для построения этой строки.

Java VM Spec - это "недостающее руководство" для javap.