在 Java 7 之前,JVM 内存中有一个称为PermGen的区域,JVM 用来保存它的类。在Java 8中,它被移除并被称为Metaspace的区域所取代。
PermGen 和 Metaspace 之间最重要的区别是什么?
我知道的唯一区别是java.lang.OutOfMemoryError: PermGen space
不能再抛出并且MaxPermSize
忽略VM参数。
从用户的角度来看,主要的区别——我认为前面的答案不够强调——是Metaspace 默认自动增加它的大小(直到底层操作系统提供的大小),而 PermGen 总是有一个固定的最大大小。您可以使用 JVM 参数为 Metaspace 设置一个固定的最大值,但不能使 PermGen 自动增加。
在很大程度上,这只是名称的改变。早在引入 PermGen 时,没有 Java EE 或动态类(卸载)加载,因此一旦加载了一个类,它就会卡在内存中,直到 JVM 关闭 - 因此是永久生成。如今,类可能在 JVM 的生命周期内被加载和卸载,因此元空间对于保存元数据的区域更有意义。
它们都包含java.lang.Class
实例,并且都遭受ClassLoader 泄漏。唯一的区别是,使用 Metaspace 默认设置,您需要更长的时间才能注意到症状(因为它会尽可能地自动增加),即您只是将问题推得更远而不解决它。OTOH 我想操作系统内存用完的影响可能比 JVM PermGen 用完更严重,所以我不确定这是否是一个很大的改进。
无论您是使用带有 PermGen 或 Metaspace 的 JVM,如果您正在执行动态类卸载,您应该采取措施防止类加载器泄漏,例如使用我的ClassLoader Leak Prevention 库。
再见,再见 PermGen,你好元空间
PermGen已被完全删除。
元空间垃圾收集——一旦类元数据使用量达到MaxMetaspaceSize
.
被占用的空间Metadata
不再与 . 连续Java heap
,metadata
现在已经移动到本机内存的一个称为 . 的区域Metaspace
。
用简单的话来说,
由于类元数据是从本机内存分配的,因此最大可用空间是总可用系统内存。因此,您将不再遇到OOM errors
并且可能最终溢出到交换空间中。
删除PermGen
并不意味着您的类加载器泄漏问题消失了。所以,是的,你仍然需要监控你的消耗并相应地计划,因为泄漏最终会消耗你的整个本机内存。
简而言之,如果不受限制,元空间大小会根据加载类元数据的需要在本机内存中自动增加-XX:MaxMetaspaceSize
在这里让它变得简单。
什么是 PermGen : PermGen 是与主内存堆分离的特殊堆空间。类元数据在此处加载。java 7:PermGen 是 JVM 跟踪已加载类的元数据的空间。
java 8:PermGen 被 Metaspace 取代,具有根据加载类元数据的要求自动增加本机内存的能力。
永久代
元空间