Java 8为Metaspace保留了至少1G的空间,即使设置了(最大)MetaspaceSize。

33

Java 8启动后会为元空间(Metaspace)预留1G的空间,这意味着最小的元空间大小为1G。但是我将MetaspaceSize设置为300m,MaxMetaspaceSize设置为400m。为什么Java会预留比我允许的更多的空间呢?

Java版本

$ java -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

虚拟机标志

$ jcmd 21689 VM.flags
21689:
-XX:CICompilerCount=3 -XX:ConcGCThreads=1 -XX:G1HeapRegionSize=1048576 -XX:InitialHeapSize=62914560 -XX:+ManagementServer -XX:MarkStackSize=4194304 -XX:MaxHeapSize=1006632960 -XX:MaxMetaspaceSize=399998976 -XX:MaxNewSize=603979776 -XX:MetaspaceSize=299999232 -XX:MinHeapDeltaBytes=1048576 -XX:NativeMemoryTracking=summary -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseG1GC 

神经机器翻译

[jetty9-proxy@bm01 bin]$ jcmd 21689 VM.native_memory
21689:

Native Memory Tracking:

Total: reserved=2769543KB, committed=1311159KB

-                     Class (reserved=1221904KB, committed=197904KB)
                            (classes #36543)
                            (malloc=3344KB #44041) 
                            (mmap: reserved=1218560KB, committed=194560KB) 

刚开始时就是这样的

Total: reserved=2402748KB, committed=150796KB     

-                     Class (reserved=1056956KB, committed=7868KB)
                            (classes #1300)
                            (malloc=188KB #564) 
                            (mmap: reserved=1056768KB, committed=7680KB) 

我认为你正在展示Java堆总量,而不是元空间总量。 - Buhake Sindi
我从命令结果中删除了Java堆。 - Eugene To
你在哪里看到1GB的数字与元空间大小有关? - the8472
我假设因为在Java 8中类是在元空间中,我没错吧? - Eugene To
2个回答

33

2
我也喜欢这篇详细解释为什么CompressedClassSpaceSize是一个硬限制的文章: https://stuefe.de/posts/metaspace/what-is-compressed-class-space/ - Andrei Damian-Fekete
请注意...此答案可能不正确。如果您正在使用有限且较小的元空间,并且元空间的值小于XX:CompressedClassSpaceSize,则该选项可能会被忽略,JVM可能会使用公式CompressedClassSpaceSize = MaxMetaspaceSize - 2 * InitialBootClassLoaderMetaspaceSize - Rafael

4

类(保留=1221904KB)

这并不是正在使用的内存,而只是虚拟地址空间。

已提交=197904KB

那是197MB,而不是1GB。

因此,你没有显示Java实际上消耗了1GB的内存用于类数据,只是它预留了1GB的地址空间。


1
是的,你说得对。那就是我想表达的意思。抱歉,英语不是我的母语。我会编辑主题的。 - Eugene To
1
但是它不应该保留太多内存,因为我设置了MetaspaceSize=300m和MaxMetaspaceSize=400m。不可预测的分配是不好的。我在那个VM上还有其他JVM进程,因为没有免费内存,所以我无法启动它们。 - Eugene To
您只需打开过度承诺(overcommit)即可允许其保留这么多空间。 - the8472
这是一个可能的解决方法。但是我想了解为什么Java首先要保留1G用于类。 - Eugene To
4
我认为这可能与需要一个连续的压缩类空间内存块有关,而你正在使用它。有一个名为 CompressedClassSpaceSize 的选项。 - the8472

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接