为什么我的 JVM 启动时进行了 3 次 FullGC
why my JVM did 3 times of FullGC when it started
我的作业是 Flink TaskManager 作业。启动时会启动3次GC。我不知道为什么当它达到 MetadataGCThreshold 时它增加了 Tenured Space,而 Metaspace 没有改变,甚至在 GC 之间增加。
我认为 FullGC 会减少 Tenured Space,以及一些 space 的 Metaspace。
Java HotSpot(TM) 64-Bit Server VM (25.211-b12) for linux-amd64 JRE (1.8.0_211-b12), built on Apr 1 2019 20:39:34 by "java_re" with gcc 7.3.0
Memory: 4k page, physical 4194304k(3951532k free), swap 0k(0k free)
CommandLine flags: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/flink-jvm -XX:InitialHeapSize=2899312640 -XX:MaxDirectMemorySize=9223370937343148032 -XX:MaxHeap
Size=2899312640 -XX:NewSize=2147483648 -XX:+PrintFlagsFinal -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
# first GC, the Tenured space even increase?!
2.452: [Full GC (Metadata GC Threshold) 2.452: [Tenured: 0K->14532K(735232K), 0.0623627 secs] 167782K->14532K(2622720K), [Metaspace: 20876K->20876K(1067008K)], 0.0624443 secs] [Times: user=0.05
sys=0.01, real=0.07 secs]
11.656: [Full GC (System.gc()) 11.656: [Tenured: 14532K->27057K(735232K), 0.1974158 secs] 395065K->27057K(2622720K), [Metaspace: 32454K->32454K(1077248K)], 0.1975190 secs] [Times: user=0.18 sys=
0.02, real=0.20 secs]
65.942: [Full GC (Metadata GC Threshold) 65.942: [Tenured: 27057K->55025K(735232K), 0.2259224 secs] 512544K->55025K(2622720K), [Metaspace: 53760K->53760K(1097728K)], 0.2262134 secs] [Times: user
=0.18 sys=0.03, real=0.23 secs]
============================================= ====================
跟进
感谢 Stephen 的回答,我将 MetaSpace 的 initialSize 设置为 -XX:MetaspaceSize=134217728
。我开始工作两次,第二次使用这个 jvm 参数。由于 Metadata GC Threshold
.
没有 FullGC
###### 之前: first time
bash-4.2$ tailf gc_log_2020-08-26_07-19-05_pid84.log
Java HotSpot(TM) 64-Bit Server VM (25.241-b26) for linux-amd64 JRE (1.8.0_241-b26), built on Jan 6 2020 08:59:51 by "java_re" with gcc 7.3.0
Memory: 4k page, physical 4194304k(3920180k free), swap 0k(0k free)
CommandLine flags: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/flink-jvm -XX:InitialHeapSize=2899312640 -XX:MaxDirectMemorySize=9223370937343148032 -XX:MaxHeapSize=2899312640 -XX:NewSize=2147483648 -XX:+PrintFlagsFinal -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
2.359: [Full GC (Metadata GC Threshold) 2.359: [Tenured: 0K->14643K(735232K), 0.0526437 secs] 167782K->14643K(2622720K), [Metaspace: 20937K->20937K(1067008K)], 0.0527307 secs] [Times: user=0.04 sys=0.01, real=0.05 secs]
14.576: [Full GC (System.gc()) 14.576: [Tenured: 14643K->27136K(735232K), 0.1894478 secs] 417611K->27136K(2622720K), [Metaspace: 32274K->32274K(1077248K)], 0.1895372 secs] [Times: user=0.15 sys=0.02, real=0.19 secs]
###### 添加了metadata参数之后(-XX:MetaspaceSize=134217728), second time with param
bash-4.2$ tailf gc_log_2020-08-26_07-23-19_pid85.log
Java HotSpot(TM) 64-Bit Server VM (25.241-b26) for linux-amd64 JRE (1.8.0_241-b26), built on Jan 6 2020 08:59:51 by "java_re" with gcc 7.3.0
Memory: 4k page, physical 4194304k(3920136k free), swap 0k(0k free)
CommandLine flags: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/flink-jvm -XX:InitialHeapSize=2899312640 -XX:MaxDirectMemorySize=9223370937343148032 -XX:MaxHeapSize=2899312640 -XX:MetaspaceSize=134217728 -XX:NewSize=2147483648 -XX:+PrintFlagsFinal -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
5.196: [Full GC (System.gc()) 5.196: [Tenured: 0K->27063K(735232K), 0.2379232 secs] 973363K->27063K(2622720K), [Metaspace: 32544K->32544K(1077248K)], 0.2380344 secs] [Times: user=0.25 sys=0.03, real=0.24 secs]
Why my JVM did 3 times of FullGC when it started?
第一次和第三次 Full GC 是由元space 达到其当前阈值并需要增长而触发的。由于 metaspace 主要用于保存 code-related 东西,这意味着 Flink 正在加载大量代码或生成大量动态代理或类似的东西。
您可以考虑增加初始元space大小。
第二次 Full GC 由显式 System.gc()
调用触发。我的猜测是 Flink 正在这样做。
I thought FullGC would decrease Tenured space.
不一定。如果 Full GC 是由 metaspace 填充触发的,那么你很可能会发现 new space 中的很多对象都被 tenured。在第一种情况下,很明显这已经发生了,因为在 GC 之前,tenured space 是 empty.
... while metaspace don't change, and even increase between GCs
这意味着 GC 没有在 metaspace 中发现任何垃圾。如果 ClassLoader
实例(及其所有 类 及其所有实例)变得无法访问,我只希望 metaspace 的使用减少。预计在启动期间 metaspace 使用量会增加。如果它继续增加 在 应用程序启动 并且 JVM 已完全预热后,这可能只是潜在的问题。
我的作业是 Flink TaskManager 作业。启动时会启动3次GC。我不知道为什么当它达到 MetadataGCThreshold 时它增加了 Tenured Space,而 Metaspace 没有改变,甚至在 GC 之间增加。
我认为 FullGC 会减少 Tenured Space,以及一些 space 的 Metaspace。
Java HotSpot(TM) 64-Bit Server VM (25.211-b12) for linux-amd64 JRE (1.8.0_211-b12), built on Apr 1 2019 20:39:34 by "java_re" with gcc 7.3.0
Memory: 4k page, physical 4194304k(3951532k free), swap 0k(0k free)
CommandLine flags: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/flink-jvm -XX:InitialHeapSize=2899312640 -XX:MaxDirectMemorySize=9223370937343148032 -XX:MaxHeap
Size=2899312640 -XX:NewSize=2147483648 -XX:+PrintFlagsFinal -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
# first GC, the Tenured space even increase?!
2.452: [Full GC (Metadata GC Threshold) 2.452: [Tenured: 0K->14532K(735232K), 0.0623627 secs] 167782K->14532K(2622720K), [Metaspace: 20876K->20876K(1067008K)], 0.0624443 secs] [Times: user=0.05
sys=0.01, real=0.07 secs]
11.656: [Full GC (System.gc()) 11.656: [Tenured: 14532K->27057K(735232K), 0.1974158 secs] 395065K->27057K(2622720K), [Metaspace: 32454K->32454K(1077248K)], 0.1975190 secs] [Times: user=0.18 sys=
0.02, real=0.20 secs]
65.942: [Full GC (Metadata GC Threshold) 65.942: [Tenured: 27057K->55025K(735232K), 0.2259224 secs] 512544K->55025K(2622720K), [Metaspace: 53760K->53760K(1097728K)], 0.2262134 secs] [Times: user
=0.18 sys=0.03, real=0.23 secs]
============================================= ====================
跟进
感谢 Stephen 的回答,我将 MetaSpace 的 initialSize 设置为 -XX:MetaspaceSize=134217728
。我开始工作两次,第二次使用这个 jvm 参数。由于 Metadata GC Threshold
.
###### 之前: first time
bash-4.2$ tailf gc_log_2020-08-26_07-19-05_pid84.log
Java HotSpot(TM) 64-Bit Server VM (25.241-b26) for linux-amd64 JRE (1.8.0_241-b26), built on Jan 6 2020 08:59:51 by "java_re" with gcc 7.3.0
Memory: 4k page, physical 4194304k(3920180k free), swap 0k(0k free)
CommandLine flags: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/flink-jvm -XX:InitialHeapSize=2899312640 -XX:MaxDirectMemorySize=9223370937343148032 -XX:MaxHeapSize=2899312640 -XX:NewSize=2147483648 -XX:+PrintFlagsFinal -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
2.359: [Full GC (Metadata GC Threshold) 2.359: [Tenured: 0K->14643K(735232K), 0.0526437 secs] 167782K->14643K(2622720K), [Metaspace: 20937K->20937K(1067008K)], 0.0527307 secs] [Times: user=0.04 sys=0.01, real=0.05 secs]
14.576: [Full GC (System.gc()) 14.576: [Tenured: 14643K->27136K(735232K), 0.1894478 secs] 417611K->27136K(2622720K), [Metaspace: 32274K->32274K(1077248K)], 0.1895372 secs] [Times: user=0.15 sys=0.02, real=0.19 secs]
###### 添加了metadata参数之后(-XX:MetaspaceSize=134217728), second time with param
bash-4.2$ tailf gc_log_2020-08-26_07-23-19_pid85.log
Java HotSpot(TM) 64-Bit Server VM (25.241-b26) for linux-amd64 JRE (1.8.0_241-b26), built on Jan 6 2020 08:59:51 by "java_re" with gcc 7.3.0
Memory: 4k page, physical 4194304k(3920136k free), swap 0k(0k free)
CommandLine flags: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/flink-jvm -XX:InitialHeapSize=2899312640 -XX:MaxDirectMemorySize=9223370937343148032 -XX:MaxHeapSize=2899312640 -XX:MetaspaceSize=134217728 -XX:NewSize=2147483648 -XX:+PrintFlagsFinal -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
5.196: [Full GC (System.gc()) 5.196: [Tenured: 0K->27063K(735232K), 0.2379232 secs] 973363K->27063K(2622720K), [Metaspace: 32544K->32544K(1077248K)], 0.2380344 secs] [Times: user=0.25 sys=0.03, real=0.24 secs]
Why my JVM did 3 times of FullGC when it started?
第一次和第三次 Full GC 是由元space 达到其当前阈值并需要增长而触发的。由于 metaspace 主要用于保存 code-related 东西,这意味着 Flink 正在加载大量代码或生成大量动态代理或类似的东西。
您可以考虑增加初始元space大小。
第二次 Full GC 由显式 System.gc()
调用触发。我的猜测是 Flink 正在这样做。
I thought FullGC would decrease Tenured space.
不一定。如果 Full GC 是由 metaspace 填充触发的,那么你很可能会发现 new space 中的很多对象都被 tenured。在第一种情况下,很明显这已经发生了,因为在 GC 之前,tenured space 是 empty.
... while metaspace don't change, and even increase between GCs
这意味着 GC 没有在 metaspace 中发现任何垃圾。如果 ClassLoader
实例(及其所有 类 及其所有实例)变得无法访问,我只希望 metaspace 的使用减少。预计在启动期间 metaspace 使用量会增加。如果它继续增加 在 应用程序启动 并且 JVM 已完全预热后,这可能只是潜在的问题。