什么是PermGen?
当装入类时,永久生成内存池包含永久类元数据和描述符信息
PermGen空间总是为类和附加到它们的项(即静态成员)保留
PermGem空间在内存中与Java堆相邻,并具有相同的垃圾回收循环,但它不是Java堆的一部分
什么是元空间?
在JDK8中,PermGen空间已经完全被Metaspace取代,它不再与Java堆相邻,现在存在于本机内存中
元空间的最大大小取决于可用的本机内存空间量,因为默认情况下,它可以根据需要动态调整大小(加载的类越多,分配的内存就越多)
重要提示:删除PermGen并不意味着类装入器泄漏问题就消失了。这就意味着泄漏将最终消耗您的整个本机内存,导致交换,只会变得更糟!
元空间内存管理(metaspace会gc吗)
元空间没有将GC绑定到Java堆,而是有一个metaspace vm,它使用自己的内存管理技术
一个规则是,只要类加载器是活动的,元数据就在元空间中保持活动状态,并且不能被释放
每个类装入器的存储区域称为“元空间”,这些元空间聚集在一起形成元空间
元空间有垃圾回收吗?
每个类加载器的元空间的回收只能在其类加载器不再活动并被GC报告为死机之后发生
初始空间大小调整是如何配置的
一旦watermark
水印被命中,如果类加载器不再活动,则会触发一个完整的GC来卸载这些类,并根据释放的元空间量重置高水位线的新值
如果释放的空间不足,则高水位线上升;如果释放的空间过大,则高水位线下降
重要提示:完整的GC很昂贵,因此建议将-XX:MetaspaceSize
设置为更高的值,以避免初始的垃圾回收,这也是元空间垃圾回收条件。
元空间Metaspace配置
- XX:MetaspaceSize={},其中{}是为类元数据分配的初始空间量(初始高水位线)(以字节为单位),这可能会导致GC卸载类。数额是近似的。在第一次达到高水位线后,下一个高水位线由垃圾收集器管理,默认情况下,32位设置为16M,64位设置为21M
- XX:MaxMetaspaceSize={},其中{]是为类元数据分配的最大空间量(以字节为单位)。此标志可用于限制为类元数据分配的空间量。这个值是近似值。,默认情况下,没有设置限制,这意味着元空间有可能增长到可用的本机内存大小
- XX:MinMetaspaceFreeRatio={},其中{}是GC后类元数据可用容量的最小百分比,以避免为类元数据分配的空间量(高水位线)增加,从而导致垃圾回收。元空间的垃圾回收将增加将使元空间更具侵略性
- XX:MaxMetaspaceFreeRatio={],其中{}是GC后类元数据可用容量的最大百分比,以避免为类元数据分配的空间量(高水位线)减少,从而导致垃圾回收。增加将减少元空间缩小的机会
元空间警告
允许Metaspace在没有cap的情况下动态调整大小可能会导致它消耗您的整个本机内存,从而在类装入器泄漏的情况下导致交换
动态调整的代价很高,因为每次达到高水位线时,它都会触发一个完整的 元空间 gc 来卸载类
metaspace VM使用一个具有多个块大小的分块分配器,这取决于类加载器的类型,自由块可能与类项所需的块大小不同,从而导致碎片
元空间虚拟机还没有使用压缩,所以碎片化是目前的一个主要问题
即使设置了XX:MaxMetaspaceSize
,保留的本机内存占用空间也是指定的最大大小的两倍
这意味着,如果将元空间大小限制为128MB,它仍将保留大约256MB的本机内存
调试元空间
注意:对于JDK8Build13,您必须用-XX:+UnlockDiagnosticVMOptions
启动Java,以使下面的一些工作正常
jmap–clstats{PID}
打印类装入器统计信息。
它现在取代了–permstat
,后者用于打印JDK8之前的JVMs的类装入器统计信息
jstat–gc{LVMID}
现在打印元空间信息
jcmd{PID}GC.class_stats
统计是一个新的诊断命令,它使最终用户能够连接到活动的JVM并转储Java类元数据的详细柱状图。
结论与建议
为了解决本文元空间警告部分中提出的问题,我建议我们减少甚至完全取消动态调整到元空间的能力,并限制最大大小。这基本上允许元空间像PermGen空间一样有效地工作,但现在它存在于本机内存中。以下配置将实现此目的:
-XX:MetaspaceSize=<initial_size>
-XX:MaxMetaspaceSize=<initial_size>
-XX:MinMetaspaceFreeRatio=0
-XX:MaxMetaspaceFreeRatio=100
除特别注明外,本站所有文章均为老K的Java博客原创,转载请注明出处来自https://javakk.com/845.html
暂无评论