PermGen 和 Metaspace 有什么区别?

在 Java7之前,JVM 内存中有一个叫做 PermGen的区域,JVM 用来保存它的类。在 爪哇8中,它被移除并被称为 元空间的区域所取代。

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

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

66867 次浏览

再见,再见 PermGen,你好 Metaspace

PermGen 已被完全清除。

Metaspace 垃圾收集 -一旦类元数据的使用达到 MaxMetaspaceSize,就会触发死类和类加载器的垃圾收集。

占用的空间 Metadata不再与 Java heap相连,metadata现在已经移动到本机内存中的一个区域称为 Metaspace

简而言之,

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

删除 PermGen并不意味着您的类装入器泄漏问题已经消失。因此,是的,您仍然必须监视您的消耗并相应地进行计划,因为泄漏将最终消耗您的整个本机内存。

其他一些文章,包括分析: Link1Link2这个

从用户的角度来看,主要的区别在于 默认情况下自动增加元空间的大小(取决于底层操作系统提供的大小) ,而 PermGen 总是有一个固定的最大大小。您可以使用 JVM 参数为 Metaspace 设置一个固定的最大值,但是不能使 PermGen 自动增加。

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

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

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

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

我是来让事情简单化的。

什么是 PermGen: PermGen 是一个独立于主内存堆的特殊堆空间。 Java7: PermGen 是 JVM 跟踪已加载类的元数据的空间。
Java 8: PermGen 被 Metaspace 取代,它能够根据加载类元数据的需求自动增加本机内存。

PermGen

  • (永久生成)是与主内存分离的特殊堆空间。
  • JVM 在 PermGen 中跟踪类元数据。 此外,JVM 将所有静态内容存储在此。
  • 由于内存大小有限,PermGen 可以抛出 OutOfMemory 错误。

元空间

  • 元空间是一个新的内存空间。
  • 它替换了老的 PermGen 内存空间。
  • 它现在可以处理内存分配。
  • 默认情况下,元空间会自动增长。