首页 > 解决方案 > 是在 Class Constant Pool、String Pool 还是 Young Generation 中分配字符串文字的空间?GC 何时可以访问字符串文字?

问题描述

我已阅读以下 stackoverflow 问题,但仍有几个问题不清楚。

假设我有以下 java 类:

class Main {
    public static void main(String[] args) {
        String str = "hello";
    }
}

编译 Main.java 文件时,对变量和方法的所有引用都作为符号引用存储在类的常量池中(存储在 Main.class 文件中)。符号引用是逻辑引用,而不是实际指向物理内存位置的引用。

类常量池将具有表示“hello”字符串文字的Utf8条目。

Constant pool:
   #1 = Methodref          #4.#13         // java/lang/Object."<init>":()V
   #2 = String             #14            // hello
   #3 = Class              #15            // Main
   #4 = Class              #16            // java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               Code
   #8 = Utf8               LineNumberTable
   #9 = Utf8               main
  #10 = Utf8               ([Ljava/lang/String;)V
  #11 = Utf8               SourceFile
  #12 = Utf8               Main.java
  #13 = NameAndType        #5:#6          // "<init>":()V
  #14 = Utf8               hello          /////// CONSTANT_Utf8_info entry ///////
  #15 = Utf8               Main
  #16 = Utf8               java/lang/Object

public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=2, args_size=1
         0: ldc           #2                  // String hello
         2: astore_1
         3: return
      LineNumberTable:
        line 3: 0
        line 4: 3

注意#14 常量池条目。

当 JVM 加载并链接 Main.class 文件时,它会在方法区的堆上为此类创建运行时类常量池(我想这是 .class 文件中类常量池的对象表示)。对于 .class 文件中的 Utf8 条目,JVM在链接过程中创建CONSTANT_Utf8_info对象。

根据规范,CONSTANT_Utf8_info对象包含表示“hello”字符串的字节数组。这个字节数组是分配在运行时类常量池、字符串池还是堆的年轻代空间内?

字符串池数据结构的深度如何?它是否包含对来自运行时类常量池的字符串文字的引用或表示字符串文字的哈希表/数组?

根据下面的文章 String Pool 被认为是一个Hashtable<oop, Symbol>但不清楚什么是 oop 和 Symbol 以及它们代表什么数据结构。

你能解释一下当 JVM 从上面的字节码执行“ldc #2”行时在内部发生了什么(内存是如何分配的,在什么空间中,堆栈上有什么)。

你能说 GC 何时可以访问“hello”字符串文字吗?

如果您在回答这个问题时留下一些指向官方 JVM 规范的链接以及一些证据,我将不胜感激。

标签: javastringmemorymemory-managementheap-memory

解决方案


推荐阅读