Wenn die GC-Methode von Java (Parallel GC, G1GC usw.) nicht durch die Option angegeben wird, habe ich versucht, den Prozess mit JavaVM-Quellcode zu verfolgen, um zu sehen, wie er bestimmt wird. Die Quelle stammt von OpenJDK Java11. Src / Hotspot wird im folgenden Quellpfad weggelassen.
Um die Schlussfolgerung zuerst zu schreiben, lautet die GC-Methode wie folgt, wenn sie nicht durch die Option angegeben wird.
Bedingungen | GC-Methode |
---|---|
Serverklassenmaschine | UseG1GC |
Client-Klassenmaschine | UseSerialGC |
Eine Maschine der Serverklasse ist im Grunde eine Maschine mit 2 oder mehr CPUs und 2G oder mehr Speicher.
Es wird in der folgenden Reihenfolge aufgerufen, wenn JavaVM gestartet wird.
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
Folgen Sie nacheinander jeder Quelle.
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;
...
Wenn Java-Argumente mit Arguments :: parse analysiert werden und die GC-Methode angegeben wird, wird die Option true. Beispiel: -XX: + UseParallelGC setzt UseParallelGC auf true. Grundsätzlich verwendet der Wert jeder Option von JVM die Variable mit dem Namen der Option in der Quelle.
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()) { //★ Wenn die GC-Methode nicht angegeben ist
// Try select GC ergonomically
select_gc_ergonomically(); //★ Bestimmen Sie hier die GC-Methode
.....
is_no_gc_selected
is_no_gc_selected gibt true zurück, wenn keine Methode angegeben ist, false, wenn die GC-Methode bereits angegeben ist.
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 ist unten definiert.
python
#define FOR_EACH_SUPPORTED_GC(var) \
for (const SupportedGC* var = &SupportedGCs[0]; var < &SupportedGCs[ARRAY_SIZE(SupportedGCs)]; var++)
SupportedGCs listet die unterstützten GC-Methoden auf.
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
Hier wird die GC-Methode abhängig davon bestimmt, ob es sich um eine Serverklassenmaschine handelt oder nicht.
python
void GCConfig::select_gc_ergonomically() {
if (os::is_server_class_machine()) {
#if INCLUDE_G1GC
FLAG_SET_ERGO_IF_DEFAULT(bool, UseG1GC, true); //★ G1GC für Maschinen der Serverklasse
#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 für Maschinen der Clientklasse
#endif
}
}
is_server_class_machine
is_server_class_machine gibt unter den folgenden Bedingungen true (dh Serverklassenmaschine) oder false zurück.
Bedingungen | Rückgabewert |
---|---|
Wenn die Option NeverActAsServerClassMachine angegeben ist | false |
Wenn die Option AlwaysActAsServerClassMachine angegeben ist | true |
2 CPUs oder mehr und Speicher ca. 2G oder mehr | true |
anders als das | false |
share/runtime/os.cpp
bool os::is_server_class_machine() {
// First check for the early returns
if (NeverActAsServerClassMachine) { //★ Wenn NeverActAsServerClassMachine angegeben ist, wird dies als kein Serverklassencomputer angesehen.
return false;
}
if (AlwaysActAsServerClassMachine) { //★ Wenn AlwaysActAsServerClassMachine angegeben ist, wird dies als Serverklassencomputer betrachtet.
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? */ //★ Richtig, wenn 2 oder mehr CPUs und 2G oder mehr Speicher vorhanden sind
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