jvm方法区的演进细节

本文探讨了Java虚拟机(JVM)在不同版本中方法区的变化,从JDK6的永久代,到JDK7的调整,直至JDK8及以后元空间的引入。永久代由于其空间大小难确定、易引发OOM以及调优复杂性而被元空间替代,以提高内存管理和垃圾回收效率。字符串常量池从永久代移到堆中以实现更高效的回收。文章指出,静态变量的变动原因暂未找到明确解释。

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

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

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

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

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

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

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

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

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

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

这个暂时还找不到答案

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值