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