15

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

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

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

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

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

Oracle 文档说没有指南可以知道将 MetaspaceSize 设置为什么。但是有没有办法找出设置它的正确值是多少?

我从 Oracle 文档中得到的一个提示是:

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 值?
4

3 回答 3

12

MetaspaceSizeFull GC是触发a 时的值,它不是初始空间,也不是最大空间。

它的默认值是20MB(至少在jdk-8to上jdk-13):

java -XX:+PrintFlagsFinal -version | grep MetaspaceSize

将产生:

size_t MetaspaceSize = 21807104 // 20MB

这意味着当Metaspace到达20MBa时Full GC将被触发,如果你能避免它,那就太好了。

考虑到元空间可能包含多少数据(方法、注释等),在我看来,这20MB是一个非常小的值。不幸的是,选择一个正确的值并不容易。

您有两个选择,启用 gc 日志记录-Xlog:gc并让应用程序运行一段时间,然后找到如下实例:

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

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

使用以下方法开始该过程:

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

Non-class space并在应用程序运行至少一天后获得价值,恕我直言。

关于如何控制还有其他各种设置Metaspace,您可以像这样找到它们:

java -XX:+PrintFlagsFinal -version | grep Metaspace
于 2019-11-19T19:57:21.353 回答
8

我认为最有趣的问题是#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 的评论几乎回答了您关于如何为您的实现确定默认元空间设置的前 2 个问题......为了完整起见,我将其包含在此处:

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”

于 2017-09-27T17:39:16.173 回答
5

从 Java 8 开始,可以使用以下命令行选项控制两个最重要的元空间设置:

  • -XX:MetaspaceSize=N- 当最初为类元数据提交的空间达到这个级别时,会引发垃圾收集;随后可能会根据收集结果提高或降低水平,
  • -XX:MaxMetaspaceSize=N- 设置元空间的最大大小。

引用Oracle HotSpot VM 垃圾收集调优指南

  • “类元数据在相应的Java类卸载时被释放。Java类由于垃圾回收而被卸载,垃圾回收可能会引发卸载类和释放类元数据。当为类元数据提交的空间达到一定水平时(高水位标记),垃圾收集被诱导。在垃圾收集之后,高水位标记可能会根据从类元数据中释放的空间量来提高或降低。高水位标记将被提高,以便不过早引发另一次垃圾收集。高水位标记最初设置为命令行选项的值-XX:MetaspaceSize。[...] 的默认大小-XX:MetaspaceSize取决于平台,范围从 12 MB 到大约 20 MB。
  • “默认情况下,可用于类元数据的本机内存量是无限的。使用该选项-XX:MaxMetaspaceSize对用于类元数据的本机内存量设置上限。”

WildFly 应用服务器将元空间选项standalone.conf分别设置为 96 MB / 256 MB,如下所示:

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

但是,MaxMetaspaceSize在大型生产应用程序中可能需要更大,因为它需要包含应用程序中所有已加载类的元数据,并且您可能希望为 指定更高的值MetaspaceSize以避免早期垃圾收集。

有关如何凭经验确定元空间设置的说明,另请参阅@Eugene 的回答。

于 2019-08-02T15:28:40.500 回答