java 常量池有几个_关于JAVA几个常量池的问题?

我们基于 OpenJDK 8 之后的版本讨论。下面给出的源码是 OpenJDK 17 ea

当我们创建一个类对象时:这个类首先会被类加载器加载,在发生类加载的时候,对应类的元数据被存入元空间。元数据分为两部分存入元空间,一部分存入了元空间的类空间另一部分存入了元空间的非类空间。如 图00 所示:

默认压缩类指针是开启的,和压缩对象指针类似(可以参考这篇文章),压缩类指针也是占用 32 位,在 64 位操作系统中,MetaWord 占用 8 字节,也就是压缩类指针最多可以管理 32G 的内存。

对象头的压缩类指针指向 MetaSpace 的类空间,类空间中存储各种指针型数据,例如实现方法多态以及 virtual call 的 vtable 与 itable 保存着方法代码地址的引用指针。非类空间中存储着比较大的元数据,例如常量池,字节码,JIT 编译后的代码等等。由于编译后的代码可能非常大,以及 JVM 对于多语言支持的扩展可能动态加载很多类,所以将 MetaSpace 的类空间与非类空间区分开。

JVM 启动参数 -XX:CompressedClassSpaceSize 指定的是压缩类空间大小,默认是 1G。-XX:MaxMetaspaceSize控制的是 MetaSpace 的总大小。

常量池存在于非类空间中。但是,感觉题主问的主要并不是Constant Pool ,而是 Symbol Table 和 String table。

对应源码:

JVM 源码中的 Constant Pool 其实是一个全局公共数组,每加载一个类,这个类元数据的指针就会加入这个数组,指针指向的实际的数据,例如字面量,符号常量等等,都会放入全局公共 Symbol Table 以及 全局公共 StringTable.运行时常量池是每个类加载之后各有一个还是全局共享的?

常量池,不论是 Constant Pool,还是Symbol Table还是String Table,都是全局共享的。题主看到的有争议的,估计说的是,每个类的元数据的引用,是在每个类独有的 Klass* 指针对象中。

2. 运行时常量池中还保存Class文件常量池中保存的字符串吗?还是说被统一划分到全局字符串常量池中?

没太明白,Class文件常量池中的字面量字符串,都会加载入 String Table 中。

3. 对于String str=new String("abc");这样的语句之所以会说创建的两个对象是因为"abc"作为字面量被保存在Class文件常量池而在类加载的连接阶段在堆中创建了对象并保存引用在字符串常量池,而new String("abc")在运行时又会在堆中开辟空间创建对象,所以说创建了两个对象这样理解对吗?

对的,很准确。

(4)Class文件常量池中的常量是在什么时候进入字符串常量池和运行时时常量池的?准备阶段还是解析阶段?

准确的来说是解析阶段,解析类文件生成 Contant Pool 以及放入 Symbol Table 还有 String Table。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值