jvm方法区的演进细节

只有hotspot才有永久代,,在hotspot中方法区的变化如下:
jdk6时有永久代,静态变量放在永久代中
在这里插入图片描述

jdk7时,有永久代,但逐渐被放弃,字符串常量池、静态变量从永久代移除,保存到堆中。
在这里插入图片描述

jdk8及以后,就没有永久代了,类型信息,字段,方法,常量保存在本地内存中的元空间里,但字符串常量以及静态变量仍然放在堆中。
在这里插入图片描述

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

1、官网的说法是JRockit没有永久代,在hotspot合并后,就不提供这样的参数配置了。
2、为永久代设置空间大小是很难确定的,如果在某些场景下动态加载类过多,容易产生永久代的oom,比如某个功能在运行的过程中需要加载很多类,就会oom,所以用使用了直接内存的元空间替代。
3、对永久代的调优是很困难的,永久代的垃圾回收条件比较苛刻,因此不知道设置什么值的情况下,让其自动扩展,使用本地内存,就很少出现full gc的情况。

字符串常量池为什么要变化?

在jdk中将StringTabel放进了堆空间中,因为永久代的回收效率很低,只有在full gc时才会触发,而full gc是老年代空间不足或永久代不足时才会触发,我们在开发过程中会有大量的字符串被创建,如果回收效率低会导致永久代内存不足,但放在堆里就能及时回收。

Q1:为啥字符串要单独放在字符串常量池里面?字符串不也是对象吗?

因为做缓存,且字符串常量池里的常量是不可重复的,就保证了唯一性,将用字面量定义的值相等的对象指向同一个字符串常量池的常量,也会省了很多空间。字符串是特殊的对象,当然用new String声明的字符串对象还是在堆里(不是在堆里的字符串常量池)。

Q2:为什么静态变量要变化?

这个暂时还找不到答案

猜你喜欢

转载自blog.csdn.net/lyd135364/article/details/121209644
今日推荐