1 /* 2 * Copyright (c) 2004, 2018, 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 gc 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 driver jdk.test.lib.FileInstaller . . 58 * @run main/othervm gc.gctests.PhantomReference.phantom001.phantom001 -ms low 59 */ 60 61 package gc.gctests.PhantomReference.phantom001; 62 63 import java.lang.ref.*; 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 { 98 99 int iteration; 100 private volatile boolean finalized; 101 102 public void run() { 103 try { 104 log.info("iteration " + iteration); 105 ReferenceQueue queue = new ReferenceQueue(); 106 PhantomReference reference; 107 int code = iteration % TYPES_COUNT; 108 String type; 109 // Define a specific type for each thread to test 110 switch (code) { 111 case 0: 112 reference = new PhantomReference(new byte[SIZE], queue); 113 type = "byte"; 114 break; 115 case 1: 116 reference = new PhantomReference(new short[SIZE], queue); 117 type = "short"; 118 break; 119 case 2: 120 reference = new PhantomReference(new int[SIZE], queue); 121 type = "int"; 122 break; 123 case 3: 124 reference = new PhantomReference(new long[SIZE], queue); 125 type = "long"; 126 break; 127 case 4: 128 reference = new PhantomReference(new char[SIZE], queue); 129 type = "char"; 130 break; 131 case 5: 132 reference = new PhantomReference(new boolean[SIZE], queue); 133 type = "boolean"; 134 break; 135 case 6: 136 reference = new PhantomReference(new double[SIZE], queue); 137 type = "double"; 138 break; 139 case 7: 140 reference = new PhantomReference(new float[SIZE], queue); 141 type = "float"; 142 break; 143 case 8: 144 reference = new PhantomReference(new Object[SIZE], queue); 145 type = "Object"; 146 break; 147 case 9: 148 reference = new PhantomReference(new NonbranchyTree(SIZE, 0.3f, SIZE), 149 queue); 150 type = "NonbranchyTree"; 151 break; 152 case 10: 153 reference = new PhantomReference(internedStringProducer.create(SIZE), queue); 154 type = "InternedString"; 155 break; 156 default: 157 reference = new PhantomReference(new Referent(), queue); 158 type = "class"; 159 } 160 161 int initialFactor = memoryStrategy.equals(MemoryStrategy.HIGH) ? 1 : (memoryStrategy.equals(MemoryStrategy.LOW) ? 10 : 2); 162 GarbageUtils.eatMemory(getExecutionController(), garbageProducer, initialFactor , 10, 0); 163 if (type.equals("class")) { 164 while (!finalized && getExecutionController().continueExecution()) { 165 System.runFinalization(); //does not guarantee finalization, but increases the chance 166 try { 167 Thread.sleep(100); 168 } catch (InterruptedException e) {} 169 GarbageUtils.eatMemory(getExecutionController(), garbageProducer, initialFactor , 10, 0); 170 } 171 172 //provoke gc once more to make finalized object phantom reachable 173 GarbageUtils.eatMemory(getExecutionController(), garbageProducer, initialFactor , 10, 0); 174 } 175 if (!getExecutionController().continueExecution()) { 176 // we were interrrupted by stresser. just exit... 177 return; 178 } 179 Reference polledReference = null; 180 try { 181 polledReference = queue.remove(); 182 } catch (InterruptedException e) { 183 log.error("Unexpected InterruptedException during queue.remove()."); 184 setFailed(true); 185 } 186 // Check the reference and the queue 187 // The polled reference must be equal to the one enqueued to 188 // the queue 189 190 if (polledReference != reference) { 191 log.error("The original reference is not equal to polled reference."); 192 setFailed(true); 193 } 194 195 // queue.poll() once again must return null now, since there is 196 // only one reference in the queue 197 polledReference = queue.poll(); 198 if (polledReference != null) { 199 log.error("There are more than one references in the queue."); 200 setFailed(true); 201 } 202 reference.clear(); 203 } catch (OutOfMemoryError e) { 204 } 205 iteration++; 206 } 207 208 class Referent { 209 210 //We need discard this flag to make second and following checks with type.equals("class") useful 211 public Referent() { 212 finalized = false; 213 } 214 215 protected void finalize() { 216 finalized = true; 217 } 218 } 219 } 220 221 }