Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest.java
38821 views
1
/*
2
* Copyright (c) 2003, 2015, 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 4530538
27
* @summary Basic unit test of memory management testing:
28
* 1) setUsageThreshold() and getUsageThreshold()
29
* 2) test low memory detection on the old generation.
30
*
31
* @author Mandy Chung
32
*
33
* @library /lib/testlibrary/
34
* @build LowMemoryTest MemoryUtil RunUtil
35
* @run main/timeout=600 LowMemoryTest
36
* @requires vm.opt.ExplicitGCInvokesConcurrent != "true"
37
* @requires vm.opt.ExplicitGCInvokesConcurrentAndUnloadsClasses != "true"
38
* @requires vm.opt.DisableExplicitGC != "true"
39
*/
40
41
import java.lang.management.*;
42
import java.util.*;
43
import java.util.concurrent.Phaser;
44
import javax.management.*;
45
import javax.management.openmbean.CompositeData;
46
47
public class LowMemoryTest {
48
private static final MemoryMXBean mm = ManagementFactory.getMemoryMXBean();
49
private static final List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
50
private static final Phaser phaser = new Phaser(2);
51
private static MemoryPoolMXBean mpool = null;
52
private static boolean trace = false;
53
private static boolean testFailed = false;
54
private static final int NUM_TRIGGERS = 5;
55
private static final int NUM_CHUNKS = 2;
56
private static long chunkSize;
57
58
/**
59
* Run the test multiple times with different GC versions.
60
* First with default command line specified by the framework.
61
* Then with GC versions specified by the test.
62
*/
63
public static void main(String a[]) throws Throwable {
64
final String main = "LowMemoryTest$TestMain";
65
RunUtil.runTestKeepGcOpts(main);
66
RunUtil.runTestClearGcOpts(main, "-XX:+UseSerialGC");
67
RunUtil.runTestClearGcOpts(main, "-XX:+UseParallelGC");
68
RunUtil.runTestClearGcOpts(main, "-XX:+UseG1GC");
69
RunUtil.runTestClearGcOpts(main, "-XX:+UseConcMarkSweepGC");
70
}
71
72
private static volatile boolean listenerInvoked = false;
73
static class SensorListener implements NotificationListener {
74
@Override
75
public void handleNotification(Notification notif, Object handback) {
76
String type = notif.getType();
77
if (type.equals(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED) ||
78
type.equals(MemoryNotificationInfo.
79
MEMORY_COLLECTION_THRESHOLD_EXCEEDED)) {
80
81
MemoryNotificationInfo minfo = MemoryNotificationInfo.
82
from((CompositeData) notif.getUserData());
83
84
MemoryUtil.printMemoryNotificationInfo(minfo, type);
85
listenerInvoked = true;
86
}
87
}
88
}
89
90
static class TestListener implements NotificationListener {
91
private boolean isRelaxed = false;
92
private int triggers = 0;
93
private final long[] count = new long[NUM_TRIGGERS * 2];
94
private final long[] usedMemory = new long[NUM_TRIGGERS * 2];
95
96
public TestListener() {
97
isRelaxed = ManagementFactory.getRuntimeMXBean().getInputArguments().contains("-XX:+UseConcMarkSweepGC");
98
}
99
100
@Override
101
public void handleNotification(Notification notif, Object handback) {
102
MemoryNotificationInfo minfo = MemoryNotificationInfo.
103
from((CompositeData) notif.getUserData());
104
count[triggers] = minfo.getCount();
105
usedMemory[triggers] = minfo.getUsage().getUsed();
106
triggers++;
107
}
108
public void checkResult() throws Exception {
109
if ((!isRelaxed && triggers != NUM_TRIGGERS) ||
110
(isRelaxed && triggers < NUM_TRIGGERS)) {
111
throw new RuntimeException("Unexpected number of triggers = " +
112
triggers + " but expected to be " + NUM_TRIGGERS);
113
}
114
115
for (int i = 0; i < triggers; i++) {
116
if (count[i] != i+1) {
117
throw new RuntimeException("Unexpected count of" +
118
" notification #" + i +
119
" count = " + count[i] +
120
" but expected to be " + (i+1));
121
}
122
if (usedMemory[i] < newThreshold) {
123
throw new RuntimeException("Used memory = " +
124
usedMemory[i] + " is less than the threshold = " +
125
newThreshold);
126
}
127
}
128
}
129
}
130
131
private static long newThreshold;
132
133
private static class TestMain {
134
public static void main(String args[]) throws Exception {
135
if (args.length > 0 && args[0].equals("trace")) {
136
trace = true;
137
}
138
139
// Find the Old generation which supports low memory detection
140
ListIterator iter = pools.listIterator();
141
while (iter.hasNext()) {
142
MemoryPoolMXBean p = (MemoryPoolMXBean) iter.next();
143
if (p.getType() == MemoryType.HEAP &&
144
p.isUsageThresholdSupported()) {
145
mpool = p;
146
if (trace) {
147
System.out.println("Selected memory pool for low memory " +
148
"detection.");
149
MemoryUtil.printMemoryPool(mpool);
150
}
151
break;
152
}
153
}
154
155
TestListener listener = new TestListener();
156
SensorListener l2 = new SensorListener();
157
NotificationEmitter emitter = (NotificationEmitter) mm;
158
emitter.addNotificationListener(listener, null, null);
159
emitter.addNotificationListener(l2, null, null);
160
161
Thread allocator = new AllocatorThread();
162
Thread sweeper = new SweeperThread();
163
164
// Now set threshold
165
MemoryUsage mu = mpool.getUsage();
166
chunkSize = (mu.getMax() - mu.getUsed()) / 20;
167
newThreshold = mu.getUsed() + (chunkSize * NUM_CHUNKS);
168
169
System.out.println("Setting threshold for " + mpool.getName() +
170
" from " + mpool.getUsageThreshold() + " to " + newThreshold +
171
". Current used = " + mu.getUsed());
172
mpool.setUsageThreshold(newThreshold);
173
174
if (mpool.getUsageThreshold() != newThreshold) {
175
throw new RuntimeException("TEST FAILED: " +
176
"Threshold for Memory pool " + mpool.getName() +
177
"is " + mpool.getUsageThreshold() + " but expected to be" +
178
newThreshold);
179
}
180
181
182
allocator.start();
183
// Force Allocator start first
184
phaser.arriveAndAwaitAdvance();
185
sweeper.start();
186
187
188
try {
189
allocator.join();
190
// Wait until AllocatorThread's done
191
phaser.arriveAndAwaitAdvance();
192
sweeper.join();
193
} catch (InterruptedException e) {
194
System.out.println("Unexpected exception:" + e);
195
testFailed = true;
196
}
197
198
listener.checkResult();
199
200
if (testFailed)
201
throw new RuntimeException("TEST FAILED.");
202
203
System.out.println(RunUtil.successMessage);
204
205
}
206
}
207
208
private static void goSleep(long ms) {
209
try {
210
Thread.sleep(ms);
211
} catch (InterruptedException e) {
212
System.out.println("Unexpected exception:" + e);
213
testFailed = true;
214
}
215
}
216
217
private static final List<Object> objectPool = new ArrayList<>();
218
static class AllocatorThread extends Thread {
219
public void doTask() {
220
int iterations = 0;
221
int numElements = (int) (chunkSize / 4); // minimal object size
222
while (!listenerInvoked || mpool.getUsage().getUsed() < mpool.getUsageThreshold()) {
223
iterations++;
224
if (trace) {
225
System.out.println(" Iteration " + iterations +
226
": before allocation " +
227
mpool.getUsage().getUsed());
228
}
229
230
Object[] o = new Object[numElements];
231
if (iterations <= NUM_CHUNKS) {
232
// only hold a reference to the first NUM_CHUNKS
233
// allocated objects
234
objectPool.add(o);
235
}
236
237
if (trace) {
238
System.out.println(" " +
239
" after allocation " +
240
mpool.getUsage().getUsed());
241
}
242
goSleep(100);
243
}
244
}
245
@Override
246
public void run() {
247
for (int i = 1; i <= NUM_TRIGGERS; i++) {
248
// Sync with SweeperThread's second phase.
249
phaser.arriveAndAwaitAdvance();
250
System.out.println("AllocatorThread is doing task " + i +
251
" phase " + phaser.getPhase());
252
doTask();
253
// Sync with SweeperThread's first phase.
254
phaser.arriveAndAwaitAdvance();
255
System.out.println("AllocatorThread done task " + i +
256
" phase " + phaser.getPhase());
257
if (testFailed) {
258
return;
259
}
260
}
261
}
262
}
263
264
static class SweeperThread extends Thread {
265
private void doTask() {
266
for (; mpool.getUsage().getUsed() >=
267
mpool.getUsageThreshold();) {
268
// clear all allocated objects and invoke GC
269
objectPool.clear();
270
mm.gc();
271
goSleep(100);
272
}
273
}
274
@Override
275
public void run() {
276
for (int i = 1; i <= NUM_TRIGGERS; i++) {
277
// Sync with AllocatorThread's first phase.
278
phaser.arriveAndAwaitAdvance();
279
System.out.println("SweepThread is doing task " + i +
280
" phase " + phaser.getPhase());
281
doTask();
282
283
listenerInvoked = false;
284
285
// Sync with AllocatorThread's second phase.
286
phaser.arriveAndAwaitAdvance();
287
System.out.println("SweepThread done task " + i +
288
" phase " + phaser.getPhase());
289
if (testFailed) return;
290
}
291
}
292
}
293
}
294
295