Java 11 默认垃圾回收器竟然不是 G1

Java JVM About 4,877 words

疑惑

Java 9之后JVM的默认垃圾回收器就是G1了,但今天在Kubernetes容器Pod中查看时发现用的竟然是SerialGC

查看命令行参数

可以看到默认的垃圾回收器竟然是SerialGC串行化GC

java -XX:+PrintCommandLineFlags -version

输出

bash-4.4$ java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=215354880 -XX:MaxHeapSize=3445678080 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseSerialGC 
openjdk version "11.0.16" 2022-07-19
OpenJDK Runtime Environment 18.9 (build 11.0.16+8)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.16+8, mixed mode, sharing)

查看操作系统指标

发现生效的CPU个数只有1个。

java -XshowSettings:system -version

输出

bash-4.4$ java -XshowSettings:system -version
Operating System Metrics:
    Provider: cgroupv1
    Effective CPU Count: 1
    CPU Period: 100000us
    CPU Quota: -1
    CPU Shares: 2us
    List of Processors, 4 total: 
    0 1 2 3 
    List of Effective Processors, 4 total: 
    0 1 2 3 
    List of Memory Nodes, 1 total: 
    0 
    List of Available Memory Nodes, 1 total: 
    0 
    Memory Limit: 12.84G
    Memory Soft Limit: Unlimited
    Memory & Swap Limit: Unlimited

openjdk version "11.0.16" 2022-07-19
OpenJDK Runtime Environment 18.9 (build 11.0.16+8)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.16+8, mixed mode, sharing)

查看 JVM 参数默认值

bash-4.4$ java -XX:+PrintFlagsFinal -version | grep GC
     bool UseConcMarkSweepGC                       = false                                     {product} {default}
     bool UseG1GC                                  = false                                     {product} {default}
     bool UseParallelGC                            = false                                     {product} {default}
     bool UseParallelOldGC                         = false                                     {product} {default}
     bool UseSerialGC                              = true                                      {product} {ergonomic}
openjdk version "11.0.16" 2022-07-19
OpenJDK Runtime Environment 18.9 (build 11.0.16+8)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.16+8, mixed mode, sharing)

原因

{ergonomic}指的是该标志会自动设置,取决于可用的CPU处理器和内存大小。

Java 10中当机器有2个可用的处理器和2GB内存时,将JVM认为是服务器模式,可以使用-XX:+AlwaysActAsServerClassMachine打开Server模式,或者-XX:+NeverActAsServerClassMachine关闭Server模式。

Server模式时选择G1GCClient模式时选择SerialGC

JVM 源码

判断是否是Server机器

// This is the working definition of a server class machine:
// >= 2 physical CPU's and >=2GB of memory, with some fuzz
// because the graphics memory (?) sometimes masks physical memory.
// If you want to change the definition of a server class machine
// on some OS or platform, e.g., >=4GB on Windows platforms,
// then you'll have to parameterize this method based on that state,
// as was done for logical processors here, or replicate and
// specialize this method for each platform.  (Or fix os to have
// some inheritance structure and use subclassing.  Sigh.)
// If you want some platform to always or never behave as a server
// class machine, change the setting of AlwaysActAsServerClassMachine
// and NeverActAsServerClassMachine in globals*.hpp.
bool os::is_server_class_machine() {
  // First check for the early returns
  if (NeverActAsServerClassMachine) {
    return false;
  }
  if (AlwaysActAsServerClassMachine) {
    return true;
  }
  // Then actually look at the machine
  bool         result            = false;
  const unsigned int    server_processors = 2;
  const julong server_memory     = 2UL * G;
  // We seem not to get our full complement of memory.
  //     We allow some part (1/8?) of the memory to be "missing",
  //     based on the sizes of DIMMs, and maybe graphics cards.
  const julong missing_memory   = 256UL * M;

  /* Is this a server class machine? */
  if ((os::active_processor_count() >= (int)server_processors) &&
      (os::physical_memory() >= (server_memory - missing_memory))) {
    const unsigned int logical_processors =
      VM_Version::logical_processors_per_package();
    if (logical_processors > 1) {
      const unsigned int physical_packages =
        os::active_processor_count() / logical_processors;
      if (physical_packages >= server_processors) {
        result = true;
      }
    } else {
      result = true;
    }
  }
  return result;
}

选择GC参数

void GCArguments::select_gc_ergonomically() {
#if INCLUDE_ALL_GCS
  if (os::is_server_class_machine()) {
    FLAG_SET_ERGO_IF_DEFAULT(bool, UseG1GC, true);
  } else {
    FLAG_SET_ERGO_IF_DEFAULT(bool, UseSerialGC, true);
  }
#else
  UNSUPPORTED_OPTION(UseG1GC);
  UNSUPPORTED_OPTION(UseParallelGC);
  UNSUPPORTED_OPTION(UseParallelOldGC);
  UNSUPPORTED_OPTION(UseConcMarkSweepGC);
  FLAG_SET_ERGO_IF_DEFAULT(bool, UseSerialGC, true);
#endif // INCLUDE_ALL_GCS
}

参考链接

https://stackoverflow.com/questions/52474162/why-is-serialgc-chosen-over-g1gc

definition of a server class machine

select gc ergonomically

Views: 3,200 · Posted: 2023-06-08

————        END        ————

Give me a Star, Thanks:)

https://github.com/fendoudebb/LiteNote

扫描下方二维码关注公众号和小程序↓↓↓

扫描下方二维码关注公众号和小程序↓↓↓


Today On History
Browsing Refresh