元空间的运行时常量池究竟是全局一个还是每个 class 独立一个?网上众说纷纭,该如何求证? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
Sunhcer
V2EX    Java

元空间的运行时常量池究竟是全局一个还是每个 class 独立一个?网上众说纷纭,该如何求证?

  •  
  •   Sunhcer Apr 27, 2022 via Android 3501 views
    This topic created in 1461 days ago, the information mentioned may be changed or developed.
    Supplement 1    Apr 27, 2022
    同时关于 jdk8 中运行时常量池的位置也有两种说法,一种称在堆区,,另外一种称在元空间…
    关于三种常量池的位子,越搜索越迷惑…
    18 replies    2022-05-05 16:14:34 +08:00
    xuanbg
        1
    xuanbg  
       Apr 27, 2022
    当一个类被加载并且它在 JVM 中的运行时表示正在准备时,它的类加载器会分配元空间来存储类的元数据。所以很明显就是每个类一个元空间。
    Sunhcer
        2
    Sunhcer  
    OP
       Apr 27, 2022 via Android
    @xuanbg 我可以参考什么文献来证实这种说法吗?其实对于运行时常量池在堆区还是元空间也比较迷惑
    xuanbg
        3
    xuanbg  
       Apr 27, 2022
    常量池在元空间。因为常量和对象无关,所以 JVM 的设计就是把常量放元空间以节省内存。
    xuanbg
        4
    xuanbg  
       Apr 27, 2022
    https://wiki.openjdk.java.net/display/HotSpot/Metaspace
    这个算不算权威的参考文档?
    JasonLaw
        5
    JasonLaw  
       Apr 27, 2022 via iPhone
    A1exlee
        6
    A1exlee  
       Apr 27, 2022
    放在堆里的应该说的是字符串池,字符串池从 1.7 开始就从方法区移到堆里了。运行时常量池还是在元空间里
    Sunhcer
        7
    Sunhcer  
    OP
       Apr 27, 2022 via Android
    @JasonLaw 感谢回复,我浏览了对于方法区的描述,这个版本的描述是否适用于 jdk8 呢?按文档的说法,常量在方法区,8 中方法区的实现是元空间,那就是说运行时常量池还是在元空间的嘛

    @xuanbg 权威,看不太懂,我这样阐述是否有问题呢?元空间内存角度上是一片动态扩展的内存区域,不同的类加载器在这片内存空间划分各自的领域,同一个类加载器加载的 class 元空间都在同一片区域,但是这里没有找到关于运行时常量池的描述,依旧不确定是一个还是多个
    JasonLaw
        8
    JasonLaw  
       Apr 27, 2022 via iPhone
    @Sunhcer #7 具体的 JVM 实现要看文档,这本书更多的是在讲 JVM specification 。我也没怎么研究具体的 JVM 实现,sorry ,解答不了你的疑问。
    1sen
        9
    1sen  
       Apr 27, 2022
    可以去了解一下字节码文件的结构,其中就包括运行时常量池,可以在一定程度上解决你的疑问
    Sunhcer
        10
    Sunhcer  
    OP
       Apr 27, 2022 via Android
    @weivi 类文件常量池跟运行时常量池不同吧
    1sen
        11
    1sen  
       Apr 27, 2022
    @Sunhcer 是同一个东西 ,下面的内容摘自周志明的《深入理解 java 虚拟机》第三版
    ----------------------------------------------------------------------------------------------------------
    常量池中主要存放两大类常量:字面量( Literal )和符号引用( Symbolic References )。字面量比
    较接近于 Java 语言层面的常量概念,如文本字符串、被声明为 final 的常量值等。而符号引用则属于编译
    原理方面的概念,主要包括下面几类常量:
    被模块导出或者开放的包( Package )
    类和接口的全限定名( Fully Qualified Name )
    字段的名称和描述符( Descriptor )
    方法的名称和描述符
    方法句柄和方法类型( Method Handle 、Method Type 、Invoke Dynamic )
    动态调用点和动态常量( Dynamically-Computed Call Site 、Dynamically-Computed Constant )
    ikas
        12
    ikas  
       Apr 27, 2022   1
    首先你先要分清楚 jvm 规范,与 jvm 的具体实现
    jvm 规范中:
    1.方法区域在逻辑上是堆的一部分,但是并不要求方法区域的位置
    2.运行时常量池都是从 Java 虚拟机的方法区域分配的

    具体的 jvm 实现,比如 openjdk8+:
    永久生成的部分内容移动到 Java 堆,其余内容移动到本机内存

    参考
    https://docs.oracle.com/javase/specs/jvms/se18/html/jvms-2.html#jvms-2.5.4
    https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5.4
    http://openjdk.java.net/jeps/122
    Sunhcer
        13
    Sunhcer  
    OP
       Apr 27, 2022
    @weivi 是不同的,我跟倾向于这种说法:
    class 文件常量池存储的是当 class 文件被 java 虚拟机加载进来后存放在方法区的一些字面量和符号引用,字面量包括字符串,基本类型的常量。
    运行时常量池是当 class 文件被加载完成后,java 虚拟机会将 class 文件常量池里的内容转移到运行时常量池里,在 class 文件常量池的符号引用有一部分是会被转变为直接引用的。
    Sunhcer
        14
    Sunhcer  
    OP
       Apr 27, 2022
    @ikas 厉害了,我在这里找到一句话似乎可以终结疑问;
    htts://docs.oracle.com/javase/specs/jvms/se18/html/jvms-5.html

    The Java Virtual Machine maintains a run-time constant pool for each class and interface (§2.5.5).
    Java 虚拟机为每个类和接口维护一个运行时常量池; 那就是独立的喽
    大佬,喝冰可乐!
    1sen
        15
    1sen  
       Apr 28, 2022
    @Sunhcer 你说的这个文件常量池是记录在字节码文件中的,是保存于磁盘上的数据,类加载完成以后其实和 jvm 就没什么关系了。运行时常量池是根据这些文件上的数据,在内存里面形成的数据。我认为这俩本质上就是一个东西,只不过是同一种数据的两种形式而已,一种是磁盘中的形式,一种是主存中的形式。
    Sunhcer
        16
    Sunhcer  
    OP
       Apr 29, 2022 via Android
    @weivi 同一种来源的数据在不同阶段的不同呈现,这样说更准确; 来源上是一样,但数据不一样:打个比喻就像是,一个是带占位符的短信模板,一个是填充好的短信
    1sen
        17
    1sen  
       Apr 29, 2022
    @Sunhcer java 虚拟机规范关于运行时常量池介绍的第一句话。
    -------------------------------------------------------------------------------------
    A run-time constant pool is a per-class or per-interface run-time representation of the constant_pool table in a class file (§4.4)
    Aresxue
        18
    Aresxue  
       May 5, 2022
    目前每个 class 独立一个, 但官方有意图想做到一个 jar 中所有类共享一个常量池,至于全局一个可能有些弊大于利不是很说得准。
    About     Help     Advertise     Blog     API     FAQ     Solana     6082 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 56ms UTC 02:32 PVG 10:32 LAX 19:32 JFK 22:32
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86