|
1 /* |
|
2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. |
|
3 * Copyright (c) 2017, SAP SE and/or its affiliates. All rights reserved. |
|
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
5 * |
|
6 * This code is free software; you can redistribute it and/or modify it |
|
7 * under the terms of the GNU General Public License version 2 only, as |
|
8 * published by the Free Software Foundation. |
|
9 * |
|
10 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
13 * version 2 for more details (a copy is included in the LICENSE file that |
|
14 * accompanied this code). |
|
15 * |
|
16 * You should have received a copy of the GNU General Public License version |
|
17 * 2 along with this work; if not, write to the Free Software Foundation, |
|
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
19 * |
|
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
21 * or visit www.oracle.com if you need additional information or have any |
|
22 * questions. |
|
23 */ |
|
24 |
|
25 /* |
|
26 * @test TestJNIBlockFullGC |
|
27 * @summary Check that in G1 a Full GC to reclaim space can not be blocked out by the GC locker. |
|
28 * @key gc |
|
29 * @requires vm.gc.G1 |
|
30 * @run main/othervm/native -Xmx64m -XX:+UseG1GC -Xlog:gc=info,gc+alloc=trace -XX:MaxGCPauseMillis=10 TestJNIBlockFullGC 10 10000 10000 10000 30000 10000 0.7 |
|
31 */ |
|
32 |
|
33 import java.lang.ref.SoftReference; |
|
34 |
|
35 public class TestJNIBlockFullGC { |
|
36 |
|
37 static { |
|
38 System.loadLibrary("TestJNIBlockFullGC"); |
|
39 } |
|
40 |
|
41 public static volatile Object tmp; |
|
42 |
|
43 public static volatile boolean hadError = false; |
|
44 |
|
45 private static native int TestCriticalArray0(int[] x); |
|
46 |
|
47 public static class Node { |
|
48 public SoftReference<Node> next; |
|
49 long payload1; |
|
50 long payload2; |
|
51 long payload3; |
|
52 long payload4; |
|
53 |
|
54 public Node(int load) { |
|
55 payload1 = payload2 = payload3 = payload4 = load; |
|
56 } |
|
57 } |
|
58 |
|
59 public static void warmUp(long warmupEndTime, int size) { |
|
60 // First let the GC assume most of our objects will die. |
|
61 Node[] roots = new Node[size]; |
|
62 |
|
63 while (System.currentTimeMillis() < warmupEndTime) { |
|
64 int index = (int) (Math.random() * roots.length); |
|
65 roots[index] = new Node(1); |
|
66 } |
|
67 |
|
68 // Make sure the young generation is empty. |
|
69 for (int i = 0; i < roots.length; ++i) { |
|
70 roots[i] = null; |
|
71 } |
|
72 } |
|
73 |
|
74 public static void runTest(long endTime, int size, double alive) { |
|
75 final int length = 10000; |
|
76 int[] array1 = new int[length]; |
|
77 for (int x = 1; x < length; x++) { |
|
78 array1[x] = x; |
|
79 } |
|
80 |
|
81 Node[] roots = new Node[size]; |
|
82 try { |
|
83 int index = 0; |
|
84 roots[0] = new Node(0); |
|
85 |
|
86 while (!hadError && (System.currentTimeMillis() < endTime)) { |
|
87 int test_val1 = TestCriticalArray0(array1); |
|
88 |
|
89 if (Math.random() > alive) { |
|
90 tmp = new Node(test_val1); |
|
91 } else { |
|
92 index = (int) (Math.random() * roots.length); |
|
93 |
|
94 if (roots[index] != null) { |
|
95 Node node = new Node(test_val1); |
|
96 node.next = new SoftReference<Node>(roots[index]); |
|
97 roots[index] = node; |
|
98 } else { |
|
99 roots[index] = new Node(test_val1); |
|
100 } |
|
101 } |
|
102 } |
|
103 } catch (OutOfMemoryError e) { |
|
104 hadError = true; |
|
105 e.printStackTrace(); |
|
106 } |
|
107 } |
|
108 |
|
109 private static void joinThreads(Thread[] threads) throws Exception { |
|
110 for (int i = 0; i < threads.length; i++) { |
|
111 try { |
|
112 if (threads[i] != null) { |
|
113 threads[i].join(); |
|
114 } |
|
115 } catch (InterruptedException e) { |
|
116 e.printStackTrace(); |
|
117 throw e; |
|
118 } |
|
119 } |
|
120 } |
|
121 |
|
122 public static void main(String[] args) throws Exception { |
|
123 if (args.length < 7){ |
|
124 System.out.println("Usage: java TestJNIBlockFullGC <warmupThreads> <warmup-time-in-millis> <warmup iterations> <threads> <time-in-millis> <iterations> <aliveFrac>"); |
|
125 System.exit(0); |
|
126 } |
|
127 |
|
128 int warmupThreads = Integer.parseInt(args[0]); |
|
129 System.out.println("# Warmup Threads = " + warmupThreads); |
|
130 |
|
131 int warmupDuration = Integer.parseInt(args[1]); |
|
132 System.out.println("WarmUp Duration = " + warmupDuration); |
|
133 int warmupIterations = Integer.parseInt(args[2]); |
|
134 System.out.println("# Warmup Iterations = "+ warmupIterations); |
|
135 |
|
136 int mainThreads = Integer.parseInt(args[3]); |
|
137 System.out.println("# Main Threads = " + mainThreads); |
|
138 int mainDuration = Integer.parseInt(args[4]); |
|
139 System.out.println("Main Duration = " + mainDuration); |
|
140 int mainIterations = Integer.parseInt(args[5]); |
|
141 System.out.println("# Main Iterations = " + mainIterations); |
|
142 |
|
143 double liveFrac = Double.parseDouble(args[6]); |
|
144 System.out.println("Live Fraction = " + liveFrac); |
|
145 |
|
146 Thread threads[] = new Thread[Math.max(warmupThreads, mainThreads)]; |
|
147 |
|
148 System.out.println("Start warm-up threads!"); |
|
149 long warmupStartTime = System.currentTimeMillis(); |
|
150 for (int i = 0; i < warmupThreads; i++) { |
|
151 threads[i] = new Thread() { |
|
152 public void run() { |
|
153 warmUp(warmupStartTime + warmupDuration, warmupIterations); |
|
154 }; |
|
155 }; |
|
156 threads[i].start(); |
|
157 } |
|
158 |
|
159 joinThreads(threads); |
|
160 |
|
161 System.gc(); |
|
162 System.out.println("Keep alive a lot"); |
|
163 |
|
164 long startTime = System.currentTimeMillis(); |
|
165 for (int i = 0; i < mainThreads; i++) { |
|
166 threads[i] = new Thread() { |
|
167 public void run() { |
|
168 runTest(startTime + mainDuration, mainIterations, liveFrac); |
|
169 }; |
|
170 }; |
|
171 threads[i].start(); |
|
172 } |
|
173 System.out.println("All threads started"); |
|
174 |
|
175 joinThreads(threads); |
|
176 |
|
177 if (hadError) { |
|
178 throw new RuntimeException("Experienced an OoME during execution."); |
|
179 } |
|
180 } |
|
181 } |