2
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.
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
27
* @requires vm.gc != "Epsilon"
29
* @build jdk.test.whitebox.WhiteBox
30
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
33
* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
34
* gc.TestReferenceRefersTo
37
import java.lang.ref.PhantomReference;
38
import java.lang.ref.Reference;
39
import java.lang.ref.ReferenceQueue;
40
import java.lang.ref.WeakReference;
41
import jdk.test.whitebox.WhiteBox;
43
public class TestReferenceRefersTo {
44
private static final WhiteBox WB = WhiteBox.getWhiteBox();
46
private static final class TestObject {
47
public final int value;
49
public TestObject(int value) {
54
private static volatile TestObject testObjectNone = null;
55
private static volatile TestObject testObject1 = null;
56
private static volatile TestObject testObject2 = null;
57
private static volatile TestObject testObject3 = null;
58
private static volatile TestObject testObject4 = null;
60
private static ReferenceQueue<TestObject> queue = null;
62
private static PhantomReference<TestObject> testPhantom1 = null;
64
private static WeakReference<TestObject> testWeak2 = null;
65
private static WeakReference<TestObject> testWeak3 = null;
66
private static WeakReference<TestObject> testWeak4 = null;
68
private static void setup() {
69
testObjectNone = new TestObject(0);
70
testObject1 = new TestObject(1);
71
testObject2 = new TestObject(2);
72
testObject3 = new TestObject(3);
73
testObject4 = new TestObject(4);
75
queue = new ReferenceQueue<TestObject>();
77
testPhantom1 = new PhantomReference<TestObject>(testObject1, queue);
79
testWeak2 = new WeakReference<TestObject>(testObject2, queue);
80
testWeak3 = new WeakReference<TestObject>(testObject3, queue);
81
testWeak4 = new WeakReference<TestObject>(testObject4, queue);
84
private static void gcUntilOld(Object o) throws Exception {
85
if (!WB.isObjectInOldGen(o)) {
87
if (!WB.isObjectInOldGen(o)) {
88
fail("object not promoted by full gc");
93
private static void gcUntilOld() throws Exception {
94
gcUntilOld(testObjectNone);
95
gcUntilOld(testObject1);
96
gcUntilOld(testObject2);
97
gcUntilOld(testObject3);
98
gcUntilOld(testObject4);
100
gcUntilOld(testPhantom1);
102
gcUntilOld(testWeak2);
103
gcUntilOld(testWeak3);
104
gcUntilOld(testWeak4);
107
private static void progress(String msg) {
108
System.out.println(msg);
111
private static void fail(String msg) throws Exception {
112
throw new RuntimeException(msg);
115
private static void expectCleared(Reference<TestObject> ref,
116
String which) throws Exception {
117
expectNotValue(ref, testObjectNone, which);
118
if (!ref.refersTo(null)) {
119
fail("expected " + which + " to be cleared");
123
private static void expectNotCleared(Reference<TestObject> ref,
124
String which) throws Exception {
125
expectNotValue(ref, testObjectNone, which);
126
if (ref.refersTo(null)) {
127
fail("expected " + which + " to not be cleared");
131
private static void expectValue(Reference<TestObject> ref,
133
String which) throws Exception {
134
expectNotValue(ref, testObjectNone, which);
135
expectNotCleared(ref, which);
136
if (!ref.refersTo(value)) {
137
fail(which + " doesn't refer to expected value");
141
private static void expectNotValue(Reference<TestObject> ref,
143
String which) throws Exception {
144
if (ref.refersTo(value)) {
145
fail(which + " refers to unexpected value");
149
private static void checkInitialStates() throws Exception {
150
expectValue(testPhantom1, testObject1, "testPhantom1");
151
expectValue(testWeak2, testObject2, "testWeak2");
152
expectValue(testWeak3, testObject3, "testWeak3");
153
expectValue(testWeak4, testObject4, "testWeak4");
156
private static void discardStrongReferences() {
157
// testObjectNone not dropped
160
// testObject3 not dropped
164
private static void testConcurrentCollection() throws Exception {
165
progress("setup concurrent collection test");
167
progress("gcUntilOld");
170
progress("acquire control of concurrent cycles");
171
WB.concurrentGCAcquireControl();
173
progress("check initial states");
174
checkInitialStates();
176
progress("discard strong references");
177
discardStrongReferences();
179
progress("run GC to before marking completed");
180
WB.concurrentGCRunTo(WB.BEFORE_MARKING_COMPLETED);
182
progress("fetch test objects, possibly keeping some alive");
183
expectNotCleared(testPhantom1, "testPhantom1");
184
expectNotCleared(testWeak2, "testWeak2");
185
expectValue(testWeak3, testObject3, "testWeak3");
187
// For some collectors, calling get() will keep testObject4 alive.
188
if (testWeak4.get() == null) {
189
fail("testWeak4 unexpectedly == null");
192
progress("finish collection");
193
WB.concurrentGCRunToIdle();
195
progress("verify expected clears");
196
expectCleared(testPhantom1, "testPhantom1");
197
expectCleared(testWeak2, "testWeak2");
198
expectValue(testWeak3, testObject3, "testWeak3");
200
progress("verify get returns expected values");
201
if (testWeak2.get() != null) {
202
fail("testWeak2.get() != null");
205
TestObject obj3 = testWeak3.get();
207
fail("testWeak3.get() returned null");
208
} else if (obj3.value != 3) {
209
fail("testWeak3.get().value is " + obj3.value);
212
TestObject obj4 = testWeak4.get();
214
progress("verify queue entries");
215
long timeout = 60000; // 1 minute of milliseconds.
217
Reference<? extends TestObject> ref = queue.remove(timeout);
220
} else if (ref == testPhantom1) {
222
} else if (ref == testWeak2) {
224
} else if (ref == testWeak3) {
226
} else if (ref == testWeak4) {
229
fail("unexpected reference in queue");
232
if (testPhantom1 != null) {
233
fail("testPhantom1 not notified");
234
} else if (testWeak2 != null) {
235
fail("testWeak2 not notified");
236
} else if (testWeak3 == null) {
237
fail("testWeak3 notified");
239
if ((testWeak4 == null) != (obj4 == null)) {
240
fail("either referent is cleared and we got notified, or neither of this happened: referent: "
241
+ obj4 + ", notified: " + (testWeak4 == null));
245
progress("release control of concurrent cycles");
246
WB.concurrentGCReleaseControl();
248
progress("finished concurrent collection test");
251
private static void testSimpleCollection() throws Exception {
252
progress("setup simple collection test");
254
progress("gcUntilOld");
257
progress("check initial states");
258
checkInitialStates();
260
progress("discard strong references");
261
TestObject tw4 = testWeak4.get(); // Keep testObject4 alive.
262
discardStrongReferences();
264
progress("collect garbage");
267
progress("verify expected clears");
268
expectCleared(testPhantom1, "testPhantom1");
269
expectCleared(testWeak2, "testWeak2");
270
expectValue(testWeak3, testObject3, "testWeak3");
271
expectNotCleared(testWeak4, "testWeak4");
273
progress("verify get returns expected values");
274
if (testWeak2.get() != null) {
275
fail("testWeak2.get() != null");
276
} else if (testWeak3.get() != testObject3) {
277
fail("testWeak3.get() is not expected value");
278
} else if (testWeak4.get() != tw4) {
279
fail("testWeak4.get() is not expected value");
282
progress("finished simple collection test");
285
public static void main(String[] args) throws Exception {
286
if (WB.supportsConcurrentGCBreakpoints()) {
287
testConcurrentCollection();
289
testSimpleCollection();