这个java.lang.OutOfMemoryError:Metaspace
表示为Java类元数据分配的本机内存量已被耗尽。即我们经常遇到的 java metaspace 内存溢出问题。
在Java8和更高版本中,分配给Java类的最大内存量(MaxMetaspaceSize
)默认是不受限制的,因此在大多数情况下不需要更改此设置。另一方面,如果您想限制Java类的内存,可以按照如下方式设置:
java -XX:MaxMetaspaceSize=3200m
问题是-XX:MaxMetaspaceSize
只是一个上限。当前的元空间大小(即已提交)将更小。事实上,有一个名为MaxMetaspaceFreeRatio(默认值为70%)的设置,这意味着元空间的实际大小永远不会超过其占用率的230%。
为了让它首先增长,它必须填满,强制垃圾回收来释放对象,只有当它不能达到MinMetaspaceFreeRatio(默认值为40%)的目标时,它才会扩展当前的元空间。然而,这不能超过GC循环后入住率的230%。
Java HotSpotVM如何管理元空间数据
java hotspot按如下方式管理用于元数据的空间:从操作系统请求空间,然后将空间分成块。类装入器从其块中为元数据分配空间。
类元数据在相应的Java类被卸载并且其块被回收以供重用或返回给操作系统时释放。Java类是由于垃圾收集而卸载的,为了卸载类和释放类元数据,可能会触发垃圾收集。当为类元数据提交的空间达到某个阈值(高水位线)时,将触发垃圾回收。
垃圾收集之后,根据从类元数据中释放的空间量,可以提高或降低高水位线。如果回收后的剩余空间还是不够用就会报 metaspace outofmemory 的错误提示。
使用 jstat 命令检查元空间容量
监视元空间大小的最简单方法是使用JDK中提供的jstat
工具。当与选项-gcmetacapacity
一起使用时,它提供以下信息:
jstat -gcmetacapacity (PID)
比如下面的配置:
MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC FGCT CGC CGCT
0.0 374784.0 140360.0 0.0 253952.0 21168.0 23 0 0.000 6 0.046
下面是对标签的描述:
- 最小元空间容量(kB)。
- 最大元空间容量(kB)。
- MC:元空间容量(kB)。
- 压缩类空间最小容量(kB)。
- 压缩类空间最大容量(kB)。
- YGC:年轻一代GC事件的数量。
- FGC:完整GC事件数。
- FGCT:完整的垃圾收集时间。
- GCT:总垃圾收集时间。
其他选项包括参数-gcutil
:
jstat -gcutil (PID) | awk '{print($5)}'
这将以空间当前容量的百分比打印元空间利用率。
从 Heap Dump 堆转储查询元空间
可以通过堆转储执行进一步的检查:
然后,如果您查看了OQL控制台,就可以执行OQL查询来对您的类执行即席分析。例如,通过执行以下查询,可以从每个类加载器加载一个类列表:
select map(sort(map(heap.objects('java.lang.ClassLoader'), '{loader: it, count: it.classes.elementCount }'), 'lhs.count < rhs.count'), 'toHtml(it) + "
"')
这是一个宝贵的提示,可以用来确定类加载器是否正在加载越来越多的类。
使用Java本机内存跟踪监视元空间大小
监视元数据确切数量的一个好方法是使用NativeMemoryTracking,可以通过以下设置添加:
-XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=detail -XX:+PrintNMTStatistics
启用本机内存跟踪后,可以使用以下命令请求JVM内存使用情况报告:
jcmd <pid> VM.native_memory
如果检查jcmd
输出,您将在底部找到内部(提交)部分中提交/使用的本机内存量
本机内存跟踪:
Total: reserved=1334532KB, committed=369276KB
- Java Heap (reserved=524288KB, committed=132096KB)
(mmap: reserved=524288KB, committed=132096KB)
- Class (reserved=351761KB, committed=112629KB)
(classes #19111)
( instance classes #17977, array classes #1134)
(malloc=3601KB #66765)
(mmap: reserved=348160KB, committed=109028KB)
( Metadata: )
( reserved=94208KB, committed=92824KB)
( used=85533KB)
( free=7291KB)
( waste=0KB =0.00%)
( Class space:)
( reserved=253952KB, committed=16204KB)
( used=12643KB)
( free=3561KB)
( waste=0KB =0.00%)
在以Metaspace开头的行中,used
值是用于加载类的空间量。committed
值是可用于块的空间量。保留值是为元数据保留(但不一定要提交)的空间量。
还可以使用阿里开源的Arthas在线诊断工具来排查metaspace元空间内存溢出的问题:https://javakk.com/160.html
除特别注明外,本站所有文章均为老K的Java博客原创,转载请注明出处来自https://javakk.com/790.html
暂无评论