JVM中的Permgen vs Metaspace

47 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情

前言

在Java 8中,方法区Metaspace取代了Permgen,那jvm为什么这么做呢?

Permgen

Permgen代表永久世代。它是一种特殊类型的堆空间,与主内存堆分离。JVM使用Permgen来跟踪加载的类元数据、静态内容(静态方法、对静态对象的引用等等)。

Permgen的默认大小如下:

  • 64MB: 32位JVM
  • 82MB: 64位JVM

可以通过以下选项修改默认大小:

  • -XX:PermSize=[size]是PermGen空间的初始或最小大小,例如: -XX:PermSize=512m
  • -XX:MaxPermSize=[size]是最大的大小。例如: -XX:MaxPermSize=512m

由于其有限的内存大小,Permgen会发生OutOfMemoryError。

Metaspace

元空间是Java 8中引入的一种新的内存空间。它已经取代了旧的永久代。永久代和元空间的主要区别在于,默认情况下,元空间会自动增加其大小,而永久生成总是有一个固定的最大大小。

通过引入Metaspace,垃圾收集也得到了优化。一旦类元数据的使用达到其最大元空间大小,垃圾收集器将自动触发对不要的类进行清理。

可以通过设置以下选项中的一个或几个来调优Metaspace:

  • -XX:MetaspaceSize=100M: 设置元空间初始大小,当元空间达到这个大小时,会触发垃圾回收,根据收集结果,该大小随后可能会升高或降低。
  • -XX:MetaspaceSize=N: 设置元空间的最大大小。
  • -XX:InitialBootClassLoaderMetaspaceSize=32M: 决定了给引导类加载器的第一个块的大小。它不施加任何限制,当那个块用完时,会分配一个新的块。
  • -XX:MinMetaspaceFreeRatio=50: 如果类元数据的提交可用空间占类元数据提交总空间的百分比小于MinMetaspaceFreeRatio,则提高metspace GC的阈值,但阈值的增量大小必须满足MinMetaspaceFreeRatio的要求,否则不提高阈值。
  • -XX:MaxMetaspaceFreeRatio=80:该参数的效果与MinMetaspaceFreeRatio相反。
  • -XX:MinMetaspaceExpansion=4M: 增加metspace GC阈值时对增量大小的最小要求。
  • -XX:MaxMetaspaceExpansion=16M: 增加metspace GC阈值时对增量大小的最大要求。如果增量大小超过MinMetaspaceExpansion但小于MaxMetaspaceExpansion,则增量大小为MaxMetaspaceExpansion。如果增量大小超过MaxMetaspaceExpansion,则增量大小为MinMetaspaceExpansion +原始增量大小。

因此,通过这种改进,JVM减少了OutOfMemory的可能。