解析后的解析引用(即针对符号引用的直接内存地址)存储在 JVM 中的何处?
Where the resolved reference(that means direct memory address against symbolic reference) stored in JVM after resolution?
我研究过 JVM(尤其是 JDK 8 版本),在研究 class 链接时,我还没有弄清楚从符号引用中确定的直接内存地址在哪里分辨率。
解析有几种,比如type(class/interface)、field、method等,不过我只是做了一个class例子来简单说明一下
在JVM规范中,有一些词。
5.1 The Run-Time Constant Pool
The Java Virtual Machine maintains a per-type constant pool (§2.5.5), a run-time data structure that serves many of the purposes of the symbol table of a conventional programming language implementation.
The constant_pool table (§4.4) in the binary representation of a class or interface is used to construct the run-time constant pool upon class or interface creation (§5.3). All references in the run-time constant pool are initially symbolic.
规范说,所有引用一开始都是符号引用。
这是一个示例 Main class。
public class Main {
public static void main(String[] args) {
Object obj = new Object();
}
}
这是 Main class 的常量池信息。
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 The CONSTANT_Class_info Structure
The CONSTANT_Class_info structure is used to represent a class or an > interface:
CONSTANT_Class_info {
u1 tag;
u2 name_index;
}
这里,对象class在Mainclass的main方法中被引用。在 Main class 中,对象 class 从未被引用。(当命令 java Main
刚被执行时;)这意味着 Main 的常量池中的 Object Class entry(here, #2: CONSTANT_Class_info structure.)
有 name_index # 13. #13 是包含 Object class 名称的 CONSTANT_Utf8_info 结构,#13 是 Object class 的符号引用。(老实说,我可能不确定这个 Utf8 常量池条目是对的符号引用#2(对象的 Class 池条目))
当 JVM 的执行引擎仅执行具有对象 class 引用(在此类中,0: new #2
)的字节码时,#2 引用 #13(符号引用)。所以需要解析到JVM方法区ObjectClass的直接地址。 Class 分辨率发生。
问题来了。
我已经阅读并搜索了 JVM 规范、博客、文章,但我找不到 JVM 中符号引用存储的解析直接内存地址在哪里。
我在一个blog中找到了一些资料,它说,
Binding is the process of the field, method or class identified by the symbolic reference being replaced by a direct reference, this only happens once because the symbolic reference is completely replaced.
它说,替换。
在#2 常量池条目中,Object class 的符号引用存储在 CONSTANT_Class_info 结构的 name_index(u2 类型)字段中。
name_index字段的值是不是改成了Object的直接内存地址Class(可能在方法区的Object clsas的运行时常量池中)????
如果不是,直接地址存储在哪里?
请给我答案。谢谢。
规范没有说明 JVM 在哪里存储已解析的常量池条目。它是特定于实现的细节。
在 HotSpot JVM 中,常量池驻留在元空间中。它由两个相关的数组组成:一个标签数组和一个值数组。标签描述相应值的类型。但这些 与 JVMS §4.4 中定义的标签不同。 JVM 在 class 文件解析阶段用自己的标签填充常量池。
有 4 种不同类型的常量池条目表示对 Java Class 的引用:
JVM_CONSTANT_ClassIndex
最初包含一个常量池 Utf8 条目的整数索引,名称为 class。
JVM_CONSTANT_UnresolvedClass
。常量池的初始内容完全加载后,JVM 将 JVM_CONSTANT_ClassIndex
标记更改为 JVM_CONSTANT_UnresolvedClass
并将相应的 cp 条目替换为符号名称。
JVM_CONSTANT_UnresolvedClassInError
与JVM_CONSTANT_UnresolvedClass
的含义相同,但表示class解析尝试失败。
JVM_CONSTANT_Class
是已解析 class. 内部表示的原始地址
因此,您的猜测是正确的:在常量池解析期间,HotSpot JVM 会修改 cp 条目并更改相应的 cp 标签。即JVM_CONSTANT_UnresolvedClass
变为JVM_CONSTANT_Class
,符号引用被替换为同一个常量池值数组中的直接地址权
您可以在 ConstantPool::klass_at_impl 中找到实现。
我研究过 JVM(尤其是 JDK 8 版本),在研究 class 链接时,我还没有弄清楚从符号引用中确定的直接内存地址在哪里分辨率。
解析有几种,比如type(class/interface)、field、method等,不过我只是做了一个class例子来简单说明一下
在JVM规范中,有一些词。
5.1 The Run-Time Constant Pool The Java Virtual Machine maintains a per-type constant pool (§2.5.5), a run-time data structure that serves many of the purposes of the symbol table of a conventional programming language implementation. The constant_pool table (§4.4) in the binary representation of a class or interface is used to construct the run-time constant pool upon class or interface creation (§5.3). All references in the run-time constant pool are initially symbolic.
规范说,所有引用一开始都是符号引用。
这是一个示例 Main class。
public class Main {
public static void main(String[] args) {
Object obj = new Object();
}
}
这是 Main class 的常量池信息。
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 The CONSTANT_Class_info Structure
The CONSTANT_Class_info structure is used to represent a class or an > interface:
CONSTANT_Class_info {
u1 tag;
u2 name_index;
}
这里,对象class在Mainclass的main方法中被引用。在 Main class 中,对象 class 从未被引用。(当命令 java Main
刚被执行时;)这意味着 Main 的常量池中的 Object Class entry(here, #2: CONSTANT_Class_info structure.)
有 name_index # 13. #13 是包含 Object class 名称的 CONSTANT_Utf8_info 结构,#13 是 Object class 的符号引用。(老实说,我可能不确定这个 Utf8 常量池条目是对的符号引用#2(对象的 Class 池条目))
当 JVM 的执行引擎仅执行具有对象 class 引用(在此类中,0: new #2
)的字节码时,#2 引用 #13(符号引用)。所以需要解析到JVM方法区ObjectClass的直接地址。 Class 分辨率发生。
问题来了。 我已经阅读并搜索了 JVM 规范、博客、文章,但我找不到 JVM 中符号引用存储的解析直接内存地址在哪里。
我在一个blog中找到了一些资料,它说,
Binding is the process of the field, method or class identified by the symbolic reference being replaced by a direct reference, this only happens once because the symbolic reference is completely replaced.
它说,替换。 在#2 常量池条目中,Object class 的符号引用存储在 CONSTANT_Class_info 结构的 name_index(u2 类型)字段中。
name_index字段的值是不是改成了Object的直接内存地址Class(可能在方法区的Object clsas的运行时常量池中)????
如果不是,直接地址存储在哪里?
请给我答案。谢谢。
规范没有说明 JVM 在哪里存储已解析的常量池条目。它是特定于实现的细节。
在 HotSpot JVM 中,常量池驻留在元空间中。它由两个相关的数组组成:一个标签数组和一个值数组。标签描述相应值的类型。但这些 与 JVMS §4.4 中定义的标签不同。 JVM 在 class 文件解析阶段用自己的标签填充常量池。
有 4 种不同类型的常量池条目表示对 Java Class 的引用:
JVM_CONSTANT_ClassIndex
最初包含一个常量池 Utf8 条目的整数索引,名称为 class。JVM_CONSTANT_UnresolvedClass
。常量池的初始内容完全加载后,JVM 将JVM_CONSTANT_ClassIndex
标记更改为JVM_CONSTANT_UnresolvedClass
并将相应的 cp 条目替换为符号名称。JVM_CONSTANT_UnresolvedClassInError
与JVM_CONSTANT_UnresolvedClass
的含义相同,但表示class解析尝试失败。JVM_CONSTANT_Class
是已解析 class. 内部表示的原始地址
因此,您的猜测是正确的:在常量池解析期间,HotSpot JVM 会修改 cp 条目并更改相应的 cp 标签。即JVM_CONSTANT_UnresolvedClass
变为JVM_CONSTANT_Class
,符号引用被替换为同一个常量池值数组中的直接地址权
您可以在 ConstantPool::klass_at_impl 中找到实现。