Java GC method determination conditions

Introduction

When the Java GC method (Parallel GC, G1GC, etc.) is not specified by the option, I tried to follow the process in the Java VM source code to see how it is determined. The source is from OpenJDK Java11. Src / hotspot is omitted in the following source path.

Conclusion

To write the conclusion first, if the GC method is not specified by the option, it will be as follows.

conditions GC method
Server class machine UseG1GC
Client class machine UseSerialGC

A server class machine is basically a machine with 2 or more CPUs and 2G or more of memory.

Source details

It is called in the following order when JavaVM is started.

Threads::create_vm (share/runtime/thread.cpp)
  Arguments::apply_ergo (share/runtime/arguments.cpp)
    Arguments::set_ergonomics_flags
      GCConfig::initialize (share/gc/shared/gcConfig.cpp)
        select_gc
          select_gc_ergonomically

Follow each source in turn.

share/runtime/thread.cpp


jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
  ....
  // Parse arguments
  // Note: this internally calls os::init_container_support()
  jint parse_result = Arguments::parse(args);
  if (parse_result != JNI_OK) return parse_result;

  os::init_before_ergo();

  jint ergo_result = Arguments::apply_ergo();   // ★
  if (ergo_result != JNI_OK) return ergo_result;
  ...

If java arguments are parsed with Arguments :: parse and the GC method is specified, the option will be true. For example, -XX: + UseParallelGC will set UseParallelGC to true. Basically, the value of each option in the JVM uses a variable with the name of the option on the source.

share/runtime/arguments.cpp


jint Arguments::apply_ergo() {
  // Set flags based on ergonomics.
  jint result = set_ergonomics_flags();  //  ★
  if (result != JNI_OK) return result;

  .....

jint Arguments::set_ergonomics_flags() {
  GCConfig::initialize();   //  ★

  set_conservative_max_heap_alignment();
  .....

share/gc/shared/gcConfig.cpp


void GCConfig::initialize() {
  assert(_arguments == NULL, "Already initialized");
  _arguments = select_gc();  //  ★
}
....
GCArguments* GCConfig::select_gc() {
  // Fail immediately if an unsupported GC is selected
  fail_if_unsupported_gc_is_selected();

  if (is_no_gc_selected()) {   //★ If the GC method is not specified
    // Try select GC ergonomically
    select_gc_ergonomically();    //★ Determine the GC method here
    .....

is_no_gc_selected

is_no_gc_selected returns true if no method is specified, false if the GC method is already specified.

share/gc/shared/gcConfig.cpp


bool GCConfig::is_no_gc_selected() {
  FOR_EACH_SUPPORTED_GC(gc) {   //  ★
    if (gc->_flag) {
      return false;
    }
  }

  return true;
}

FOR_EACH_SUPPORTED_GC is defined below.

python


#define FOR_EACH_SUPPORTED_GC(var)                                          \
  for (const SupportedGC* var = &SupportedGCs[0]; var < &SupportedGCs[ARRAY_SIZE(SupportedGCs)]; var++)

SupportedGCs lists the supported GC methods.

python


static const SupportedGC SupportedGCs[] = {
       CMSGC_ONLY_ARG(SupportedGC(UseConcMarkSweepGC, CollectedHeap::CMS,      cmsArguments,      "concurrent mark sweep gc"))
   EPSILONGC_ONLY_ARG(SupportedGC(UseEpsilonGC,       CollectedHeap::Epsilon,  epsilonArguments,  "epsilon gc"))
        G1GC_ONLY_ARG(SupportedGC(UseG1GC,            CollectedHeap::G1,       g1Arguments,       "g1 gc"))
  PARALLELGC_ONLY_ARG(SupportedGC(UseParallelGC,      CollectedHeap::Parallel, parallelArguments, "parallel gc"))
  PARALLELGC_ONLY_ARG(SupportedGC(UseParallelOldGC,   CollectedHeap::Parallel, parallelArguments, "parallel gc"))
    SERIALGC_ONLY_ARG(SupportedGC(UseSerialGC,        CollectedHeap::Serial,   serialArguments,   "serial gc"))
         ZGC_ONLY_ARG(SupportedGC(UseZGC,             CollectedHeap::Z,        zArguments,        "z gc"))
};

select_gc_ergonomically

Here, the GC method is determined depending on whether or not it is a server class machine.

python


void GCConfig::select_gc_ergonomically() {
  if (os::is_server_class_machine()) {
#if INCLUDE_G1GC
    FLAG_SET_ERGO_IF_DEFAULT(bool, UseG1GC, true);  //★ G1GC for server class machines
#elif INCLUDE_PARALLELGC
    FLAG_SET_ERGO_IF_DEFAULT(bool, UseParallelGC, true);
#elif INCLUDE_SERIALGC
    FLAG_SET_ERGO_IF_DEFAULT(bool, UseSerialGC, true);
#endif
  } else {
#if INCLUDE_SERIALGC
    FLAG_SET_ERGO_IF_DEFAULT(bool, UseSerialGC, true);  //★ SerialGC for client class machines
#endif
  }
}

is_server_class_machine

is_server_class_machine returns true (that is, server class machine) or false under the following conditions.

conditions Return value
When the option NeverActAsServerClassMachine is specified false
When the option AlwaysActAsServerClassMachine is specified true
2 or more CPUs and 2G or more of memory true
other than that false

share/runtime/os.cpp


bool os::is_server_class_machine() {
  // First check for the early returns
  if (NeverActAsServerClassMachine) {  //★ If NeverActAsServerClassMachine is specified, it is regarded as not a server class machine.
    return false;
  }
  if (AlwaysActAsServerClassMachine) { //★ If AlwaysActAsServerClassMachine is specified, it is regarded as a server class machine.
    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? */  //★ True if 2 or more CPUs and 2G or more of memory
  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;
}

Recommended Posts

Java GC method determination conditions
Java method
java (method)
Java method
[Java] method
[Java] method
Java8 method reference
[Java] forEach method
java8 method reference
[Java] Random method
[Java] split method
JAVA DB connection method
Java learning 2 (learning calculation method)
Java learning memo (method)
Organize Java GC mechanism
About Java method binding
[Java ~ Method ~] Study memo (5)
About method splitting (Java)
Studying Java 8 (see method)
Type determination in Java
Java programming (class method)
[Java] Basic method notes
A note about Java GC
Java Silver Study Method Memo
Create a java method [Memo] [java11]
Java test code method collection
[Java Silver] About equals method
[Java] Timer processing implementation method
[Java] Random number generation method (Random)
Java methods and method overloads
Benefits of Java static method
[Java Silver] Array generation method
[Java] New Thread generation method (1)
[Java] Object-oriented syntax --class method / argument
Automatic photo resizing method in Java
Java method list (memorial) (under construction)
[Java] How to use join method
Screen transition by Post method [Java]
[Java] Object-oriented syntax-class / field / method / scope
Java comparison using the compareTo () method
[Java beginner] == operator and equals method
Try to extract java public method
Try using IBM Java method tracing
[Java] Proxy setting method when starting Java
Java beginner design pattern (Factory Method pattern)
[Java] Processing time measurement method memo
Call the super method in Java