1 /*
   2  * Copyright (c) 2011, 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/AllocateWithoutOomTest.
  29  * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, jrockit]
  30  * VM Testbase readme:
  31  * DESCRIPTION
  32  *   Small stress test that should be able to run for a specified
  33  *   time without hitting an OOM.
  34  *
  35  * COMMENTS
  36  * This test was ported from JRockit test suite.
  37  *
  38  * @library /vmTestbase
  39  *          /test/lib
  40  * @run driver jdk.test.lib.FileInstaller . .
  41  * @run main/othervm
  42  *      -XX:-UseGCOverheadLimit
  43  *      gc.gctests.AllocateWithoutOomTest.AllocateWithoutOomTest
  44  */
  45 
  46 package gc.gctests.AllocateWithoutOomTest;
  47 
  48 import java.util.ArrayList;
  49 import java.util.Random;
  50 import nsk.share.TestFailure;
  51 import nsk.share.gc.GC;
  52 import nsk.share.gc.GCTestBase;
  53 import nsk.share.test.Stresser;
  54 
  55 /**
  56  * Small stress test that should be able to run for a specified
  57  * time without hitting an OOM.
  58  */
  59 public class AllocateWithoutOomTest extends GCTestBase {
  60 
  61     /**
  62      * Small stress test that allocates objects in a certain interval
  63      * and runs for a specified time. It should not throw any OOM during
  64      * the execution.
  65      *
  66      * @return success if the test runs for the specified time without
  67      *         and exceptions being thrown.
  68      */
  69     @Override
  70     public void run() {
  71         int minSize;
  72         int maxSize;
  73 
  74 
  75 
  76         minSize = 2048;
  77         maxSize = 32768;
  78 
  79 
  80         ArrayList placeholder = new ArrayList();
  81         long multiplier = maxSize - minSize;
  82         Random rndGenerator = new Random(runParams.getSeed());
  83 
  84         long memoryUpperLimit = runParams.getTestMemory();
  85         long memoryLowerLimit = runParams.getTestMemory() / 3;
  86         long memoryAllocatedLowerLimit = memoryUpperLimit
  87                 - memoryLowerLimit;
  88 
  89 
  90         long totalAllocatedMemory = 0;
  91         long totalAllocatedObjects = 0;
  92         int allocationSize = -1;
  93         long roundCounter = 1;
  94 
  95         try {
  96             Stresser stresser = new Stresser(runParams.getStressOptions());
  97             stresser.start(0);
  98             while (stresser.continueExecution()) {
  99                 while (totalAllocatedMemory < memoryUpperLimit) {
 100                     allocationSize = ((int) (rndGenerator.nextDouble()
 101                             * multiplier)) + minSize;
 102                     byte[] tmp = new byte[allocationSize];
 103                     totalAllocatedMemory += allocationSize;
 104                     totalAllocatedObjects++;
 105                     placeholder.add(tmp);
 106                     tmp = null;
 107                 }
 108 
 109                 // NOTE: Start on index 1 to make sure we don't remove to many
 110                 // consecutive objects in the beginning
 111                 int indexToRemove = 1;
 112 
 113                 while (totalAllocatedMemory > memoryAllocatedLowerLimit) {
 114                     // NOTE: Terminate if we only have zero objects left
 115                     if (placeholder.size() == 0) {
 116                         throw new TestFailure("No more objects to free, "
 117                                 + "so we can't continue");
 118                     }
 119 
 120                     if (indexToRemove >= placeholder.size()) {
 121                         indexToRemove = (placeholder.size() == 1) ? 0 : 1;
 122                     }
 123 
 124                     byte[] tmp = (byte[]) placeholder.remove(indexToRemove);
 125 
 126                     totalAllocatedMemory -= tmp.length;
 127                     totalAllocatedObjects--;
 128 
 129                     tmp = null;
 130                     // NOTE: Since we removed one object, we only need to
 131                     // increment index by 1 to move two steps. We want to
 132                     // remove every other object to create fragmentation
 133                     indexToRemove++;
 134                 }
 135 
 136                 roundCounter++;
 137             }
 138             placeholder = null;
 139             log.info("Passed. Completed " + roundCounter
 140                     + " rounds during the test");
 141         } catch (OutOfMemoryError oome) {
 142             placeholder = null;
 143             throw new TestFailure("OOM thrown when allocating an object of size "
 144                     + allocationSize, oome);
 145         } finally {
 146             placeholder = null;
 147         }
 148     }
 149 
 150     public static void main(String[] args) {
 151         GC.runTest(new AllocateWithoutOomTest(), args);
 152     }
 153 }