1 /*
2  * Copyright (c) 2015, 2019, 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 package gc.arguments;
25 
26 import java.util.concurrent.Callable;
27 
28 /**
29  * Helper class which allocates memory.
30  *
31  * Typical usage:
32  * <pre>
33  * {@code
34  *           AllocationHelper allocator = new AllocationHelper(MAX_ITERATIONS, ARRAY_LENGTH, CHUNK_SIZE,
35  *                   () -> (verifier()));
36  *           // Allocate byte[CHUNK_SIZE] ARRAY_LENGTH times. Total allocated bytes will be CHUNK_SIZE * ARRAY_LENGTH + refs length.
37  *           // Then invoke verifier and iterate MAX_ITERATIONS times.
38  *           allocator.allocateMemoryAndVerify();
39  * }
40  * </pre>
41  */
42 public final class AllocationHelper {
43 
44     private final int arrayLength;
45     private final int maxIterations;
46     private final int chunkSize;
47 
48     // garbageStorage is used to store link to garbage to prevent optimization.
49     private static Object garbageStorage;
50     private byte garbage[][];
51     private final Callable<?> verifierInstance;
52 
53     /**
54      * Create an AllocationHelper with specified iteration count, array length, chunk size and verifier.
55      *
56      * @param maxIterations
57      * @param arrayLength
58      * @param chunkSize
59      * @param verifier - Callable instance which will be invoked after all allocation cycle. Can be null;
60      */
AllocationHelper(int maxIterations, int arrayLength, int chunkSize, Callable<?> verifier)61     public AllocationHelper(int maxIterations, int arrayLength, int chunkSize, Callable<?> verifier) {
62         if ((arrayLength <= 0) || (maxIterations <= 0) || (chunkSize <= 0)) {
63             throw new IllegalArgumentException("maxIterations, arrayLength and chunkSize should be greater then 0.");
64         }
65         this.arrayLength = arrayLength;
66         this.maxIterations = maxIterations;
67         this.chunkSize = chunkSize;
68         verifierInstance = verifier;
69         garbage = new byte[this.arrayLength][];
70         garbageStorage = garbage;
71     }
72 
allocateMemoryOneIteration()73     private void allocateMemoryOneIteration() {
74         for (int j = 0; j < arrayLength; j++) {
75             garbage[j] = new byte[chunkSize];
76         }
77     }
78 
79     /**
80      * Allocate memory and invoke Verifier during all iteration.
81      *
82      * @throws java.lang.Exception
83      */
allocateMemoryAndVerify()84     public void allocateMemoryAndVerify() throws Exception {
85         for (int i = 0; i < maxIterations; i++) {
86             allocateMemoryOneIteration();
87             if (verifierInstance != null) {
88                 verifierInstance.call();
89             }
90         }
91     }
92 
93     /**
94      * The same as allocateMemoryAndVerify() but hides OOME
95      *
96      * @throws Exception
97      */
allocateMemoryAndVerifyNoOOME()98     public void allocateMemoryAndVerifyNoOOME() throws Exception {
99         try {
100             allocateMemoryAndVerify();
101         } catch (OutOfMemoryError e) {
102             // exit on OOME
103         }
104     }
105 
106     /**
107      * Release link to allocated garbage to make it available for further GC
108      */
release()109     public void release() {
110         if (garbage != null) {
111             garbage = null;
112             garbageStorage = null;
113         }
114     }
115 }
116