Java 8使用能够动态扩展的元空间(metaspace)。当元空间(metaspace)变得充满时,GC将运行在元空间(metaspace)上。那么这是否意味着GC永远不会在元空间(metaspace)上运行?
我的Java 8应用程序占用了大量内存。我想知道运行时metaspace的大小是多少。我该如何做到这一点?
我正在考虑设置MaxMetaspaceSize
。我应该将其设置为什么值?有什么建议吗?
选项 1:
执行
jstat -gc PID
(使用要监控的JVM的PID替换PID)将返回类似于以下内容的结果:
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
103936.0 107008.0 0.0 41618.3 820736.0 401794.3 444928.0 183545.7 181888.0 137262.8 28544.0 20386.6 313 16.024 8 3.706 19.729
根据这篇文章,我们感兴趣的内容是:
MC: Metaspace capacity (kB)
MU: Metaspace utilization (kB)
在这种情况下,大约有181mb的元空间被承诺,而目前使用了137mb。2016-04-06T01:50:04.842+0200: 7.795: [Full GC (Metadata GC Threshold)
[PSYoungGen: 7139K->0K(177152K)]
[ParOldGen: 18396K->22213K(101888K)] 25535K->22213K(279040K),
[Metaspace: 34904K->34904K(1081344K)], 0.1408610 secs]
[Times: user=0.45 sys=0.00, real=0.14 secs]
由于达到了先前的阈值,这意味着对元空间进行了调整。
[Metaspace: 34904K->34904K(1081344K)], 0.1408610 secs]
包含相关信息:在GC之前和之后,使用了34.9MB。你可以在最新的这些日志条目中找到当前大小(即:GC之后的大小)。
请记住,当Metaspace被调整大小时,会运行完整的GC。因此,当您已经知道默认值约为21MB(取决于主机配置)不足够时,建议配置一个良好的起始值。
有关调整Metaspace大小的详细信息,请参见此处。
for (MemoryPoolMXBean memoryMXBean : ManagementFactory.getMemoryPoolMXBeans()) {
if ("Metaspace".equals(memoryMXBean.getName())) {
System.out.println(memoryMXBean.getUsage().getUsed()/1024/1024 + " mb");
}
}
如果您认为监视和修复可能导致泄漏,那么设置MaxMetaspaceSize
是更好的选择。
jcmd <pid> GC.heap_info
可以获取有关Metaspace大小的基本信息,而且不需要启用NMT。 - Juraj Martinka
man jstat
可以正确解释"MC: Metaspace capacity (kB)"和"MU: Metacspace utilization (kB)"的含义,而不是"committed"和"used"。 - moxn