| /* |
| * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| |
| /* |
| * @test |
| * @key stress |
| * |
| * @summary converted from VM testbase nsk/stress/jni/gclocker/gcl001. |
| * VM testbase keywords: [stress, quick, feature_283, nonconcurrent, exclude] |
| * VM testbase comments: 8208207 |
| * VM testbase readme: |
| * DESCRIPTION |
| * Check compatibility of GC Locker improvements with JNI CS |
| * Two types of concurrent threads are present: |
| * A) Create N 'JNI CS' threads. Each of them will: |
| * 1. Create primitive array and string with random data |
| * 2. Pass it to native method |
| * 3. Sort/Hash data in JNI CS mixing string and array critical sections |
| * 4. Check isCopy == false |
| * 5. Return from native |
| * 6. Check data to be processed correctly |
| * B) Create M ' Garbage producer/memory allocation' threads. Each of them will: |
| * 1. Allocate memory blocks and make them garbage. |
| * 2. Check for OOM errors. |
| * |
| * @library /vmTestbase |
| * /test/lib |
| * @run driver jdk.test.lib.FileInstaller . . |
| * @ignore 8208207 |
| * @run main/othervm/native/timeout=480 |
| * -XX:-UseGCOverheadLimit |
| * nsk.stress.jni.gclocker.gcl001 |
| * -stressThreadsFactor 8 |
| */ |
| |
| package nsk.stress.jni.gclocker; |
| |
| import nsk.share.gc.GC; |
| import nsk.share.gc.ThreadedGCTest; |
| import nsk.share.gc.gp.array.BooleanArrayProducer; |
| import nsk.share.gc.gp.array.ByteArrayProducer; |
| import nsk.share.gc.gp.array.CharArrayProducer; |
| import nsk.share.gc.gp.array.DoubleArrayProducer; |
| import nsk.share.gc.gp.array.FloatArrayProducer; |
| import nsk.share.gc.gp.array.IntArrayProducer; |
| import nsk.share.gc.gp.array.LongArrayProducer; |
| import nsk.share.gc.gp.array.ShortArrayProducer; |
| import nsk.share.test.ExecutionController; |
| import nsk.share.test.LocalRandom; |
| |
| import java.util.Random; |
| |
| public class gcl001 extends ThreadedGCTest { |
| |
| static { |
| System.loadLibrary("gcl001"); |
| } |
| |
| int maxBlockSize; |
| |
| public static void main(String[] args) { |
| GC.runTest(new gcl001(), args); |
| } |
| |
| @Override |
| public void run() { |
| // each thread have only one block at the time |
| // so we should occupy less then 60% of heap with live objects |
| long maxSize = runParams.getTestMemory() / runParams.getNumberOfThreads(); |
| if (maxSize > Integer.MAX_VALUE - 1) { |
| maxSize = Integer.MAX_VALUE - 1; |
| } |
| maxBlockSize = (int) maxSize; |
| log.info("Maximium block size = " + maxBlockSize); |
| super.run(); |
| } |
| |
| @Override |
| protected Runnable createRunnable(int i) { |
| if (i < runParams.getNumberOfThreads() / 2) { |
| return CreateJNIWorker(i, maxBlockSize); |
| } else { |
| return new GarbageProducer(maxBlockSize); |
| } |
| } |
| |
| public Runnable CreateJNIWorker(int number, int size) { |
| JNIAbstractWorker worker = null; |
| switch (number % 8) { |
| case 0: |
| worker = new JNIBooleanWorker(size); |
| break; |
| case 1: |
| worker = new JNIByteWorker(size); |
| break; |
| case 2: |
| worker = new JNICharWorker(size); |
| break; |
| case 3: |
| worker = new JNIShortWorker(size); |
| break; |
| case 4: |
| worker = new JNIIntWorker(size); |
| break; |
| case 5: |
| worker = new JNILongWorker(size); |
| break; |
| case 6: |
| worker = new JNIFloatWorker(size); |
| break; |
| case 7: |
| worker = new JNIDoubleWorker(size); |
| break; |
| } |
| return worker; |
| } |
| |
| int random(int maxSize) { |
| int res = LocalRandom.nextInt(maxSize); |
| return res > 128 ? res : 128; |
| } |
| |
| public static Object tmp; |
| |
| class GarbageProducer implements Runnable { |
| |
| private int maxSize; |
| ExecutionController stresser; |
| ByteArrayProducer bp; |
| |
| GarbageProducer(int size) { |
| this.maxSize = size; |
| bp = new ByteArrayProducer(); |
| } |
| |
| public void run() { |
| if (stresser == null) { |
| stresser = getExecutionController(); |
| } |
| |
| while (stresser.continueExecution()) { |
| try { |
| byte[] arr = bp.create(random(maxSize)); |
| tmp = arr; |
| } catch (OutOfMemoryError oome) { |
| // Do nothing. |
| } |
| } |
| } |
| } |
| |
| abstract class JNIAbstractWorker extends JNIWorker implements Runnable { |
| |
| ExecutionController stresser; |
| private int maxSize; |
| |
| public JNIAbstractWorker(int maxSize) { |
| this.maxSize = maxSize; |
| } |
| |
| public void check(boolean condition, String message) { |
| if (!condition) { |
| throw new Error(message); |
| } |
| } |
| |
| abstract void doit(int size); |
| |
| public void run() { |
| // create array with random elements |
| // store min and max element for further check |
| // create new string |
| // call JNI methods |
| // check min/max as sort result |
| // check string hash |
| |
| if (stresser == null) { |
| stresser = getExecutionController(); |
| } |
| while (stresser.continueExecution()) { |
| // let make at least several values for long/float |
| try { |
| doit(random(maxSize)); |
| } catch (OutOfMemoryError oome) { |
| // Do nothing. |
| } |
| } |
| } |
| } |
| |
| // BYTE |
| class JNIBooleanWorker extends JNIAbstractWorker { |
| |
| BooleanArrayProducer gp = new BooleanArrayProducer(); |
| |
| public JNIBooleanWorker(int size) { |
| super(size); |
| } |
| |
| void doit(int size) { |
| |
| boolean[] array = gp.create(size); |
| // just to be sure that we have true & false |
| array[0] = true; |
| array[array.length - 1] = false; |
| String str = "unsupported"; |
| int nativeHash = NativeCall(array, str); |
| int javaHash = 0; |
| for (int i = 0; i < str.length(); ++i) { |
| javaHash += (int) str.charAt(i); |
| } |
| check(array[0] == false && array[array.length - 1] == true |
| && javaHash == nativeHash, "Data validation failure"); |
| |
| } |
| } |
| |
| class JNIByteWorker extends JNIAbstractWorker { |
| |
| ByteArrayProducer gp = new ByteArrayProducer(); |
| |
| public JNIByteWorker(int size) { |
| super(size); |
| } |
| |
| void doit(int size) { |
| |
| byte[] array = gp.create(size); |
| byte min = Byte.MAX_VALUE, max = Byte.MIN_VALUE; |
| for (int i = 0; i < array.length; ++i) { |
| if (array[i] > max) { |
| max = array[i]; |
| } |
| |
| if (array[i] < min) { |
| min = array[i]; |
| } |
| } |
| String str = "Min: " + min + " Max: " + max; |
| int nativeHash = NativeCall(array, str); |
| int javaHash = 0; |
| for (int i = 0; i < str.length(); ++i) { |
| javaHash += (int) str.charAt(i); |
| } |
| |
| check(array[0] == min && array[array.length - 1] == max |
| && javaHash == nativeHash, "Data validation failure"); |
| |
| } |
| } |
| |
| // CHAR |
| class JNICharWorker extends JNIAbstractWorker { |
| |
| CharArrayProducer gp = new CharArrayProducer(); |
| |
| public JNICharWorker(int size) { |
| super(size); |
| } |
| |
| void doit(int size) { |
| char[] array = gp.create(size); |
| Random rand = new Random(); |
| char min = 0xffff, max = 0; |
| for (int i = 0; i < array.length; ++i) { |
| array[i] = (char) rand.nextInt(); |
| if (array[i] > max) { |
| max = array[i]; |
| } |
| |
| if (array[i] < min) { |
| min = array[i]; |
| } |
| } |
| String str = "Min: " + min + " Max: " + max; |
| int nativeHash = NativeCall(array, str); |
| int javaHash = 0; |
| for (int i = 0; i < str.length(); ++i) { |
| javaHash += (int) str.charAt(i); |
| } |
| |
| check(array[0] == min && array[array.length - 1] == max |
| && javaHash == nativeHash, "Data validation failure"); |
| |
| } |
| } |
| |
| // SHORT |
| class JNIShortWorker extends JNIAbstractWorker { |
| |
| ShortArrayProducer gp = new ShortArrayProducer(); |
| |
| public JNIShortWorker(int size) { |
| super(size); |
| } |
| |
| void doit(int size) { |
| |
| short[] array = gp.create(size); |
| short min = Short.MAX_VALUE, max = Short.MIN_VALUE; |
| for (int i = 0; i < array.length; ++i) { |
| if (array[i] > max) { |
| max = array[i]; |
| } |
| |
| if (array[i] < min) { |
| min = array[i]; |
| } |
| } |
| String str = "Min: " + min + " Max: " + max; |
| int nativeHash = NativeCall(array, str); |
| int javaHash = 0; |
| for (int i = 0; i < str.length(); ++i) { |
| javaHash += (int) str.charAt(i); |
| } |
| |
| check(array[0] == min && array[array.length - 1] == max |
| && javaHash == nativeHash, "Data validation failure"); |
| } |
| } |
| |
| // INT |
| class JNIIntWorker extends JNIAbstractWorker { |
| |
| IntArrayProducer gp = new IntArrayProducer(); |
| |
| public JNIIntWorker(int size) { |
| super(size); |
| } |
| |
| void doit(int size) { |
| int[] array = gp.create(size); |
| int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE; |
| for (int i = 0; i < array.length; ++i) { |
| if (array[i] > max) { |
| max = array[i]; |
| } |
| |
| if (array[i] < min) { |
| min = array[i]; |
| } |
| } |
| String str = "Min: " + min + " Max: " + max; |
| int nativeHash = NativeCall(array, str); |
| int javaHash = 0; |
| for (int i = 0; i < str.length(); ++i) { |
| javaHash += (int) str.charAt(i); |
| } |
| |
| check(array[0] == min && array[array.length - 1] == max |
| && javaHash == nativeHash, "Data validation failure"); |
| |
| } |
| } |
| |
| // LONG |
| class JNILongWorker extends JNIAbstractWorker { |
| |
| LongArrayProducer gp = new LongArrayProducer(); |
| |
| public JNILongWorker(int size) { |
| super(size); |
| } |
| |
| void doit(int size) { |
| |
| long[] array = gp.create(size); |
| long min = Long.MAX_VALUE, max = Long.MIN_VALUE; |
| for (int i = 0; i < array.length; ++i) { |
| if (array[i] > max) { |
| max = array[i]; |
| } |
| |
| if (array[i] < min) { |
| min = array[i]; |
| } |
| } |
| String str = "Min: " + min + " Max: " + max; |
| int nativeHash = NativeCall(array, str); |
| int javaHash = 0; |
| for (int i = 0; i < str.length(); ++i) { |
| javaHash += (int) str.charAt(i); |
| } |
| |
| check(array[0] == min && array[array.length - 1] == max |
| && javaHash == nativeHash, "Data validation failure"); |
| |
| } |
| } |
| |
| // FLOAT |
| class JNIFloatWorker extends JNIAbstractWorker { |
| |
| FloatArrayProducer gp = new FloatArrayProducer(); |
| |
| public JNIFloatWorker(int size) { |
| super(size); |
| } |
| |
| void doit(int size) { |
| |
| float[] array = gp.create(size); |
| float min = Float.MAX_VALUE, max = Float.MIN_VALUE; |
| for (int i = 0; i < array.length; ++i) { |
| if (array[i] > max) { |
| max = array[i]; |
| } |
| |
| if (array[i] < min) { |
| min = array[i]; |
| } |
| } |
| String str = "Min: " + min + " Max: " + max; |
| int nativeHash = NativeCall(array, str); |
| int javaHash = 0; |
| for (int i = 0; i < str.length(); ++i) { |
| javaHash += (int) str.charAt(i); |
| } |
| |
| check(array[0] == min && array[array.length - 1] == max |
| && javaHash == nativeHash, "Data validation failure"); |
| } |
| } |
| |
| // DOUBLE |
| class JNIDoubleWorker extends JNIAbstractWorker { |
| |
| DoubleArrayProducer gp = new DoubleArrayProducer(); |
| |
| public JNIDoubleWorker(int size) { |
| super(size); |
| } |
| |
| void doit(int size) { |
| |
| double[] array = gp.create(size); |
| Random rand = new Random(); |
| double min = Double.MAX_VALUE, max = Double.MIN_VALUE; |
| for (int i = 0; i < array.length; ++i) { |
| if (array[i] > max) { |
| max = array[i]; |
| } |
| |
| if (array[i] < min) { |
| min = array[i]; |
| } |
| } |
| String str = "Min: " + min + " Max: " + max; |
| int nativeHash = NativeCall(array, str); |
| int javaHash = 0; |
| for (int i = 0; i < str.length(); ++i) { |
| javaHash += (int) str.charAt(i); |
| } |
| |
| check(array[0] == min && array[array.length - 1] == max |
| && javaHash == nativeHash, "Data validation failure"); |
| } |
| } |
| } |
| |
| class JNIWorker { |
| |
| protected native int NativeCall(boolean[] array, String str); |
| |
| protected native int NativeCall(byte[] array, String str); |
| |
| protected native int NativeCall(char[] array, String str); |
| |
| protected native int NativeCall(short[] array, String str); |
| |
| protected native int NativeCall(int[] array, String str); |
| |
| protected native int NativeCall(long[] array, String str); |
| |
| protected native int NativeCall(float[] array, String str); |
| |
| protected native int NativeCall(double[] array, String str); |
| } |