为什么选择SerialGC而不是G1GC?

2022-09-04 19:48:48

我在非常相似的虚拟机上运行Java,我找不到为什么在一种情况下选择SerialGC而不是G1GC的解释。它是相同的Java版本,相同的操作系统,相同的AWS实例类型,我怀疑唯一的区别是容器设置,但我不知道如何查明哪些更改。有没有办法解释为什么 VM 决定选择此设置或其他设置?

两种情况下的 Java 版本:

Java(TM) SE Runtime Environment 18.3 (build 10.0.1+10)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.1+10, mixed mode)

在一种情况下运行 Java 时:

java -XX:+PrintFlagsFinal -XX:+PrintCommandLineFlag

输出:

Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8
-XX:InitialHeapSize=253366976 -XX:MaxHeapSize=4053871616 -XX:+PrintCommandLineFlags -XX:+PrintFlagsFinal -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseSerialGC
[Global flags]
(...)
   bool UseG1GC                                  = false                                    {product} {default}
     bool UseParallelGC                            = false                                    {product} {default}
     bool UseSerialGC                              = true                                     {product} {ergonomic}

另一个:

Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8
-XX:G1ConcRefinementThreads=8 -XX:InitialHeapSize=253480064 -XX:MaxHeapSize=4055681024 -XX:+PrintCommandLineFlags -XX:+PrintFlagsFinal -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC
[Global flags]
(...)
   bool UseG1GC                                  = true                                    {product} {ergonomic}
     bool UseParallelGC                            = false                                    {product} {default}
     bool UseSerialGC                              = false                                     {product} {default}

答案 1

{ergonomic}表示该标志是根据可用处理器的数量和 RAM 量自动设置的。-XX:+PrintFlagsFinal

JDK 10 将计算机视为“服务器”,如果它至少有 2 个可用的 CPU 和 2 GB RAM。这可以由 JVM 标志覆盖。-XX:+AlwaysActAsServerClassMachine-XX:+NeverActAsServerClassMachine

“服务器”配置假定 G1 为默认 GC,而“客户端”计算机默认使用 SerialGC

要计算可用处理器的数量,JDK 不仅使用操作系统中可见的 CPU,还使用处理器关联和 cgroup 限制,包括

  • cpu.shares
  • cpu.cfs_quota_us
  • cpuset.cpus

由于您在容器中运行 Java,因此容器可能会施加 cgroup 限制,从而导致可用 CPU 或内存量减少。用于查找每个特定环境中的有效限制。-Xlog:os+container=trace


答案 2