emi*_*tar 6 java jvm resolution dynamic-linking symbolic-references
我研究过 JVM(尤其是 JDK 8 版本),并且在研究类链接时,我还没有弄清楚从解析中的符号引用确定的直接内存地址在哪里。
\n\n解析有很多种,比如类型(类/接口)、字段、方法等,但我只是做了一个类的例子来简单解释。
\n\n在JVM规范中,有一些词。
\n\n\n\n\n5.1 运行时常量池\n Java 虚拟机维护一个每种类型的常量池 (\xc2\xa72.5.5),这是一种运行时数据结构,可用于传统编程语言的符号表的许多用途实现。\n 类或接口的二进制表示形式中的constant_pool 表(\xc2\xa74.4) 用于在创建类或接口(\xc2\xa75.3) 时构造运行时常量池。运行时常量池中的所有引用最初都是符号性的。
\n
规范中说,所有引用首先都是符号引用。
\n\n这是一个示例主类。
\n\npublic class Main {\n public static void main(String[] args) {\n Object obj = new Object();\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n这是主类的常量池信息。
\n\nConstant pool:\n#1 = Methodref #2.#12 // java/lang/Object."<init>":()V\n#2 = Class #13 // java/lang/Object\n#3 = Class #14 // Main\n#4 = Utf8 <init>\n#5 = Utf8 ()V\n#6 = Utf8 Code\n#7 = Utf8 LineNumberTable\n#8 = Utf8 main\n#9 = Utf8 ([Ljava/lang/String;)V\n#10 = Utf8 SourceFile\n#11 = Utf8 Main.java\n#12 = NameAndType #4:#5 // "<init>":()V\n#13 = Utf8 java/lang/Object\n#14 = Utf8 Main\n{\n public Main();\n descriptor: ()V\n flags: ACC_PUBLIC\n Code:\n stack=1, locals=1, args_size=1\n 0: aload_0\n 1: invokespecial #1 // Method java/lang/Object."<init>":()V\n 4: return\n LineNumberTable:\n line 1: 0\n\n public static void main(java.lang.String[]);\n descriptor: ([Ljava/lang/String;)V\n flags: ACC_PUBLIC, ACC_STATIC\n Code:\n stack=2, locals=2, args_size=1\n 0: new #2 // class java/lang/Object\n 3: dup\n 4: invokespecial #1 // Method java/lang/Object."<init>":()V\n 7: astore_1\n 8: return\n LineNumberTable:\n line 3: 0\n line 4: 8\n}\nSourceFile: "Main.java"\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n4.4.1 CONSTANT_Class_info 结构
\n
\n CONSTANT_Class_info 结构用于表示类或 > 接口:
\n CONSTANT_Class_info {
\n u1 tag;
\n u2 名称_索引;
\n}
这里,在Main类的main方法中引用了Object类。在Main类中,Object类永远不会被引用。(当命令java Main刚刚执行时;)这意味着Object Class entry(here, #2: CONSTANT_Class_info structure.)Main\的常量池中有name_index #13。#13 是包含 Object 类名称的 CONSTANT_Utf8_info 结构,#13 是 Object 类的符号引用。(老实说,我可能不确定这个 Utf8 常量池条目是 #2(Object\ 的类池条目)的符号引用)
当 JVM 的执行引擎只执行一个具有对象类引用(在本类中为0: new #2)的字节码时,#2 引用#13(符号引用)。因此,需要将其解析为JVM中方法区上对象类的直接地址。并且发生类解析。
这是问题。\n我已经阅读并搜索了 JVM 规范、博客、文章,但我找不到 JVM 中符号引用存储的已解析直接内存地址。
\n\n我在博客中找到了一些信息,它说:
\n\n\n\n\n绑定是由符号引用标识的字段、方法或类被直接引用替换的过程,这只发生一次,因为符号引用被完全替换。
\n
\ n在#2常量池条目中,Object类的符号引用存储在CONSTANT_Class_info结构的name_index(u2 type)字段中。
\n\nname_index字段的值是否更改为Object Class的直接内存地址(可能在方法区中Object clsas的运行时常量池中)???
\n\n如果不是,直接地址存储在哪里?
\n\n请给我答案。谢谢。
\n规范没有说明 JVM 将解析的常量池条目存储在哪里。这是特定于实现的细节。
\n\n在 HotSpot JVM 中,常量池驻留在元空间中。它由两个相关数组组成:标签数组和值数组。标签描述了相应值的类型。但这些标签与JVMS\xc2\xa0\xc2\xa74.4中定义的标签不同。JVM在类文件解析阶段用自己的标签填充常量池。
\n\n有 4 种不同类型的常量池条目表示对 Java 类的引用:
\n\nJVM_CONSTANT_ClassIndex最初包含带有类名的常量池 Utf8 条目的整数索引。JVM_CONSTANT_UnresolvedClass。当常量池的初始内容完全加载后,JVM将JVM_CONSTANT_ClassIndex标记更改为JVM_CONSTANT_UnresolvedClass符号名称并替换相应的cp条目。JVM_CONSTANT_UnresolvedClassInError与 的含义相同JVM_CONSTANT_UnresolvedClass,但表示类解析尝试失败。JVM_CONSTANT_Class是已解析类的内部表示的原始地址。所以,您的猜测是正确的:在常量池解析期间,HotSpot JVM 会就地修改 cp 条目并更改相应的 cp 标记。也就是说,JVM_CONSTANT_UnresolvedClass变为JVM_CONSTANT_Class,并且符号引用被替换为同一常量池值数组中的直接地址。
您可以在ConstantPool::klass_at_impl中找到实现。
\n| 归档时间: |
|
| 查看次数: |
675 次 |
| 最近记录: |