默认垃圾收集器 Hotspot JVM 的标准 11/17

Pau*_*979 20 java garbage-collection jvm java-11 java-17

我找到了一个资料来源,描述了使用的默认 gc 根据可用资源而变化。看来jvm使用g1gc或serial gc取决于硬件和操作系统。

在某些硬件和操作系统配置上默认选择串行收集器

有人可以指出关于具体标准是什么以及如何在 dockerized/kubernetes 环境中应用的更详细的资料来源吗?换句话说:

可以将k8s中pod的资源请求设置为例如。1500 mCpu 让 jvm 使用串行 gc 并更改为 2 Cpu 将默认 gc 更改为 g1gc?何时使用哪个 gc 的限制是否会根据 jvm 版本(11 与 17)而变化?

usu*_*rio 32

在 JDK 11 和 17 中,Serial当只有一个 CPU 可用时,会使用收集器。否则G1被选中

如果您限制容器可用的 CPUS 数量,JVM 将选择Serial而不是默认值G1

JDK11

1个CPU

docker run --cpus=1 --rm -it eclipse-temurin:11 java -Xlog:gc* -version
[0.004s][info][gc] Using **Serial**
Run Code Online (Sandbox Code Playgroud)

它用Serial

多个CPU

docker run --cpus=2 --rm -it eclipse-temurin:11 java -Xlog:gc* -version
[0.008s][info][gc     ] Using G1
Run Code Online (Sandbox Code Playgroud)

它用G1

JDK17

1个CPU

docker run --cpus=1 --rm -it eclipse-temurin:17 java -Xlog:gc* -version
[0.004s][info][gc] Using Serial
Run Code Online (Sandbox Code Playgroud)

它用Serial

多个CPU

docker run --cpus=2 --rm -it eclipse-temurin:17 java -Xlog:gc* -version
[0.007s][info][gc] Using G1
Run Code Online (Sandbox Code Playgroud)

它用G1


apa*_*gin 21

在当前的 OpenJDK 中,默认选择 G1 GC 作为“服务器类机器”,否则选择 Serial GC。“服务器级机器”被定义为具有 2 个或更多非 HT CPU 和 2 个或更多 GiB RAM 的系统。

确切的算法可以在src/hotspot/share/runtime/os.cpp中找到:

// 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;
}
Run Code Online (Sandbox Code Playgroud)

  • @Paul7979 这并不是一个人写下了所有内容。最有可能的是,有人试图在稍后的某个时间回顾一下这个已经存在的代码正在做的事情。我希望,有人会对负责数组长度限制的代码执行相同的操作(事实上我们无法分配 `new byte[Integer.MAX_VALUE]`),因为显然没有人真正知道为什么存在这种限制。 (3认同)