Skip to content

Commit 774213f

Browse files
author
Vladimir Kempik
committed
8256844: Make NMT late-initializable
Reviewed-by: stuefe Backport-of: eec64f55870cf51746755d8fa59098a82109e826
1 parent 437c634 commit 774213f

24 files changed

+1430
-429
lines changed

src/hotspot/share/runtime/arguments.cpp

Lines changed: 21 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
#include "runtime/safepointMechanism.hpp"
5454
#include "runtime/vm_version.hpp"
5555
#include "services/management.hpp"
56-
#include "services/memTracker.hpp"
56+
#include "services/nmtCommon.hpp"
5757
#include "utilities/align.hpp"
5858
#include "utilities/defaultStream.hpp"
5959
#include "utilities/macros.hpp"
@@ -1985,17 +1985,6 @@ bool Arguments::check_vm_args_consistency() {
19851985
status = false;
19861986
}
19871987

1988-
if (PrintNMTStatistics) {
1989-
#if INCLUDE_NMT
1990-
if (MemTracker::tracking_level() == NMT_off) {
1991-
#endif // INCLUDE_NMT
1992-
warning("PrintNMTStatistics is disabled, because native memory tracking is not enabled");
1993-
PrintNMTStatistics = false;
1994-
#if INCLUDE_NMT
1995-
}
1996-
#endif
1997-
}
1998-
19991988
status = CompilerConfig::check_args_consistency(status);
20001989
#if INCLUDE_JVMCI
20011990
if (status && EnableJVMCI) {
@@ -3718,29 +3707,6 @@ jint Arguments::match_special_option_and_act(const JavaVMInitArgs* args,
37183707
JVMFlag::printFlags(tty, false);
37193708
vm_exit(0);
37203709
}
3721-
if (match_option(option, "-XX:NativeMemoryTracking", &tail)) {
3722-
#if INCLUDE_NMT
3723-
// The launcher did not setup nmt environment variable properly.
3724-
if (!MemTracker::check_launcher_nmt_support(tail)) {
3725-
warning("Native Memory Tracking did not setup properly, using wrong launcher?");
3726-
}
3727-
3728-
// Verify if nmt option is valid.
3729-
if (MemTracker::verify_nmt_option()) {
3730-
// Late initialization, still in single-threaded mode.
3731-
if (MemTracker::tracking_level() >= NMT_summary) {
3732-
MemTracker::init();
3733-
}
3734-
} else {
3735-
vm_exit_during_initialization("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]", NULL);
3736-
}
3737-
continue;
3738-
#else
3739-
jio_fprintf(defaultStream::error_stream(),
3740-
"Native Memory Tracking is not supported in this VM\n");
3741-
return JNI_ERR;
3742-
#endif
3743-
}
37443710

37453711
#ifndef PRODUCT
37463712
if (match_option(option, "-XX:+PrintFlagsWithComments")) {
@@ -3992,6 +3958,26 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) {
39923958
no_shared_spaces("CDS Disabled");
39933959
#endif // INCLUDE_CDS
39943960

3961+
#if INCLUDE_NMT
3962+
// Verify NMT arguments
3963+
const NMT_TrackingLevel lvl = NMTUtil::parse_tracking_level(NativeMemoryTracking);
3964+
if (lvl == NMT_unknown) {
3965+
jio_fprintf(defaultStream::error_stream(),
3966+
"Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]", NULL);
3967+
return JNI_ERR;
3968+
}
3969+
if (PrintNMTStatistics && lvl == NMT_off) {
3970+
warning("PrintNMTStatistics is disabled, because native memory tracking is not enabled");
3971+
FLAG_SET_DEFAULT(PrintNMTStatistics, false);
3972+
}
3973+
#else
3974+
if (!FLAG_IS_DEFAULT(NativeMemoryTracking) || PrintNMTStatistics) {
3975+
warning("Native Memory Tracking is not supported in this VM");
3976+
FLAG_SET_DEFAULT(NativeMemoryTracking, "off");
3977+
FLAG_SET_DEFAULT(PrintNMTStatistics, false);
3978+
}
3979+
#endif // INCLUDE_NMT
3980+
39953981
if (TraceDependencies && VerifyDependencies) {
39963982
if (!FLAG_IS_DEFAULT(TraceDependencies)) {
39973983
warning("TraceDependencies results may be inflated by VerifyDependencies");

src/hotspot/share/runtime/os.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#include "services/attachListener.hpp"
6565
#include "services/mallocTracker.hpp"
6666
#include "services/memTracker.hpp"
67+
#include "services/nmtPreInit.hpp"
6768
#include "services/nmtCommon.hpp"
6869
#include "services/threadService.hpp"
6970
#include "utilities/align.hpp"
@@ -681,6 +682,15 @@ void* os::malloc(size_t size, MEMFLAGS memflags, const NativeCallStack& stack) {
681682
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
682683
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
683684

685+
#if INCLUDE_NMT
686+
{
687+
void* rc = NULL;
688+
if (NMTPreInit::handle_malloc(&rc, size)) {
689+
return rc;
690+
}
691+
}
692+
#endif
693+
684694
// Since os::malloc can be called when the libjvm.{dll,so} is
685695
// first loaded and we don't have a thread yet we must accept NULL also here.
686696
assert(!os::ThreadCrashProtection::is_crash_protected(Thread::current_or_null()),
@@ -740,6 +750,15 @@ void* os::realloc(void *memblock, size_t size, MEMFLAGS flags) {
740750

741751
void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCallStack& stack) {
742752

753+
#if INCLUDE_NMT
754+
{
755+
void* rc = NULL;
756+
if (NMTPreInit::handle_realloc(&rc, memblock, size)) {
757+
return rc;
758+
}
759+
}
760+
#endif
761+
743762
// For the test flag -XX:MallocMaxTestWords
744763
if (has_reached_max_malloc_test_peak(size)) {
745764
return NULL;
@@ -790,6 +809,13 @@ void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCa
790809

791810
// handles NULL pointers
792811
void os::free(void *memblock) {
812+
813+
#if INCLUDE_NMT
814+
if (NMTPreInit::handle_free(memblock)) {
815+
return;
816+
}
817+
#endif
818+
793819
NOT_PRODUCT(inc_stat_counter(&num_frees, 1));
794820
#ifdef ASSERT
795821
if (memblock == NULL) return;

src/hotspot/share/runtime/thread.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2769,6 +2769,11 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
27692769
jint parse_result = Arguments::parse(args);
27702770
if (parse_result != JNI_OK) return parse_result;
27712771

2772+
#if INCLUDE_NMT
2773+
// Initialize NMT right after argument parsing to keep the pre-NMT-init window small.
2774+
MemTracker::initialize();
2775+
#endif // INCLUDE_NMT
2776+
27722777
os::init_before_ergo();
27732778

27742779
jint ergo_result = Arguments::apply_ergo();

src/hotspot/share/services/memTracker.cpp

Lines changed: 38 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,20 @@
2323
*/
2424
#include "precompiled.hpp"
2525
#include "jvm.h"
26+
#include "logging/log.hpp"
27+
#include "logging/logStream.hpp"
2628
#include "memory/metaspaceUtils.hpp"
2729
#include "runtime/atomic.hpp"
30+
#include "runtime/globals.hpp"
2831
#include "runtime/orderAccess.hpp"
2932
#include "runtime/vmThread.hpp"
3033
#include "runtime/vmOperations.hpp"
3134
#include "services/memBaseline.hpp"
3235
#include "services/memReporter.hpp"
3336
#include "services/mallocTracker.inline.hpp"
3437
#include "services/memTracker.hpp"
38+
#include "services/nmtCommon.hpp"
39+
#include "services/nmtPreInit.hpp"
3540
#include "services/threadStackTracker.hpp"
3641
#include "utilities/debug.hpp"
3742
#include "utilities/defaultStream.hpp"
@@ -45,79 +50,44 @@ volatile NMT_TrackingLevel MemTracker::_tracking_level = NMT_unknown;
4550
NMT_TrackingLevel MemTracker::_cmdline_tracking_level = NMT_unknown;
4651

4752
MemBaseline MemTracker::_baseline;
48-
bool MemTracker::_is_nmt_env_valid = true;
4953

50-
static const size_t buffer_size = 64;
54+
void MemTracker::initialize() {
55+
bool rc = true;
56+
assert(_tracking_level == NMT_unknown, "only call once");
57+
58+
NMT_TrackingLevel level = NMTUtil::parse_tracking_level(NativeMemoryTracking);
59+
// Should have been validated before in arguments.cpp
60+
assert(level == NMT_off || level == NMT_summary || level == NMT_detail,
61+
"Invalid setting for NativeMemoryTracking (%s)", NativeMemoryTracking);
5162

52-
NMT_TrackingLevel MemTracker::init_tracking_level() {
5363
// Memory type is encoded into tracking header as a byte field,
5464
// make sure that we don't overflow it.
5565
STATIC_ASSERT(mt_number_of_types <= max_jubyte);
5666

57-
char nmt_env_variable[buffer_size];
58-
jio_snprintf(nmt_env_variable, sizeof(nmt_env_variable), "NMT_LEVEL_%d", os::current_process_id());
59-
const char* nmt_env_value;
60-
#ifdef _WINDOWS
61-
// Read the NMT environment variable from the PEB instead of the CRT
62-
char value[buffer_size];
63-
nmt_env_value = GetEnvironmentVariable(nmt_env_variable, value, (DWORD)sizeof(value)) != 0 ? value : NULL;
64-
#else
65-
nmt_env_value = ::getenv(nmt_env_variable);
66-
#endif
67-
NMT_TrackingLevel level = NMT_off;
68-
if (nmt_env_value != NULL) {
69-
if (strcmp(nmt_env_value, "summary") == 0) {
70-
level = NMT_summary;
71-
} else if (strcmp(nmt_env_value, "detail") == 0) {
72-
level = NMT_detail;
73-
} else if (strcmp(nmt_env_value, "off") != 0) {
74-
// The value of the environment variable is invalid
75-
_is_nmt_env_valid = false;
76-
}
77-
// Remove the environment variable to avoid leaking to child processes
78-
os::unsetenv(nmt_env_variable);
79-
}
80-
81-
if (!MallocTracker::initialize(level) ||
82-
!VirtualMemoryTracker::initialize(level)) {
83-
level = NMT_off;
84-
}
85-
return level;
86-
}
87-
88-
void MemTracker::init() {
89-
NMT_TrackingLevel level = tracking_level();
90-
if (level >= NMT_summary) {
91-
if (!VirtualMemoryTracker::late_initialize(level) ||
92-
!ThreadStackTracker::late_initialize(level)) {
93-
shutdown();
67+
if (level > NMT_off) {
68+
if (!MallocTracker::initialize(level) ||
69+
!VirtualMemoryTracker::initialize(level) ||
70+
!ThreadStackTracker::initialize(level)) {
71+
assert(false, "NMT initialization failed");
72+
level = NMT_off;
73+
log_warning(nmt)("NMT initialization failed. NMT disabled.");
9474
return;
9575
}
9676
}
97-
}
9877

99-
bool MemTracker::check_launcher_nmt_support(const char* value) {
100-
if (strcmp(value, "=detail") == 0) {
101-
if (MemTracker::tracking_level() != NMT_detail) {
102-
return false;
103-
}
104-
} else if (strcmp(value, "=summary") == 0) {
105-
if (MemTracker::tracking_level() != NMT_summary) {
106-
return false;
107-
}
108-
} else if (strcmp(value, "=off") == 0) {
109-
if (MemTracker::tracking_level() != NMT_off) {
110-
return false;
111-
}
112-
} else {
113-
_is_nmt_env_valid = false;
114-
}
78+
NMTPreInit::pre_to_post();
11579

116-
return true;
117-
}
80+
_tracking_level = _cmdline_tracking_level = level;
11881

119-
bool MemTracker::verify_nmt_option() {
120-
return _is_nmt_env_valid;
82+
// Log state right after NMT initialization
83+
if (log_is_enabled(Info, nmt)) {
84+
LogTarget(Info, nmt) lt;
85+
LogStream ls(lt);
86+
ls.print_cr("NMT initialized: %s", NMTUtil::tracking_level_to_string(_tracking_level));
87+
ls.print_cr("Preinit state: ");
88+
NMTPreInit::print_state(&ls);
89+
ls.cr();
90+
}
12191
}
12292

12393
void* MemTracker::malloc_base(void* memblock) {
@@ -174,6 +144,8 @@ bool MemTracker::transition_to(NMT_TrackingLevel level) {
174144
void MemTracker::error_report(outputStream* output) {
175145
if (tracking_level() >= NMT_summary) {
176146
report(true, output, MemReporterBase::default_scale); // just print summary for error case.
147+
output->print("Preinit state:");
148+
NMTPreInit::print_state(output);
177149
}
178150
}
179151

@@ -214,9 +186,14 @@ void MemTracker::report(bool summary_only, outputStream* output, size_t scale) {
214186
void MemTracker::tuning_statistics(outputStream* out) {
215187
// NMT statistics
216188
out->print_cr("Native Memory Tracking Statistics:");
189+
out->print_cr("State: %s", NMTUtil::tracking_level_to_string(_tracking_level));
217190
out->print_cr("Malloc allocation site table size: %d", MallocSiteTable::hash_buckets());
218191
out->print_cr(" Tracking stack depth: %d", NMT_TrackingStackDepth);
219192
NOT_PRODUCT(out->print_cr("Peak concurrent access: %d", MallocSiteTable::access_peak_count());)
220193
out->cr();
221194
MallocSiteTable::print_tuning_statistics(out);
195+
out->cr();
196+
out->print_cr("Preinit state:");
197+
NMTPreInit::print_state(out);
198+
out->cr();
222199
}

0 commit comments

Comments
 (0)