我正在调查 OutOfMemoryError: Compressed Class Space 问题。我认为,我找到了它的根本原因和解决方案(由 Hibernate Validator 方法调用的 JAXBContext.newInstance():在用户提交的每个操作之后 buildValidatorFactory),但在我的研究中,我注意到一件令人困惑的事情。
我尝试运行 jcmd VM.native_memory 和 jstat -gc 来跟踪类提交大小和 CCSU(压缩类空间使用):
d:\experiments>jcmd 59692 VM.native_memory summary
Native Memory Tracking:
Total: reserved=10039335KB, committed=889895KB
- Java Heap (reserved=8353792KB, committed=522240KB)
(mmap: reserved=8353792KB, committed=522240KB)
- Class (reserved=1072460KB, **committed=24268KB**)
(classes #2518)
(malloc=9548KB #2393)
(mmap: reserved=1062912KB, committed=14720KB)
和
d:\experiments>jstat -gc 59692 2s
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT CGC CGCT GCT
21504,0 21504,0 0,0 0,0 131072,0 56218,7 139264,0 7755,5 14976,0 14318,5 1920,0 1721,7 2 0,012 1 0,036 - - 0,048
我预计 NMT 中的“已提交类别”指标和 jstat 中的 CCSU 指标之间没有重大区别,但 jstat 显示的已用内存大约只有 1.72 MB,而已提交类别超过 24 MB。所以我生成了 GC.class_stats 统计数据,它显示 KlassBytes 大约是 1738616 B -> 1,739 MB - 所以它与 CCSU 中的 jstat 显示的值大致相同。我还发现其他元数据(如方法、常量等)占用了大约 14,44 MB(这与 mmap 中的值大致相同:committed=14720KB - 但我不知道这个数字是多少)。
那么剩下的部分在哪里呢?NMT 给出的数字到底是多少?