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 //gctest02.java 24 25 26 /* 27 * @test 28 * @key gc 29 * 30 * @summary converted from VM Testbase gc/gctests/gctest02. 31 * VM Testbase keywords: [gc] 32 * 33 * @library /vmTestbase 34 * /test/lib 35 * @run driver jdk.test.lib.FileInstaller . . 36 * @run main/othervm gc.gctests.gctest02.gctest02 100 37 */ 38 39 package gc.gctests.gctest02; 40 41 import nsk.share.TestFailure; 42 import nsk.share.TestBug; 43 /* stress testing 44 create 16 memory evil threads requesting to allocate 45 the object of sizes from 8 to ( 2 ^ 19). 46 The live time of objects is random (0 ~ 1000). 47 Here we let the threads that reference the objects 48 to simulate the object life time. 49 */ 50 51 import java.util.Random; 52 53 class PopulationException extends Exception { 54 //this exception is used to signal that we've 55 //reached the end of the test 56 } 57 58 //the LocalRandom class is used to isolate the pseudo-random 59 //number generator from other parts of the system which might 60 //silently be using it. 61 //This is to make sure the tests are repeatable 62 63 class LocalRandom { 64 public static Random rGen = null; 65 random()66 public static double random() { 67 //should fail if rGen is not initialized 68 return rGen.nextDouble(); 69 } 70 } 71 72 class ThreadCount { 73 static int count= 0; inc()74 static synchronized void inc() { count++; } dec()75 static synchronized void dec() { count --; } get()76 static synchronized int get() { return count; } 77 } 78 79 class Person { 80 String name; 81 int ssid; 82 int age; 83 int buf[]; 84 int bufsz; 85 static int populationCount = 0; 86 static int populationLimit = 0; 87 Person(String n, int ssid, int age, int bufsz)88 Person(String n, int ssid, int age, int bufsz) 89 throws PopulationException { 90 name = n; 91 this.ssid = ssid; 92 this.age = age; 93 if ( bufsz > 0 ) { 94 this.bufsz = bufsz; 95 this.buf = new int[bufsz]; 96 } 97 incPopulation(); 98 if (getPopulation() > getPopulationLimit()) { 99 throw new PopulationException(); 100 } 101 } getPopulationLimit()102 public static synchronized int getPopulationLimit() { 103 return populationLimit; 104 } setPopulationLimit(int newLimit)105 public static synchronized void setPopulationLimit(int newLimit) { 106 populationLimit = newLimit; 107 } getPopulation()108 public static synchronized int getPopulation() { 109 return populationCount; 110 } incPopulation()111 public static synchronized void incPopulation() { 112 populationCount ++; 113 } 114 115 } 116 117 // hr (humane resource) dept is using objects. 118 // Put the hr thread to sleep to keep the reference to objects 119 class hr extends Thread { 120 Person pp; 121 int lifetime; 122 hr(Person p, int l)123 hr(Person p, int l) { 124 pp = p; 125 lifetime = l; 126 } 127 run()128 public void run() { 129 // just sleep to emulate the life time of object referenced by p 130 try { sleep(lifetime); } 131 catch (InterruptedException e) {} 132 } 133 } 134 135 class Memevil extends Thread { 136 int sum; 137 int bufsz = 64; 138 boolean debug = false; 139 Memevil(int bufsz)140 Memevil(int bufsz) { 141 sum = 0; 142 this.bufsz = bufsz; 143 } 144 /* Person object is live short, it will be garbage after 145 * control returns 146 */ doit()147 private boolean doit() { 148 try { 149 Person p = new Person("Duke", 100, 100, bufsz); 150 hr useit = new hr(p, (int)(100*LocalRandom.random())); 151 useit.start(); 152 return true; 153 } 154 catch (PopulationException e) { 155 return false; 156 } 157 catch (OutOfMemoryError e ) { 158 System.err.println(getName() + ": Out of Memory"); 159 return false; 160 } 161 } run()162 public void run() { 163 while ( doit() ) { 164 if ( LocalRandom.random() > 0.6668) { 165 try { 166 sleep(10); // to be nice 167 } 168 catch (InterruptedException e) { 169 } 170 } 171 Thread.yield(); 172 } 173 //we've reached the population limit, so we're exiting the thread 174 ThreadCount.dec(); 175 } 176 } 177 178 class Escaper extends Thread { run()179 public void run() { 180 while ( ThreadCount.get() > 0 ) { 181 int buf[] = new int[32]; 182 { 183 yield(); 184 } 185 } 186 } 187 } 188 189 public class gctest02 { main(String args[] )190 public static void main(String args[] ) { 191 int bufsz = 8; 192 int peopleLimit = 1000; 193 long randomSeed = System.currentTimeMillis(); 194 Memevil me=null; 195 if (args.length > 0) 196 { 197 try 198 { 199 peopleLimit = new Integer(args[0]).intValue(); 200 } 201 catch (NumberFormatException e) 202 { 203 throw new TestBug( 204 "Bad input to gctest02. Expected integer, got: ->" 205 + args[0] + "<-", e); 206 } 207 } 208 209 if (args.length == 2) 210 { 211 try 212 { 213 randomSeed = new Long(args[1]).longValue(); 214 } 215 catch (NumberFormatException e) 216 { 217 throw new TestBug( 218 "Bad input to gctest02. Expected long, got: ->" 219 + args[0] + "<-", e); 220 } 221 } 222 Person.setPopulationLimit(peopleLimit); 223 System.out.println("Seed value: " + randomSeed); 224 for (int ii=0; ii<40; ii++) { 225 bufsz = 8; 226 LocalRandom.rGen = new Random(randomSeed); 227 Person.populationCount = 0; 228 Escaper you = new Escaper(); 229 you.setName("Escaper"); 230 ThreadCount.inc(); 231 you.start(); 232 me = new Memevil(bufsz); 233 me.setName("Memevil" + bufsz); 234 bufsz = 2*bufsz; 235 me.start(); 236 Thread.yield(); 237 for (int i=1; i<11; i++) { 238 ThreadCount.inc(); 239 me = new Memevil(bufsz); 240 me.setName("Memevil" + bufsz); 241 bufsz = 2*bufsz; 242 me.start(); 243 Thread.yield(); 244 } 245 try { 246 you.join(); 247 } 248 catch (InterruptedException e) { 249 throw new TestFailure("InterruptedException in gctest2.main()"); 250 } 251 for (int i=1; i<11; i++) { 252 try { me.join(); } 253 catch (InterruptedException e) { 254 throw new TestFailure("InterruptedException in gctest2.main()"); 255 } 256 } 257 } 258 System.out.println("Test passed."); 259 } 260 } 261