blob: 448e7f0180debbb7a7c8cfeeff85ad9b38452b5d [file] [log] [blame]
/*
* 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);
}