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 
Worker(int arraySize)90         public Worker(int arraySize) {
91             this.arraySize = arraySize;
92             list = new ArrayList<Object>();
93         }
94 
run()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
run()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
run()198     public void run() {
199         if (testConditions()) {
200             super.run();
201         }
202     }
203 
204     @Override
createRunnable(int i)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 
testConditions()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 
main(String[] args)229     public static void main(String[] args) {
230         GC.runTest(new access(), args);
231     }
232 }
233