1 /*
   2  * Copyright (c) 2003, 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
  27  *
  28  * @summary converted from VM Testbase gc/gctests/Steal/steal001.
  29  * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent]
  30  * VM Testbase readme:
  31  * DESCRIPTION
  32  *     The test checks that Garbage Collector correctly uses stealing technique:
  33  *     no unexpected exceptions and errors are thrown; the JVM is not crashed.
  34  *     Actually, the test is intended for Parallel Collector.
  35  *     The test starts just one thread and fills the memory with NonbranyTrees
  36  *     (the number of nodes of the tree and its size are based on
  37  *     Runtime.maxMemory() value) until OutOfMemoryError is thrown. All references
  38  *     to the trees are saved in a java.util.Vector. Then the test removes a
  39  *     number of trees from the vector, this number is equal to number of
  40  *     processors (returned by nsk.share.gc.Algorithms.availableProcessors()).
  41  *     Algorithms.eatMemory(int) is invoked after that to provoke GC to clean the
  42  *     memory. Then procedure is repeated.
  43  *
  44  * @library /vmTestbase
  45  *          /test/lib
  46  * @run driver jdk.test.lib.FileInstaller . .
  47  * @run main/othervm -XX:-UseGCOverheadLimit gc.gctests.Steal.steal001.steal001
  48  */
  49 
  50 package gc.gctests.Steal.steal001;
  51 
  52 import java.util.*;
  53 import java.util.concurrent.ThreadLocalRandom;
  54 import nsk.share.gc.*;
  55 import nsk.share.gc.gp.GarbageUtils;
  56 import nsk.share.test.ExecutionController;
  57 
  58 public class steal001 extends ThreadedGCTest {
  59     // Preload ThreadLocalRandom class to avoid class initialization failure
  60     // due to OOM error in static class initializer
  61     final static public ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
  62 
  63     // Internal number of iterations to remove and create new elements
  64     // for the vector
  65     final static int INTERNAL_ITERATIONS = 10;
  66     // Approximate number of trees to fill the heap with
  67     final static int TREES = 50;
  68     // Number of nodes for each tree
  69     final static int NODES = 500;
  70 
  71     private class Eater implements Runnable {
  72 
  73         private int nodeSize;
  74         private List<NonbranchyTree> list;
  75         int processors = Runtime.getRuntime().availableProcessors();
  76         ExecutionController stresser;
  77 
  78         public Eater(int nodeSize) {
  79             list = new ArrayList<>();
  80             this.nodeSize = nodeSize;
  81         }
  82 
  83         @Override
  84         public void run() {
  85             if (stresser == null) {
  86                 stresser = getExecutionController();
  87             }
  88             int counter = NODES;
  89             while (stresser.continueExecution()) {
  90                 fillHeap(counter);
  91                 removeElements();
  92                 counter = (counter == 1) ? 1 : counter - 1;
  93             }
  94         }
  95 
  96         // Fill the memory with trees of defined size until OutOfMemoryError
  97         private void fillHeap(int n) {
  98             try {
  99                 while (stresser.continueExecution()) {
 100                     // Passing in the ExecutionController to make sure we
 101                     // stop allocating nodes when time is up.
 102                     list.add(new NonbranchyTree(n, 0.3f, nodeSize, stresser));
 103                 }
 104             } catch (OutOfMemoryError e) {
 105             }
 106         }
 107 
 108         // Remove a number of elements (equal to number of processors) from the
 109         // vector and provoke GC to clean the heap
 110         private void removeElements() {
 111             if (list.size() <= 0) {
 112                 return;
 113             }
 114             list.remove(0);
 115             GarbageUtils.eatMemory(stresser);
 116         }
 117     }
 118 
 119     @Override
 120     protected Runnable createRunnable(int i) {
 121         // Perform calculations specific to the test
 122         double treeSize = Runtime.getRuntime().maxMemory() / TREES;
 123         int nodeSize = (int) (treeSize / NODES - NonbranchyTree.MIN_NODE_SIZE);
 124         nodeSize = Math.max(1, nodeSize);
 125         return new Eater(nodeSize);
 126     }
 127 
 128     public static void main(String args[]) {
 129         // just to preload GarbageUtils and avoid exception
 130         // in removeElements()
 131         GarbageUtils.getGarbageProducers();
 132         GC.runTest(new steal001(), args);
 133     }
 134 }