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 /*
  26  * @test
  27  * @key gc
  28  *
  29  * @summary converted from VM Testbase gc/gctests/nativeGC05.
  30  * VM Testbase keywords: [gc]
  31  * VM Testbase readme:
  32  * ********************************
  33  * set TIMEOUT = 20
  34  * *******************************
  35  * This test creates a 2 dimensional matrix of (100X100)10,000 elements.
  36  * Each element in this matrix houses the address of a "Cell" that
  37  * occupies about 100 bytes. The total memory occupied by this structure is
  38  * about 1M.
  39  * Once this structure, has been built, 5 threads are let loose that
  40  * randomly choose an element in this matrix and set its contents to null
  41  * effectively creating 100bytes of garbage. The threads continue to act
  42  * until all 5 threads combined have "nulled out" half the cells in the matrix,
  43  * which amounts to 0.5Meg of garbage. The indices of each "nulled out"
  44  * cell is stored in a stack. This information is later used during
  45  * the refilling stage by the native function, kickOffRefiller();
  46  * The native function, kickOffRefiller() refills all the lacunae in the
  47  * matrix with new cells.
  48  * This process of nulling out" and refilling is repeated 50 times.
  49  * Every iteration produces  0.5 Meg
  50  * of garbage. The maximum amount of live memory at use at any time is 1Meg.
  51  * If no garbage collection takes place during any of the ten iterations,
  52  * the total amount(live + garbage) of heap space consumed at the end
  53  * of the program is 0.5*50 + 1 = 26Meg.
  54  * The test fails if an OutOfMemory Exception is thrown.
  55  *        -----------------------------        --------
  56  *       |     |     |     |     |     |       | 100  |
  57  *       |     |     |     |     |  *--|------>| bytes|
  58  *       |     |     |     |     |     |       --------
  59  *        -----------------------------
  60  *       .     .     .     .     .     .
  61  *       .     .     .     .     .     .
  62  *       .     .     .     .     .     .
  63  *       .
  64  *       |     |     |     |     |     |
  65  *       |     |     |     |     |     |
  66  *       |     |     |     |     |     |
  67  *        ------------------------------
  68  *       |     |     |     |     |     |
  69  *       |     |     |     |     |     |
  70  *       |     |     |     |     |     |
  71  *        ------------------------------
  72  *       |     |     |     |     |     |
  73  *       |     |     |     |     |     |
  74  *       |     |     |     |     |     |
  75  *        ------------------------------
  76  *       |     |     |     |     |     |
  77  *       |     |     |     |     |     |
  78  *       |     |     |     |     |     |
  79  *        -----------------------------
  80  *
  81  * @library /vmTestbase
  82  *          /test/lib
  83  * @run driver jdk.test.lib.FileInstaller . .
  84  * @run main/othervm/native gc.gctests.nativeGC05.nativeGC05
  85  */
  86 
  87 package gc.gctests.nativeGC05;
  88 
  89 import nsk.share.TestFailure;
  90 import nsk.share.test.*;
  91 import nsk.share.gc.*;
  92 import java.util.Stack;
  93 
  94 public class nativeGC05 extends GCTestBase {
  95         private final int threadCount = 5;
  96         private Stack<IndexPair> emptiedLocations = new Stack<IndexPair>();
  97         private Matrix matrix = new Matrix(100, 100);
  98 
  99         public native void kickOffRefillers(Matrix matrix, Stack s);
 100 
 101         private class CellEmptier extends Thread {
 102                 public CellEmptier() {
 103                 }
 104 
 105                 boolean keepEmptying(){
 106                         int numberOfCells;
 107                         int matrixSize;
 108 
 109                         matrixSize = matrix.returnArrayBound();
 110                         numberOfCells = (matrixSize + 1) * (matrixSize + 1) ;
 111                         if (matrix.getCellCount() < numberOfCells/2)
 112                                 return true;
 113                         else
 114                                 return false;
 115                 }
 116 
 117                 public void run() {
 118                         int i, j, matrixSize,emptyCells;
 119 
 120                         matrixSize = matrix.returnArrayBound();
 121                         while (keepEmptying()) {
 122                                 i = LocalRandom.nextInt(0, matrixSize);
 123                                 j = LocalRandom.nextInt(0, matrixSize);
 124                                 emptiedLocations.push(new IndexPair(i,j)); //Register empty node
 125                                 matrix.clear(i,j);
 126                         }
 127                 }
 128         }
 129 
 130 
 131         private class StackDump extends Thread {
 132                 public StackDump() {
 133                 }
 134 
 135                 public void run() {
 136                         int emptyCells;
 137 
 138                         while (true) {
 139                                 emptyCells = emptiedLocations.size();
 140                                 System.out.println("Number of empty cells = " + emptyCells);
 141                         }
 142                 }
 143         }
 144 
 145 
 146         public void run() {
 147                 Thread emptierArray[] = new Thread[threadCount];
 148                 int count = 0;
 149                 int memoryReserve[] = new int[10000];
 150 
 151                 //Create 5 CellEmptier Threads. There should be about 1Meg of
 152                 // created garbage by the times these 5 threads return.
 153 
 154                 try {
 155                         while (count < 50) {
 156                                 for (int i = 0; i < threadCount; i++)
 157                                         emptierArray[i] = new CellEmptier();
 158                                 for (int i = 0; i < threadCount; i++)
 159                                         emptierArray[i].start();
 160 
 161                                 // wait for "emptier" threads to finish their job
 162 
 163                                 int i = 0;
 164                                 while (i < threadCount) {
 165                                         try {
 166                                                 emptierArray[i].join();
 167                                         } catch(InterruptedException e) {
 168                                         }
 169                                         i++;
 170                                 }
 171 
 172                                 // Now start refilling.
 173 
 174                                 kickOffRefillers(matrix, emptiedLocations);
 175 
 176                                 // reset count of cells emptied out and start again.
 177                                 matrix.resetCellCount();
 178                                 count++;
 179                         }
 180                 } catch (OutOfMemoryError e) {
 181                         memoryReserve = null;
 182                         System.gc();
 183                         throw new TestFailure("Test Failed at " + count + "th iteration.");
 184                 }
 185                 System.out.println("Test passed.");
 186         }
 187 
 188         public static void main(String args[]) {
 189                 GC.runTest(new nativeGC05(), args);
 190         }
 191 
 192         static {
 193                 System.loadLibrary("nativeGC05");
 194         }
 195 }