Sizing Permgen and Metaspace

当JVM加载classes时,它必须跟踪关于这些classes的特定的元数据。这样的元数据被放在一个独立的heap space中。Java 7里叫permgen,Java 8里叫metaspace。

 

Permgen和metaspace不是同一个东西。java 7里,permgen包含了一些杂项对象(和class data无关);它们在Java 8里被移到了平常的heap中去了。Java 8还从根本上改动了保存在

该特殊区域里的元数据的类型。作为一般用户,我们只需要知道permgen和metaspace存储了一些class相关的数据,在特定的情况下,这些区域的size需要被调整。

 

注意permgen/metaspace不会存储实际的类的实例,也不会存储反射对象(比如说Method对象);这些对象是放在regular heap中。permgen/metaspace里的信息只会被编译器和

JVM运行时使用,这些信息叫作class metadata。

 

没有一个好的方法预先计算出一个程序它的permgen/metaspace需要多少空间。该空间大小将和class的数量成比例,所以大的程序将需要更大的区域。metaspace不需要调整,因为它

默认会根据需要使用尽量多的空间。

JVM Default initial size Default maximum permgen size Default maximum metaspace size

32-bit client JVM 12 MB 64 MB Unlimited

32-bit server JVM 16 MB 64 MB Unlimited

64-bit JVM 20.75 MB 82 MB Unlimited

 

permgen的size通过-XX:PermSize=N和-XX:MaxPermSize=N来指定

metaspace的size通过-XX:MetaspaceSize=N和-XX:MaxMetaspaceSize=N来指定

 

Metaspace太大了?

因为metaspace的默认size不受限制,那就有可能(特别是在一个32位的JVM中)一个Java 8应用填满了metaspace,造成了内存溢出错误。第8章里谈到的Native Memory Tracking

工具可以帮助诊断该情况。如果metaspace增长变得太大了,你可以降低MaxMetaspaceSize的值——但填满后,应用最终会报告OutOfMemoryError。弄清楚为什么class metadata

太大才能真正解决该问题。

 

Resizing这些区域需要一个full GC,因此这是一个昂贵的操作。如果在一个程序的启动过程中(加载classes),有大量的full GCs,那常常是因为permgen或metaspace正在被resized,

因此加大初始大小是一个不错的主义。定义了大量classes的Java 7应用程序应当还要加大maximum size。应用服务器通常将maximum permgen size指定为128MB、192MB,或更多。

 

Heap dumps可以被用来诊断有哪些classloaders存在,之后就可以帮助决定if a classloader leak is filling up permgen(or metaspace)。否则的话,jmap带上-permstat(java 7)或

-clstats(Java 8)可以打印出关于classloaders的信息。

你可能感兴趣的:(JMAP,permgen,metaspace)