125

在 Java 7 之前,JVM 内存中有一个称为PermGen的区域,JVM 用来保存它的类。在Java 8中,它被移除并被称为Metaspace的区域所取代。

PermGen 和 Metaspace 之间最重要的区别是什么?

我知道的唯一区别是java.lang.OutOfMemoryError: PermGen space不能再抛出并且MaxPermSize忽略VM参数。

4

5 回答 5

151

从用户的角度来看,主要的区别——我认为前面的答案不够强调——是Metaspace 默认自动增加它的大小(直到底层操作系统提供的大小),而 PermGen 总是有一个固定的最大大小。您可以使用 JVM 参数为 Metaspace 设置一个固定的最大值,但不能使 PermGen 自动增加。

在很大程度上,这只是名称的改变。早在引入 PermGen 时,没有 Java EE 或动态类(卸载)加载,因此一旦加载了一个类,它就会卡在内存中,直到 JVM 关闭 - 因此是永久生成。如今,类可能在 JVM 的生命周期内被加载和卸载,因此元空间对于保存元数据的区域更有意义。

它们都包含java.lang.Class实例,并且都遭受ClassLoader 泄漏。唯一的区别是,使用 Metaspace 默认设置,您需要更长的时间才能注意到症状(因为它会尽可能地自动增加),即您只是将问题推得更远而不解决它。OTOH 我想操作系统内存用完的影响可能比 JVM PermGen 用完更严重,所以我不确定这是否是一个很大的改进。

无论您是使用带有 PermGen 或 Metaspace 的 JVM,如果您正在执行动态类卸载,您应该采取措施防止类加载器泄漏,例如使用我的ClassLoader Leak Prevention 库

于 2014-11-26T08:12:12.427 回答
49

再见,再见 PermGen,你好元空间

PermGen已被完全删除。

元空间垃圾收集——一旦类元数据使用量达到MaxMetaspaceSize.

被占用的空间Metadata不再与 . 连续Java heapmetadata现在已经移动到本机内存的一个称为 . 的区域Metaspace

用简单的话来说

由于类元数据是从本机内存分配的,因此最大可用空间是总可用系统内存。因此,您将不再遇到OOM errors并且可能最终溢出到交换空间中。

删除PermGen并不意味着您的类加载器泄漏问题消失了。所以,是的,你仍然需要监控你的消耗并相应地计划,因为泄漏最终会消耗你的整个本机内存。

其他一些文章,有分析:Link1Link2,和这个

于 2014-11-25T16:00:38.407 回答
12

简而言之,如果不受限制,元空间大小会根据加载类元数据的需要在本机内存中自动增加-XX:MaxMetaspaceSize

于 2016-05-29T04:53:48.043 回答
2

在这里让它变得简单。

什么是 PermGen : PermGen 是与主内存堆分离的特殊堆空间。类元数据在此处加载。java 7:PermGen 是 JVM 跟踪已加载类的元数据的空间。
java 8:PermGen 被 Metaspace 取代,具有根据加载类元数据的要求自动增加本机内存的能力。

于 2021-02-15T12:34:22.023 回答
2

永久代

  • (永久代)是一个与主存分离的特殊堆空间。
  • JVM 跟踪 PermGen 中的类元数据。此外,JVM 将所有静态内容存储在其中。
  • 由于内存大小有限,PermGen 可能会抛出 OutOfMemoryError。

元空间

  • 元空间是一种新的内存空间。
  • 它取代了旧的 PermGen 内存空间。
  • 它现在可以处理内存分配。
  • 默认情况下,元空间会自动增长。
于 2021-08-08T08:16:28.247 回答