Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 解析后JVM中存储的已解析引用(即针对符号引用的直接内存地址)在哪里?_Java_Jvm_Resolution_Dynamic Linking_Symbolic References - Fatal编程技术网

Java 解析后JVM中存储的已解析引用(即针对符号引用的直接内存地址)在哪里?

Java 解析后JVM中存储的已解析引用(即针对符号引用的直接内存地址)在哪里?,java,jvm,resolution,dynamic-linking,symbolic-references,Java,Jvm,Resolution,Dynamic Linking,Symbolic References,我研究过JVM(特别是JDK 8版本),在研究类链接的同时,我还没有找到直接内存地址的位置,该地址是由解析中的符号引用确定的 有几种解决方案,例如类型(类/接口)、字段、方法等,但我只做了一个类示例来简单解释 在JVM规范中,有一些词 5.1运行时常量池 Java虚拟机维护一个每类型常量池(§2.5.5),这是一种运行时数据结构,用于传统编程语言实现的符号表的许多目的。 类或接口二进制表示形式中的常量池表(§4.4)用于在创建类或接口时构造运行时常量池(§5.3)运行时常量池中的所有引用最初都是

我研究过JVM(特别是JDK 8版本),在研究类链接的同时,我还没有找到直接内存地址的位置,该地址是由解析中的符号引用确定的

有几种解决方案,例如类型(类/接口)、字段、方法等,但我只做了一个类示例来简单解释

在JVM规范中,有一些词

5.1运行时常量池 Java虚拟机维护一个每类型常量池(§2.5.5),这是一种运行时数据结构,用于传统编程语言实现的符号表的许多目的。 类或接口二进制表示形式中的常量池表(§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"
下面是主类的常量池信息

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"
常量池:
#1=Methodref#2.#12//java/lang/Object.“:()V
#2=类#13//java/lang/Object
#3=等级#14//Main
#4=Utf8
#5=Utf8()V
#6=Utf8代码
#7=Utf8行号表
#8=Utf8主
#9=Utf8([Ljava/lang/String;)V
#10=Utf8源文件
#11=Utf8 Main.java
#12=名称和类型#4:#5/“”:()V
#13=Utf8 java/lang/Object
#14=Utf8主
{
公用干管();
描述符:()V
旗帜:ACC_PUBLIC
代码:
堆栈=1,局部变量=1,参数大小=1
0:aload_0
1:invokespecial#1//方法java/lang/Object。“:()V
4:返回
LineNumberTable:
第1行:0
公共静态void main(java.lang.String[]);
描述符:([Ljava/lang/String;)V
标志:ACC_公共,ACC_静态
代码:
堆栈=2,局部变量=2,参数大小=1
0:new#2//类java/lang/Object
3:dup
4:invokespecial#1//方法java/lang/Object。“:()V
7:astore_1
8:返回
LineNumberTable:
第3行:0
第4行:8
}
源文件:“Main.java”
4.4.1恒定类信息结构
常量类信息结构用于表示类或>接口:
常量类信息{
u1标签;
u2名称_索引;
}

在这里,对象类在main类的main方法中被引用。在main类中,对象类从不被引用。(当命令
java main
刚刚执行时;)这意味着
对象类条目(这里,#2:常量\u类\u信息结构)
在Main的常量池中有名称#索引#13。#13是常量#Utf8#包含对象类名称的信息结构,#13是对象类的符号引用。(老实说,我可能不确定这个Utf8常量池条目是#2(对象的类池条目)的符号引用)

当JVM的执行引擎只是执行一个具有对象类引用的字节码(在本课程中,
0:new#2
),#2引用#13(符号引用)。因此,它需要解析为JVM中方法区域上对象类的直接地址。然后发生类解析

问题来了。 我已经阅读并搜索了JVM规范、博客和文章,但我找不到符号引用的解析直接内存地址存储在JVM中的何处

我在一份报告中找到了一些信息,上面说

绑定是由符号引用替换为直接引用所标识的字段、方法或类的过程,这只发生一次,因为符号引用被完全替换

它说,取代了。 在#2常量池条目中,对象类的符号引用存储在常量类信息结构的名称索引(u2类型)字段中

name_index字段的值是否更改为对象类的直接内存地址(可能在方法区域中对象CLSA的运行时常量池中)

如果没有,直接地址存储在哪里


请给我答案。谢谢。

规范没有说明JVM在何处存储解析的常量池条目。它是特定于实现的细节

在HotSpot JVM中,常量池位于元空间中。它由两个相关数组组成:标记数组和值数组。标记描述了相应值的类型。但这些标记与中定义的标记不同。JVM在类文件解析阶段使用自己的标记填充常量池

有4种不同类型的常量池条目表示对Java类的引用:

  • JVM\u CONSTANT\u ClassIndex
    最初包含一个指向具有类名的常量池Utf8项的整数索引
  • JVM\u CONSTANT\u unsolvedClass
    。在常量池的初始内容完全加载后,JVM将
    JVM\u CONSTANT\u ClassIndex
    标记更改为
    JVM\u CONSTANT\u unsolvedClass
    ,并用符号名替换相应的cp条目
  • JVM\u CONSTANT\u unsolvedClassError
    表示与
    JVM\u CONSTANT\u unsolvedClass
    相同,但表示类解析尝试失败
  • JVM\u CONSTANT\u Class
    是解析类的内部表示的原始地址
因此,您的猜测是正确的:在恒定池解析期间,HotSpot JVM修改cp条目并更改相应的cp标记。也就是说,
JVM\u constant\u unsolvedClass