设置MetaspaceSize的指南 - java 8

时间:2016-04-07 01:34:39

标签: java memory-leaks java-8 out-of-memory metaspace

64位服务器的MetaspaceSize的默认值是多少?我无法在官方文档中找到它。

我观察到,在服务器JVM进程中,GC频率有时会变高并且不断增长。如果我重启服务几次,它会恢复稳定。我认为这是由于JRE的升级。

JVM堆最大大小设置为6GB但是当出现此问题时,我们看到只使用了3GB堆。 Metaspace增长很少,几乎总是满的。我尝试将元空间增加到1GB,这样可以提高吞吐量。

我认为正在发生的事情是Metaspace默认设置为一个非常低的值,因此GC启动。每次GC发生时,高水位标记不断增加(再次以非常低的量)。

我想设置MetaspaceSize(不确定当前值是多少)。

Oracle文档称,没有指导方针可以知道将MetaspaceSize设置为什么。但有没有办法找出设置它的正确值是什么?

我从Oracle docs得到的一个提示是:

If the committed space available for class metadata as a percentage of the total committed space for class metadata is greater than MaxMetaspaceFreeRatio, then the high-water mark will be lowered. If it is less than MinMetaspaceFreeRatio, then the high-water mark will be raised.

但仍然无法弄清楚如何稳定GCs。我有三个问题:

  1. 64位服务器上的默认MetaspaceSize是什么?
  2. 默认比例是什么:MaxMetaspaceFreeRatio,MinMetaspaceFreeRatio设置为?答:显示Min为40,Max为70
  3. 如何决定Metaspacesize值?

3 个答案:

答案 0 :(得分:1)

我认为最有趣的问题是#3,所以我先回答这个问题。我接近它的方法是使用这些设置启动gc日志记录24小时运行我的应用程序:

-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintGCCause
-XX:+PrintTenuringDistribution
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintGCApplicationConcurrentTime
-Xloggc:gc.log

然后我这样做了:

grep Metaspace gc.log

并且看到"使用"价值迅速增长到80M ......所以我将MetaspaceSize设置为100M

-XX:MetaspaceSize=100M

并且瞧 - 由于元空间而没有更多的gcs。

看起来@ Pillar的评论几乎回答了关于如何确定实施的默认Metaspace设置的前两个问题......为了完整起见,我将在此处包含它:

java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version -XX:+UseG1GC | grep Metaspace

从技术上讲,@ Pillar的评论并没有告诉你任何64位服务器的默认元空间大小,但是那是因为你的第一个问题有点误导,因为根据文档这些默认值因实施而异。

请参阅:

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/considerations.html

具体来说,它所在的底部部分," MetaspaceSize的默认大小取决于平台,范围从12 MB到大约20 MB"

答案 1 :(得分:1)

根据Java Performance: The Definitive Guide,第128页和Oracle HotSpot VM Garbage Collection Tuning Guide,元空间的默认大小是无限的。

从Java 8开始,元空间的初始大小和最大大小可以通过以下方式设置

  • -XX:MetaspaceSize=N-设置元空间的初始大小
  • -XX:MaxMetaspaceSize=N-设置元空间的最大大小。

WildFly应用服务器将standalone.conf中的初始和最大元空间值分别设置为96 MB / 256 MB,如下所示:

... -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m ...

但是,MaxMetaspaceSize在大型生产应用程序中可能需要更大,因为它需要包含应用程序中所有已加载类的元数据。

答案 2 :(得分:1)

MetaspaceSize是将触发Full GC时的值,它的不是初始空间或最大空间。

其默认值为20MB(至少在jdk-8jdk-13上):

java -XX:+PrintFlagsFinal -version | grep MetaspaceSize

将产生:

size_t MetaspaceSize = 21807104 // 20MB

这意味着当Metaspace到达20MB时会触发Full GC,如果可以避免的话,那会很好。

考虑到潜在的数据元空间可以容纳多少(方法,注释等),在我看来20MB一开始的价值很小。不幸的是,选择正确的值并不容易。

您有两个选择,启用gc日志记录-Xlog:gc,然后让该应用运行一段时间,然后找到类似以下的实例:

[Full GC (Metadata GC Threshold) ...]

并从中了解您需要设置什么以及如何设置。

Or 使用以下命令开始该过程:

java -XX:NativeMemoryTracking=detail

通过以下方式连接到PID

jcmd <YourJVMPID> VM.metaspace

找到这样的行:

 Virtual space:
    Non-class space:        8.00 MB reserved,       4.25 MB ( 53%) committed
    Class space:            1.00 GB reserved,     512.00 KB ( <1%) committed
    Both:                   1.01 GB reserved,       4.75 MB ( <1%) committed

在应用运行至少一天IMHO之后,从Non-class space获取值。

关于如何控制Metaspace的其他设置,您可以像这样找到:

java -XX:+PrintFlagsFinal -version | grep Metaspace