乐趣区

关于后端:为什么用元空间替代永久代

永恒代和元空间都是 HotSpot 虚拟机中的概念,HotSpot 虚拟机是 Sun JDK 和 Open JDK 中自带的虚拟机,也是目前应用范畴最宽泛的 Java 虚拟机,当咱们提到虚拟机时,大概率指的就是 HotSpot 虚拟机。

但从《Java 虚拟机标准》的层面来说,并没有所谓的“永恒代”和“元空间”等区域,详见官网文档:https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-2.html#jvms-2.5。《Java 虚拟机标准》只是规定了一个区域叫“办法区(Method Area)”,而 “永恒代”和“元空间”是 HotSpot 虚拟机在不同的 JDK 版本下,对办法区的具体实现而已。这就如同,世界羽协规定羽毛球较量必须要应用羽毛球拍(办法区),而中国羽毛球运动员,第一年应用的是红双喜牌的羽毛球拍(永恒代),第二年应用的是李宁牌羽毛球拍(元空间)一样。

那么问题来了,永恒代为什么被元空间给代替了?

1. 官网答案

对于这个问题,官网在 JEP 122: Remove the Permanent Generation(移除永恒代)中给出了答案,原文内容如下:

Motivation(动机)
This is part of the JRockit and Hotspot convergence effort. JRockit customers do not need to configure the permanent generation (since JRockit does not have a permanent generation) and are accustomed to not configuring the permanent generation.

以上内容翻译成中文粗心是:

这是 JRockit 虚拟机和 HotSpot 虚拟机交融工作的一部分。JRockit 客户不须要配置永恒层代(因为 JRockit 没有永恒代),所以要移除永恒代。

JRockit 是 Java 官网收买的一家号称史上运行最快的 Java 虚拟机厂商,之后 Java 官网在 JDK 8 时将 JRockit 虚拟机和 HotSpot 虚拟机进行了整合。

PS:JEP 是 JDK Enhancement Proposal 的缩写,翻译成中文是 JDK 改良提案。你也能够把它了解为 JDK 的更新文档。

通过官网的形容,咱们仿佛找到了答案,也就是说,之所以要勾销“永恒代”是因为 Java 官网收买了 JRockit,之后在将 JRockit 和 HotSpot 进行整合时,因为 JRockit 中没有“永恒代”,所以把永恒代给移除了

PS:下面的那段形容如同说的曾经很分明了,但又如同什么也没说。这就好比,我问你“为什么要买车?”,你说“他人都买车了,所以我要买车”,但为什么他人要买车?

2. 背地的起因

上述给出了移除永恒代的答复,但却没有给出背地的起因,那接下来咱们就来讨论一下,为什么要移除永恒代?以及为什么要有元空间?

2.1 升高 OOM

当应用永恒代实现办法区时,永恒代的最大容量受制于 PermSize 和 MaxPermSize 参数设置的大小,而这两个参数的大小又很难确定,因为在程序运行时须要加载多少类是很难估算的,如果这两个参数设置的过小就会频繁的触发 FullGC 和导致 OOM(Out of Memory,内存溢出)。

然而,当应用元空间代替了永恒代之后,呈现 OOM 的几率就被大大降低了,因为元空间应用的是本地内存,这样元空间的大小就只和本地内存的大小无关了,从而大大降低了 OOM 的问题。

2.2 升高运维老本

因为元空间应用的是本地内存,这样就无需运维人员再去专门设置和调整元空间的大小了。

3. 办法区发展史

在 HotSpot 虚拟机中,办法区的实现经验了以下 3 个阶段:

  1. JDK 1.6 及之前:办法区应用永恒代实现,动态变量寄存在永恒代
  2. JDK 1.7:“去永恒代”的前置版本,还存在永恒代,不过 曾经将字符串常量池和动态变量从永恒代移到了堆上
  3. JDK 1.8 及当前:无永恒代,应用元空间(寄存在本地内存中)实现办法区,常量保留在元空间,但字符串常量池和动态变量仍然保留在堆中

总结

永恒代和元空间都是 HotSpot 虚拟机对《Java 虚拟机标准》中办法区的实现,在 JDK 1.8 之前 HotSpot 是应用永恒代来实现办法区的,但这样会导致 JVM 调优比拟艰难,且容易产生 OOM 的问题,而 JDK 1.8 及之后,应用的是元空间寄存在本地内存中的形式来代替永恒代的,这样就升高了 OOM 产生的可能性,也是 JRockit 和 HotSpot 交融之后的改变之一。

参考 & 鸣谢

openjdk.org/jeps/122

本文已收录到 Gitee 开源仓库《Java 面试指南》,其中蕴含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、音讯队列等模块。Java 面试有它就够了:超全 Java 常见面试题,继续更新 …

退出移动版