1 /*
2 * Copyright (c) 2007, 2020, 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 /*
26 * @test
27 * @key stress randomness
28 *
29 * @summary converted from VM testbase nsk/stress/jni/gclocker/gcl001.
30 * VM testbase keywords: [stress, quick, feature_283, nonconcurrent]
31 * VM testbase readme:
32 * DESCRIPTION
33 * Check compatibility of GC Locker improvements with JNI CS
34 * Two types of concurrent threads are present:
35 * A) Create N 'JNI CS' threads. Each of them will:
36 * 1. Create primitive array and string with random data
37 * 2. Pass it to native method
38 * 3. Sort/Hash data in JNI CS mixing string and array critical sections
39 * 4. Return from native
40 * 5. Check data to be processed correctly
41 * B) Create M ' Garbage producer/memory allocation' threads. Each of them will:
42 * 1. Allocate memory blocks and make them garbage.
43 * 2. Check for OOM errors.
44 *
45 * @library /vmTestbase
46 * /test/lib
47 * @run main/othervm/native/timeout=480
48 * -XX:-UseGCOverheadLimit
49 * nsk.stress.jni.gclocker.gcl001
50 * -stressThreadsFactor 8
51 */
52
53 package nsk.stress.jni.gclocker;
54
55 import nsk.share.gc.DefaultProducer;
56 import nsk.share.gc.GC;
57 import nsk.share.gc.ThreadedGCTest;
58 import nsk.share.gc.gp.array.BooleanArrayProducer;
59 import nsk.share.gc.gp.array.ByteArrayProducer;
60 import nsk.share.gc.gp.array.CharArrayProducer;
61 import nsk.share.gc.gp.array.DoubleArrayProducer;
62 import nsk.share.gc.gp.array.FloatArrayProducer;
63 import nsk.share.gc.gp.array.IntArrayProducer;
64 import nsk.share.gc.gp.array.LongArrayProducer;
65 import nsk.share.gc.gp.array.ShortArrayProducer;
66 import nsk.share.test.ExecutionController;
67 import nsk.share.test.LocalRandom;
68
69 public class gcl001 extends ThreadedGCTest {
70
71 static {
72 System.loadLibrary("gcl001");
73 }
74
75 int maxBlockSize;
76
77 public static void main(String[] args) {
78 GC.runTest(new gcl001(), args);
79 }
80
81 @Override
82 public void run() {
83 // each thread have only one block at the time
84 // so we should occupy less then 60% of heap with live objects
85 long maxSize = runParams.getTestMemory() / runParams.getNumberOfThreads();
86 if (maxSize > Integer.MAX_VALUE - 1) {
87 maxSize = Integer.MAX_VALUE - 1;
88 }
89 maxBlockSize = (int) maxSize;
90 log.info("Maximium block size = " + maxBlockSize);
91 super.run();
92 }
93
94 @Override
95 protected Runnable createRunnable(int i) {
96 if (i < runParams.getNumberOfThreads() / 2) {
97 return CreateJNIWorker(i, maxBlockSize);
98 } else {
99 return new GarbageProducer(maxBlockSize);
100 }
101 }
102
103 public Runnable CreateJNIWorker(int number, int size) {
104 JNIAbstractWorker worker = null;
105 switch (number % 8) {
106 case 0:
107 worker = new JNIBooleanWorker(size);
108 break;
109 case 1:
110 worker = new JNIByteWorker(size);
111 break;
112 case 2:
113 worker = new JNICharWorker(size);
114 break;
115 case 3:
116 worker = new JNIShortWorker(size);
117 break;
118 case 4:
119 worker = new JNIIntWorker(size);
120 break;
121 case 5:
122 worker = new JNILongWorker(size);
123 break;
124 case 6:
125 worker = new JNIFloatWorker(size);
126 break;
127 case 7:
128 worker = new JNIDoubleWorker(size);
129 break;
130 }
131 return worker;
132 }
133
134 int random(int maxSize) {
135 int res = LocalRandom.nextInt(maxSize);
136 return res > 128 ? res : 128;
137 }
138
139 public static Object tmp;
140
141 class GarbageProducer implements Runnable {
142
143 private int maxSize;
144 ExecutionController stresser;
145 DefaultProducer gp;
146
147 GarbageProducer(int size) {
148 this.maxSize = size;
149 gp = new DefaultProducer();
150 }
151
152 public void run() {
153 if (stresser == null) {
154 stresser = getExecutionController();
155 }
156
157 while (stresser.continueExecution()) {
158 try {
159 tmp = gp.create(random(maxSize));
160 } catch (OutOfMemoryError oome) {
161 // Do nothing.
162 }
163 }
164 }
165 }
166
167 abstract class JNIAbstractWorker extends JNIWorker implements Runnable {
168
169 ExecutionController stresser;
170 private int maxSize;
171
172 public JNIAbstractWorker(int maxSize) {
173 this.maxSize = maxSize;
174 }
175
176 public void check(boolean condition, String message) {
177 if (!condition) {
178 throw new Error(message);
179 }
180 }
181
182 abstract void doit(int size);
183
184 public void run() {
185 // create array with random elements
186 // store min and max element for further check
187 // create new string
188 // call JNI methods
189 // check min/max as sort result
190 // check string hash
191
192 if (stresser == null) {
193 stresser = getExecutionController();
194 }
195 while (stresser.continueExecution()) {
196 // let make at least several values for long/float
197 try {
198 doit(random(maxSize));
199 } catch (OutOfMemoryError oome) {
200 // Do nothing.
201 }
202 }
203 }
204 }
205
206 // BYTE
207 class JNIBooleanWorker extends JNIAbstractWorker {
208
209 BooleanArrayProducer gp = new BooleanArrayProducer();
210
211 public JNIBooleanWorker(int size) {
212 super(size);
213 }
214
215 void doit(int size) {
216
217 boolean[] array = gp.create(size);
218 // just to be sure that we have true & false
219 array[0] = true;
220 array[array.length - 1] = false;
221 String str = "unsupported";
222 int nativeHash = NativeCall(array, str);
223 int javaHash = 0;
224 for (int i = 0; i < str.length(); ++i) {
225 javaHash += (int) str.charAt(i);
226 }
227 javaHash += javaHash;
228 check(array[0] == false && array[array.length - 1] == true
229 && javaHash == nativeHash, "Data validation failure");
230
231 }
232 }
233
234 class JNIByteWorker extends JNIAbstractWorker {
235
236 ByteArrayProducer gp = new ByteArrayProducer();
237
238 public JNIByteWorker(int size) {
239 super(size);
240 }
241
242 void doit(int size) {
243
244 byte[] array = gp.create(size);
245 byte min = Byte.MAX_VALUE, max = Byte.MIN_VALUE;
246 for (int i = 0; i < array.length; ++i) {
247 if (array[i] > max) {
248 max = array[i];
249 }
250
251 if (array[i] < min) {
252 min = array[i];
253 }
254 }
255 String str = "Min: " + min + " Max: " + max;
256 int nativeHash = NativeCall(array, str);
257 int javaHash = 0;
258 for (int i = 0; i < str.length(); ++i) {
259 javaHash += (int) str.charAt(i);
260 }
261 javaHash += javaHash;
262 check(array[0] == min && array[array.length - 1] == max
263 && javaHash == nativeHash, "Data validation failure");
264
265 }
266 }
267
268 // CHAR
269 class JNICharWorker extends JNIAbstractWorker {
270
271 CharArrayProducer gp = new CharArrayProducer();
272
273 public JNICharWorker(int size) {
274 super(size);
275 }
276
277 void doit(int size) {
278 char[] array = gp.create(size);
279 char min = 0xffff, max = 0;
280 for (int i = 0; i < array.length; ++i) {
281 array[i] = (char) LocalRandom.nextInt();
282 if (array[i] > max) {
283 max = array[i];
284 }
285
286 if (array[i] < min) {
287 min = array[i];
288 }
289 }
290 String str = "Min: " + min + " Max: " + max;
291 int nativeHash = NativeCall(array, str);
292 int javaHash = 0;
293 for (int i = 0; i < str.length(); ++i) {
294 javaHash += (int) str.charAt(i);
295 }
296 javaHash += javaHash;
297 check(array[0] == min && array[array.length - 1] == max
298 && javaHash == nativeHash, "Data validation failure");
299
300 }
301 }
302
303 // SHORT
304 class JNIShortWorker extends JNIAbstractWorker {
305
306 ShortArrayProducer gp = new ShortArrayProducer();
307
308 public JNIShortWorker(int size) {
309 super(size);
310 }
311
312 void doit(int size) {
313
314 short[] array = gp.create(size);
315 short min = Short.MAX_VALUE, max = Short.MIN_VALUE;
316 for (int i = 0; i < array.length; ++i) {
317 if (array[i] > max) {
318 max = array[i];
319 }
320
321 if (array[i] < min) {
322 min = array[i];
323 }
324 }
325 String str = "Min: " + min + " Max: " + max;
326 int nativeHash = NativeCall(array, str);
327 int javaHash = 0;
328 for (int i = 0; i < str.length(); ++i) {
329 javaHash += (int) str.charAt(i);
330 }
331 javaHash += javaHash;
332 check(array[0] == min && array[array.length - 1] == max
333 && javaHash == nativeHash, "Data validation failure");
334 }
335 }
336
337 // INT
338 class JNIIntWorker extends JNIAbstractWorker {
339
340 IntArrayProducer gp = new IntArrayProducer();
341
342 public JNIIntWorker(int size) {
343 super(size);
344 }
345
346 void doit(int size) {
347 int[] array = gp.create(size);
348 int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE;
349 for (int i = 0; i < array.length; ++i) {
350 if (array[i] > max) {
351 max = array[i];
352 }
353
354 if (array[i] < min) {
355 min = array[i];
356 }
357 }
358 String str = "Min: " + min + " Max: " + max;
359 int nativeHash = NativeCall(array, str);
360 int javaHash = 0;
361 for (int i = 0; i < str.length(); ++i) {
362 javaHash += (int) str.charAt(i);
363 }
364 javaHash += javaHash;
365 check(array[0] == min && array[array.length - 1] == max
366 && javaHash == nativeHash, "Data validation failure");
367
368 }
369 }
370
371 // LONG
372 class JNILongWorker extends JNIAbstractWorker {
373
374 LongArrayProducer gp = new LongArrayProducer();
375
376 public JNILongWorker(int size) {
377 super(size);
378 }
379
380 void doit(int size) {
381
382 long[] array = gp.create(size);
383 long min = Long.MAX_VALUE, max = Long.MIN_VALUE;
384 for (int i = 0; i < array.length; ++i) {
385 if (array[i] > max) {
386 max = array[i];
387 }
388
389 if (array[i] < min) {
390 min = array[i];
391 }
392 }
393 String str = "Min: " + min + " Max: " + max;
394 int nativeHash = NativeCall(array, str);
395 int javaHash = 0;
396 for (int i = 0; i < str.length(); ++i) {
397 javaHash += (int) str.charAt(i);
398 }
399 javaHash += javaHash;
400 check(array[0] == min && array[array.length - 1] == max
401 && javaHash == nativeHash, "Data validation failure");
402
403 }
404 }
405
406 // FLOAT
407 class JNIFloatWorker extends JNIAbstractWorker {
408
409 FloatArrayProducer gp = new FloatArrayProducer();
410
411 public JNIFloatWorker(int size) {
412 super(size);
413 }
414
415 void doit(int size) {
416
417 float[] array = gp.create(size);
418 float min = Float.MAX_VALUE, max = Float.MIN_VALUE;
419 for (int i = 0; i < array.length; ++i) {
420 if (array[i] > max) {
421 max = array[i];
422 }
423
424 if (array[i] < min) {
425 min = array[i];
426 }
427 }
428 String str = "Min: " + min + " Max: " + max;
429 int nativeHash = NativeCall(array, str);
430 int javaHash = 0;
431 for (int i = 0; i < str.length(); ++i) {
432 javaHash += (int) str.charAt(i);
433 }
434 javaHash += javaHash;
435 check(array[0] == min && array[array.length - 1] == max
436 && javaHash == nativeHash, "Data validation failure");
437 }
438 }
439
440 // DOUBLE
441 class JNIDoubleWorker extends JNIAbstractWorker {
442
443 DoubleArrayProducer gp = new DoubleArrayProducer();
444
445 public JNIDoubleWorker(int size) {
446 super(size);
447 }
448
449 void doit(int size) {
450
451 double[] array = gp.create(size);
452 double min = Double.MAX_VALUE, max = Double.MIN_VALUE;
453 for (int i = 0; i < array.length; ++i) {
454 if (array[i] > max) {
455 max = array[i];
456 }
457
458 if (array[i] < min) {
459 min = array[i];
460 }
461 }
462 String str = "Min: " + min + " Max: " + max;
463 int nativeHash = NativeCall(array, str);
464 int javaHash = 0;
465 for (int i = 0; i < str.length(); ++i) {
466 javaHash += (int) str.charAt(i);
467 }
468 javaHash += javaHash;
469 check(array[0] == min && array[array.length - 1] == max
470 && javaHash == nativeHash, "Data validation failure");
471 }
472 }
473 }
474
475 class JNIWorker {
476
477 protected native int NativeCall(boolean[] array, String str);
478
479 protected native int NativeCall(byte[] array, String str);
480
481 protected native int NativeCall(char[] array, String str);
482
483 protected native int NativeCall(short[] array, String str);
484
485 protected native int NativeCall(int[] array, String str);
486
487 protected native int NativeCall(long[] array, String str);
488
489 protected native int NativeCall(float[] array, String str);
490
491 protected native int NativeCall(double[] array, String str);
492 }