永久代和元空间都是HotSpot虚拟机中的概念。HotSpot虚拟机是SunJDK和OpenJDK自带的虚拟机。它也是使用最广泛的Java虚拟机。当我们提到虚拟机时,很可能指的是HotSpot虚拟机。但是从《Java 虚拟机规范》的角度来看,并没有所谓的“永久代”和“元空间”。具体可以参考官方文档:https://img.ydisp.cn/news/20230213/ylcvdknh2dp.htmlVirtualMachineSpecification只规定了一个区域叫做“MethodArea”,而“permanentgeneration”和“metaspace”是HotSpot虚拟机在不同JDK版本下对方法区的具体实现。就好比世界羽协规定羽毛球比赛必须使用羽毛球拍(法区),而中国羽毛球运动员第一年使用双喜牌羽毛球拍(永久代),第二年使用李宁牌羽毛球拍年取(元空间)相同。那么问题来了,为什么永久代要换成元空间呢?1.官方回答关于这个问题,JEP122中给出了官方回答:RemovethePermanentGeneration(移除永久代)。原文如下:Motivation(动机)这是JRockit和Hotspot融合努力的一部分。JRockit客户不需要配置永久代(因为JRockit没有永久代)并且习惯于不配置永久代。JRockit客户端不需要配置永久代(因为JRockit没有永久代),所以去掉永久代。JRockit被Java正式收购,号称是史上运行速度最快的Java虚拟机厂商。后来,Java在JDK8中正式集成了JRockit虚拟机和HotSpot虚拟机。PS:JEP是JDKEnhancementProposal的缩写,翻译成中文就是JDK改进提案。你也可以理解为JDK的更新文档。通过官方的描述,我们似乎找到了答案,那就是之所以取消“永久代”是因为Java官方收购了JRockit,然后在集成JRockit和HotSpot的时候,因为JRockit中没有“永久代”,所以永久代被去掉了。PS:上面的描述好像很清楚,但是好像没说什么。这就好比,我问你“为什么要买车?”,你说“别人都买车,我也想买车”,但别人为什么要买车?2.背后的原因上面给出了永久代移除的答案,但是没有给出背后的原因。那我们接下来讨论一下,为什么要去掉永久代呢?为什么是元空间?2.1减少OOM使用永久代实现方法区时,永久代的最大容量受制于PermSize和MaxPermSize参数设置的大小,而这两个参数的大小很难确定,因为它很重要的是加载程序运行时需要加载多少类。很难估计。如果这两个参数设置得太小,会频繁触发FullGC,导致OOM(OutofMemory,内存溢出)。但是当永久代被元空间取代后,OOM的几率就大大降低了,因为元空间使用的是本地内存,所以元空间的大小只与本地内存的大小有关,大大减少了OOM问题.2.2降低运维成本由于元空间使用本地内存,运维人员无需专门设置和调整元空间的大小。3、方法区的发展历史在HotSpot虚拟机中,方法区的实现经历了以下三个阶段:JDK1.6及之前:方法区使用永久代实现,静态变量存放在永久一代;JDK1.7:“移除永久代”之前版本的JDK仍然有永久代,但是字符串常量池和静态变量已经从永久代移到了堆中;JDK1.8及以后:无永久代,使用元空间(存放在本地内存中)实现方法区,常量存放在元空间中,但字符串常量池和静态变量仍存放在堆中。综上所述,无论是永久代还是元空间,都是HotSpot虚拟机对《Java 虚拟机规范》中方法区的实现。在JDK1.8之前,HotSpot是使用永久代来实现方法区的,但是这样会使JVM调优变得更加困难,容易出现OOM,但是在JDK1.8之后,元空间存储在本地内存中,而不是永久代,这降低了OOM的可能性,也是JRockit和HotSpot整合后的变化之一。参考和致谢openjdk.org/jeps/122
