Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/phantom001/phantom001.java
64507 views
1
/*
2
* Copyright (c) 2004, 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
* @key stress randomness
27
*
28
* @summary converted from VM Testbase gc/gctests/PhantomReference/phantom001.
29
* VM Testbase keywords: [gc, stress, stressopt, nonconcurrent]
30
* VM Testbase readme:
31
* DESCRIPTION
32
* The test checks that Garbage Collector correctly works with
33
* PhantomReferences. It also checks that no unexpected exceptions and errors
34
* are thrown or the JVM is not crashed.
35
* The test starts a number of threads. Each thread run tests for some time
36
* or serveral iterations. See javadoc StressOptions for configuration.
37
* First of all each thread defines what type to check (there are 11 types
38
* totally). As soon as the type is defined, a PhantomRefence is created that
39
* refers to an array of tested type and is registered with in a queue. A
40
* PhantomRefence for NonbranchyTree and Referent calsses does not refer to
41
* arrays, but to instances of the classes.
42
* After that a thread performs next checks for the reference:
43
* 1. The reference is in queue after GC is provoked with
44
* Algorithms.eatMemory() method (a single thread eats the memory).
45
* 2. reference.get() returns null.
46
* 3. queue.poll() returns the reference that was created.
47
* 4. queue.poll() again returns null.
48
* 5. If the checked type is class (Referent), then it must be finalized,
49
* since the reference is already enqueued.
50
* 6. reference.clear() does not throw any exception.
51
* The test extends ThreadedGCTest and implements GarbageProducerAware and
52
* MemoryStrategyAware interfaces. The corresponding javadoc documentation
53
* for additional test configuration.
54
*
55
* @library /vmTestbase
56
* /test/lib
57
* @run main/othervm gc.gctests.PhantomReference.phantom001.phantom001 -ms low
58
*/
59
60
package gc.gctests.PhantomReference.phantom001;
61
62
import java.lang.ref.*;
63
import java.time.LocalTime;
64
import nsk.share.gc.*;
65
import nsk.share.gc.gp.*;
66
import nsk.share.gc.gp.string.InternedStringProducer;
67
import nsk.share.gc.gp.string.RandomStringProducer;
68
69
public class phantom001 extends ThreadedGCTest implements GarbageProducerAware, MemoryStrategyAware {
70
71
private GarbageProducer garbageProducer;
72
private MemoryStrategy memoryStrategy;
73
private InternedStringProducer internedStringProducer = new InternedStringProducer(new RandomStringProducer(10));
74
// Total number of types to test
75
final static int TYPES_COUNT = 12;
76
// Size of array of each tested type. The constant also specifies the
77
// number of nodes in a NonbranchyTree and size of each node
78
final static int SIZE = 100;
79
80
protected Runnable createRunnable(int i) {
81
return new Test();
82
}
83
84
public void setGarbageProducer(GarbageProducer garbageProducer) {
85
this.garbageProducer = garbageProducer;
86
}
87
88
public void setMemoryStrategy(MemoryStrategy memoryStrategy) {
89
this.memoryStrategy = memoryStrategy;
90
}
91
92
public static void main(String[] args) {
93
GC.runTest(new phantom001(), args);
94
}
95
96
// The class implements the logic of the testcase
97
class Test implements Runnable, OOMStress {
98
99
int iteration;
100
private volatile boolean finalized;
101
102
private String addMessageContext(String message) {
103
return "T:" + Thread.currentThread().getId() +
104
" I:" + iteration +
105
" " + LocalTime.now().toString() +
106
": " + message;
107
}
108
109
private void info(String message) {
110
log.info(addMessageContext(message));
111
}
112
113
private void progress(String message) {
114
// Uncomment this to get more verbose logging.
115
// log.debug(addMessageContext(message));
116
}
117
118
private void fail(String message) {
119
log.error(addMessageContext("[FAILED] " + message));
120
setFailed(true);
121
}
122
123
private boolean shouldTerminate() {
124
return !getExecutionController().continueExecution();
125
}
126
127
private void eatMemory(int initialFactor) {
128
GarbageUtils.eatMemory(getExecutionController(),
129
garbageProducer,
130
initialFactor, 10, 0);
131
}
132
133
public void run() {
134
try {
135
int code = iteration % TYPES_COUNT;
136
info("start code " + code);
137
ReferenceQueue queue = new ReferenceQueue();
138
PhantomReference reference;
139
String type;
140
// Define a specific type for each thread to test
141
switch (code) {
142
case 0:
143
reference = new PhantomReference(new byte[SIZE], queue);
144
type = "byte";
145
break;
146
case 1:
147
reference = new PhantomReference(new short[SIZE], queue);
148
type = "short";
149
break;
150
case 2:
151
reference = new PhantomReference(new int[SIZE], queue);
152
type = "int";
153
break;
154
case 3:
155
reference = new PhantomReference(new long[SIZE], queue);
156
type = "long";
157
break;
158
case 4:
159
reference = new PhantomReference(new char[SIZE], queue);
160
type = "char";
161
break;
162
case 5:
163
reference = new PhantomReference(new boolean[SIZE], queue);
164
type = "boolean";
165
break;
166
case 6:
167
reference = new PhantomReference(new double[SIZE], queue);
168
type = "double";
169
break;
170
case 7:
171
reference = new PhantomReference(new float[SIZE], queue);
172
type = "float";
173
break;
174
case 8:
175
reference = new PhantomReference(new Object[SIZE], queue);
176
type = "Object";
177
break;
178
case 9:
179
reference = new PhantomReference(new NonbranchyTree(SIZE, 0.3f, SIZE),
180
queue);
181
type = "NonbranchyTree";
182
break;
183
case 10:
184
reference = new PhantomReference(internedStringProducer.create(SIZE), queue);
185
type = "InternedString";
186
break;
187
default:
188
reference = new PhantomReference(new Referent(), queue);
189
type = "class";
190
}
191
192
int initialFactor = memoryStrategy.equals(MemoryStrategy.HIGH) ? 1 : (memoryStrategy.equals(MemoryStrategy.LOW) ? 10 : 2);
193
194
// If referent is finalizable, provoke GCs and wait for finalization.
195
if (type.equals("class")) {
196
progress("Waiting for finalization: " + type);
197
for (int checks = 0; !finalized && !shouldTerminate(); ++checks) {
198
// There are scenarios where one eatMemory() isn't enough,
199
// but 10 iterations really ought to be sufficient.
200
if (checks > 10) {
201
fail("Waiting for finalization: " + type);
202
return;
203
}
204
eatMemory(initialFactor);
205
// Give some time for finalizer to run.
206
try {
207
Thread.sleep(100);
208
} catch (InterruptedException e) {}
209
}
210
}
211
212
// Provoke GCs and wait for reference to be enqueued.
213
progress("Waiting for enqueue: " + type);
214
Reference polled = queue.poll();
215
for (int checks = 0; polled == null && !shouldTerminate(); ++checks) {
216
// There are scenarios where one eatMemory() isn't enough,
217
// but 10 iterations really ought to be sufficient.
218
if (checks > 10) {
219
fail("Waiting for enqueue: " + type);
220
return;
221
}
222
eatMemory(initialFactor);
223
// Give some time for reference to be enqueued.
224
try {
225
polled = queue.remove(100);
226
} catch (InterruptedException e) {}
227
}
228
229
if (polled == null && shouldTerminate()) {
230
info("Terminated: " + type);
231
return;
232
}
233
234
// The polled reference must be equal to the one enqueued to
235
// the queue
236
if (polled != reference) {
237
fail("The original reference is not equal to polled reference.");
238
return;
239
}
240
241
// queue.poll() once again must return null now, since there is
242
// only one reference in the queue
243
if (queue.poll() != null) {
244
fail("There are more than one reference in the queue.");
245
return;
246
}
247
progress("Finished: " + type);
248
} catch (OutOfMemoryError e) {
249
} finally {
250
iteration++;
251
}
252
}
253
254
class Referent {
255
256
//We need discard this flag to make second and following checks with type.equals("class") useful
257
public Referent() {
258
finalized = false;
259
}
260
261
protected void finalize() {
262
finalized = true;
263
}
264
}
265
}
266
267
}
268
269