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