Skip to content

Commit eec64f5

Browse files
committed
8256844: Make NMT late-initializable
Reviewed-by: coleenp, zgu
1 parent 4df1bc4 commit eec64f5

25 files changed

+1438
-434
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"
@@ -1991,17 +1991,6 @@ bool Arguments::check_vm_args_consistency() {
19911991
status = false;
19921992
}
19931993

1994-
if (PrintNMTStatistics) {
1995-
#if INCLUDE_NMT
1996-
if (MemTracker::tracking_level() == NMT_off) {
1997-
#endif // INCLUDE_NMT
1998-
warning("PrintNMTStatistics is disabled, because native memory tracking is not enabled");
1999-
PrintNMTStatistics = false;
2000-
#if INCLUDE_NMT
2001-
}
2002-
#endif
2003-
}
2004-
20051994
status = CompilerConfig::check_args_consistency(status);
20061995
#if INCLUDE_JVMCI
20071996
if (status && EnableJVMCI) {
@@ -3708,29 +3697,6 @@ jint Arguments::match_special_option_and_act(const JavaVMInitArgs* args,
37083697
JVMFlag::printFlags(tty, false);
37093698
vm_exit(0);
37103699
}
3711-
if (match_option(option, "-XX:NativeMemoryTracking", &tail)) {
3712-
#if INCLUDE_NMT
3713-
// The launcher did not setup nmt environment variable properly.
3714-
if (!MemTracker::check_launcher_nmt_support(tail)) {
3715-
warning("Native Memory Tracking did not setup properly, using wrong launcher?");
3716-
}
3717-
3718-
// Verify if nmt option is valid.
3719-
if (MemTracker::verify_nmt_option()) {
3720-
// Late initialization, still in single-threaded mode.
3721-
if (MemTracker::tracking_level() >= NMT_summary) {
3722-
MemTracker::init();
3723-
}
3724-
} else {
3725-
vm_exit_during_initialization("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]", NULL);
3726-
}
3727-
continue;
3728-
#else
3729-
jio_fprintf(defaultStream::error_stream(),
3730-
"Native Memory Tracking is not supported in this VM\n");
3731-
return JNI_ERR;
3732-
#endif
3733-
}
37343700

37353701
#ifndef PRODUCT
37363702
if (match_option(option, "-XX:+PrintFlagsWithComments")) {
@@ -3982,6 +3948,26 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) {
39823948
no_shared_spaces("CDS Disabled");
39833949
#endif // INCLUDE_CDS
39843950

3951+
#if INCLUDE_NMT
3952+
// Verify NMT arguments
3953+
const NMT_TrackingLevel lvl = NMTUtil::parse_tracking_level(NativeMemoryTracking);
3954+
if (lvl == NMT_unknown) {
3955+
jio_fprintf(defaultStream::error_stream(),
3956+
"Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]", NULL);
3957+
return JNI_ERR;
3958+
}
3959+
if (PrintNMTStatistics && lvl == NMT_off) {
3960+
warning("PrintNMTStatistics is disabled, because native memory tracking is not enabled");
3961+
FLAG_SET_DEFAULT(PrintNMTStatistics, false);
3962+
}
3963+
#else
3964+
if (!FLAG_IS_DEFAULT(NativeMemoryTracking) || PrintNMTStatistics) {
3965+
warning("Native Memory Tracking is not supported in this VM");
3966+
FLAG_SET_DEFAULT(NativeMemoryTracking, "off");
3967+
FLAG_SET_DEFAULT(PrintNMTStatistics, false);
3968+
}
3969+
#endif // INCLUDE_NMT
3970+
39853971
if (TraceDependencies && VerifyDependencies) {
39863972
if (!FLAG_IS_DEFAULT(TraceDependencies)) {
39873973
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"
@@ -646,6 +647,15 @@ void* os::malloc(size_t size, MEMFLAGS memflags, const NativeCallStack& stack) {
646647
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
647648
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
648649

650+
#if INCLUDE_NMT
651+
{
652+
void* rc = NULL;
653+
if (NMTPreInit::handle_malloc(&rc, size)) {
654+
return rc;
655+
}
656+
}
657+
#endif
658+
649659
// Since os::malloc can be called when the libjvm.{dll,so} is
650660
// first loaded and we don't have a thread yet we must accept NULL also here.
651661
assert(!os::ThreadCrashProtection::is_crash_protected(Thread::current_or_null()),
@@ -705,6 +715,15 @@ void* os::realloc(void *memblock, size_t size, MEMFLAGS flags) {
705715

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

718+
#if INCLUDE_NMT
719+
{
720+
void* rc = NULL;
721+
if (NMTPreInit::handle_realloc(&rc, memblock, size)) {
722+
return rc;
723+
}
724+
}
725+
#endif
726+
708727
// For the test flag -XX:MallocMaxTestWords
709728
if (has_reached_max_malloc_test_peak(size)) {
710729
return NULL;
@@ -755,6 +774,13 @@ void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCa
755774

756775
// handles NULL pointers
757776
void os::free(void *memblock) {
777+
778+
#if INCLUDE_NMT
779+
if (NMTPreInit::handle_free(memblock)) {
780+
return;
781+
}
782+
#endif
783+
758784
NOT_PRODUCT(inc_stat_counter(&num_frees, 1));
759785
#ifdef ASSERT
760786
if (memblock == NULL) return;

src/hotspot/share/runtime/thread.cpp

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

2710+
#if INCLUDE_NMT
2711+
// Initialize NMT right after argument parsing to keep the pre-NMT-init window small.
2712+
MemTracker::initialize();
2713+
#endif // INCLUDE_NMT
2714+
27102715
os::init_before_ergo();
27112716

27122717
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)