Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/hotspot/share/services/memTracker.cpp
64440 views
1
/*
2
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
#include "precompiled.hpp"
25
#include "jvm.h"
26
#include "logging/log.hpp"
27
#include "logging/logStream.hpp"
28
#include "memory/metaspaceUtils.hpp"
29
#include "runtime/atomic.hpp"
30
#include "runtime/globals.hpp"
31
#include "runtime/orderAccess.hpp"
32
#include "runtime/vmThread.hpp"
33
#include "runtime/vmOperations.hpp"
34
#include "services/memBaseline.hpp"
35
#include "services/memReporter.hpp"
36
#include "services/mallocTracker.inline.hpp"
37
#include "services/memTracker.hpp"
38
#include "services/nmtCommon.hpp"
39
#include "services/nmtPreInit.hpp"
40
#include "services/threadStackTracker.hpp"
41
#include "utilities/debug.hpp"
42
#include "utilities/defaultStream.hpp"
43
#include "utilities/vmError.hpp"
44
45
#ifdef _WINDOWS
46
#include <windows.h>
47
#endif
48
49
volatile NMT_TrackingLevel MemTracker::_tracking_level = NMT_unknown;
50
NMT_TrackingLevel MemTracker::_cmdline_tracking_level = NMT_unknown;
51
52
MemBaseline MemTracker::_baseline;
53
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);
62
63
// Memory type is encoded into tracking header as a byte field,
64
// make sure that we don't overflow it.
65
STATIC_ASSERT(mt_number_of_types <= max_jubyte);
66
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.");
74
return;
75
}
76
}
77
78
NMTPreInit::pre_to_post();
79
80
_tracking_level = _cmdline_tracking_level = level;
81
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
}
91
}
92
93
void* MemTracker::malloc_base(void* memblock) {
94
return MallocTracker::get_base(memblock);
95
}
96
97
void Tracker::record(address addr, size_t size) {
98
if (MemTracker::tracking_level() < NMT_summary) return;
99
switch(_type) {
100
case uncommit:
101
VirtualMemoryTracker::remove_uncommitted_region(addr, size);
102
break;
103
case release:
104
VirtualMemoryTracker::remove_released_region(addr, size);
105
break;
106
default:
107
ShouldNotReachHere();
108
}
109
}
110
111
112
// Shutdown can only be issued via JCmd, and NMT JCmd is serialized by lock
113
void MemTracker::shutdown() {
114
// We can only shutdown NMT to minimal tracking level if it is ever on.
115
if (tracking_level() > NMT_minimal) {
116
transition_to(NMT_minimal);
117
}
118
}
119
120
bool MemTracker::transition_to(NMT_TrackingLevel level) {
121
NMT_TrackingLevel current_level = tracking_level();
122
123
assert(level != NMT_off || current_level == NMT_off, "Cannot transition NMT to off");
124
125
if (current_level == level) {
126
return true;
127
} else if (current_level > level) {
128
// Downgrade tracking level, we want to lower the tracking level first
129
_tracking_level = level;
130
// Make _tracking_level visible immediately.
131
OrderAccess::fence();
132
VirtualMemoryTracker::transition(current_level, level);
133
MallocTracker::transition(current_level, level);
134
ThreadStackTracker::transition(current_level, level);
135
} else {
136
// Upgrading tracking level is not supported and has never been supported.
137
// Allocating and deallocating malloc tracking structures is not thread safe and
138
// leads to inconsistencies unless a lot coarser locks are added.
139
}
140
return true;
141
}
142
143
// Report during error reporting.
144
void MemTracker::error_report(outputStream* output) {
145
if (tracking_level() >= NMT_summary) {
146
report(true, output, MemReporterBase::default_scale); // just print summary for error case.
147
output->print("Preinit state:");
148
NMTPreInit::print_state(output);
149
}
150
}
151
152
// Report when handling PrintNMTStatistics before VM shutdown.
153
static volatile bool g_final_report_did_run = false;
154
void MemTracker::final_report(outputStream* output) {
155
// This function is called during both error reporting and normal VM exit.
156
// However, it should only ever run once. E.g. if the VM crashes after
157
// printing the final report during normal VM exit, it should not print
158
// the final report again. In addition, it should be guarded from
159
// recursive calls in case NMT reporting itself crashes.
160
if (Atomic::cmpxchg(&g_final_report_did_run, false, true) == false) {
161
NMT_TrackingLevel level = tracking_level();
162
if (level >= NMT_summary) {
163
report(level == NMT_summary, output, 1);
164
}
165
}
166
}
167
168
void MemTracker::report(bool summary_only, outputStream* output, size_t scale) {
169
assert(output != NULL, "No output stream");
170
MemBaseline baseline;
171
if (baseline.baseline(summary_only)) {
172
if (summary_only) {
173
MemSummaryReporter rpt(baseline, output, scale);
174
rpt.report();
175
} else {
176
MemDetailReporter rpt(baseline, output, scale);
177
rpt.report();
178
output->print("Metaspace:");
179
// The basic metaspace report avoids any locking and should be safe to
180
// be called at any time.
181
MetaspaceUtils::print_basic_report(output, scale);
182
}
183
}
184
}
185
186
void MemTracker::tuning_statistics(outputStream* out) {
187
// NMT statistics
188
out->print_cr("Native Memory Tracking Statistics:");
189
out->print_cr("State: %s", NMTUtil::tracking_level_to_string(_tracking_level));
190
out->print_cr("Malloc allocation site table size: %d", MallocSiteTable::hash_buckets());
191
out->print_cr(" Tracking stack depth: %d", NMT_TrackingStackDepth);
192
NOT_PRODUCT(out->print_cr("Peak concurrent access: %d", MallocSiteTable::access_peak_count());)
193
out->cr();
194
MallocSiteTable::print_tuning_statistics(out);
195
out->cr();
196
out->print_cr("Preinit state:");
197
NMTPreInit::print_state(out);
198
out->cr();
199
}
200
201