Skip to content

Commit 222a17e

Browse files
committed
8262122: [TESTBUG] Shenandoah-specific variant of TestReferenceRefersTo
Reviewed-by: shade
1 parent a777e82 commit 222a17e

File tree

1 file changed

+325
-0
lines changed

1 file changed

+325
-0
lines changed
Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
/*
2+
* Copyright (c) 2020, 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+
package gc.shenandoah;
25+
26+
/* @test
27+
* @requires vm.gc.Shenandoah
28+
* @library /test/lib
29+
* @build sun.hotspot.WhiteBox
30+
* @modules java.base
31+
* @run main ClassFileInstaller sun.hotspot.WhiteBox
32+
* @run main/othervm
33+
* -Xbootclasspath/a:.
34+
* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
35+
* -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCMode=satb
36+
* gc.shenandoah.TestReferenceRefersToShenandoah
37+
*/
38+
39+
/* @test
40+
* @requires vm.gc.Shenandoah
41+
* @library /test/lib
42+
* @build sun.hotspot.WhiteBox
43+
* @modules java.base
44+
* @run main ClassFileInstaller sun.hotspot.WhiteBox
45+
* @run main/othervm
46+
* -Xbootclasspath/a:.
47+
* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
48+
* -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCMode=iu
49+
* gc.shenandoah.TestReferenceRefersToShenandoah
50+
*/
51+
52+
import java.lang.ref.PhantomReference;
53+
import java.lang.ref.Reference;
54+
import java.lang.ref.ReferenceQueue;
55+
import java.lang.ref.WeakReference;
56+
import sun.hotspot.WhiteBox;
57+
58+
public class TestReferenceRefersToShenandoah {
59+
private static final WhiteBox WB = WhiteBox.getWhiteBox();
60+
61+
private static final class TestObject {
62+
public final int value;
63+
64+
public TestObject(int value) {
65+
this.value = value;
66+
}
67+
}
68+
69+
private static volatile TestObject testObjectNone = null;
70+
private static volatile TestObject testObject1 = null;
71+
private static volatile TestObject testObject2 = null;
72+
private static volatile TestObject testObject3 = null;
73+
private static volatile TestObject testObject4 = null;
74+
75+
private static ReferenceQueue<TestObject> queue = null;
76+
77+
private static PhantomReference<TestObject> testPhantom1 = null;
78+
79+
private static WeakReference<TestObject> testWeak2 = null;
80+
private static WeakReference<TestObject> testWeak3 = null;
81+
private static WeakReference<TestObject> testWeak4 = null;
82+
83+
private static void setup() {
84+
testObjectNone = new TestObject(0);
85+
testObject1 = new TestObject(1);
86+
testObject2 = new TestObject(2);
87+
testObject3 = new TestObject(3);
88+
testObject4 = new TestObject(4);
89+
90+
queue = new ReferenceQueue<TestObject>();
91+
92+
testPhantom1 = new PhantomReference<TestObject>(testObject1, queue);
93+
94+
testWeak2 = new WeakReference<TestObject>(testObject2, queue);
95+
testWeak3 = new WeakReference<TestObject>(testObject3, queue);
96+
testWeak4 = new WeakReference<TestObject>(testObject4, queue);
97+
}
98+
99+
private static void gcUntilOld(Object o) throws Exception {
100+
if (!WB.isObjectInOldGen(o)) {
101+
WB.fullGC();
102+
if (!WB.isObjectInOldGen(o)) {
103+
fail("object not promoted by full gc");
104+
}
105+
}
106+
}
107+
108+
private static void gcUntilOld() throws Exception {
109+
gcUntilOld(testObjectNone);
110+
gcUntilOld(testObject1);
111+
gcUntilOld(testObject2);
112+
gcUntilOld(testObject3);
113+
gcUntilOld(testObject4);
114+
115+
gcUntilOld(testPhantom1);
116+
117+
gcUntilOld(testWeak2);
118+
gcUntilOld(testWeak3);
119+
gcUntilOld(testWeak4);
120+
}
121+
122+
private static void progress(String msg) {
123+
System.out.println(msg);
124+
}
125+
126+
private static void fail(String msg) throws Exception {
127+
throw new RuntimeException(msg);
128+
}
129+
130+
private static void expectCleared(Reference<TestObject> ref,
131+
String which) throws Exception {
132+
expectNotValue(ref, testObjectNone, which);
133+
if (!ref.refersTo(null)) {
134+
fail("expected " + which + " to be cleared");
135+
}
136+
}
137+
138+
private static void expectNotCleared(Reference<TestObject> ref,
139+
String which) throws Exception {
140+
expectNotValue(ref, testObjectNone, which);
141+
if (ref.refersTo(null)) {
142+
fail("expected " + which + " to not be cleared");
143+
}
144+
}
145+
146+
private static void expectValue(Reference<TestObject> ref,
147+
TestObject value,
148+
String which) throws Exception {
149+
expectNotValue(ref, testObjectNone, which);
150+
expectNotCleared(ref, which);
151+
if (!ref.refersTo(value)) {
152+
fail(which + " doesn't refer to expected value");
153+
}
154+
}
155+
156+
private static void expectNotValue(Reference<TestObject> ref,
157+
TestObject value,
158+
String which) throws Exception {
159+
if (ref.refersTo(value)) {
160+
fail(which + " refers to unexpected value");
161+
}
162+
}
163+
164+
private static void checkInitialStates() throws Exception {
165+
expectValue(testPhantom1, testObject1, "testPhantom1");
166+
expectValue(testWeak2, testObject2, "testWeak2");
167+
expectValue(testWeak3, testObject3, "testWeak3");
168+
expectValue(testWeak4, testObject4, "testWeak4");
169+
}
170+
171+
private static void discardStrongReferences() {
172+
// testObjectNone not dropped
173+
testObject1 = null;
174+
testObject2 = null;
175+
// testObject3 not dropped
176+
testObject4 = null;
177+
}
178+
179+
private static boolean isShenandoahIUMode() {
180+
return "iu".equals(WB.getStringVMFlag("ShenandoahGCMode"));
181+
}
182+
183+
private static void testConcurrentCollection() throws Exception {
184+
progress("setup concurrent collection test");
185+
setup();
186+
progress("gcUntilOld");
187+
gcUntilOld();
188+
189+
progress("acquire control of concurrent cycles");
190+
WB.concurrentGCAcquireControl();
191+
try {
192+
progress("check initial states");
193+
checkInitialStates();
194+
195+
progress("discard strong references");
196+
discardStrongReferences();
197+
198+
progress("run GC to before marking completed");
199+
WB.concurrentGCRunTo(WB.BEFORE_MARKING_COMPLETED);
200+
201+
progress("fetch test objects, possibly keeping some alive");
202+
expectNotCleared(testPhantom1, "testPhantom1");
203+
expectNotCleared(testWeak2, "testWeak2");
204+
expectValue(testWeak3, testObject3, "testWeak3");
205+
206+
// For some collectors, calling get() will keep testObject4 alive.
207+
if (testWeak4.get() == null) {
208+
fail("testWeak4 unexpectedly == null");
209+
}
210+
211+
progress("finish collection");
212+
WB.concurrentGCRunToIdle();
213+
214+
progress("verify expected clears");
215+
expectCleared(testPhantom1, "testPhantom1");
216+
expectCleared(testWeak2, "testWeak2");
217+
expectValue(testWeak3, testObject3, "testWeak3");
218+
// This is true for all currently supported concurrent collectors,
219+
// except Shenandoah+IU, which allows clearing refs even when
220+
// accessed during concurrent marking.
221+
if (isShenandoahIUMode()) {
222+
expectCleared(testWeak4, "testWeak4");
223+
} else {
224+
expectNotCleared(testWeak4, "testWeak4");
225+
}
226+
227+
progress("verify get returns expected values");
228+
if (testWeak2.get() != null) {
229+
fail("testWeak2.get() != null");
230+
}
231+
232+
TestObject obj3 = testWeak3.get();
233+
if (obj3 == null) {
234+
fail("testWeak3.get() returned null");
235+
} else if (obj3.value != 3) {
236+
fail("testWeak3.get().value is " + obj3.value);
237+
}
238+
239+
TestObject obj4 = testWeak4.get();
240+
if (!isShenandoahIUMode()) {
241+
if (obj4 == null) {
242+
fail("testWeak4.get() returned null");
243+
} else if (obj4.value != 4) {
244+
fail("testWeak4.get().value is " + obj4.value);
245+
}
246+
}
247+
248+
progress("verify queue entries");
249+
long timeout = 60000; // 1 minute of milliseconds.
250+
while (true) {
251+
Reference<? extends TestObject> ref = queue.remove(timeout);
252+
if (ref == null) {
253+
break;
254+
} else if (ref == testPhantom1) {
255+
testPhantom1 = null;
256+
} else if (ref == testWeak2) {
257+
testWeak2 = null;
258+
} else if (ref == testWeak3) {
259+
testWeak3 = null;
260+
} else if (ref == testWeak4) {
261+
testWeak4 = null;
262+
} else {
263+
fail("unexpected reference in queue");
264+
}
265+
}
266+
if (testPhantom1 != null) {
267+
fail("testPhantom1 not notified");
268+
} else if (testWeak2 != null) {
269+
fail("testWeak2 not notified");
270+
} else if (testWeak3 == null) {
271+
fail("testWeak3 notified");
272+
} else if (testWeak4 == null) {
273+
if (obj4 != null) {
274+
fail("testWeak4 notified");
275+
}
276+
}
277+
278+
} finally {
279+
progress("release control of concurrent cycles");
280+
WB.concurrentGCReleaseControl();
281+
}
282+
progress("finished concurrent collection test");
283+
}
284+
285+
private static void testSimpleCollection() throws Exception {
286+
progress("setup simple collection test");
287+
setup();
288+
progress("gcUntilOld");
289+
gcUntilOld();
290+
291+
progress("check initial states");
292+
checkInitialStates();
293+
294+
progress("discard strong references");
295+
TestObject tw4 = testWeak4.get(); // Keep testObject4 alive.
296+
discardStrongReferences();
297+
298+
progress("collect garbage");
299+
WB.fullGC();
300+
301+
progress("verify expected clears");
302+
expectCleared(testPhantom1, "testPhantom1");
303+
expectCleared(testWeak2, "testWeak2");
304+
expectValue(testWeak3, testObject3, "testWeak3");
305+
expectNotCleared(testWeak4, "testWeak4");
306+
307+
progress("verify get returns expected values");
308+
if (testWeak2.get() != null) {
309+
fail("testWeak2.get() != null");
310+
} else if (testWeak3.get() != testObject3) {
311+
fail("testWeak3.get() is not expected value");
312+
} else if (testWeak4.get() != tw4) {
313+
fail("testWeak4.get() is not expected value");
314+
}
315+
316+
progress("finished simple collection test");
317+
}
318+
319+
public static void main(String[] args) throws Exception {
320+
if (WB.supportsConcurrentGCBreakpoints()) {
321+
testConcurrentCollection();
322+
}
323+
testSimpleCollection();
324+
}
325+
}

0 commit comments

Comments
 (0)