JVM常量池

5 篇文章 0 订阅

java语义中的常量池有三个概念:

1. 一个是class文件中的常量池,这里存放着类、字段和方法的名称,静态成员变量的值,字符串常量等一系列类相关的信息:

Constant pool:

#1 = Class #2 // com/learn/clazz/file/SampleClass

#2 = Utf8 com/learn/clazz/file/SampleClass

#3 = Class #4 // java/util/ArrayList

#4 = Utf8 java/util/ArrayList

#5 = Class #6 // java/lang/Cloneable

#6 = Utf8 java/lang/Cloneable

#7 = Class #8 // java/io/Serializable

#8 = Utf8 java/io/Serializable

#9 = Utf8 serialVersionUID

#10 = Utf8 J

...

 

2. 另一个是JVM执行过程中的运行时常量池,运行时常量池是每个class或interface的class文件常量池在内存中的映射,类加载时被创建。每个运行时常量池所使用的内存区域都在JVM方法区中分配,JVM规范中说明,方法区逻辑上是堆的一部分,但无需像堆一样被gc,JVM并没有规定具体的方法区实现。hostspot实现中,方法区在jdk7和jdk8的实现中有较大变动,详情见 JVM运行时内存区域 方法区介绍。

 

3. 还有一个是字符串常量池,这个概念没有在JVM Specification中找到,Specification只说字符串常量存放在运行时常量池,对于如何组织字符串常量并没有约定。hotspot实现中和字符串常量池相关的概念是StringTable,在JVM启动参数中增加-XX:+PrintStringTableStatistics,能在程序执行结束后输出应用的常量池使用情况(只能在程序终止的时候,正常或异常):

SymbolTable statistics:

Number of buckets : 20011 = 160088 bytes, avg 8.000

Number of entries : 11609 = 278616 bytes, avg 24.000

Number of literals : 11609 = 510272 bytes, avg 43.955

Total footprint : = 948976 bytes

Average bucket size : 0.580

Variance of bucket size : 0.581

Std. dev. of bucket size: 0.762

Maximum bucket size : 6

StringTable statistics:

Number of buckets : 60013 = 480104 bytes, avg 8.000

Number of entries : 1583 = 37992 bytes, avg 24.000

Number of literals : 1583 = 145688 bytes, avg 92.033

Total footprint : = 663784 bytes

Average bucket size : 0.026

Variance of bucket size : 0.027

Std. dev. of bucket size: 0.163

Maximum bucket size : 2

StringTable使用HashTable的数据结构存储,Number of buckets : 60013意味着table的长度是60013,这是缺省的值,可以使用 -XX:StringTableSize=10000 改变。单个bucket 8bytes意味着是64位系统。Number of entries表示hashTable中元素个数,Number of literals表示字符串常量的个数,Maximum bucket size : 2 表示当前单个槽中最多存放两个entity,该指标决定了hash碰撞的程度(冲突过多影响gc时遍历StringTable做数据回收的效率,要增加buckets size,网上有看到增加buckets size提升ygc效率)。

java代码中的字符串常量引用都记录在StringTable里,从jdk7开始,字符串对象开始记录在堆,因此StringTable过大会造成oom。java代码中的字符串常量和用户通过String.intern()方式操作的字符串会进入StringTable。在堆内存不够用时,StringTable中引用的字符串常量也可以被gc回收。

jdk7版本里,字符串常量被移到了堆中,符号表移到native memory。

字符串常量池存在的意义是相同字符串复用,减少内存开销。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值