1. Введение
Когда мы компилируем файл .java
, мы получаем отдельный файл класса с расширением .class .
Файл .class
состоит из нескольких разделов, одним из которых является постоянный пул.
В этом кратком руководстве мы рассмотрим детали постоянного пула. Кроме того, мы увидим, какие типы он поддерживает и как он форматирует информацию.
2. Постоянный пул в Java
Проще говоря, пул констант содержит константы, необходимые для запуска кода определенного класса. По сути, это структура данных времени выполнения, похожая на таблицу символов. Это представление среды выполнения для каждого класса или интерфейса в файле класса Java.
Содержимое пула констант состоит из символических ссылок, сгенерированных компилятором. Эти ссылки представляют собой имена переменных, методов, интерфейсов и классов, на которые ссылается код. JVM использует их для связывания кода с другими классами, от которых он зависит.
Давайте разберемся со структурой постоянного пула, используя простой класс Java:
public class ConstantPool {
public void sayHello() {
System.out.println("Hello World");
}
}
Чтобы просмотреть содержимое пула констант, нам нужно сначала скомпилировать файл, а затем выполнить команду:
javap -v name.class
Приведенная выше команда даст:
#1 = Methodref #6.#14 // java/lang/Object."<init>":()V
#2 = Fieldref #15.#16 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #17 // Hello World
#4 = Methodref #18.#19 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Class #20 // com/foreach/jvm/ConstantPool
#6 = Class #21 // java/lang/Object
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 sayHello
#12 = Utf8 SourceFile
#13 = Utf8 ConstantPool.java
#14 = NameAndType #7:#8 // "<init>":()V
#15 = Class #22 // java/lang/System
#16 = NameAndType #23:#24 // out:Ljava/io/PrintStream;
#17 = Utf8 Hello World
#18 = Class #25 // java/io/PrintStream
#19 = NameAndType #26:#27 // println:(Ljava/lang/String;)V
#20 = Utf8 com/foreach/jvm/ConstantPool
#21 = Utf8 java/lang/Object
#22 = Utf8 java/lang/System
#23 = Utf8 out
#24 = Utf8 Ljava/io/PrintStream;
#25 = Utf8 java/io/PrintStream
#26 = Utf8 println
#27 = Utf8 (Ljava/lang/String;)V
#n
указывает ссылки на пул констант. №17 — это символическая ссылка на строку «Hello World»
, №18 — System.out
, а №19 — println.
Точно так же #
8 указывает, что возвращаемый тип метода — void
, а #20 — полное имя класса.
Важно отметить, что таблица постоянного пула начинается с индекса 1. Значение индекса 0 считается недопустимым индексом.
2.1. Типы
Постоянный пул поддерживает несколько типов:
Integer
,Float
: с 32-битными константамиDouble
,Long
: с 64-битными константамиString
: 16-битная строковая константа, указывающая на другую запись в пуле, содержащую фактические байты.Class
: содержит полное имя классаUtf8
: поток байтовNameAndType
: пара значений, разделенных двоеточием, первая запись представляет имя, а вторая запись указывает типFieldref
,Methodref
,InterfaceMethodref
: пара значений, разделенных точками, первое значение указывает на записьClass
, а второе значение указывает на записьNameAndType.
А как насчет других типов, таких как boolean
, short
и byte
? Эти типы представлены как целочисленные
константы в пуле.
2.2. Формат
Каждая запись в таблице подчиняется общему формату:
cp_info {
u1 tag;
u1 info[];
}
Начальный 1-байтовый тег указывает тип константы. Как только JVM захватывает и перехватывает теги, она знает, что следует за тегом. Обычно за тегом следуют два или более байта, несущие информацию об этой константе.
Давайте посмотрим на некоторые типы и индексы их тегов:
УТФ8
: 1Целое
: 3Поплавок
: 4Длинный
: 5Двойной
: 6- Ссылка на класс: 7
- `
Ссылка на
строку : 8`
Постоянный пул любого класса или интерфейса создается только после завершения загрузки JVM.
3. Заключение
В этой быстрой статье мы узнали о постоянном пуле в JVM. Мы видели, что он содержит символические ссылки, которые используются для поиска реальных объектов. Также смотрим, как пул форматирует информацию о константах и их типах.
Как всегда, фрагмент кода можно найти на Github .