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