欢迎光临
我们一直在努力

运行时常量池和字符串常量池,字符串常量池是实例还是引用

首先明确class常量池、运行时常量池、字符串常量池不是同一个概念。

常量池表(Constant Pool Table)

常量池表(Constant Pool Table)是Class文件(字节码文件)的一部分,在编译阶段,用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中(运行时常量池就是常量池在程序运行时的称呼)。常量池,可以看做是一张表,虚拟机指令根据这张常量表找到要执行的类名,方法名,参数类型、字面量等信息。

运行时常量池( Runtime Constant Pool) 运行时常量池( Runtime Constant Pool)是方法区的一部分。在加载类和接口到虚拟机后,就会创建对应的运行时常量池。JVM为每个已加载的类型(类或接口)都维护一个常量池。池中的数据项像数组项一样,是通过索引访问的。运行时常量池中包含多种不同的常量,包括编译期就已经明确的数值字面量,也包括到运行期解析后才能够获得的方法或者字段引用。此时不再是常量池中的符号地址了,这里换为真实地址。运行时常量池,相对于Class文件常量池的另一重要特征是:具备动态性。运行时常量池类似于传统编程语言中的符号表(symbol table),但是它所包含的数据却比符号表要更加丰富一些。当创建类或接口的运行时常量池时,如果构造运行时常量池所需的内存空间超过了方法区所能提供的最大值,则JVM会抛OutofMemoryError异常。 字符串常量池 (StringTable) String table又称为String pool,String的String Pool(字符串常量池)是一个固定大小的Hashtable,默认值大小长度是1009。如果放进String Pool的String非常多,就会造成Hash冲突严重,从而导致链表会很长,而链表长了后直接会造成的影响就是当调用String.intern()方法时性能会大幅下降。使用-XX:StringTablesize可设置StringTable的长度。在JDK6中StringTable是固定的,就是1009的长度,所以如果常量池中的字符串过多就会导致效率下降很快,StringTablesize设置没有要求。在JDK7中,StringTable的长度默认值是60013,StringTablesize设置没有要求。在JDK8中,StringTable的长度默认值是60013,StringTable可以设置的最小值为1009。字符串常量kddxtd的到底是什么这里先不做过多介绍了。

永久代演进过程
美国高防vps 1.首先明确:只有Hotspot才有永久代。BEA JRockit、IBMJ9等来说,是不存在永久代的概念的。原则上如何实现方法区属于虚拟机实现细节,不受《Java虚拟机规范》管束,并不要求统一
2.Hotspot中方法区的变化:

JDK1.6及以前有永久代(permanent generation),字符串常量池、静态变量存储在永久代上JDK1.7有永久代,但已经逐步 “去永久代”,字符串常量池,静态变量移除,保存在堆中JDK1.8无永久代,类型信息,字段,方法,常量保存在本地内存的元空间,但字符串常量池、静态变量仍然在堆中。

JDK1.6及以前

JDK1.7

JDK1.8

Class常量池与运行时常量池示意图:

总结

JDK1.6之前:
永久代(方法区)里存储着class文件的信息和运行时常量池(动态常量池),class文件的信息包括类信息和class常量池(静态常量池),运行时常量池(动态常量池)里包含着字符串常量池。
JDK1.7:
永久代(方法区)里存储着class文件的信息和运行时常量池(动态常量池),class文件的信息包括类信息和class常量池(静态常量池),字符串常量池在堆中。
JDK1.8:
元空间里存储着class文件的信息和运行时常量池(动态常量池),class文件的信息包括类信息和class常量池(静态常量池),字符串常量池在堆中。

38840486

赞(0)
【声明】:本博客不参与任何交易,也非中介,仅记录个人感兴趣的主机测评结果和优惠活动,内容均不作直接、间接、法定、约定的保证。访问本博客请务必遵守有关互联网的相关法律、规定与规则。一旦您访问本博客,即表示您已经知晓并接受了此声明通告。