Где разрешенная ссылка (что означает прямой адрес памяти против символьной ссылки) хранится в JVM после разрешения?
Я изучал JVM(особенно версию JDK 8) и, изучая связи классов, я не выяснил, где находится прямой адрес памяти, который был определен из символьной ссылки в разрешении.
Существует несколько видов разрешений, таких как тип (класс / интерфейс), поле, метод и т. Д., Но я просто приведу пример класса для простого объяснения.
В спецификации JVM есть несколько слов.
5.1 Пул постоянных времени исполнения Виртуальная машина Java поддерживает постоянный пул для каждого типа (§2.5.5), структуру данных времени выполнения, которая служит многим целям таблицы символов в традиционной реализации языка программирования. Таблица constant_pool (§4.4) в двоичном представлении класса или интерфейса используется для создания пула констант во время выполнения при создании класса или интерфейса (§5.3). Все ссылки в пуле постоянных времени выполнения изначально являются символическими.
В спецификации сказано: "Все ссылки сначала являются символическими.
Вот пример основного класса.
public class Main {
public static void main(String[] args) {
Object obj = new Object();
}
}
Вот информация о константном пуле основного класса.
Constant pool:
#1 = Methodref #2.#12 // java/lang/Object."<init>":()V
#2 = Class #13 // java/lang/Object
#3 = Class #14 // Main
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 LineNumberTable
#8 = Utf8 main
#9 = Utf8 ([Ljava/lang/String;)V
#10 = Utf8 SourceFile
#11 = Utf8 Main.java
#12 = NameAndType #4:#5 // "<init>":()V
#13 = Utf8 java/lang/Object
#14 = Utf8 Main
{
public Main();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: new #2 // class java/lang/Object
3: dup
4: invokespecial #1 // Method java/lang/Object."<init>":()V
7: astore_1
8: return
LineNumberTable:
line 3: 0
line 4: 8
}
SourceFile: "Main.java"
4.4.1 Структура CONSTANT_Class_info
Структура CONSTANT_Class_info используется для представления класса или> интерфейса:
CONSTANT_Class_info {
тег u1;
u2 name_index;
}
Здесь класс Object упоминается в методе main класса Main. В главном классе класс Object никогда не упоминается.(Когда команда java Main
просто извинился;) это значит Object Class entry(here, #2: CONSTANT_Class_info structure.)
в постоянном пуле Майна есть name_index #13. #13 - это структура CONSTANT_Utf8_info, содержащая имя класса Object, а # 13 - символьная ссылка на класс Object.(Честно говоря, я не уверен, что эта запись пула констант Utf8 является символической ссылкой #2(запись пула классов объекта))
Когда JVM выполняет механизм исполнения, он просто выполняет байт-код, который имеет ссылку на класс Object (в этом разделе 0: new #2
), № 2 ссылки № 13(символьная ссылка). Таким образом, его необходимо разрешить по прямому адресу класса объекта в области методов в JVM. И разрешение класса происходит.
Вот вопрос. Я читал и искал спецификации JVM, а также блоги, статьи, но не смог найти, где разрешен прямой адрес памяти для символьных хранилищ ссылок в JVM.
Я нашел некоторую информацию в блоге, он сказал,
Привязка - это процесс, в котором поле, метод или класс, идентифицируемые символической ссылкой, заменяются прямой ссылкой, это происходит только один раз, поскольку символическая ссылка полностью заменяется.
Он сказал, заменил. В записи константы №2 символическая ссылка класса Object хранится в поле name_index(тип u2) структуры CONSTANT_Class_info.
Изменено ли значение поля name_index на прямой адрес памяти класса объекта (возможно, в пуле постоянных времени выполнения для класса объекта в области метода)????
Если нет, то где хранится прямой адрес?
Пожалуйста, дайте мне ответ. Спасибо.
1 ответ
В спецификации не указано, где JVM хранит разрешенные записи константного пула. Это специфичная для реализации деталь.
В JVM HotSpot постоянный пул находится в Metaspace. Он состоит из двух связанных массивов: массив тегов и массив значений. Теги описывают типы соответствующих значений. Но это не те теги, которые определены в JVMS §4.4. JVM заполняет постоянный пул своими собственными тегами на этапе разбора файла класса.
Существует 4 различных типа записей константного пула, которые обозначают ссылку на класс Java:
JVM_CONSTANT_ClassIndex
изначально содержит целочисленный индекс для записи Utf8 с постоянным пулом с именем класса.JVM_CONSTANT_UnresolvedClass
, После того, как начальное содержимое пула констант полностью загружено, JVM изменяетсяJVM_CONSTANT_ClassIndex
теги кJVM_CONSTANT_UnresolvedClass
и заменяет соответствующие записи cp символическими именами.JVM_CONSTANT_UnresolvedClassInError
означает так же, какJVM_CONSTANT_UnresolvedClass
, но означает, что попытка разрешения класса не удалась.JVM_CONSTANT_Class
является необработанным адресом для внутреннего представления разрешенного класса.
Итак, ваше предположение было верным: при постоянном разрешении пула JVM HotSpot изменяет записи cp на месте и изменяет соответствующие теги cp. То есть, JVM_CONSTANT_UnresolvedClass
становится JVM_CONSTANT_Class
и символьная ссылка заменяется прямым адресом прямо в том же массиве постоянных значений пула.
Вы можете найти реализацию в ConstantPool:: klass_at_impl.