方法区的演进
- 在jdk1.6及之前,在永久代,静态变量存放在永久代上。
- jdk1.7,有永久代,但已经逐步“去永久代”,字符串常量池丶静态变量移除,保存在堆中。
- 在jdk1.8后没有永久代,类型信息丶字段丶常量保存在本地内存的元空间,但字符串常量池丶静态变量还在堆中。
永久代为什么要被元空间替换?
元空间的最大可分配空间就是系统可用内存空间。
- 为永久代设置空间大小是很难确定的,在某一些场景下,如果动态加载类过多,很容易产生OOM,元空间并不在虚拟机中,而是使用的本地内存。因此,默认情况下,元空间的大小仅受到本地内存限制。
- 对永久代进行调优是很困难的。方法区的垃圾收集主要回收二部分内容:常量池中废弃的常量和不再使用的类型。
StringTable为什么要调整
jdk7中将StringTable放到了堆空间中。因为永久代的回收效率很低,在full gc的时候才会被触发。而full gc是老年代的空间不足丶永久代不足才会触发。这就导致StringTable回收效率不高。而我们开发中会有大量的字符串被创建,回收效率低,导致永久代内存不足。放在堆里,能及时回收内存。