JDK1.6到JDK1.8方法区的变化(大坑)

前言

来自小张的博客
JDK1.6到JDK1.8最明显的变化就是方法区的实现问题了,所以本章也是主要描述方法区的变化

从永久代到元空间

方法区(jdk7中实现为永久代,jdk8中为元空间),元空间并不在虚拟机中,而是使用本地内存,它和堆在逻辑上是连续的,但在物理上是不连续的,所以也叫非堆。

题外话 方法区与堆是线程间共享的
上图
image-1668007361027
可见方法区分为类的信息、常量池、方法数据、方法代码

变化

JDK版本方法区实现变化
jdk1.6永久代字符串常量池、运行时常量池、静态变量都是在永久代中
jdk1.7永久代字符串常量池和静态变量被移动到了堆当中,运行时常量池还是在永久代中
jdk1.8元空间字符串常量池和静态变量仍然在堆当中;运行时常量池、类型信息、常量、字段、方法被移动都了元空间中

JDK1.7时并没有完全取消永久代,而是采用永久代+堆的形式,直到jdk1.8才正式取消永久代使用元空间实现方法区。

大坑

注意:jdk1.7时将字符串常量池与静态变量移入堆之后,在jdk1.8元空间时并没有将其移到元空间,还是将其继续留在了堆空间
外链图片转存失败

PermGen(永久代)

PermGen , 就是 PermGen space ,全称是 Permanent Generation space ,是指内存的永久保存区域。
PermGen space 是JDK7及之前, HotSpot虚拟机基于JVM规范对方法区的一个落地实现。在JDK8被移除。

Metaspace(元空间、JDK8及之后):

元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。
移除PermGen(永久代)从从JDK7 就开始。例如,字符串内部池,已经在JDK7 中从永久代中移除。直到JDK8 的发布将宣告 PermGen(永久代)的终结。
元空间则是JDK1.8及之后,HotSpot虚拟机对方法区的新实现。

为什么使用元空间替换永久代?

通过上面分析,大家应该大致了解了 JVM 的内存划分,也清楚了 JDK8 中永久代 向 元空间的转换。不过大家应该都有一个疑问,就是为什么要做这个转换?所以,最后给大家总结以下几点原因:

  • 表面上看是为了避免OOM异常。
  • 因为通常使用PermSize和MaxPermSize设置永久代的大小就决定了永久代的上限,但是不是总能知道应该设置为多大合适, 如果使用默认值很容易遇到OOM错误。
  • 当使用元空间时,可以加载多少类的元数据就不再由MaxPermSize控制, 而由系统的实际可用空间来控制。
  • 更深层的原因还是要合并HotSpot和JRockit的代码,JRockit从来没有所谓的永久代,也不需要开发运维人员设置永久代的大小,但是运行良好。同时也不用担心运行性能问题了,在覆盖到的测试中, 程序启动和运行速度降低不超过1%,但是这点性能损失换来了更大的安全保障。

总结

  • 1)字符串存在永久代中,容易出现性能问题和内存溢出。
  • 2)类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。
  • 3)永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

造 山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值