1 /*
   2  * Copyright (c) 2010, 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/huge/quicklook/largeheap/Access.
  29  * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent]
  30  * VM Testbase readme:
  31  * DESCRIPTION
  32  *     The test is intended to test 64-bit VM for large memory and heap
  33  *     functionalities. This test checks that no unexpected exceptions and errors
  34  *     are thrown or the JVM is not crashed during allocation of different
  35  *     objects within 32-bit address range.
  36  *     First of all the test checks that the maximum amount of memory that
  37  *     the Java virtual machine will attempt to use (Runtime.maxMemory()) is
  38  *     greater than 4G. If that value is less than 4G, the test passes, otherwise
  39  *     it starts testing.
  40  *     A number of threads is started. That number is set in *.cfg file or is
  41  *     calculated by the test itself based on the machine (see
  42  *     nsk.share.gc.Algorithms.getThreadsCount() method).
  43  *     Each thread creates 9 arrays - one of each of the following types: byte,
  44  *     short, char, int, long, boolean, double, float, Object. All arrays have
  45  *     the same size, and that size is calculated so that all threads together are
  46  *     supposed to eat about 1.3G of the heap (30% of 4G).
  47  *
  48  * @library /vmTestbase
  49  *          /test/lib
  50  * @run driver jdk.test.lib.FileInstaller . .
  51  * @run main/othervm -XX:-UseGCOverheadLimit gc.huge.quicklook.largeheap.Access.access
  52  */
  53 
  54 package gc.huge.quicklook.largeheap.Access;
  55 
  56 import java.util.concurrent.ThreadLocalRandom;
  57 import java.util.ArrayList;
  58 import nsk.share.TestFailure;
  59 import nsk.share.gc.*;
  60 
  61 public class access extends ThreadedGCTest {
  62 
  63     // The test should fill just about 30% of 4G range (32-bit address range)
  64     final static double PART_OF_HEAP = 0.3;
  65     final static long GIGOBYTE = 1024 * 1024 * 1024;
  66     // Approximate number of bytes for one element of each tested type
  67     // (byte, short, char, int, long, double, float, Object)
  68     final static long TYPES_SIZE =
  69             Memory.getByteSize()
  70             + Memory.getShortSize()
  71             + Memory.getIntSize()
  72             + Memory.getCharSize()
  73             + Memory.getLongSize()
  74             + Memory.getDoubleSize()
  75             + Memory.getFloatSize();
  76     //+ Memory.getBooleanSize()
  77     //+ Memory.getReferenceObjectSize();
  78     private final static int STORAGE_SIZE_DIM1 = 65536;
  79     private final static int STORAGE_SIZE_DIM2 = (int) (4 * GIGOBYTE / Memory.getLongSize() / STORAGE_SIZE_DIM1);
  80     // An array to eat 4G of heap
  81     private static long[][] storage = new long[STORAGE_SIZE_DIM1][];
  82     private volatile boolean is4GAllocated = false;
  83     private final Object lock = new Object();
  84 
  85     private class Worker implements Runnable {
  86 
  87         private int arraySize;
  88         private ArrayList<Object> list;
  89 
  90         public Worker(int arraySize) {
  91             this.arraySize = arraySize;
  92             list = new ArrayList<Object>();
  93         }
  94 
  95         public void run() {
  96             try {
  97                 synchronized (lock) {
  98                     while (!is4GAllocated && getExecutionController().continueExecution()) {
  99                         try {
 100                             lock.wait(100);
 101                         } catch (InterruptedException ie) {
 102                         }
 103                     }
 104                 }
 105                 while (getExecutionController().continueExecution()) {
 106                     byte[] barray = new byte[arraySize];
 107                     short[] sarray = new short[arraySize];
 108                     char[] carray = new char[arraySize];
 109                     int[] iarray = new int[arraySize];
 110                     long[] larray = new long[arraySize];
 111                     double[] darray = new double[arraySize];
 112                     float[] farray = new float[arraySize];
 113                     list.add(barray);
 114                     list.add(sarray);
 115                     list.add(carray);
 116                     list.add(iarray);
 117                     list.add(larray);
 118                     list.add(darray);
 119                     list.add(darray);
 120                     for (int i = 0; i < arraySize; i++) {
 121                         larray[i] = (long) (i + 42);
 122                         darray[i] = (double) (42 * i);
 123                         farray[i] = (float) (0.6 * i);
 124                         if (i % 10000 == 0 &&
 125                             getExecutionController().continueExecution()) {
 126                             return;
 127                         }
 128                     }
 129 
 130                     for (int i = arraySize - 1; i > 0; i -= 10) {
 131                         if (larray[i] != (long) (i + 42)) {
 132                             throw new TestFailure("The value = "
 133                                     + larray[i] + " when expected ="
 134                                     + (long) (i + 42));
 135                         }
 136                         if (darray[i] - (double) (42 * i) > 0.001) {
 137                             throw new TestFailure("The value = "
 138                                     + darray[i] + " when expected ="
 139                                     + (double) (i + 42));
 140                         }
 141                         if (farray[i] - (float) (0.6 * i) > 0.001) {
 142                             throw new TestFailure("The value = "
 143                                     + farray[i] + " when expected ="
 144                                     + (float) (i + 42));
 145                         }
 146                         if (i % 10000 == 0 &&
 147                             getExecutionController().continueExecution()) {
 148                             return;
 149                         }
 150                     }
 151                     for (Object obj : list) {
 152                         // check hashcode just to avoid optimization
 153                         if (obj.hashCode() == -1) {
 154                             throw new TestFailure("Unexpected hashcode");
 155                         }
 156                     }
 157                 }
 158             } finally {
 159                 list.clear();
 160             }
 161         }
 162     }
 163 
 164     class MainWorker implements Runnable {
 165 
 166         @Override
 167         public void run() {
 168             synchronized (lock) {
 169                 for (int i = 0; i < STORAGE_SIZE_DIM1; i++) {
 170                     if (!getExecutionController().continueExecution()) {
 171                         log.debug("Test run out of time before 4G were allocated");
 172                         lock.notifyAll();
 173                         return;
 174                     }
 175                     storage[i] = new long[STORAGE_SIZE_DIM2];
 176                 }
 177                 log.debug("The 4G are allocated, starting to test");
 178                 is4GAllocated = true;
 179                 lock.notifyAll();
 180             }
 181             ThreadLocalRandom random = ThreadLocalRandom.current();
 182             while (getExecutionController().continueExecution()) {
 183                 int i = random.nextInt(STORAGE_SIZE_DIM1);
 184                 int j = random.nextInt(STORAGE_SIZE_DIM2);
 185                 long value = random.nextLong(Long.MAX_VALUE);
 186                 storage[i][j] = value;
 187                 if (storage[i][j] != value) {
 188                     throw new TestFailure("The value = "
 189                             + storage[i][j] + " when expected ="
 190                             + value);
 191                 }
 192             }
 193 
 194         }
 195     }
 196 
 197     @Override
 198     public void run() {
 199         if (testConditions()) {
 200             super.run();
 201         }
 202     }
 203 
 204     @Override
 205     protected Runnable createRunnable(int i) {
 206         // Size of array for all types
 207         long proposedSize = (long) ((Runtime.getRuntime().maxMemory() - 4 * GIGOBYTE * PART_OF_HEAP)
 208                 / (runParams.getNumberOfThreads() - 1) / TYPES_SIZE);
 209         int arraySize = Algorithms.getArraySize(proposedSize);
 210         if (i == 0) {
 211             return new MainWorker();
 212         }
 213         return new Worker(arraySize);
 214     }
 215 
 216     public boolean testConditions() {
 217         long maxMemory = Runtime.getRuntime().maxMemory();
 218         // If a machine has less than 4G for heap, there is nothing to test,
 219         // so exit peacefully
 220         if (maxMemory < 5 * GIGOBYTE) {
 221             log.debug("Heap is less than 5G ("
 222                     + maxMemory + " bytes), nothing to "
 223                     + "test");
 224             return false;
 225         }
 226         return true;
 227     }
 228 
 229     public static void main(String[] args) {
 230         GC.runTest(new access(), args);
 231     }
 232 }