1 /* 2 * Copyright (c) 2004, 2020, 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 nsk.share.gc.*; 64 import nsk.share.gc.gp.*; 65 import nsk.share.gc.gp.string.InternedStringProducer; 66 import nsk.share.gc.gp.string.RandomStringProducer; 67 68 public class phantom001 extends ThreadedGCTest implements GarbageProducerAware, MemoryStrategyAware { 69 70 private GarbageProducer garbageProducer; 71 private MemoryStrategy memoryStrategy; 72 private InternedStringProducer internedStringProducer = new InternedStringProducer(new RandomStringProducer(10)); 73 // Total number of types to test 74 final static int TYPES_COUNT = 12; 75 // Size of array of each tested type. The constant also specifies the 76 // number of nodes in a NonbranchyTree and size of each node 77 final static int SIZE = 100; 78 createRunnable(int i)79 protected Runnable createRunnable(int i) { 80 return new Test(); 81 } 82 setGarbageProducer(GarbageProducer garbageProducer)83 public void setGarbageProducer(GarbageProducer garbageProducer) { 84 this.garbageProducer = garbageProducer; 85 } 86 setMemoryStrategy(MemoryStrategy memoryStrategy)87 public void setMemoryStrategy(MemoryStrategy memoryStrategy) { 88 this.memoryStrategy = memoryStrategy; 89 } 90 main(String[] args)91 public static void main(String[] args) { 92 GC.runTest(new phantom001(), args); 93 } 94 95 // The class implements the logic of the testcase 96 class Test implements Runnable { 97 98 int iteration; 99 private volatile boolean finalized; 100 run()101 public void run() { 102 try { 103 log.info("iteration " + iteration); 104 ReferenceQueue queue = new ReferenceQueue(); 105 PhantomReference reference; 106 int code = iteration % TYPES_COUNT; 107 String type; 108 // Define a specific type for each thread to test 109 switch (code) { 110 case 0: 111 reference = new PhantomReference(new byte[SIZE], queue); 112 type = "byte"; 113 break; 114 case 1: 115 reference = new PhantomReference(new short[SIZE], queue); 116 type = "short"; 117 break; 118 case 2: 119 reference = new PhantomReference(new int[SIZE], queue); 120 type = "int"; 121 break; 122 case 3: 123 reference = new PhantomReference(new long[SIZE], queue); 124 type = "long"; 125 break; 126 case 4: 127 reference = new PhantomReference(new char[SIZE], queue); 128 type = "char"; 129 break; 130 case 5: 131 reference = new PhantomReference(new boolean[SIZE], queue); 132 type = "boolean"; 133 break; 134 case 6: 135 reference = new PhantomReference(new double[SIZE], queue); 136 type = "double"; 137 break; 138 case 7: 139 reference = new PhantomReference(new float[SIZE], queue); 140 type = "float"; 141 break; 142 case 8: 143 reference = new PhantomReference(new Object[SIZE], queue); 144 type = "Object"; 145 break; 146 case 9: 147 reference = new PhantomReference(new NonbranchyTree(SIZE, 0.3f, SIZE), 148 queue); 149 type = "NonbranchyTree"; 150 break; 151 case 10: 152 reference = new PhantomReference(internedStringProducer.create(SIZE), queue); 153 type = "InternedString"; 154 break; 155 default: 156 reference = new PhantomReference(new Referent(), queue); 157 type = "class"; 158 } 159 160 int initialFactor = memoryStrategy.equals(MemoryStrategy.HIGH) ? 1 : (memoryStrategy.equals(MemoryStrategy.LOW) ? 10 : 2); 161 GarbageUtils.eatMemory(getExecutionController(), garbageProducer, initialFactor , 10, 0); 162 if (type.equals("class")) { 163 while (!finalized && getExecutionController().continueExecution()) { 164 System.runFinalization(); //does not guarantee finalization, but increases the chance 165 try { 166 Thread.sleep(100); 167 } catch (InterruptedException e) {} 168 GarbageUtils.eatMemory(getExecutionController(), garbageProducer, initialFactor , 10, 0); 169 } 170 171 //provoke gc once more to make finalized object phantom reachable 172 GarbageUtils.eatMemory(getExecutionController(), garbageProducer, initialFactor , 10, 0); 173 } 174 if (!getExecutionController().continueExecution()) { 175 // we were interrrupted by stresser. just exit... 176 return; 177 } 178 Reference polledReference = null; 179 try { 180 polledReference = queue.remove(); 181 } catch (InterruptedException e) { 182 log.error("Unexpected InterruptedException during queue.remove()."); 183 setFailed(true); 184 } 185 // Check the reference and the queue 186 // The polled reference must be equal to the one enqueued to 187 // the queue 188 189 if (polledReference != reference) { 190 log.error("The original reference is not equal to polled reference."); 191 setFailed(true); 192 } 193 194 // queue.poll() once again must return null now, since there is 195 // only one reference in the queue 196 polledReference = queue.poll(); 197 if (polledReference != null) { 198 log.error("There are more than one references in the queue."); 199 setFailed(true); 200 } 201 reference.clear(); 202 } catch (OutOfMemoryError e) { 203 } 204 iteration++; 205 } 206 207 class Referent { 208 209 //We need discard this flag to make second and following checks with type.equals("class") useful Referent()210 public Referent() { 211 finalized = false; 212 } 213 finalize()214 protected void finalize() { 215 finalized = true; 216 } 217 } 218 } 219 220 } 221