1 /* 2 * Copyright (c) 2002, 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 randomness 27 * 28 * @summary converted from VM Testbase gc/gctests/ReferencesGC. 29 * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, quick] 30 * 31 * @library /vmTestbase 32 * /test/lib 33 * @run driver jdk.test.lib.FileInstaller . . 34 * @run main/othervm 35 * -XX:-UseGCOverheadLimit 36 * gc.gctests.ReferencesGC.ReferencesGC 37 * -range 200 38 * -ratio 0.9 39 * -t 1 40 */ 41 42 package gc.gctests.ReferencesGC; 43 44 import java.lang.ref.*; 45 import nsk.share.TestFailure; 46 import nsk.share.gc.Algorithms; 47 import nsk.share.gc.GC; 48 import nsk.share.gc.ThreadedGCTest; 49 import nsk.share.gc.gp.GarbageProducer; 50 import nsk.share.gc.gp.GarbageUtils; 51 import nsk.share.test.ExecutionController; 52 53 public class ReferencesGC extends ThreadedGCTest { 54 55 static int RANGE = 256; 56 static float RATIO = (float) 1.0; 57 58 public static void main(String[] args) { 59 parseArgs(args); 60 GC.runTest(new ReferencesGC(), args); 61 } 62 63 public static void parseArgs(String[] args) { 64 for (int i = 0; i < args.length; i++) { 65 if (args[i].compareTo("-range") == 0) { 66 RANGE = new Integer(args[++i]).intValue(); 67 } else if (args[i].compareTo("-ratio") == 0) { 68 RATIO = new Float(args[++i]).floatValue(); 69 } 70 } 71 } 72 73 private class Worker implements Runnable { 74 75 static final int WEAK = 0; 76 static final int SOFT = 1; 77 static final int PHANTOM = 2; 78 private ExecutionController stresser; 79 int finalizationMaxTime = 1000 * 60 * runParams.getNumberOfThreads(); 80 int[] alive = new int[3]; 81 int[] enqued = new int[3]; 82 CircularLinkedList holder[] = new CircularLinkedList[RANGE]; 83 WeakReference wr[] = new WeakReference[RANGE]; 84 SoftReference sr[] = new SoftReference[RANGE]; 85 PhantomReference phr[] = new PhantomReference[RANGE]; 86 ReferenceQueue refq = new ReferenceQueue(); 87 GarbageProducer gp = GarbageUtils.getArrayProducers().get(0); 88 int iter = 0; 89 90 @Override 91 public void run() { 92 if (stresser == null) { 93 stresser = getExecutionController(); 94 } 95 96 while (stresser.continueExecution()) { 97 int totalQ = 0; 98 try { 99 refq = new ReferenceQueue(); 100 alive = new int[3]; 101 enqued = new int[3]; 102 for (int j = 0; j < RANGE; j++) { 103 holder[j] = new CircularLinkedList(); 104 holder[j].addNelements(300); 105 wr[j] = new WeakReference(holder[j], refq); 106 sr[j] = new SoftReference(holder[j], refq); 107 phr[j] = new PhantomReference(holder[j], refq); 108 } 109 } catch (OutOfMemoryError oome) { 110 // we should just skip the test 111 // the other thread could eat all memory 112 continue; 113 } 114 115 for (int i = 0; i < RANGE; i++) { 116 if (wr[i].isEnqueued()) { 117 ++totalQ; 118 } 119 if (sr[i].isEnqueued()) { 120 ++totalQ; 121 } 122 if (phr[i].isEnqueued()) { 123 ++totalQ; 124 } 125 } 126 if (totalQ != 0) { 127 throw new TestFailure("There are " + totalQ + " references in the queue instead 0 before null-assigment."); 128 } 129 130 for (int i = 0; i < (int) (RANGE * RATIO); i++) { 131 holder[i] = null; 132 } 133 134 Algorithms.eatMemory(stresser); 135 if (!stresser.continueExecution()) { 136 break; 137 } 138 // At this point OOME was thrown and accordingly to spec 139 // all weak refs should be processed 140 141 alive = new int[3]; 142 enqued = new int[3]; 143 for (int i = 0; i < RANGE; i++) { 144 if (wr[i].get() != null) { 145 ++alive[WEAK]; 146 } 147 if (wr[i].isEnqueued()) { 148 ++enqued[WEAK]; 149 } 150 if (sr[i].get() != null) { 151 ++alive[SOFT]; 152 } 153 if (sr[i].isEnqueued()) { 154 ++enqued[SOFT]; 155 } 156 if (phr[i].isEnqueued()) { 157 ++enqued[PHANTOM]; 158 } 159 } 160 161 long waitTime = System.currentTimeMillis() + finalizationMaxTime; 162 while (totalQ < (RANGE * RATIO * 3 * 0.9) && (System.currentTimeMillis() < waitTime)) { 163 alive = new int[3]; 164 enqued = new int[3]; 165 for (int i = 0; i < RANGE; i++) { 166 if (wr[i].get() != null) { 167 ++alive[WEAK]; 168 } 169 if (wr[i].isEnqueued()) { 170 ++enqued[WEAK]; 171 } 172 if (sr[i].get() != null) { 173 ++alive[SOFT]; 174 } 175 if (sr[i].isEnqueued()) { 176 ++enqued[SOFT]; 177 } 178 if (phr[i].isEnqueued()) { 179 ++enqued[PHANTOM]; 180 } 181 } 182 totalQ = (enqued[WEAK] + enqued[SOFT] + enqued[PHANTOM]); 183 if (totalQ < (int) (3 * RANGE * RATIO * 0.9)) { 184 log.debug("After null-assignment to " + (int) (RANGE * RATIO) + 185 //" elements from " + lower + " to " + (upper - 1) + 186 " and provoking gc found:\n\t" + 187 enqued[WEAK] + " weak\n\t" + 188 enqued[SOFT] + " soft\n\t" + 189 enqued[PHANTOM] + " phantom " + 190 " queuened refs and \n\t" + 191 alive[WEAK] + " weak\n\t" + 192 alive[SOFT] + " soft\n\t" + 193 "alive refs."); 194 try { 195 log.debug("sleeping to give gc one more chance ......"); 196 Thread.sleep(1000); 197 } catch (InterruptedException ie) { 198 } 199 } 200 } 201 log.debug("iteration.... " + iter++); 202 if (totalQ < (int) (3 * RANGE * RATIO * 0.9) || totalQ > (int) (3 * RANGE * RATIO)) { 203 throw new TestFailure("Test failed"); 204 } 205 } 206 } 207 } 208 209 @Override 210 protected Runnable createRunnable(int i) { 211 return new Worker(); 212 } 213 }