Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java
41155 views
1
/*
2
* Copyright (c) 2003, 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
/*
25
* @test
26
* @bug 4959889 6992968
27
* @summary Basic unit test of memory management testing:
28
* 1) setCollectionUsageThreshold() and getCollectionUsageThreshold()
29
* 2) test notification emitted for two different memory pools.
30
*
31
* @author Mandy Chung
32
*
33
* @library /test/lib
34
* @modules jdk.management
35
* @build CollectionUsageThreshold MemoryUtil RunUtil
36
* @requires vm.opt.ExplicitGCInvokesConcurrent == "false" | vm.opt.ExplicitGCInvokesConcurrent == "null"
37
* @build sun.hotspot.WhiteBox
38
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
39
* @run main/othervm/timeout=300 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. CollectionUsageThreshold
40
*/
41
42
import java.util.*;
43
import java.util.concurrent.*;
44
import java.util.concurrent.atomic.AtomicInteger;
45
import javax.management.*;
46
import javax.management.openmbean.CompositeData;
47
import java.lang.management.*;
48
import static java.lang.management.MemoryNotificationInfo.*;;
49
import static java.lang.management.ManagementFactory.*;
50
51
import sun.hotspot.code.Compiler;
52
53
public class CollectionUsageThreshold {
54
private static final MemoryMXBean mm = getMemoryMXBean();
55
private static final Map<String, PoolRecord> result = new HashMap<>();
56
private static boolean trace = false;
57
private static volatile int numMemoryPools = 1;
58
private static final int NUM_GCS = 3;
59
private static final int THRESHOLD = 10;
60
private static volatile int numGCs = 0;
61
62
// semaphore to signal the arrival of a low memory notification
63
private static final Semaphore signals = new Semaphore(0);
64
// barrier for the main thread to wait until the checker thread
65
// finishes checking the low memory notification result
66
private static final CyclicBarrier barrier = new CyclicBarrier(2);
67
68
/**
69
* Run the test multiple times with different GC versions.
70
* First with default command line specified by the framework.
71
* Then with GC versions specified by the test.
72
*/
73
public static void main(String a[]) throws Throwable {
74
final String main = "CollectionUsageThreshold$TestMain";
75
RunUtil.runTestKeepGcOpts(main);
76
RunUtil.runTestClearGcOpts(main, "-XX:+UseSerialGC");
77
RunUtil.runTestClearGcOpts(main, "-XX:+UseParallelGC");
78
RunUtil.runTestClearGcOpts(main, "-XX:+UseG1GC");
79
}
80
81
static class PoolRecord {
82
private final MemoryPoolMXBean pool;
83
private final AtomicInteger listenerInvoked = new AtomicInteger(0);
84
private volatile long notifCount = 0;
85
PoolRecord(MemoryPoolMXBean p) {
86
this.pool = p;
87
}
88
int getListenerInvokedCount() {
89
return listenerInvoked.get();
90
}
91
long getNotifCount() {
92
return notifCount;
93
}
94
MemoryPoolMXBean getPool() {
95
return pool;
96
}
97
void addNotification(MemoryNotificationInfo minfo) {
98
listenerInvoked.incrementAndGet();
99
notifCount = minfo.getCount();
100
}
101
}
102
103
static class SensorListener implements NotificationListener {
104
@Override
105
public void handleNotification(Notification notif, Object handback) {
106
String type = notif.getType();
107
if (MEMORY_THRESHOLD_EXCEEDED.equals(type) ||
108
MEMORY_COLLECTION_THRESHOLD_EXCEEDED.equals(type)) {
109
MemoryNotificationInfo minfo = MemoryNotificationInfo.
110
from((CompositeData) notif.getUserData());
111
112
MemoryUtil.printMemoryNotificationInfo(minfo, type);
113
PoolRecord pr = (PoolRecord) result.get(minfo.getPoolName());
114
if (pr == null) {
115
throw new RuntimeException("Pool " + minfo.getPoolName() +
116
" is not selected");
117
}
118
if (!MEMORY_COLLECTION_THRESHOLD_EXCEEDED.equals(type)) {
119
throw new RuntimeException("Pool " + minfo.getPoolName() +
120
" got unexpected notification type: " +
121
type);
122
}
123
pr.addNotification(minfo);
124
System.out.println("notifying the checker thread to check result");
125
signals.release();
126
}
127
}
128
}
129
130
private static class TestMain {
131
public static void main(String args[]) throws Exception {
132
if (args.length > 0 && args[0].equals("trace")) {
133
trace = true;
134
}
135
136
List<MemoryPoolMXBean> pools = getMemoryPoolMXBeans();
137
List<MemoryManagerMXBean> managers = getMemoryManagerMXBeans();
138
139
if (trace) {
140
MemoryUtil.printMemoryPools(pools);
141
MemoryUtil.printMemoryManagers(managers);
142
}
143
144
// Find the Old generation which supports low memory detection
145
for (MemoryPoolMXBean p : pools) {
146
if (p.isUsageThresholdSupported() && p.isCollectionUsageThresholdSupported()) {
147
if (p.getName().toLowerCase().contains("perm")) {
148
// if we have a "perm gen" pool increase the number of expected
149
// memory pools by one.
150
numMemoryPools++;
151
}
152
PoolRecord pr = new PoolRecord(p);
153
result.put(p.getName(), pr);
154
if (result.size() == numMemoryPools) {
155
break;
156
}
157
}
158
}
159
if (result.size() != numMemoryPools) {
160
throw new RuntimeException("Unexpected number of selected pools");
161
}
162
163
try {
164
// This test creates a checker thread responsible for checking
165
// the low memory notifications. It blocks until a permit
166
// from the signals semaphore is available.
167
Checker checker = new Checker("Checker thread");
168
checker.setDaemon(true);
169
checker.start();
170
171
for (PoolRecord pr : result.values()) {
172
pr.getPool().setCollectionUsageThreshold(THRESHOLD);
173
System.out.println("Collection usage threshold of " +
174
pr.getPool().getName() + " set to " + THRESHOLD);
175
}
176
177
SensorListener listener = new SensorListener();
178
NotificationEmitter emitter = (NotificationEmitter) mm;
179
emitter.addNotificationListener(listener, null, null);
180
181
// The main thread invokes GC to trigger the VM to perform
182
// low memory detection and then waits until the checker thread
183
// finishes its work to check for a low-memory notification.
184
//
185
// At GC time, VM will issue low-memory notification and invoke
186
// the listener which will release a permit to the signals semaphore.
187
// When the checker thread acquires the permit and finishes
188
// checking the low-memory notification, it will also call
189
// barrier.await() to signal the main thread to resume its work.
190
for (int i = 0; i < NUM_GCS; i++) {
191
invokeGC();
192
barrier.await();
193
}
194
} finally {
195
// restore the default
196
for (PoolRecord pr : result.values()) {
197
pr.getPool().setCollectionUsageThreshold(0);
198
}
199
}
200
System.out.println(RunUtil.successMessage);
201
}
202
203
204
private static void invokeGC() {
205
System.out.println("Calling System.gc()");
206
numGCs++;
207
mm.gc();
208
209
if (trace) {
210
for (PoolRecord pr : result.values()) {
211
System.out.println("Usage after GC for: " + pr.getPool().getName());
212
MemoryUtil.printMemoryUsage(pr.getPool().getUsage());
213
}
214
}
215
}
216
}
217
218
static class Checker extends Thread {
219
Checker(String name) {
220
super(name);
221
};
222
@Override
223
public void run() {
224
while (true) {
225
try {
226
signals.acquire(numMemoryPools);
227
checkResult();
228
} catch (InterruptedException | BrokenBarrierException e) {
229
throw new RuntimeException(e);
230
}
231
}
232
}
233
private void checkResult() throws InterruptedException, BrokenBarrierException {
234
for (PoolRecord pr : result.values()) {
235
if (pr.getListenerInvokedCount() != numGCs) {
236
fail("Listeners invoked count = " +
237
pr.getListenerInvokedCount() + " expected to be " +
238
numGCs);
239
}
240
if (pr.getNotifCount() != numGCs) {
241
fail("Notif Count = " +
242
pr.getNotifCount() + " expected to be " +
243
numGCs);
244
}
245
246
long count = pr.getPool().getCollectionUsageThresholdCount();
247
if (count != numGCs) {
248
fail("CollectionUsageThresholdCount = " +
249
count + " expected to be " + numGCs);
250
}
251
if (!pr.getPool().isCollectionUsageThresholdExceeded()) {
252
fail("isCollectionUsageThresholdExceeded" +
253
" expected to be true");
254
}
255
}
256
// wait until the main thread is waiting for notification
257
barrier.await();
258
System.out.println("notifying main thread to continue - result checking finished");
259
}
260
261
private void fail(String msg) {
262
// reset the barrier to cause BrokenBarrierException to avoid hanging
263
barrier.reset();
264
throw new RuntimeException(msg);
265
}
266
}
267
}
268
269