Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/services/memTracker.cpp
41145 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 "memory/metaspaceUtils.hpp"
27
#include "runtime/atomic.hpp"
28
#include "runtime/orderAccess.hpp"
29
#include "runtime/vmThread.hpp"
30
#include "runtime/vmOperations.hpp"
31
#include "services/memBaseline.hpp"
32
#include "services/memReporter.hpp"
33
#include "services/mallocTracker.inline.hpp"
34
#include "services/memTracker.hpp"
35
#include "services/threadStackTracker.hpp"
36
#include "utilities/debug.hpp"
37
#include "utilities/defaultStream.hpp"
38
#include "utilities/vmError.hpp"
39
40
#ifdef _WINDOWS
41
#include <windows.h>
42
#endif
43
44
volatile NMT_TrackingLevel MemTracker::_tracking_level = NMT_unknown;
45
NMT_TrackingLevel MemTracker::_cmdline_tracking_level = NMT_unknown;
46
47
MemBaseline MemTracker::_baseline;
48
bool MemTracker::_is_nmt_env_valid = true;
49
50
static const size_t buffer_size = 64;
51
52
NMT_TrackingLevel MemTracker::init_tracking_level() {
53
// Memory type is encoded into tracking header as a byte field,
54
// make sure that we don't overflow it.
55
STATIC_ASSERT(mt_number_of_types <= max_jubyte);
56
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();
94
return;
95
}
96
}
97
}
98
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
}
115
116
return true;
117
}
118
119
bool MemTracker::verify_nmt_option() {
120
return _is_nmt_env_valid;
121
}
122
123
void* MemTracker::malloc_base(void* memblock) {
124
return MallocTracker::get_base(memblock);
125
}
126
127
void Tracker::record(address addr, size_t size) {
128
if (MemTracker::tracking_level() < NMT_summary) return;
129
switch(_type) {
130
case uncommit:
131
VirtualMemoryTracker::remove_uncommitted_region(addr, size);
132
break;
133
case release:
134
VirtualMemoryTracker::remove_released_region(addr, size);
135
break;
136
default:
137
ShouldNotReachHere();
138
}
139
}
140
141
142
// Shutdown can only be issued via JCmd, and NMT JCmd is serialized by lock
143
void MemTracker::shutdown() {
144
// We can only shutdown NMT to minimal tracking level if it is ever on.
145
if (tracking_level() > NMT_minimal) {
146
transition_to(NMT_minimal);
147
}
148
}
149
150
bool MemTracker::transition_to(NMT_TrackingLevel level) {
151
NMT_TrackingLevel current_level = tracking_level();
152
153
assert(level != NMT_off || current_level == NMT_off, "Cannot transition NMT to off");
154
155
if (current_level == level) {
156
return true;
157
} else if (current_level > level) {
158
// Downgrade tracking level, we want to lower the tracking level first
159
_tracking_level = level;
160
// Make _tracking_level visible immediately.
161
OrderAccess::fence();
162
VirtualMemoryTracker::transition(current_level, level);
163
MallocTracker::transition(current_level, level);
164
ThreadStackTracker::transition(current_level, level);
165
} else {
166
// Upgrading tracking level is not supported and has never been supported.
167
// Allocating and deallocating malloc tracking structures is not thread safe and
168
// leads to inconsistencies unless a lot coarser locks are added.
169
}
170
return true;
171
}
172
173
// Report during error reporting.
174
void MemTracker::error_report(outputStream* output) {
175
if (tracking_level() >= NMT_summary) {
176
report(true, output, MemReporterBase::default_scale); // just print summary for error case.
177
}
178
}
179
180
// Report when handling PrintNMTStatistics before VM shutdown.
181
static volatile bool g_final_report_did_run = false;
182
void MemTracker::final_report(outputStream* output) {
183
// This function is called during both error reporting and normal VM exit.
184
// However, it should only ever run once. E.g. if the VM crashes after
185
// printing the final report during normal VM exit, it should not print
186
// the final report again. In addition, it should be guarded from
187
// recursive calls in case NMT reporting itself crashes.
188
if (Atomic::cmpxchg(&g_final_report_did_run, false, true) == false) {
189
NMT_TrackingLevel level = tracking_level();
190
if (level >= NMT_summary) {
191
report(level == NMT_summary, output, 1);
192
}
193
}
194
}
195
196
void MemTracker::report(bool summary_only, outputStream* output, size_t scale) {
197
assert(output != NULL, "No output stream");
198
MemBaseline baseline;
199
if (baseline.baseline(summary_only)) {
200
if (summary_only) {
201
MemSummaryReporter rpt(baseline, output, scale);
202
rpt.report();
203
} else {
204
MemDetailReporter rpt(baseline, output, scale);
205
rpt.report();
206
output->print("Metaspace:");
207
// The basic metaspace report avoids any locking and should be safe to
208
// be called at any time.
209
MetaspaceUtils::print_basic_report(output, scale);
210
}
211
}
212
}
213
214
void MemTracker::tuning_statistics(outputStream* out) {
215
// NMT statistics
216
out->print_cr("Native Memory Tracking Statistics:");
217
out->print_cr("Malloc allocation site table size: %d", MallocSiteTable::hash_buckets());
218
out->print_cr(" Tracking stack depth: %d", NMT_TrackingStackDepth);
219
NOT_PRODUCT(out->print_cr("Peak concurrent access: %d", MallocSiteTable::access_peak_count());)
220
out->cr();
221
MallocSiteTable::print_tuning_statistics(out);
222
}
223
224