18、JVM实战:运行时常量池、图示举例方法区的使用、方法区的演进细节

一、运行时常量池

运行时常量池(Runtime constant Poo1)是方法区的一部分。常量池表(Constant Pool Table)是class文件的一部分,用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。运行时常量池,在加载类和接口到虚拟机后,就会创建对应的运行时常量池。

JVM为每个已加载的类型(类或接口)都维护一个常量池。池中的数据项像数组项一样,是通过索引访问的。运行时常量池中包含多种不同的常量,包括编译期就已经明确的数值字面量,也包括到运行期解析后才能够获得的方法或者字段引用。此时不再是常量池中的符号地址了,这里换为真实地址。

  • 运行时常量池,相对于class文件常量池的另一重要特征是:具备动态性。string.intern()。

运行时常量池类似于传统编程语言中的符号表( symbol table),但是它所包含的数据却比符号表要更加丰富一些。当创建类或接口的运行时常量池时,如果构造运行时常量池所需的内存空间超过了方法区所能提供的最大值,则JVM会抛OutOfMemoryError异常。

二、图示举例方法区的使用

*

*

* *

*

*

*

*

*

*

*

*

*

*

*

*

三、方法区的演进细节

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

*

*

*

*

永久代为什么要被元空间替换?

随着Java8的到来,Hotspot vM中再也见不到永久代了。但是这并不意味着类的元数据信息也消失了。这些数据被移到了一个与堆不相连的本地内存区域,这个区域叫做元空间(Metaspace ) 。

由于类的元数据分配在本地内存中,元空间的最大可分配空间就是系统可用内存空间。这项改动是很有必要的,原因有:

(1)为永久代设置空间大小是很难确定的。在某些场景下,如果动态加载类过多,容易产生Perm区的OOM。比如某个实际web工程中,因为功能点比较多,在运行过程中,要不断动态加载很多类,经常出现致命错误。

“Exception in thread ' dubbo client x.x connector’java.lang.OutOfMemoryError: PermGen space"

而元空间和永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。

(2)对永久代进行调优是很困难的。

版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址: