java string table_聊聊jvm的StringTable及SymbolTable

本文主要研究一下jvm的StringTable及SymbolTable

StringTable及SymbolTable

JDK的变动

在java7的时候将字符串常量池移到java heap,字符串常量池被限制在整个应用的堆内存中,在运行时调用String.intern()增加字符串常量不会使永久代OOM了。使用-XX:StringTableSize可以设置StringTableSize,默认是65536

java8的时候去除PermGen,将其中的方法区移到non-heap中的Metaspace,因而SymbolTable也跟随Metaspace移到了non-heap中

SymbolTable

symbolic references in Runtime Constant Pool

一个完整的类加载过程必须经历加载(Loading)、连接(Linking)、初始化(Initialization)这三个步骤

其中类加载阶段就是由类加载器负责根据一个类的全限定名来读取此类的二进制字节流到JVM内部,然后将其转换为一个与目标类型对应的java.lang.Class对象实例;连接阶段要做的是将加载到JVM中的二进制字节流的类数据信息合并到JVM的运行时状态中,经由验证(Verification)、准备(Preparation)、解析(Resolution)三个阶段;初始化阶段将一个类中所有被static关键字标识的代码统一执行一遍,如果执行的是静态变量,那么就会使用用户指定的值覆盖之前在准备阶段设置的初始值;如果执行的是static代码块,那么在初始化阶段,JVM就会执行static代码块中定义的所有操作

在连接(Linking)步骤里头的解析(Resolution)阶段,需要将常量池中所有的符号引用(classes、interfaces、fields、methods referenced in the constant pool)转为直接引用(得到类或者字段、方法在内存中的指针或者偏移量,以便直接调用该方法)

SymbolTable这个词在传统编程语言的实现里头比较常用(This data structure serves many of the purposes of the symbol table of a conventional programming language implementation),而在jvm里头对应的是Runtime Constant Pool中的symbolic references(Runtime Constant Pool除了symbolic references还包含了static constants),它是在类加载的时候(Resolution in Linking)根据class元数据中的constant pool table创建的,因而称为Runtime Constant Pool;这部分属于metaspcae,在native memory中

查看StringTable

/ # jcmd 1 VM.stringtable

1:

StringTable statistics:

Number of buckets : 65536 = 524288 bytes, each 8

Number of entries : 23407 = 374512 bytes, each 16

Number of literals : 23407 = 2153344 bytes, avg 91.996

Total footprsize_t : = 3052144 bytes

Average bucket size : 0.357

Variance of bucket size : 0.360

Std. dev. of bucket size: 0.600

Maximum bucket size : 5

使用jcmd pid VM.stringtable可以在运行时查看

查看SymbolTable

/ # jcmd 1 VM.symboltable

1:

SymbolTable statistics:

Number of buckets : 32768 = 262144 bytes, each 8

Number of entries : 128885 = 2062160 bytes, each 16

Number of literals : 128885 = 7160912 bytes, avg 55.560

Total footprsize_t : = 9485216 bytes

Average bucket size : 3.933

Variance of bucket size : 3.982

Std. dev. of bucket size: 1.996

Maximum bucket size : 14

使用jcmd pid VM.symboltable可以在运行时查看

同时查看StringTable及SymbolTable

-XX:+PrintStringTableStatistics

SymbolTable statistics:

Number of buckets : 32768 = 262144 bytes, each 8

Number of entries : 129215 = 2067440 bytes, each 16

Number of literals : 129215 = 7173248 bytes, avg 55.514

Total footprsize_t : = 9502832 bytes

Average bucket size : 3.943

Variance of bucket size : 3.990

Std. dev. of bucket size: 1.998

Maximum bucket size : 14

StringTable statistics:

Number of buckets : 65536 = 524288 bytes, each 8

Number of entries : 23470 = 375520 bytes, each 16

Number of literals : 23470 = 2157736 bytes, avg 91.936

Total footprsize_t : = 3057544 bytes

Average bucket size : 0.358

Variance of bucket size : 0.361

Std. dev. of bucket size: 0.601

Maximum bucket size : 5

启动时添加-XX:+PrintStringTableStatistics参数,在jvm进程退出时会输出SymbolTable statistics及StringTable statistics

jcmd pid VM.native_memory

/ # jcmd 1 VM.native_memory scale=MB

1:

Native Memory Tracking:

Total: reserved=1857MB, committed=112MB

- Java Heap (reserved=502MB, committed=32MB)

(mmap: reserved=502MB, committed=32MB)

- Class (reserved=1065MB, committed=47MB)

(classes #8386)

( instance classes #7843, array classes #543)

(malloc=1MB #21250)

(mmap: reserved=1064MB, committed=45MB)

( Metadata: )

( reserved=40MB, committed=40MB)

( used=39MB)

( free=1MB)

( waste=0MB =0.00%)

( Class space:)

( reserved=1024MB, committed=6MB)

( used=5MB)

( free=0MB)

( waste=0MB =0.00%)

- Thread (reserved=29MB, committed=3MB)

(thread #29)

(stack: reserved=29MB, committed=2MB)

- Code (reserved=243MB, committed=15MB)

(malloc=1MB #4744)

(mmap: reserved=242MB, committed=14MB)

- GC (reserved=2MB, committed=0MB)

(mmap: reserved=2MB, committed=0MB)

- Internal (reserved=1MB, committed=1MB)

(malloc=1MB #2172)

- Symbol (reserved=10MB, committed=10MB)

(malloc=7MB #223735)

(arena=3MB #1)

- Native Memory Tracking (reserved=4MB, committed=4MB)

(tracking overhead=4MB)

使用jcmd pid VM.native_memory输出的Symbol部分包含了StringTable(interned String)及SymbolTable

小结

在java7的时候将字符串常量池则移到java heap,字符串常量池被限制在整个应用的堆内存中,在运行时调用String.intern()增加字符串常量不会使永久代OOM了。使用-XX:StringTableSize可以设置StringTableSize,默认是65536;java8的时候去除PermGen,将其中的方法区移到non-heap中的Metaspace,因而SymbolTable也跟随Metaspace移到了non-heap中

StringTable位于heap中(java7+),而SymbolTable则在native memory中;使用jcmd pid VM.stringtable可以在运行时查看StringTable;使用jcmd pid VM.symboltable可以在运行时查看SymbolTable

在启动时添加-XX:+PrintStringTableStatistics参数,在jvm进程退出时会输出SymbolTable statistics及StringTable statistics;使用jcmd pid VM.native_memory输出的Symbol部分包含了heap中StringTable(interned String)及non heap中的SymbolTable

doc

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值