mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-14 09:53:18 +00:00
8199271: [TESTBUG] open source VM testbase stress tests
Reviewed-by: mseledtsov, sspitsyn, erikj
This commit is contained in:
parent
072459a055
commit
5dcd1ced4c
@ -109,6 +109,13 @@ NSK_GC_LOCK_REF_INCLUDES := \
|
||||
-I$(VM_TESTBASE_DIR)/nsk/share/native \
|
||||
-I$(VM_TESTBASE_DIR)/nsk/share/jni
|
||||
|
||||
NSK_STRACE_INCLUDES := \
|
||||
-I$(VM_TESTBASE_DIR)/nsk/share/native \
|
||||
-I$(VM_TESTBASE_DIR)/nsk/share/jni
|
||||
|
||||
NSK_STRESS_JNI_INCLUDES := \
|
||||
-I$(VM_TESTBASE_DIR)/nsk/stress/jni
|
||||
|
||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libProcessUtils := $(VM_SHARE_INCLUDES)
|
||||
|
||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libThreadController := $(NSK_MONITORING_INCLUDES)
|
||||
@ -150,6 +157,20 @@ BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libJNILocalRefLocker := $(NSK_GC_LOCK_REF_I
|
||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libJNIRefLocker := $(NSK_GC_LOCK_REF_INCLUDES)
|
||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libJNIWeakGlobalRefLocker := $(NSK_GC_LOCK_REF_INCLUDES)
|
||||
|
||||
|
||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace003 := $(NSK_STRACE_INCLUDES)
|
||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace004 := $(NSK_STRACE_INCLUDES)
|
||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace005 := $(NSK_STRACE_INCLUDES)
|
||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace006 := $(NSK_STRACE_INCLUDES)
|
||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace008 := $(NSK_STRACE_INCLUDES)
|
||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace009 := $(NSK_STRACE_INCLUDES)
|
||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace011 := $(NSK_STRACE_INCLUDES)
|
||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace012 := $(NSK_STRACE_INCLUDES)
|
||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace014 := $(NSK_STRACE_INCLUDES)
|
||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace015 := $(NSK_STRACE_INCLUDES)
|
||||
|
||||
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgcl001 := $(NSK_STRESS_JNI_INCLUDES)
|
||||
|
||||
################################################################################
|
||||
|
||||
# Platform specific setup
|
||||
|
||||
@ -1157,6 +1157,9 @@ vmTestbase_nsk_jdi_quick = \
|
||||
vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues002/getArgumentValues002.java \
|
||||
vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues003/getArgumentValues003.java
|
||||
|
||||
vmTestbase_nsk_stress = \
|
||||
vmTestbase/nsk/stress
|
||||
|
||||
vmTestbase_vm_g1classunloading = \
|
||||
vmTestbase/gc/g1/unloading/tests
|
||||
|
||||
@ -1264,4 +1267,3 @@ vmTestbase_vm_heapdump_quick = \
|
||||
vmTestbase/heapdump/OnOOMToPath/TestDescription.java \
|
||||
vmTestbase/heapdump/JMapHeapCore/TestDescription.java \
|
||||
vmTestbase/heapdump/JMapMetaspace/TestDescription.java
|
||||
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
#
|
||||
# Copyright (c) 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.
|
||||
#
|
||||
|
||||
exclusiveAccess.dirs=.
|
||||
291
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except001.java
Normal file
291
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except001.java
Normal file
@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/except/except001.
|
||||
* VM testbase keywords: [stress, diehard, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This checks if OutOfMemoryError exception is correctly enwrapped into
|
||||
* InvocationTargetException when thrown inside a method invoked via
|
||||
* reflection.
|
||||
* The test tries to occupy all of memory available in the heap by
|
||||
* allocating lots of new Object() instances. Instances of the "empty"
|
||||
* type Object are the smallest objects, so they apparently should occupy
|
||||
* most fine-grained fragments in the heap. Thus, there apparently should
|
||||
* not remain any free space to incarnate new Throwable instance, and VM
|
||||
* possibly could crash while trying to throw new OutOfMemoryError and
|
||||
* enwrap it into new InvocationTargetException instance.
|
||||
* By the way, the test checks time elapsed to allocate memory. Both
|
||||
* classic VM and HotSpot seem to fall into poor performance of memory
|
||||
* allocation when heap is almost over. E.g.: HotSpot 1.3-betaH may spend
|
||||
* more than 1 minute to allocate next Object in this case (tested on
|
||||
* Pentium-II, 350MHz, 128Mb RAM). To avoid this problem, the test enforce
|
||||
* OutOfMemoryError if more then 5 minutes is spent to allocate "last bytes"
|
||||
* of memory.
|
||||
* COMMENTS
|
||||
* HotSpot releases 1.0-fcsE (both Win32 and Sparc), and 1.3-betaH (Win32)
|
||||
* fail on this test due to poor performance of memory allocation.
|
||||
* #4248801 (P3/S5) slow memory allocation when heap is almost exhausted
|
||||
* Despite this bug is treated fixed in HotSpot 1.0.1, it still does suffer
|
||||
* slow memory allocation when running on PC having 64Mb or less of RAM.
|
||||
* There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance (HotSpot bug)
|
||||
* #4245060 (P4/S5) poor garbage collector performance (Classic VM bug)
|
||||
* However, printing of the test's error messages, warnings, and of execution
|
||||
* trace may fail under JDK 1.2 for Win32 even so.
|
||||
* HotSpot 2.0-devA (Win32) crashes due to the known HotSpot bug:
|
||||
* #4239828 (P1/S4) 1.3c1: VM crashes when heap is exhausted
|
||||
*
|
||||
* @run main/othervm -Xms50M -Xmx200M nsk.stress.except.except001
|
||||
*/
|
||||
|
||||
package nsk.stress.except;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* This checks if <code>OutOfMemoryError</code> exception is correctly
|
||||
* enwrapped into <code>InvocationTargetException</code> when thrown inside
|
||||
* a method invoked via reflection.
|
||||
* <p>
|
||||
* <p>The test tries to occupy all of memory available in the heap by
|
||||
* allocating lots of new <code>Object()</code> instances. Instances of the
|
||||
* ``empty'' type <code>Object</code> are the smallest objects, so they
|
||||
* apparently should occupy most fine-grained fragments in the heap.
|
||||
* Thus, there apparently should not remain any free space to incarnate new
|
||||
* <code>Throwable</code> instance, and VM possibly could crash while trying
|
||||
* to throw new <code>OutOfMemoryError</code> and enwrap it into new
|
||||
* <code>InvocationTargetException</code> instance.
|
||||
* <p>
|
||||
* <p>By the way, the test checks time elapsed to allocate memory.
|
||||
* Both classic VM and HotSpot seem to fall into poor performance of memory
|
||||
* allocation when heap is almost over. E.g.: HotSpot 1.3-betaH may spend
|
||||
* more than 1 minute to allocate next <code>Object</code> in this case
|
||||
* (tested on Pentium-II, 350MHz, 128Mb RAM). To workaround this problem,
|
||||
* the test enforces <code>OutOfMemoryError</code> if more then 5 minutes
|
||||
* is spent to allocate ``last bytes'' of the memory.
|
||||
*/
|
||||
public class except001 {
|
||||
/**
|
||||
* This field allows or supresses printing with <code>display()</code>
|
||||
* method.
|
||||
*
|
||||
* @see #display(Object)
|
||||
* @see #complain(Object)
|
||||
* @see #out
|
||||
*/
|
||||
private static boolean MODE_VERBOSE = true;
|
||||
/*
|
||||
* Storage for a lot of tiny objects
|
||||
* "static volatile" keywords are for preventing heap optimization
|
||||
*/
|
||||
private static volatile Object pool[] = null;
|
||||
|
||||
/**
|
||||
* Print execution trace if <code>MODE_VERBOSE</code> is <code>true</code>
|
||||
* (optional).
|
||||
*
|
||||
* @see #MODE_VERBOSE
|
||||
* @see #complain(Object)
|
||||
* @see #out
|
||||
*/
|
||||
private static void display(Object message) {
|
||||
if (MODE_VERBOSE)
|
||||
out.println(message.toString());
|
||||
out.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print error <code>message</code>.
|
||||
*
|
||||
* @see #display(Object)
|
||||
* @see #out
|
||||
*/
|
||||
private static void complain(Object message) {
|
||||
out.println("# " + message);
|
||||
out.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* The log-stream assigned at runtime by the method
|
||||
* <code>run(args,out)</code>.
|
||||
*
|
||||
* @see #display(Object)
|
||||
* @see #complain(Object)
|
||||
* @see #run(String[], PrintStream)
|
||||
*/
|
||||
private static PrintStream out;
|
||||
|
||||
/**
|
||||
* Try to allocate lots of instances of the type <code>Object</code>.
|
||||
* Such instances are most fine-grained, and thus they should occupy
|
||||
* smallest fragments of free memory in the heap.
|
||||
* <p>
|
||||
* <p>By the way, break the test, if JVM has spent more than
|
||||
* 5 minutes to allocate latest portions of memory.
|
||||
*/
|
||||
public static void raiseOutOfMemory() throws OutOfMemoryError {
|
||||
try {
|
||||
// Repository for objects, which should be allocated:
|
||||
int index = 0;
|
||||
for (int size = 1 << 30; size > 0 && pool == null; size >>= 1)
|
||||
try {
|
||||
pool = new Object[size];
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
if (pool == null)
|
||||
throw new Error("HS bug: cannot allocate new Object[1]");
|
||||
|
||||
// Sum up time spent, when it was hard to JVM to allocate next object
|
||||
// (i.e.: when JVM has spent more than 1 second to allocate new object):
|
||||
double totalDelay = 0;
|
||||
long timeMark = System.currentTimeMillis();
|
||||
|
||||
for (; index < pool.length; index++) {
|
||||
//-------------------------
|
||||
pool[index] = new Object();
|
||||
long nextTimeMark = System.currentTimeMillis();
|
||||
long elapsed = nextTimeMark - timeMark;
|
||||
timeMark = nextTimeMark;
|
||||
//----------------------
|
||||
if (elapsed > 1000) {
|
||||
double seconds = elapsed / 1000.0;
|
||||
display(
|
||||
"pool[" + index +
|
||||
"]=new Object(); // elapsed " + seconds + "s");
|
||||
totalDelay += seconds;
|
||||
if (totalDelay > 300) {
|
||||
complain(
|
||||
"Memory allocation became slow: so heap seems exhausted.");
|
||||
throw new OutOfMemoryError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This method should never return:
|
||||
throw new Error("TEST_BUG: failed to provoke OutOfMemoryError");
|
||||
} finally {
|
||||
// Make sure there will be enough memory for next object allocation
|
||||
pool = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the method <code>raiseOutOfMemory()</code> with reflection,
|
||||
* and check if the exception it throws is just
|
||||
* <code>OutOfMemoryError</code> enwrapped into
|
||||
* <code>InvocationTargetException</code> instance.
|
||||
* <p>
|
||||
* <p>Before the test begins, <code>this.out</code> filed is assigned
|
||||
* to the parameter <code>out</code>. Parameter <code>args[]</code>
|
||||
* is ignored.
|
||||
*
|
||||
* @see #raiseOutOfMemory()
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
out.println("# While printing this message, JVM seems to initiate the output");
|
||||
out.println("# stream, so that it will not need more memory to print later,");
|
||||
out.println("# when the heap would fail to provide more memory.");
|
||||
out.println("# ");
|
||||
out.println("# That problem is caused by the known JDK/HotSpot bugs:");
|
||||
out.println("# 4239841 (P1/S5) 1.1: poor garbage collector performance");
|
||||
out.println("# 4245060 (P4/S5) poor garbage collector performance");
|
||||
out.println("# ");
|
||||
out.println("# This message is just intended to work-around that problem.");
|
||||
out.println("# If printing should fail even so.");
|
||||
|
||||
if (args.length > 0) {
|
||||
if (args[0].toLowerCase().startsWith("-v"))
|
||||
MODE_VERBOSE = true;
|
||||
}
|
||||
|
||||
except001.out = out;
|
||||
Class testClass = except001.class;
|
||||
try {
|
||||
Method testMethod = testClass.getMethod("raiseOutOfMemory", new Class [0]);
|
||||
Object junk = testMethod.invoke(null, new Object [0]);
|
||||
|
||||
} catch (InvocationTargetException ite) {
|
||||
Throwable targetException = ite.getTargetException();
|
||||
if (targetException instanceof OutOfMemoryError) {
|
||||
display("OutOfMemoryError thrown as expected.");
|
||||
display("Test passed.");
|
||||
return 0;
|
||||
}
|
||||
complain("Unexpected InvocationTargetException: " + targetException);
|
||||
complain("Test failed.");
|
||||
return 2;
|
||||
|
||||
} catch (Exception exception) {
|
||||
complain("Unexpected exception: " + exception);
|
||||
complain("Test failed.");
|
||||
return 2;
|
||||
}
|
||||
//
|
||||
complain("The test has finished unexpectedly.");
|
||||
complain("Test failed.");
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-call to <code>run(args,out)</code>, and return JCK-like exit status.
|
||||
* (The stream <code>out</code> is assigned to <code>System.out</code> here.)
|
||||
*
|
||||
* @see #run(String[], PrintStream)
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||
// Last try. If there is some exception outside the code, test should end correctly
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
try {
|
||||
pool = null;
|
||||
System.gc();
|
||||
if (e instanceof OutOfMemoryError) {
|
||||
try {
|
||||
System.out.println("OOME : Test Skipped");
|
||||
System.exit(95);
|
||||
} catch (Throwable ignore) {
|
||||
} // No code in the handler can provoke correct exceptions.
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
throw (RuntimeException) e;
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
}
|
||||
});
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status.
|
||||
}
|
||||
|
||||
}
|
||||
301
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except002.java
Normal file
301
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except002.java
Normal file
@ -0,0 +1,301 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/except/except002.
|
||||
* VM testbase keywords: [stress, diehard, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* Throwable instance.
|
||||
* The test tries to occupy all of memory available in the heap by allocating
|
||||
* lots of new Object() instances. Instances of the type Object are the smallest
|
||||
* objects, so they apparently should occupy most fine-grained fragments in the
|
||||
* heap and leave no free space for new Throwable instance. After that, the test
|
||||
* provokes various exceptions (e.g.: by executing integer division by 0 and so
|
||||
* on), and checks if appropriate exceptions are thrown.
|
||||
* COMMENTS
|
||||
* The test needs a lot of memory to start up, so it should not run under older
|
||||
* JDK 1.1.x release due to its poorer heap utilization. Also, some checks are
|
||||
* skipped when testing classic VM, because OutOfMemoryError is correctly thrown
|
||||
* instead of target exception.
|
||||
* When the test is being self-initiating (i.e.: eating heap), memory occupation
|
||||
* is terminated if memory allocation slows down crucially. This is a workaround
|
||||
* intended to avoid the HotSpot bug:
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance (HotSpot bug)
|
||||
* #4245060 (P4/S5) poor garbage collector performance (Classic VM bug)
|
||||
* However, printing of the test's error messages, warnings, and of execution
|
||||
* trace fails under JDK 1.2 for Win32 even so. If the test fails due to this
|
||||
* problem, exit status 96 is returned instead of 97.
|
||||
* JDK 1.3 classic VM for Sparc may crash (core dump) due to the known bug:
|
||||
* #4245057 (P2/S3) VM crashes when heap is exhausted
|
||||
*
|
||||
* @run main/othervm -Xms50M -Xmx200M nsk.stress.except.except002
|
||||
*/
|
||||
|
||||
package nsk.stress.except;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* <code>Throwable</code> instance.
|
||||
* <p>
|
||||
* <p>The test tries to occupy all of memory available in the heap by
|
||||
* allocating lots of new <code>Object()</code> instances. Instances of the
|
||||
* type <code>Object</code> are the smallest objects, so they apparently should
|
||||
* occupy most fine-grained fragments in the heap and leave no free space for
|
||||
* new <code>Throwable</code> instance. After that, the test provokes various
|
||||
* exceptions (e.g.: by executing integer division by 0 and so on), and checks
|
||||
* if appropriate exceptions are thrown.
|
||||
* <p>
|
||||
* <p>Note, that memory occupation is terminated if memory allocation slows
|
||||
* down crucially. This is a workaround intended to avoid the HotSpot bug:
|
||||
* <br>
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* <p>
|
||||
* <p>There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* <br>
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance
|
||||
* <br>
|
||||
* #4245060 (P4/S5) poor garbage collector performance
|
||||
* <br>However, printing of the test's error messages, warnings, and of
|
||||
* execution trace may fail even so. If the test fails due to poor GC
|
||||
* performance, exit status 96 is returned instead of 97.
|
||||
* <p>
|
||||
* <p>Also note, that the test needs a lot of memory to start up, so it should
|
||||
* not run under older JDK 1.1.x release due to its poor heap utilization.
|
||||
*/
|
||||
public class except002 {
|
||||
/**
|
||||
* Either allow or supress printing of execution trace.
|
||||
*/
|
||||
private static boolean TRACE_ON = false;
|
||||
/**
|
||||
* Either allow or supress printing of warning messages.
|
||||
*/
|
||||
private static final boolean WARN_ON = true;
|
||||
/*
|
||||
* Storage for a lot of tiny objects
|
||||
* "static volatile" keywords are for preventing heap optimization
|
||||
*/
|
||||
public static volatile Object pool[] = null;
|
||||
/**
|
||||
* Temporary <code>log</code> for error messages, warnings and/or execution trace.
|
||||
*
|
||||
* @see #messages
|
||||
*/
|
||||
private static String log[] = new String[1000]; // up to 1000 messages
|
||||
/**
|
||||
* How many <code>messages</code> were submitted to the <code>log</code>.
|
||||
*
|
||||
* @see #log
|
||||
*/
|
||||
private static int messages = 0;
|
||||
|
||||
/**
|
||||
* Re-call to the method <code>run(out)</code> (ignore <code>args[]</code>),
|
||||
* and print the test summary - either test passed of failed.
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
if (args.length > 0) {
|
||||
if (args[0].toLowerCase().startsWith("-v"))
|
||||
TRACE_ON = true;
|
||||
}
|
||||
|
||||
int exitCode = run(out);
|
||||
pool = null;
|
||||
System.gc();
|
||||
// Print the log[] and the test summary:
|
||||
try {
|
||||
for (int i = 0; i < messages; i++)
|
||||
out.println(log[i]);
|
||||
if (exitCode == 0) {
|
||||
if (TRACE_ON)
|
||||
out.println("Test passed.");
|
||||
} else
|
||||
out.println("Test failed.");
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Poor performance of garbage collector:
|
||||
exitCode = 1;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate as much <code>Object</code> instances as possible to bring JVM
|
||||
* into stress, and then check if exceptions are correctly thrown accordingly
|
||||
* to various situations like integer division by 0, etc.
|
||||
*/
|
||||
private static int run(PrintStream out) {
|
||||
out.println("# While printing this message, JVM seems to initiate the output");
|
||||
out.println("# stream, so that it will not need more memory to print later,");
|
||||
out.println("# when the heap would fail to provide more memory.");
|
||||
out.println("# ");
|
||||
out.println("# Note, that the test maintains especial static log[] field in");
|
||||
out.println("# order to avoid printing when the heap seems exhausted.");
|
||||
out.println("# Nevertheless, printing could arise OutOfMemoryError even");
|
||||
out.println("# after all the memory allocated by the test is released.");
|
||||
out.println("# ");
|
||||
out.println("# That problem is caused by the known JDK/HotSpot bugs:");
|
||||
out.println("# 4239841 (P1/S5) 1.1: poor garbage collector performance");
|
||||
out.println("# 4245060 (P4/S5) poor garbage collector performance");
|
||||
out.println("# ");
|
||||
out.println("# This message is just intended to work-around that problem.");
|
||||
out.println("# If printing should fail even so, the test will return the");
|
||||
out.println("# exit status 96 instead of 97 to indicate the problem.");
|
||||
|
||||
// Prepare some items, which will be used by the test:
|
||||
Object trash = null;
|
||||
|
||||
// Sum up exit code:
|
||||
int exitCode = 0; // apparently PASSED
|
||||
int skipped = 0; // some checks may correctly suffer OutOfMemoryError
|
||||
// Allocate repository for a lots of tiny objects:
|
||||
for (int size = 1 << 30; size > 0 && pool == null; size >>= 1)
|
||||
try {
|
||||
pool = new Object[size];
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
if (pool == null)
|
||||
throw new Error("HS bug: cannot allocate new Object[1]");
|
||||
int poolSize = pool.length;
|
||||
int index = 0;
|
||||
|
||||
// Sum up time spent, when it was hard to JVM to allocate next object
|
||||
// (i.e.: when JVM has spent more than 1 second to allocate new object):
|
||||
double totalDelay = 0;
|
||||
long timeMark = System.currentTimeMillis();
|
||||
try {
|
||||
for (; index < poolSize; index++) {
|
||||
//-------------------------
|
||||
pool[index] = new Object();
|
||||
long nextTimeMark = System.currentTimeMillis();
|
||||
long elapsed = nextTimeMark - timeMark;
|
||||
timeMark = nextTimeMark;
|
||||
//----------------------
|
||||
if (elapsed > 1000) {
|
||||
double seconds = elapsed / 1000.0;
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"pool[" + index + "]=new Object(); // elapsed " + seconds + "s");
|
||||
totalDelay += seconds;
|
||||
if (totalDelay > 60) {
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"Memory allocation became slow; so, heap seems exhausted.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Heap seems exhausted - OutOfMemoryError thrown.";
|
||||
|
||||
// Do not release any byte once allocated:
|
||||
pool[index++] = oome;
|
||||
}
|
||||
|
||||
if (index > poolSize - 1000) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Warning: pool[] is full; so, checks would not be enough hard...";
|
||||
}
|
||||
|
||||
// Check ClassNotFoundException (positive):
|
||||
try {
|
||||
trash = Class.forName("nsk.stress.except.except002.except002$Abra$Cadabra"); // correct - should pass
|
||||
// trash = Class.forName("nsk.stress.except.except002.except002.Abra.Cadabra"); // incorrect - should fail
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: ClassNotFoundException (positive)";
|
||||
} catch (ClassNotFoundException cnfe) {
|
||||
log[messages++] = "Failure: ClassNotFoundException (positive)";
|
||||
exitCode = 2;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: ClassNotFoundException (positive)";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-call to <code>run(args,out)</code>, and return JCK-like exit status.
|
||||
* (The stream <code>out</code> is assigned to <code>System.out</code> here.)
|
||||
*
|
||||
* @see #run(String[], PrintStream)
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||
// Last try. If there is some exception outside the code, test should end correctly
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
try {
|
||||
pool = null;
|
||||
log = null;
|
||||
System.gc();
|
||||
if (e instanceof OutOfMemoryError) {
|
||||
try {
|
||||
System.out.println("OOME : Test Skipped");
|
||||
System.exit(0);
|
||||
} catch (Throwable ignore) {
|
||||
} // No code in the handler can provoke correct exceptions.
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
throw (RuntimeException) e;
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
}
|
||||
});
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status.
|
||||
}
|
||||
|
||||
/**
|
||||
* This class should be used to check <code>ClassNotFoundException</code>
|
||||
* and <code>IllegalAccessException</code>.
|
||||
*/
|
||||
private static class Abra {
|
||||
/**
|
||||
* Will try to incorrectly find this class as <code>Cadabra</code>
|
||||
* instead of <code>Abra$Cadabra</code>.
|
||||
*/
|
||||
public static class Cadabra {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
302
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except003.java
Normal file
302
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except003.java
Normal file
@ -0,0 +1,302 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/except/except003.
|
||||
* VM testbase keywords: [stress, diehard, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* Throwable instance.
|
||||
* The test tries to occupy all of memory available in the heap by allocating
|
||||
* lots of new Object() instances. Instances of the type Object are the smallest
|
||||
* objects, so they apparently should occupy most fine-grained fragments in the
|
||||
* heap and leave no free space for new Throwable instance. After that, the test
|
||||
* provokes various exceptions (e.g.: by executing integer division by 0 and so
|
||||
* on), and checks if appropriate exceptions are thrown.
|
||||
* COMMENTS
|
||||
* The test needs a lot of memory to start up, so it should not run under older
|
||||
* JDK 1.1.x release due to its poorer heap utilization. Also, some checks are
|
||||
* skipped when testing classic VM, because OutOfMemoryError is correctly thrown
|
||||
* instead of target exception.
|
||||
* When the test is being self-initiating (i.e.: eating heap), memory occupation
|
||||
* is terminated if memory allocation slows down crucially. This is a workaround
|
||||
* intended to avoid the HotSpot bug:
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance (HotSpot bug)
|
||||
* #4245060 (P4/S5) poor garbage collector performance (Classic VM bug)
|
||||
* However, printing of the test's error messages, warnings, and of execution
|
||||
* trace fails under JDK 1.2 for Win32 even so. If the test fails due to this
|
||||
* problem, exit status 96 is returned instead of 97.
|
||||
* JDK 1.3 classic VM for Sparc may crash (core dump) due to the known bug:
|
||||
* #4245057 (P2/S3) VM crashes when heap is exhausted
|
||||
*
|
||||
* @run main/othervm -Xms50M -Xmx200M nsk.stress.except.except003
|
||||
*/
|
||||
|
||||
package nsk.stress.except;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* <code>Throwable</code> instance.
|
||||
* <p>
|
||||
* <p>The test tries to occupy all of memory available in the heap by
|
||||
* allocating lots of new <code>Object()</code> instances. Instances of the
|
||||
* type <code>Object</code> are the smallest objects, so they apparently should
|
||||
* occupy most fine-grained fragments in the heap and leave no free space for
|
||||
* new <code>Throwable</code> instance. After that, the test provokes various
|
||||
* exceptions (e.g.: by executing integer division by 0 and so on), and checks
|
||||
* if appropriate exceptions are thrown.
|
||||
* <p>
|
||||
* <p>Note, that memory occupation is terminated if memory allocation slows
|
||||
* down crucially. This is a workaround intended to avoid the HotSpot bug:
|
||||
* <br>
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* <p>
|
||||
* <p>There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* <br>
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance
|
||||
* <br>
|
||||
* #4245060 (P4/S5) poor garbage collector performance
|
||||
* <br>However, printing of the test's error messages, warnings, and of
|
||||
* execution trace may fail even so. If the test fails due to poor GC
|
||||
* performance, exit status 96 is returned instead of 97.
|
||||
* <p>
|
||||
* <p>Also note, that the test needs a lot of memory to start up, so it should
|
||||
* not run under older JDK 1.1.x release due to its poor heap utilization.
|
||||
*/
|
||||
public class except003 {
|
||||
/**
|
||||
* Either allow or supress printing of execution trace.
|
||||
*/
|
||||
private static boolean TRACE_ON = false;
|
||||
/**
|
||||
* Either allow or supress printing of warning messages.
|
||||
*/
|
||||
private static final boolean WARN_ON = true;
|
||||
/*
|
||||
* Storage for a lot of tiny objects
|
||||
* "static volatile" keywords are for preventing heap optimization
|
||||
*/
|
||||
private static volatile Object pool[] = null;
|
||||
/**
|
||||
* Temporary <code>log</code> for error messages, warnings and/or execution trace.
|
||||
*
|
||||
* @see #messages
|
||||
*/
|
||||
private static String log[] = new String[1000]; // up to 1000 messages
|
||||
/**
|
||||
* How many <code>messages</code> were submitted to the <code>log</code>.
|
||||
*
|
||||
* @see #log
|
||||
*/
|
||||
private static int messages = 0;
|
||||
|
||||
/**
|
||||
* Re-call to the method <code>run(out)</code> (ignore <code>args[]</code>),
|
||||
* and print the test summary - either test passed of failed.
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
if (args.length > 0) {
|
||||
if (args[0].toLowerCase().startsWith("-v"))
|
||||
TRACE_ON = true;
|
||||
}
|
||||
|
||||
int exitCode = run(out);
|
||||
pool = null;
|
||||
System.gc();
|
||||
// Print the log[] and the test summary:
|
||||
try {
|
||||
for (int i = 0; i < messages; i++)
|
||||
out.println(log[i]);
|
||||
if (exitCode == 0) {
|
||||
if (TRACE_ON)
|
||||
out.println("Test passed.");
|
||||
} else
|
||||
out.println("Test failed.");
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Poor performance of garbage collector:
|
||||
exitCode = 1;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate as much <code>Object</code> instances as possible to bring JVM
|
||||
* into stress, and then check if exceptions are correctly thrown accordingly
|
||||
* to various situations like integer division by 0, etc.
|
||||
*/
|
||||
private static int run(PrintStream out) {
|
||||
out.println("# While printing this message, JVM seems to initiate the output");
|
||||
out.println("# stream, so that it will not need more memory to print later,");
|
||||
out.println("# when the heap would fail to provide more memory.");
|
||||
out.println("# ");
|
||||
out.println("# Note, that the test maintains especial static log[] field in");
|
||||
out.println("# order to avoid printing when the heap seems exhausted.");
|
||||
out.println("# Nevertheless, printing could arise OutOfMemoryError even");
|
||||
out.println("# after all the memory allocated by the test is released.");
|
||||
out.println("# ");
|
||||
out.println("# That problem is caused by the known JDK/HotSpot bugs:");
|
||||
out.println("# 4239841 (P1/S5) 1.1: poor garbage collector performance");
|
||||
out.println("# 4245060 (P4/S5) poor garbage collector performance");
|
||||
out.println("# ");
|
||||
out.println("# This message is just intended to work-around that problem.");
|
||||
out.println("# If printing should fail even so, the test will return the");
|
||||
out.println("# exit status 96 instead of 97 to indicate the problem.");
|
||||
|
||||
// Prepare some items, which will be used by the test:
|
||||
Object trash = null;
|
||||
|
||||
// Allocate repository for a lots of tiny objects:
|
||||
pool = null;
|
||||
// Sum up exit code:
|
||||
int exitCode = 0; // apparently PASSED
|
||||
int skipped = 0; // some checks may correctly suffer OutOfMemoryError
|
||||
for (int size = 1 << 30; size > 0 && pool == null; size >>= 1)
|
||||
try {
|
||||
pool = new Object[size];
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
if (pool == null)
|
||||
throw new Error("HS bug: cannot allocate new Object[1]");
|
||||
int poolSize = pool.length;
|
||||
int index = 0;
|
||||
|
||||
// Sum up time spent, when it was hard to JVM to allocate next object
|
||||
// (i.e.: when JVM has spent more than 1 second to allocate new object):
|
||||
double totalDelay = 0;
|
||||
long timeMark = System.currentTimeMillis();
|
||||
try {
|
||||
for (; index < poolSize; index++) {
|
||||
//-------------------------
|
||||
pool[index] = new Object();
|
||||
long nextTimeMark = System.currentTimeMillis();
|
||||
long elapsed = nextTimeMark - timeMark;
|
||||
timeMark = nextTimeMark;
|
||||
//----------------------
|
||||
if (elapsed > 1000) {
|
||||
double seconds = elapsed / 1000.0;
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"pool[" + index + "]=new Object(); // elapsed " + seconds + "s");
|
||||
totalDelay += seconds;
|
||||
if (totalDelay > 60) {
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"Memory allocation became slow; so, heap seems exhausted.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Heap seems exhausted - OutOfMemoryError thrown.";
|
||||
|
||||
// Do not release any byte once allocated:
|
||||
pool[index++] = oome;
|
||||
}
|
||||
|
||||
if (index > poolSize - 1000) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Warning: pool[] is full; so, checks would not be enough hard...";
|
||||
}
|
||||
|
||||
// Check ClassNotFoundException (negative):
|
||||
try {
|
||||
// trash = Class.forName("nsk.stress.except.except003.except003$Abra$Cadabra"); // correct - should pass
|
||||
trash = Class.forName("nsk.stress.except.except003.except003.Abra.Cadabra"); // incorrect - should fail
|
||||
log[messages++] = "Failure: ClassNotFoundException (negative)";
|
||||
exitCode = 2;
|
||||
} catch (ClassNotFoundException cnfe) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: ClassNotFoundException (negative)";
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: ClassNotFoundException (negative)";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-call to <code>run(args,out)</code>, and return JCK-like exit status.
|
||||
* (The stream <code>out</code> is assigned to <code>System.out</code> here.)
|
||||
*
|
||||
* @see #run(String[], PrintStream)
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||
// Last try. If there is some exception outside the code, test should end correctly
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
try {
|
||||
pool = null;
|
||||
log = null;
|
||||
System.gc();
|
||||
if (e instanceof OutOfMemoryError) {
|
||||
try {
|
||||
System.out.println("OOME : Test Skipped");
|
||||
System.exit(95);
|
||||
} catch (Throwable ignore) {
|
||||
} // No code in the handler can provoke correct exceptions.
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
throw (RuntimeException) e;
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
}
|
||||
});
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status.
|
||||
}
|
||||
|
||||
/**
|
||||
* This class should be used to check <code>ClassNotFoundException</code>
|
||||
* and <code>IllegalAccessException</code>.
|
||||
*/
|
||||
private static class Abra {
|
||||
/**
|
||||
* Will try to incorrectly find this class as <code>Cadabra</code>
|
||||
* instead of <code>Abra$Cadabra</code>.
|
||||
*/
|
||||
public static class Cadabra {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
553
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except004.java
Normal file
553
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except004.java
Normal file
@ -0,0 +1,553 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/except/except004.
|
||||
* VM testbase keywords: [stress, diehard, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* Throwable instance.
|
||||
* The test tries to occupy all of memory available in the heap by allocating
|
||||
* lots of new Object() instances. Instances of the type Object are the smallest
|
||||
* objects, so they apparently should occupy most fine-grained fragments in the
|
||||
* heap and leave no free space for new Throwable instance. After that, the test
|
||||
* provokes various exceptions (e.g.: by executing integer division by 0 and so
|
||||
* on), and checks if appropriate exceptions are thrown.
|
||||
* COMMENTS
|
||||
* The test needs a lot of memory to start up, so it should not run under older
|
||||
* JDK 1.1.x release due to its poorer heap utilization. Also, some checks are
|
||||
* skipped when testing classic VM, because OutOfMemoryError is correctly thrown
|
||||
* instead of target exception.
|
||||
* When the test is being self-initiating (i.e.: eating heap), memory occupation
|
||||
* is terminated if memory allocation slows down crucially. This is a workaround
|
||||
* intended to avoid the HotSpot bug:
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance (HotSpot bug)
|
||||
* #4245060 (P4/S5) poor garbage collector performance (Classic VM bug)
|
||||
* However, printing of the test's error messages, warnings, and of execution
|
||||
* trace fails under JDK 1.2 for Win32 even so. If the test fails due to this
|
||||
* problem, exit status 96 is returned instead of 97.
|
||||
* JDK 1.3 classic VM for Sparc may crash (core dump) due to the known bug:
|
||||
* #4245057 (P2/S3) VM crashes when heap is exhausted
|
||||
*
|
||||
* @run main/othervm -Xms50M -Xmx200M -XX:-UseGCOverheadLimit nsk.stress.except.except004
|
||||
*/
|
||||
|
||||
package nsk.stress.except;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* <code>Throwable</code> instance.
|
||||
* <p>
|
||||
* <p>The test tries to occupy all of memory available in the heap by
|
||||
* allocating lots of new <code>Object()</code> instances. Instances of the
|
||||
* type <code>Object</code> are the smallest objects, so they apparently should
|
||||
* occupy most fine-grained fragments in the heap and leave no free space for
|
||||
* new <code>Throwable</code> instance. After that, the test provokes various
|
||||
* exceptions (e.g.: by executing integer division by 0 and so on), and checks
|
||||
* if appropriate exceptions are thrown.
|
||||
* <p>
|
||||
* <p>Note, that memory occupation is terminated if memory allocation slows
|
||||
* down crucially. This is a workaround intended to avoid the HotSpot bug:
|
||||
* <br>
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* <p>
|
||||
* <p>There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* <br>
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance
|
||||
* <br>
|
||||
* #4245060 (P4/S5) poor garbage collector performance
|
||||
* <br>However, printing of the test's error messages, warnings, and of
|
||||
* execution trace may fail even so. If the test fails due to poor GC
|
||||
* performance, exit status 96 is returned instead of 97.
|
||||
* <p>
|
||||
* <p>Also note, that the test needs a lot of memory to start up, so it should
|
||||
* not run under older JDK 1.1.x release due to its poor heap utilization.
|
||||
*/
|
||||
public class except004 {
|
||||
/**
|
||||
* Either allow or supress printing of execution trace.
|
||||
*/
|
||||
private static boolean TRACE_ON = false;
|
||||
/**
|
||||
* Either allow or supress printing of warning messages.
|
||||
*/
|
||||
private static final boolean WARN_ON = true;
|
||||
/*
|
||||
* Storage for a lot of tiny objects
|
||||
* "static volatile" keywords are for preventing heap optimization
|
||||
*/
|
||||
private static volatile Object pool[] = null;
|
||||
/**
|
||||
* Temporary <code>log</code> for error messages, warnings and/or execution trace.
|
||||
*
|
||||
* @see #messages
|
||||
*/
|
||||
private static String log[] = new String[1000]; // up to 1000 messages
|
||||
/**
|
||||
* How many <code>messages</code> were submitted to the <code>log</code>.
|
||||
*
|
||||
* @see #log
|
||||
*/
|
||||
private static int messages = 0;
|
||||
|
||||
/**
|
||||
* Re-call to the method <code>run(out)</code> (ignore <code>args[]</code>),
|
||||
* and print the test summary - either test passed of failed.
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
if (args.length > 0) {
|
||||
if (args[0].toLowerCase().startsWith("-v"))
|
||||
TRACE_ON = true;
|
||||
}
|
||||
|
||||
int exitCode;
|
||||
try {
|
||||
exitCode = run(out);
|
||||
} finally { // ensure we have free memory for exception processing
|
||||
pool = null;
|
||||
System.gc();
|
||||
}
|
||||
if (TRACE_ON)
|
||||
out.println("Test completed.");
|
||||
|
||||
// Print the log[] and the test summary:
|
||||
try {
|
||||
for (int i = 0; i < messages; i++)
|
||||
out.println(log[i]);
|
||||
if (exitCode == 0) {
|
||||
if (TRACE_ON)
|
||||
out.println("Test passed.");
|
||||
} else
|
||||
out.println("Test failed.");
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Poor performance of garbage collector:
|
||||
exitCode = 1;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate as much <code>Object</code> instances as possible to bring JVM
|
||||
* into stress, and then check if exceptions are correctly thrown accordingly
|
||||
* to various situations like integer division by 0, etc.
|
||||
*/
|
||||
private static int run(PrintStream out) {
|
||||
out.println("# While printing this message, JVM seems to initiate the output");
|
||||
out.println("# stream, so that it will not need more memory to print later,");
|
||||
out.println("# when the heap would fail to provide more memory.");
|
||||
out.println("# ");
|
||||
out.println("# Note, that the test maintains especial static log[] field in");
|
||||
out.println("# order to avoid printing when the heap seems exhausted.");
|
||||
out.println("# Nevertheless, printing could cause OutOfMemoryError even");
|
||||
out.println("# after all the memory allocated by the test is released.");
|
||||
out.println("# ");
|
||||
out.println("# That problem is caused by the known JDK/HotSpot bugs:");
|
||||
out.println("# 4239841 (P1/S5) 1.1: poor garbage collector performance");
|
||||
out.println("# 4245060 (P4/S5) poor garbage collector performance");
|
||||
out.println("# ");
|
||||
out.println("# This message is just intended to work-around that problem.");
|
||||
out.println("# If printing should fail even so, the test will return the");
|
||||
out.println("# exit status 96 instead of 97 to indicate the problem.");
|
||||
|
||||
// run all tests normally to ensure all needed classes are loaded and
|
||||
// initialized before the heap is exhausted - else we may trigger OOME
|
||||
// in unexpected places.
|
||||
try {
|
||||
if (TRACE_ON)
|
||||
out.println("Running without heap exhaustion");
|
||||
runTests(out, false);
|
||||
} catch (Throwable unexpected) {
|
||||
out.println("Test pre-initialisation failed: " + unexpected);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (TRACE_ON)
|
||||
out.println("Running with heap exhaustion");
|
||||
|
||||
return runTests(out, true);
|
||||
}
|
||||
|
||||
private static int runTests(PrintStream out, boolean exhaustHeap) {
|
||||
// reset message index
|
||||
messages = 0;
|
||||
|
||||
// Prepare some items, which will be used by the test:
|
||||
Object stringArray[] = new String[1];
|
||||
Object integerValue = new Integer(0);
|
||||
Object doubleValue = new Double(0);
|
||||
Object trash = null;
|
||||
Field abraPrivateField;
|
||||
Field abraIntegerField;
|
||||
Field abraBooleanField;
|
||||
try {
|
||||
abraPrivateField = Abra.class.getDeclaredField("DONT_TOUCH_ME");
|
||||
abraIntegerField = Abra.class.getDeclaredField("MAIN_CYR_NUMBER");
|
||||
abraBooleanField = Abra.class.getDeclaredField("NOT_AN_INTEGER");
|
||||
} catch (NoSuchFieldException nsfe) {
|
||||
out.println("Test initialisation failed: field not found in class Abra");
|
||||
return 2;
|
||||
}
|
||||
|
||||
Abra abra = new Abra("via public constructor");
|
||||
Abra.Cadabra cadabra = new Abra.Cadabra();
|
||||
// Sum up exit code:
|
||||
int exitCode = 0; // apparently PASSED
|
||||
int skipped = 0; // some checks may correctly suffer OutOfMemoryError
|
||||
|
||||
int poolSize = 0;
|
||||
int index = 0;
|
||||
|
||||
if (exhaustHeap) {
|
||||
pool = null;
|
||||
// Allocate repository for lots of tiny objects:
|
||||
for (int size = 1 << 30; size > 0 && pool == null; size >>= 1) {
|
||||
try {
|
||||
pool = new Object[size];
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
}
|
||||
if (pool == null)
|
||||
throw new Error("HS bug: cannot allocate new Object[1]");
|
||||
poolSize = pool.length;
|
||||
index = 0;
|
||||
|
||||
// Sum up time spent, when it was hard for JVM to allocate next object
|
||||
// (i.e.: when JVM has spent more than 1 second to allocate new object):
|
||||
double totalDelay = 0;
|
||||
long timeMark = System.currentTimeMillis();
|
||||
try {
|
||||
for (; index < poolSize; index++) {
|
||||
//-------------------------
|
||||
pool[index] = new Object();
|
||||
long nextTimeMark = System.currentTimeMillis();
|
||||
long elapsed = nextTimeMark - timeMark;
|
||||
timeMark = nextTimeMark;
|
||||
//----------------------
|
||||
if (elapsed > 1000) {
|
||||
double seconds = elapsed / 1000.0;
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"pool[" + index + "]=new Object(); // elapsed " + seconds + "s");
|
||||
totalDelay += seconds;
|
||||
if (totalDelay > 60) {
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"Memory allocation became slow; so, heap seems exhausted.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Heap seems exhausted - OutOfMemoryError thrown.";
|
||||
// Do not release any byte once allocated:
|
||||
pool[index++] = oome;
|
||||
}
|
||||
|
||||
if (index > poolSize - 1000) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Warning: pool[] is full; so, checks would not be enough hard...";
|
||||
}
|
||||
} else {
|
||||
// pool gets used for array index tests
|
||||
pool = new Object[3];
|
||||
poolSize = pool.length;
|
||||
}
|
||||
|
||||
// Check ArithmeticException:
|
||||
try {
|
||||
int x, y, z;
|
||||
x = y = 0;
|
||||
z = x / y;
|
||||
log[messages++] = "Failure: ArithmeticException";
|
||||
exitCode = 2; // FAILED
|
||||
} catch (ArithmeticException ae) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: ArithmeticException";
|
||||
if (exhaustHeap)
|
||||
pool[index++] = ae;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: ArithmeticException";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
// Check ArrayIndexOutOfBoundsException:
|
||||
try {
|
||||
pool[poolSize] = pool[0];
|
||||
log[messages++] = "Failure: ArrayIndexOutOfBoundsException";
|
||||
exitCode = 2; // FAILED
|
||||
} catch (ArrayIndexOutOfBoundsException aioobe) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: ArrayIndexOutOfBoundsException";
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: ArrayIndexOutOfBoundsException";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
// Check ArrayStoreException:
|
||||
try {
|
||||
stringArray[0] = integerValue;
|
||||
log[messages++] = "Failure: ArrayStoreException";
|
||||
exitCode = 2; // FAILED
|
||||
} catch (ArrayStoreException ase) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: ArrayStoreException";
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: ArrayStoreException";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
// Check ClassCastException:
|
||||
try {
|
||||
trash = (Double) integerValue;
|
||||
log[messages++] = "Failure: ClassCastException";
|
||||
exitCode = 2; // FAILED
|
||||
} catch (ClassCastException cce) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: ClassCastException";
|
||||
if (exhaustHeap)
|
||||
pool[index++] = cce;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: ClassCastException";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
// Check CloneNotSupportedException:
|
||||
try {
|
||||
trash = abra.clone(); // illegal - should fail
|
||||
// trash = cadabra.clone(); // legal - should pass
|
||||
log[messages++] = "Failure: CloneNotSupportedException";
|
||||
exitCode = 2; // FAILED
|
||||
} catch (CloneNotSupportedException cnse) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: CloneNotSupportedException";
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: CloneNotSupportedException";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
// Check IllegalAccessException (positive):
|
||||
try {
|
||||
int junkIt = abraIntegerField.getInt(null); // legal - should pass
|
||||
// int junkIt = abraPrivateField.getInt(null); // illegal - should fail
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: IllegalAccessException (positive)";
|
||||
} catch (IllegalAccessException iae) {
|
||||
log[messages++] = "Failure: IllegalAccessException (positive)";
|
||||
exitCode = 2;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: IllegalAccessException (positive)";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
// Check IllegalAccessException (negative):
|
||||
try {
|
||||
// int junkIt = abraIntegerField.getInt(null); // legal - should pass
|
||||
int junkIt = abraPrivateField.getInt(null); // illegal - should fail
|
||||
log[messages++] = "Failure: IllegalAccessException (negative)";
|
||||
exitCode = 2; // FAILED
|
||||
} catch (IllegalAccessException iae) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: IllegalAccessException (negative)";
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: IllegalAccessException (negative)";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
// Check IllegalArgumentException (positive):
|
||||
try {
|
||||
int junkIt = abraIntegerField.getInt(null); // legal - should pass
|
||||
// int junkIt = abraBooleanField.getInt(null); // illegal - should fail
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: IllegalArgumentException (positive)";
|
||||
} catch (IllegalAccessException iae) {
|
||||
log[messages++] =
|
||||
"Failure: IllegalArgumentException (positive) incorrectly thrown IllegalAccessException";
|
||||
exitCode = 2;
|
||||
} catch (IllegalArgumentException iae) {
|
||||
log[messages++] = "Failure: IllegalArgumentException (positive)";
|
||||
exitCode = 2;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: IllegalArgumentException (positive)";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
// Check IllegalArgumentException (negative):
|
||||
try {
|
||||
// int junkIt = abraIntegerField.getInt(null); // legal - should pass
|
||||
int junkIt = abraBooleanField.getInt(null); // illegal - should fail
|
||||
log[messages++] = "Failure: IllegalArgumentException (negative)";
|
||||
exitCode = 2; // FAILED
|
||||
} catch (IllegalAccessException iae) {
|
||||
log[messages++] =
|
||||
"Failure: IllegalArgumentException (negative) incorrectly thrown IllegalAccessException";
|
||||
exitCode = 2;
|
||||
} catch (IllegalArgumentException iae) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: IllegalArgumentException (negative)";
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: IllegalArgumentException (negative)";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
// Check IllegalMonitorStateException (positive):
|
||||
try {
|
||||
synchronized (cadabra) {
|
||||
cadabra.notifyAll(); // legal - should pass
|
||||
}
|
||||
// cadabra.notifyAll(); // illegal - should fail
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: IllegalMonitorStateException (positive)";
|
||||
} catch (IllegalMonitorStateException imse) {
|
||||
log[messages++] = "Failure: IllegalMonitorStateException (positive)";
|
||||
exitCode = 2;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: IllegalMonitorStateException (positive)";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
// Check IllegalMonitorStateException (negative):
|
||||
try {
|
||||
// synchronized (cadabra) {
|
||||
// cadabra.notifyAll(); // legal - should pass
|
||||
// }
|
||||
cadabra.notifyAll(); // illegal - should fail
|
||||
log[messages++] = "Failure: IllegalMonitorStateException (negative)";
|
||||
exitCode = 2;
|
||||
} catch (IllegalMonitorStateException imse) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: IllegalMonitorStateException (negative)";
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: IllegalMonitorStateException (negative)";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-call to <code>run(args,out)</code>, and return JCK-like exit status.
|
||||
* (The stream <code>out</code> is assigned to <code>System.out</code> here.)
|
||||
*
|
||||
* @see #run(String[], PrintStream)
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||
// Last try. If there is some exception outside the code, test should end correctly
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
try {
|
||||
pool = null;
|
||||
log = null;
|
||||
System.gc();
|
||||
if (e instanceof OutOfMemoryError) {
|
||||
try {
|
||||
System.out.println("OOME : Test Skipped");
|
||||
System.exit(0);
|
||||
} catch (Throwable ignore) {
|
||||
} // No code in the handler can provoke correct exceptions.
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
if (e instanceof RuntimeException)
|
||||
throw (RuntimeException) e;
|
||||
else if (e instanceof Error)
|
||||
throw (Error) e;
|
||||
else
|
||||
throw new Error("Unexpected checked exception", e);
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
}
|
||||
});
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status.
|
||||
}
|
||||
|
||||
/**
|
||||
* This class should be used to check <code>CloneNotSupportedException</code>,
|
||||
* <code>IllegalAccessException</code>, and <code>IllegalArgumentException</code>.
|
||||
* The class extends <code>except004</code> in order that its (protected)
|
||||
* method <code>clone()</code> be available from <code>except004</code>.
|
||||
*/
|
||||
private static class Abra extends except004 {
|
||||
/**
|
||||
* Will try to incorrectly find this class as <code>Cadabra</code>
|
||||
* instead of <code>Abra$Cadabra</code>.
|
||||
*/
|
||||
public static class Cadabra implements Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Will try to incorrectly access to this field from outside this class.
|
||||
*/
|
||||
private static final int DONT_TOUCH_ME = 666;
|
||||
/**
|
||||
* Will try to incorrectly access to this field from outside this class.
|
||||
*/
|
||||
public static final int MAIN_CYR_NUMBER = 47;
|
||||
/**
|
||||
* Will try to get this field like <code>int<code> zero.
|
||||
*/
|
||||
public static final boolean NOT_AN_INTEGER = false;
|
||||
|
||||
/**
|
||||
* Will try to correctly instantiate <code>Abra.Cadabra</code>,
|
||||
* not <code>Abra</code>.
|
||||
*/
|
||||
private Abra() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Yet another constructor, which is <code>public</code>.
|
||||
*/
|
||||
public Abra(String nothingSpecial) {
|
||||
}
|
||||
}
|
||||
}
|
||||
319
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except005.java
Normal file
319
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except005.java
Normal file
@ -0,0 +1,319 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/except/except005.
|
||||
* VM testbase keywords: [stress, diehard, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* Throwable instance.
|
||||
* The test tries to occupy all of memory available in the heap by allocating
|
||||
* lots of new Object() instances. Instances of the type Object are the smallest
|
||||
* objects, so they apparently should occupy most fine-grained fragments in the
|
||||
* heap and leave no free space for new Throwable instance. After that, the test
|
||||
* provokes various exceptions (e.g.: by executing integer division by 0 and so
|
||||
* on), and checks if appropriate exceptions are thrown.
|
||||
* COMMENTS
|
||||
* The test needs a lot of memory to start up, so it should not run under older
|
||||
* JDK 1.1.x release due to its poorer heap utilization. Also, some checks are
|
||||
* skipped when testing classic VM, because OutOfMemoryError is correctly thrown
|
||||
* instead of target exception.
|
||||
* When the test is being self-initiating (i.e.: eating heap), memory occupation
|
||||
* is terminated if memory allocation slows down crucially. This is a workaround
|
||||
* intended to avoid the HotSpot bug:
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance (HotSpot bug)
|
||||
* #4245060 (P4/S5) poor garbage collector performance (Classic VM bug)
|
||||
* However, printing of the test's error messages, warnings, and of execution
|
||||
* trace fails under JDK 1.2 for Win32 even so. If the test fails due to this
|
||||
* problem, exit status 96 is returned instead of 97.
|
||||
* JDK 1.3 classic VM for Sparc may crash (core dump) due to the known bug:
|
||||
* #4245057 (P2/S3) VM crashes when heap is exhausted
|
||||
*
|
||||
* @run main/othervm -Xms50M -Xmx200M nsk.stress.except.except005
|
||||
*/
|
||||
|
||||
package nsk.stress.except;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* <code>Throwable</code> instance.
|
||||
* <p>
|
||||
* <p>The test tries to occupy all of memory available in the heap by
|
||||
* allocating lots of new <code>Object()</code> instances. Instances of the
|
||||
* type <code>Object</code> are the smallest objects, so they apparently should
|
||||
* occupy most fine-grained fragments in the heap and leave no free space for
|
||||
* new <code>Throwable</code> instance. After that, the test provokes various
|
||||
* exceptions (e.g.: by executing integer division by 0 and so on), and checks
|
||||
* if appropriate exceptions are thrown.
|
||||
* <p>
|
||||
* <p>Note, that memory occupation is terminated if memory allocation slows
|
||||
* down crucially. This is a workaround intended to avoid the HotSpot bug:
|
||||
* <br>
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* <p>
|
||||
* <p>There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* <br>
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance
|
||||
* <br>
|
||||
* #4245060 (P4/S5) poor garbage collector performance
|
||||
* <br>However, printing of the test's error messages, warnings, and of
|
||||
* execution trace may fail even so. If the test fails due to poor GC
|
||||
* performance, exit status 96 is returned instead of 97.
|
||||
* <p>
|
||||
* <p>Also note, that the test needs a lot of memory to start up, so it should
|
||||
* not run under older JDK 1.1.x release due to its poor heap utilization.
|
||||
*/
|
||||
public class except005 {
|
||||
/**
|
||||
* Either allow or supress printing of execution trace.
|
||||
*/
|
||||
private static boolean TRACE_ON = false;
|
||||
/**
|
||||
* Either allow or supress printing of warning messages.
|
||||
*/
|
||||
private static final boolean WARN_ON = true;
|
||||
|
||||
/**
|
||||
* Temporary <code>log</code> for error messages, warnings and/or execution trace.
|
||||
*
|
||||
* @see #messages
|
||||
*/
|
||||
private static String log[] = new String[1000]; // up to 1000 messages
|
||||
/**
|
||||
* <code>pool</code> to store tiny objects to fill up the Heap
|
||||
*/
|
||||
private static volatile Object pool[] = null;
|
||||
/**
|
||||
* How many <code>messages</code> were submitted to the <code>log</code>.
|
||||
*
|
||||
* @see #log
|
||||
*/
|
||||
private static int messages = 0;
|
||||
|
||||
/**
|
||||
* Re-call to the method <code>run(out)</code> (ignore <code>args[]</code>),
|
||||
* and print the test summary - either test passed of failed.
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
if (args.length > 0) {
|
||||
if (args[0].toLowerCase().startsWith("-v"))
|
||||
TRACE_ON = true;
|
||||
}
|
||||
|
||||
int exitCode = run(out);
|
||||
pool = null;
|
||||
System.gc();
|
||||
// Print the log[] and the test summary:
|
||||
try {
|
||||
for (int i = 0; i < messages; i++)
|
||||
out.println(log[i]);
|
||||
if (exitCode == 0) {
|
||||
if (TRACE_ON)
|
||||
out.println("Test passed.");
|
||||
} else
|
||||
out.println("Test failed.");
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Poor performance of garbage collector:
|
||||
exitCode = 1;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate as much <code>Object</code> instances as possible to bring JVM
|
||||
* into stress, and then check if exceptions are correctly thrown accordingly
|
||||
* to various situations like integer division by 0, etc.
|
||||
*/
|
||||
private static int run(PrintStream out) {
|
||||
out.println("# Test have been updated!");
|
||||
out.println("# stream, so that it will not need more memory to print later,");
|
||||
out.println("# when the heap would fail to provide more memory.");
|
||||
out.println("# ");
|
||||
out.println("# Note, that the test maintains especial static log[] field in");
|
||||
out.println("# order to avoid printing when the heap seems exhausted.");
|
||||
out.println("# Nevertheless, printing could arise OutOfMemoryError even");
|
||||
out.println("# after all the memory allocated by the test is released.");
|
||||
out.println("# ");
|
||||
out.println("# That problem is caused by the known JDK/HotSpot bugs:");
|
||||
out.println("# 4239841 (P1/S5) 1.1: poor garbage collector performance");
|
||||
out.println("# 4245060 (P4/S5) poor garbage collector performance");
|
||||
out.println("# ");
|
||||
out.println("# This message is just intended to work-around that problem.");
|
||||
out.println("# If printing should fail even so, the test will try to return");
|
||||
out.println("# the exit status 96 instead of 97 to indicate the problem.");
|
||||
out.println("# However, the test may fail or even crash on some platforms");
|
||||
out.println("# suffering the bug 4239841 or 4245060.");
|
||||
|
||||
// Sum up exit code:
|
||||
int exitCode = 0; // apparently PASSED
|
||||
int skipped = 0; // some checks may correctly suffer OutOfMemoryError
|
||||
// Allocate repository for a lots of tiny objects:
|
||||
for (int size = 1 << 30; size > 0 && pool == null; size >>= 1)
|
||||
try {
|
||||
pool = new Object[size];
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
if (pool == null)
|
||||
throw new Error("HS bug: cannot allocate new Object[1]");
|
||||
int poolSize = pool.length;
|
||||
int index = 0;
|
||||
|
||||
// Sum up time spent, when it was hard to JVM to allocate next object
|
||||
// (i.e.: when JVM has spent more than 1 second to allocate new object):
|
||||
double totalDelay = 0;
|
||||
long timeMark = System.currentTimeMillis();
|
||||
try {
|
||||
for (; index < poolSize; index++) {
|
||||
//-------------------------
|
||||
pool[index] = new Object();
|
||||
long nextTimeMark = System.currentTimeMillis();
|
||||
long elapsed = nextTimeMark - timeMark;
|
||||
timeMark = nextTimeMark;
|
||||
//----------------------
|
||||
if (elapsed > 1000) {
|
||||
double seconds = elapsed / 1000.0;
|
||||
if (TRACE_ON) {
|
||||
out.println(
|
||||
"pool[" + index + "]=new Object(); // elapsed " + seconds + "s");
|
||||
}
|
||||
totalDelay += seconds;
|
||||
if (totalDelay > 60) {
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"Memory allocation became slow; so, heap seems exhausted.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Heap seems exhausted - OutOfMemoryError thrown.";
|
||||
}
|
||||
if (index > poolSize - 1000) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Warning: pool[] is full; so, checks would not be enough hard...";
|
||||
}
|
||||
|
||||
// Check InstantiationException (positive):
|
||||
try {
|
||||
// Object junkIt = Abra_Cadabra.class.newInstance(); // illegal - should fail
|
||||
Object junkIt = Abra.Cadabra.class.newInstance(); // legal - should pass
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: InstantiationException (positive)";
|
||||
} catch (IllegalAccessException iae) {
|
||||
log[messages++] =
|
||||
"Failure: InstantiationException (positive) incorrectly thrown IllegalAccessException";
|
||||
pool[index++] = iae;
|
||||
exitCode = 2;
|
||||
} catch (InstantiationException ie) {
|
||||
log[messages++] = "Failure: InstantiationException (positive)";
|
||||
pool[index++] = ie;
|
||||
exitCode = 2;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: InstantiationException (positive)";
|
||||
pool[index++] = oome;
|
||||
skipped++;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-call to <code>run(args,out)</code>, and return JCK-like exit status.
|
||||
* (The stream <code>out</code> is assigned to <code>System.out</code> here.)
|
||||
*
|
||||
* @see #run(String[], PrintStream)
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||
// Last try. If there is some OOME, test should end correctly
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
try {
|
||||
pool = null;
|
||||
log = null;
|
||||
System.gc();
|
||||
if (e instanceof OutOfMemoryError) {
|
||||
try {
|
||||
System.out.println("OOME : Test Skipped");
|
||||
System.exit(0);
|
||||
} catch (Throwable ignore) {
|
||||
} // No code in the handler can provoke correct exceptions.
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
throw (RuntimeException) e;
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
}
|
||||
});
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status.
|
||||
}
|
||||
|
||||
/**
|
||||
* This class should be used to check <code>CloneNotSupportedException</code>,
|
||||
* <code>IllegalAccessException</code>, and <code>IllegalArgumentException</code>.
|
||||
* The class extends <code>except005</code> in order that its (protected)
|
||||
* method <code>clone()</code> be available from <code>except005</code>.
|
||||
*/
|
||||
private static class Abra {
|
||||
/**
|
||||
* Will correctly instantiate <code>Abra.Cadabra</code> object.
|
||||
*/
|
||||
public static class Cadabra {
|
||||
}
|
||||
|
||||
/**
|
||||
* Will try to correctly instantiate <code>Abra.Cadabra</code>,
|
||||
* not <code>Abra</code>.
|
||||
*/
|
||||
private Abra() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Will try to incorrectly instantiate and object of this class.
|
||||
*/
|
||||
private interface Abra_Cadabra {
|
||||
}
|
||||
|
||||
}
|
||||
316
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except006.java
Normal file
316
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except006.java
Normal file
@ -0,0 +1,316 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/except/except006.
|
||||
* VM testbase keywords: [stress, diehard, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* Throwable instance.
|
||||
* The test tries to occupy all of memory available in the heap by allocating
|
||||
* lots of new Object() instances. Instances of the type Object are the smallest
|
||||
* objects, so they apparently should occupy most fine-grained fragments in the
|
||||
* heap and leave no free space for new Throwable instance. After that, the test
|
||||
* provokes various exceptions (e.g.: by executing integer division by 0 and so
|
||||
* on), and checks if appropriate exceptions are thrown.
|
||||
* COMMENTS
|
||||
* The test needs a lot of memory to start up, so it should not run under older
|
||||
* JDK 1.1.x release due to its poorer heap utilization. Also, some checks are
|
||||
* skipped when testing classic VM, because OutOfMemoryError is correctly thrown
|
||||
* instead of target exception.
|
||||
* When the test is being self-initiating (i.e.: eating heap), memory occupation
|
||||
* is terminated if memory allocation slows down crucially. This is a workaround
|
||||
* intended to avoid the HotSpot bug:
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance (HotSpot bug)
|
||||
* #4245060 (P4/S5) poor garbage collector performance (Classic VM bug)
|
||||
* However, printing of the test's error messages, warnings, and of execution
|
||||
* trace fails under JDK 1.2 for Win32 even so. If the test fails due to this
|
||||
* problem, exit status 96 is returned instead of 97.
|
||||
* JDK 1.3 classic VM for Sparc may crash (core dump) due to the known bug:
|
||||
* #4245057 (P2/S3) VM crashes when heap is exhausted
|
||||
*
|
||||
* @run main/othervm -Xms50M -Xmx200M nsk.stress.except.except006
|
||||
*/
|
||||
|
||||
package nsk.stress.except;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* <code>Throwable</code> instance.
|
||||
* <p>
|
||||
* <p>The test tries to occupy all of memory available in the heap by
|
||||
* allocating lots of new <code>Object()</code> instances. Instances of the
|
||||
* type <code>Object</code> are the smallest objects, so they apparently should
|
||||
* occupy most fine-grained fragments in the heap and leave no free space for
|
||||
* new <code>Throwable</code> instance. After that, the test provokes various
|
||||
* exceptions (e.g.: by executing integer division by 0 and so on), and checks
|
||||
* if appropriate exceptions are thrown.
|
||||
* <p>
|
||||
* <p>Note, that memory occupation is terminated if memory allocation slows
|
||||
* down crucially. This is a workaround intended to avoid the HotSpot bug:
|
||||
* <br>
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* <p>
|
||||
* <p>There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* <br>
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance
|
||||
* <br>
|
||||
* #4245060 (P4/S5) poor garbage collector performance
|
||||
* <br>However, printing of the test's error messages, warnings, and of
|
||||
* execution trace may fail even so. If the test fails due to poor GC
|
||||
* performance, exit status 96 is returned instead of 97.
|
||||
* <p>
|
||||
* <p>Also note, that the test needs a lot of memory to start up, so it should
|
||||
* not run under older JDK 1.1.x release due to its poor heap utilization.
|
||||
*/
|
||||
public class except006 {
|
||||
/**
|
||||
* Either allow or supress printing of execution trace.
|
||||
*/
|
||||
private static boolean TRACE_ON = false;
|
||||
/**
|
||||
* Either allow or supress printing of warning messages.
|
||||
*/
|
||||
private static final boolean WARN_ON = true;
|
||||
/*
|
||||
* Storage for a lot of tiny objects
|
||||
* "static volatile" keywords are for preventing heap optimization
|
||||
*/
|
||||
private static volatile Object pool[] = null;
|
||||
/**
|
||||
* Temporary <code>log</code> for error messages, warnings and/or execution trace.
|
||||
*
|
||||
* @see #messages
|
||||
*/
|
||||
private static String log[] = new String[1000]; // up to 1000 messages
|
||||
/**
|
||||
* How many <code>messages</code> were submitted to the <code>log</code>.
|
||||
*
|
||||
* @see #log
|
||||
*/
|
||||
private static int messages = 0;
|
||||
|
||||
/**
|
||||
* Re-call to the method <code>run(out)</code> (ignore <code>args[]</code>),
|
||||
* and print the test summary - either test passed of failed.
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
if (args.length > 0) {
|
||||
if (args[0].toLowerCase().startsWith("-v"))
|
||||
TRACE_ON = true;
|
||||
}
|
||||
|
||||
int exitCode = run(out);
|
||||
pool = null;
|
||||
System.gc();
|
||||
// Print the log[] and the test summary:
|
||||
try {
|
||||
for (int i = 0; i < messages; i++)
|
||||
out.println(log[i]);
|
||||
if (exitCode == 0) {
|
||||
if (TRACE_ON)
|
||||
out.println("Test passed.");
|
||||
} else
|
||||
out.println("Test failed.");
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Poor performance of garbage collector:
|
||||
exitCode = 1;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate as much <code>Object</code> instances as possible to bring JVM
|
||||
* into stress, and then check if exceptions are correctly thrown accordingly
|
||||
* to various situations like integer division by 0, etc.
|
||||
*/
|
||||
private static int run(PrintStream out) {
|
||||
out.println("# While printing this message, JVM seems to initiate the output");
|
||||
out.println("# stream, so that it will not need more memory to print later,");
|
||||
out.println("# when the heap would fail to provide more memory.");
|
||||
out.println("# ");
|
||||
out.println("# Note, that the test maintains especial static log[] field in");
|
||||
out.println("# order to avoid printing when the heap seems exhausted.");
|
||||
out.println("# Nevertheless, printing could arise OutOfMemoryError even");
|
||||
out.println("# after all the memory allocated by the test is released.");
|
||||
out.println("# ");
|
||||
out.println("# That problem is caused by the known JDK/HotSpot bugs:");
|
||||
out.println("# 4239841 (P1/S5) 1.1: poor garbage collector performance");
|
||||
out.println("# 4245060 (P4/S5) poor garbage collector performance");
|
||||
out.println("# ");
|
||||
out.println("# This message is just intended to work-around that problem.");
|
||||
out.println("# If printing should fail even so, the test will try to return");
|
||||
out.println("# the exit status 96 instead of 97 to indicate the problem.");
|
||||
out.println("# However, the test may fail or even crash on some platforms");
|
||||
out.println("# suffering the bug 4239841 or 4245060.");
|
||||
|
||||
// Allocate repository for a lots of tiny objects:
|
||||
for (int size = 1 << 30; size > 0 && pool == null; size >>= 1)
|
||||
try {
|
||||
pool = new Object[size];
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
if (pool == null)
|
||||
throw new Error("HS bug: cannot allocate new Object[1]");
|
||||
int poolSize = pool.length;
|
||||
int index = 0;
|
||||
// Sum up exit code:
|
||||
int exitCode = 0; // apparently PASSED
|
||||
int skipped = 0; // some checks may correctly suffer OutOfMemoryError
|
||||
Object junkIt;
|
||||
// Sum up time spent, when it was hard to JVM to allocate next object
|
||||
// (i.e.: when JVM has spent more than 1 second to allocate new object):
|
||||
double totalDelay = 0;
|
||||
long timeMark = System.currentTimeMillis();
|
||||
try {
|
||||
for (; index < poolSize; index++) {
|
||||
//-------------------------
|
||||
pool[index] = new Object();
|
||||
long nextTimeMark = System.currentTimeMillis();
|
||||
long elapsed = nextTimeMark - timeMark;
|
||||
timeMark = nextTimeMark;
|
||||
//----------------------
|
||||
if (elapsed > 1000) {
|
||||
double seconds = elapsed / 1000.0;
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"pool[" + index + "]=new Object(); // elapsed " + seconds + "s");
|
||||
totalDelay += seconds;
|
||||
if (totalDelay > 60) {
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"Memory allocation became slow; so, heap seems exhausted.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Heap seems exhausted - OutOfMemoryError thrown.";
|
||||
}
|
||||
if (index > poolSize - 1000) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Warning: pool[] is full; so, checks would not be enough hard...";
|
||||
}
|
||||
|
||||
|
||||
// Check InstantiationException (negative):
|
||||
try {
|
||||
junkIt = Abra_Cadabra.class.newInstance(); // illegal - should fail
|
||||
// Object junkIt = Abra.Cadabra.class.newInstance(); // legal - should pass
|
||||
log[messages++] = "Failure: InstantiationException (negative)";
|
||||
exitCode = 2;
|
||||
} catch (IllegalAccessException iae) {
|
||||
log[messages++] =
|
||||
"Failure: InstantiationException (negative) incorrectly thrown IllegalAccessException";
|
||||
exitCode = 2;
|
||||
} catch (InstantiationException ie) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: InstantiationException (negative)";
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: InstantiationException (negative)";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-call to <code>run(args,out)</code>, and return JCK-like exit status.
|
||||
* (The stream <code>out</code> is assigned to <code>System.out</code> here.)
|
||||
*
|
||||
* @see #run(String[], PrintStream)
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||
// Last try. If there is some exception outside the code, test should end correctly
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
try {
|
||||
pool = null;
|
||||
log = null;
|
||||
System.gc();
|
||||
if (e instanceof OutOfMemoryError) {
|
||||
try {
|
||||
System.out.println("OOME : Test Skipped");
|
||||
System.exit(0);
|
||||
} catch (Throwable ignore) {
|
||||
} // No code in the handler can provoke correct exceptions.
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
throw (RuntimeException) e;
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
}
|
||||
});
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status.
|
||||
}
|
||||
|
||||
/**
|
||||
* This class should be used to check <code>CloneNotSupportedException</code>,
|
||||
* <code>IllegalAccessException</code>, and <code>IllegalArgumentException</code>.
|
||||
* The class extends <code>except006</code> in order that its (protected)
|
||||
* method <code>clone()</code> be available from <code>except006</code>.
|
||||
*/
|
||||
private static class Abra {
|
||||
/**
|
||||
* Will correctly instantiate <code>Abra.Cadabra</code> object.
|
||||
*/
|
||||
public static class Cadabra {
|
||||
}
|
||||
|
||||
/**
|
||||
* Will try to correctly instantiate <code>Abra.Cadabra</code>,
|
||||
* not <code>Abra</code>.
|
||||
*/
|
||||
private Abra() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Will try to incorrectly instantiate and object of this class.
|
||||
*/
|
||||
private interface Abra_Cadabra {
|
||||
}
|
||||
|
||||
}
|
||||
380
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except007.java
Normal file
380
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except007.java
Normal file
@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/except/except007.
|
||||
* VM testbase keywords: [stress, diehard, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* Throwable instance.
|
||||
* The test tries to occupy all of memory available in the heap by allocating
|
||||
* lots of new Object() instances. Instances of the type Object are the smallest
|
||||
* objects, so they apparently should occupy most fine-grained fragments in the
|
||||
* heap and leave no free space for new Throwable instance. After that, the test
|
||||
* provokes various exceptions (e.g.: by executing integer division by 0 and so
|
||||
* on), and checks if appropriate exceptions are thrown.
|
||||
* COMMENTS
|
||||
* The test needs a lot of memory to start up, so it should not run under older
|
||||
* JDK 1.1.x release due to its poorer heap utilization. Also, some checks are
|
||||
* skipped when testing classic VM, because OutOfMemoryError is correctly thrown
|
||||
* instead of target exception.
|
||||
* When the test is being self-initiating (i.e.: eating heap), memory occupation
|
||||
* is terminated if memory allocation slows down crucially. This is a workaround
|
||||
* intended to avoid the HotSpot bug:
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance (HotSpot bug)
|
||||
* #4245060 (P4/S5) poor garbage collector performance (Classic VM bug)
|
||||
* However, printing of the test's error messages, warnings, and of execution
|
||||
* trace fails under JDK 1.2 for Win32 even so. If the test fails due to this
|
||||
* problem, exit status 96 is returned instead of 97.
|
||||
* JDK 1.3 classic VM for Sparc may crash (core dump) due to the known bug:
|
||||
* #4245057 (P2/S3) VM crashes when heap is exhausted
|
||||
*
|
||||
* @run main/othervm -Xms50M -Xmx200M nsk.stress.except.except007
|
||||
*/
|
||||
|
||||
package nsk.stress.except;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* <code>Throwable</code> instance.
|
||||
* <p>
|
||||
* <p>The test tries to occupy all of memory available in the heap by
|
||||
* allocating lots of new <code>Object()</code> instances. Instances of the
|
||||
* type <code>Object</code> are the smallest objects, so they apparently should
|
||||
* occupy most fine-grained fragments in the heap and leave no free space for
|
||||
* new <code>Throwable</code> instance. After that, the test provokes various
|
||||
* exceptions (e.g.: by executing integer division by 0 and so on), and checks
|
||||
* if appropriate exceptions are thrown.
|
||||
* <p>
|
||||
* <p>Note, that memory occupation is terminated if memory allocation slows
|
||||
* down crucially. This is a workaround intended to avoid the HotSpot bug:
|
||||
* <br>
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* <p>
|
||||
* <p>There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* <br>
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance
|
||||
* <br>
|
||||
* #4245060 (P4/S5) poor garbage collector performance
|
||||
* <br>However, printing of the test's error messages, warnings, and of
|
||||
* execution trace may fail even so. If the test fails due to poor GC
|
||||
* performance, exit status 96 is returned instead of 97.
|
||||
* <p>
|
||||
* <p>Also note, that the test needs a lot of memory to start up, so it should
|
||||
* not run under older JDK 1.1.x release due to its poor heap utilization.
|
||||
*/
|
||||
public class except007 {
|
||||
/**
|
||||
* Either allow or supress printing of execution trace.
|
||||
*/
|
||||
private static boolean TRACE_ON = false;
|
||||
/**
|
||||
* Either allow or supress printing of warning messages.
|
||||
*/
|
||||
private static final boolean WARN_ON = true;
|
||||
/*
|
||||
* Storage for a lot of tiny objects
|
||||
* "static volatile" keywords are for preventing heap optimization
|
||||
*/
|
||||
private static volatile Object pool[] = null;
|
||||
/**
|
||||
* Temporary <code>log</code> for error messages, warnings and/or execution trace.
|
||||
*
|
||||
* @see #messages
|
||||
*/
|
||||
private static String log[] = new String[1000]; // up to 1000 messages
|
||||
/**
|
||||
* How many <code>messages</code> were submitted to the <code>log</code>.
|
||||
*
|
||||
* @see #log
|
||||
*/
|
||||
private static int messages = 0;
|
||||
|
||||
/**
|
||||
* Re-call to the method <code>run(out)</code> (ignore <code>args[]</code>),
|
||||
* and print the test summary - either test passed of failed.
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
if (args.length > 0) {
|
||||
if (args[0].toLowerCase().startsWith("-v"))
|
||||
TRACE_ON = true;
|
||||
}
|
||||
|
||||
int exitCode = run(out);
|
||||
pool = null;
|
||||
System.gc();
|
||||
// Print the log[] and the test summary:
|
||||
try {
|
||||
for (int i = 0; i < messages; i++)
|
||||
out.println(log[i]);
|
||||
if (exitCode == 0) {
|
||||
if (TRACE_ON)
|
||||
out.println("Test passed.");
|
||||
} else
|
||||
out.println("Test failed.");
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Poor performance of garbage collector:
|
||||
exitCode = 1;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate as much <code>Object</code> instances as possible to bring JVM
|
||||
* into stress, and then check if exceptions are correctly thrown accordingly
|
||||
* to various situations like integer division by 0, etc.
|
||||
*/
|
||||
private static int run(PrintStream out) {
|
||||
out.println("# While printing this message, JVM seems to initiate the output");
|
||||
out.println("# stream, so that it will not need more memory to print later,");
|
||||
out.println("# when the heap would fail to provide more memory.");
|
||||
out.println("# ");
|
||||
out.println("# Note, that the test maintains especial static log[] field in");
|
||||
out.println("# order to avoid printing when the heap seems exhausted.");
|
||||
out.println("# Nevertheless, printing could arise OutOfMemoryError even");
|
||||
out.println("# after all the memory allocated by the test is released.");
|
||||
out.println("# ");
|
||||
out.println("# That problem is caused by the known JDK/HotSpot bugs:");
|
||||
out.println("# 4239841 (P1/S5) 1.1: poor garbage collector performance");
|
||||
out.println("# 4245060 (P4/S5) poor garbage collector performance");
|
||||
out.println("# ");
|
||||
out.println("# This message is just intended to work-around that problem.");
|
||||
out.println("# If printing should fail even so, the test will try to return");
|
||||
out.println("# the exit status 96 instead of 97 to indicate the problem.");
|
||||
out.println("# However, the test may fail or even crash on some platforms");
|
||||
out.println("# suffering the bug 4239841 or 4245060.");
|
||||
|
||||
// Prepare some items, which will be used by the test:
|
||||
Thread rabbit = new Rabbit();
|
||||
|
||||
// Allocate repository for a lots of tiny objects:
|
||||
for (int size = 1 << 30; size > 0 && pool == null; size >>= 1)
|
||||
try {
|
||||
pool = new Object[size];
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
if (pool == null)
|
||||
throw new Error("HS bug: cannot allocate new Object[1]");
|
||||
int poolSize = pool.length;
|
||||
|
||||
int index = 0;
|
||||
pool[index++] = new Object();
|
||||
|
||||
// Sum up time spent, when it was hard to JVM to allocate next object
|
||||
// (i.e.: when JVM has spent more than 1 second to allocate new object):
|
||||
double totalDelay = 0;
|
||||
long timeMark = System.currentTimeMillis();
|
||||
try {
|
||||
for (; index < poolSize; index++) {
|
||||
//-------------------------
|
||||
pool[index] = new Object();
|
||||
long nextTimeMark = System.currentTimeMillis();
|
||||
long elapsed = nextTimeMark - timeMark;
|
||||
timeMark = nextTimeMark;
|
||||
//----------------------
|
||||
if (elapsed > 1000) {
|
||||
double seconds = elapsed / 1000.0;
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"pool[" + index + "]=new Object(); // elapsed " + seconds + "s");
|
||||
totalDelay += seconds;
|
||||
if (totalDelay > 60) {
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"Memory allocation became slow; so, heap seems exhausted.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Heap seems exhausted - OutOfMemoryError thrown.";
|
||||
}
|
||||
if (index > poolSize - 1000) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Warning: pool[] is full; so, checks would not be enough hard...";
|
||||
}
|
||||
|
||||
// Sum up exit code:
|
||||
int exitCode = 0; // apparently PASSED
|
||||
int skipped = 0; // some checks may correctly suffer OutOfMemoryError
|
||||
|
||||
// Check InterruptedException:
|
||||
try {
|
||||
synchronized (rabbit) {
|
||||
rabbit.start();
|
||||
rabbit.wait();
|
||||
}
|
||||
rabbit.interrupt();
|
||||
while (rabbit.isAlive())
|
||||
rabbit.join();
|
||||
Throwable exception = ((Rabbit) rabbit).exception;
|
||||
if (exception == null) {
|
||||
log[messages++] = "Failure: InterruptedException not thrown";
|
||||
exitCode = 2;
|
||||
} else {
|
||||
if (exception instanceof InterruptedException) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] =
|
||||
"Success: InterruptedException thrown as expected";
|
||||
} else if (exception instanceof OutOfMemoryError) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: InterruptedException";
|
||||
skipped++;
|
||||
} else {
|
||||
log[messages++] =
|
||||
"Failure: InterruptedException: unexpected exception thrown";
|
||||
exitCode = 2;
|
||||
}
|
||||
pool[index++] = exception;
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
log[messages++] = "Failure: InterruptedException thrown unexpectedly";
|
||||
exitCode = 2;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: InterruptedException";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
// Check NegativeArraySizeException:
|
||||
try {
|
||||
int negative = -1;
|
||||
byte array[] = new byte[negative];
|
||||
log[messages++] = "Failure: NegativeArraySizeException not thrown as expected";
|
||||
exitCode = 2;
|
||||
} catch (NegativeArraySizeException ie) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: NegativeArraySizeException thrown as expected";
|
||||
pool[index++] = ie;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: NegativeArraySizeException";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
// Check NullPointerException:
|
||||
try {
|
||||
Double none = null;
|
||||
double oops = none.doubleValue();
|
||||
log[messages++] = "Failure: NullPointerException not thrown as expected";
|
||||
exitCode = 2;
|
||||
} catch (NullPointerException npe) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: NullPointerException thrown as expected";
|
||||
pool[index++] = npe;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: NullPointerException";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
// Check NumberFormatException:
|
||||
try {
|
||||
double oops = Double.parseDouble("3.14159D00"); // FORTRAN-like
|
||||
log[messages++] = "Failure: NumberFormatException not thrown as expected";
|
||||
exitCode = 2;
|
||||
} catch (NumberFormatException nfe) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: NumberFormatException thrown as expected";
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Skipped: NumberFormatException";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will shoot a rabbit when it waits -- in order to provoke
|
||||
* InterruptedException.
|
||||
*/
|
||||
private static class Rabbit extends Thread {
|
||||
Throwable exception = null;
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
synchronized (this) {
|
||||
this.notify();
|
||||
this.wait();
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
exception = ie;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
exception = oome;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-call to <code>run(args,out)</code>, and return JCK-like exit status.
|
||||
* (The stream <code>out</code> is assigned to <code>System.out</code> here.)
|
||||
*
|
||||
* @see #run(String[], PrintStream)
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||
// Last try. If there is some exception outside the code, test should end correctly
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
try {
|
||||
pool = null;
|
||||
log = null;
|
||||
System.gc();
|
||||
if (e instanceof OutOfMemoryError) {
|
||||
try {
|
||||
System.out.println("OOME : Test Skipped");
|
||||
System.exit(0);
|
||||
} catch (Throwable ignore) {
|
||||
} // No code in the handler can provoke correct exceptions.
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
throw (RuntimeException) e;
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
}
|
||||
});
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status.
|
||||
}
|
||||
|
||||
}
|
||||
363
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except008.java
Normal file
363
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except008.java
Normal file
@ -0,0 +1,363 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/except/except008.
|
||||
* VM testbase keywords: [stress, diehard, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* Throwable instance.
|
||||
* The test tries to occupy all of memory available in the heap by allocating
|
||||
* lots of new Object() instances. Instances of the type Object are the smallest
|
||||
* objects, so they apparently should occupy most fine-grained fragments in the
|
||||
* heap and leave no free space for new Throwable instance. After that, the test
|
||||
* provokes various exceptions (e.g.: by executing integer division by 0 and so
|
||||
* on), and checks if appropriate exceptions are thrown.
|
||||
* COMMENTS
|
||||
* The test needs a lot of memory to start up, so it should not run under older
|
||||
* JDK 1.1.x release due to its poorer heap utilization. Also, some checks are
|
||||
* skipped when testing classic VM, because OutOfMemoryError is correctly thrown
|
||||
* instead of target exception.
|
||||
* When the test is being self-initiating (i.e.: eating heap), memory occupation
|
||||
* is terminated if memory allocation slows down crucially. This is a workaround
|
||||
* intended to avoid the HotSpot bug:
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance (HotSpot bug)
|
||||
* #4245060 (P4/S5) poor garbage collector performance (Classic VM bug)
|
||||
* However, printing of the test's error messages, warnings, and of execution
|
||||
* trace fails under JDK 1.2 for Win32 even so. If the test fails due to this
|
||||
* problem, exit status 96 is returned instead of 97.
|
||||
* JDK 1.3 classic VM for Sparc may crash (core dump) due to the known bug:
|
||||
* #4245057 (P2/S3) VM crashes when heap is exhausted
|
||||
*
|
||||
* @run main/othervm -Xms50M -Xmx200M -XX:-UseGCOverheadLimit nsk.stress.except.except008
|
||||
*/
|
||||
|
||||
package nsk.stress.except;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* <code>Throwable</code> instance.
|
||||
* <p>
|
||||
* <p>The test tries to occupy all of memory available in the heap by
|
||||
* allocating lots of new <code>Object()</code> instances. Instances of the
|
||||
* type <code>Object</code> are the smallest objects, so they apparently should
|
||||
* occupy most fine-grained fragments in the heap and leave no free space for
|
||||
* new <code>Throwable</code> instance. After that, the test provokes various
|
||||
* exceptions (e.g.: by executing integer division by 0 and so on), and checks
|
||||
* if appropriate exceptions are thrown.
|
||||
* <p>
|
||||
* <p>Note, that memory occupation is terminated if memory allocation slows
|
||||
* down crucially. This is a workaround intended to avoid the HotSpot bug:
|
||||
* <br>
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* <p>
|
||||
* <p>There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* <br>
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance
|
||||
* <br>
|
||||
* #4245060 (P4/S5) poor garbage collector performance
|
||||
* <br>However, printing of the test's error messages, warnings, and of
|
||||
* execution trace may fail even so. If the test fails due to poor GC
|
||||
* performance, exit status 96 is returned instead of 97.
|
||||
* <p>
|
||||
* <p>Also note, that the test needs a lot of memory to start up, so it should
|
||||
* not run under older JDK 1.1.x release due to its poor heap utilization.
|
||||
*/
|
||||
public class except008 {
|
||||
/**
|
||||
* Either allow or supress printing of execution trace.
|
||||
*/
|
||||
private static boolean TRACE_ON = false;
|
||||
/**
|
||||
* Either allow or supress printing of warning messages.
|
||||
*/
|
||||
private static final boolean WARN_ON = true;
|
||||
/*
|
||||
* Storage for a lot of tiny objects
|
||||
* "static volatile" keywords are for preventing heap optimization
|
||||
*/
|
||||
private static volatile Object pool[] = null;
|
||||
/**
|
||||
* Temporary <code>log</code> for error messages, warnings and/or execution trace.
|
||||
*
|
||||
* @see #messages
|
||||
*/
|
||||
private static String log[] = new String[1000]; // up to 1000 messages
|
||||
/**
|
||||
* How many <code>messages</code> were submitted to the <code>log</code>.
|
||||
*
|
||||
* @see #log
|
||||
*/
|
||||
private static int messages = 0;
|
||||
|
||||
/**
|
||||
* Re-call to the method <code>run(out)</code> (ignore <code>args[]</code>),
|
||||
* and print the test summary - either test passed of failed.
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
if (args.length > 0) {
|
||||
if (args[0].toLowerCase().startsWith("-v"))
|
||||
TRACE_ON = true;
|
||||
}
|
||||
|
||||
int exitCode = run(out);
|
||||
pool = null;
|
||||
System.gc();
|
||||
// Print the log[] and the test summary:
|
||||
try {
|
||||
for (int i = 0; i < messages; i++)
|
||||
out.println(log[i]);
|
||||
if (exitCode == 0) {
|
||||
if (TRACE_ON)
|
||||
out.println("Test passed.");
|
||||
} else
|
||||
out.println("Test failed.");
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Poor performance of garbage collector:
|
||||
exitCode = 1;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate as much <code>Object</code> instances as possible to bring JVM
|
||||
* into stress, and then check if exceptions are correctly thrown accordingly
|
||||
* to various situations like integer division by 0, etc.
|
||||
*/
|
||||
private static int run(PrintStream out) {
|
||||
out.println("# While printing this message, JVM seems to initiate the output");
|
||||
out.println("# stream, so that it will not need more memory to print later,");
|
||||
out.println("# when the heap would fail to provide more memory.");
|
||||
out.println("# ");
|
||||
out.println("# Note, that the test maintains especial static log[] field in");
|
||||
out.println("# order to avoid printing when the heap seems exhausted.");
|
||||
out.println("# Nevertheless, printing could arise OutOfMemoryError even");
|
||||
out.println("# after all the memory allocated by the test is released.");
|
||||
out.println("# ");
|
||||
out.println("# That problem is caused by the known JDK/HotSpot bugs:");
|
||||
out.println("# 4239841 (P1/S5) 1.1: poor garbage collector performance");
|
||||
out.println("# 4245060 (P4/S5) poor garbage collector performance");
|
||||
out.println("# ");
|
||||
out.println("# This message is just intended to work-around that problem.");
|
||||
out.println("# If printing should fail even so, the test will try to return");
|
||||
out.println("# the exit status 96 instead of 97 to indicate the problem.");
|
||||
out.println("# However, the test may fail or even crash on some platforms");
|
||||
out.println("# suffering the bug 4239841 or 4245060.");
|
||||
|
||||
// Prepare some items, which will be used by the test:
|
||||
Zoo zoo = new Zoo(); // load the class Zoo
|
||||
Class noArgs[] = new Class[0];
|
||||
|
||||
// Sum up exit code:
|
||||
int exitCode = 0; // apparently PASSED
|
||||
int skipped = 0; // some checks may correctly suffer OutOfMemoryError
|
||||
|
||||
// Allocate repository for a lots of tiny objects:
|
||||
for (int size = 1 << 30; size > 0 && pool == null; size >>= 1)
|
||||
try {
|
||||
pool = new Object[size];
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
if (pool == null)
|
||||
throw new Error("HS bug: cannot allocate new Object[1]");
|
||||
int poolSize = pool.length;
|
||||
|
||||
int index = 0;
|
||||
pool[index++] = new Object();
|
||||
|
||||
// Sum up time spent, when it was hard to JVM to allocate next object
|
||||
// (i.e.: when JVM has spent more than 1 second to allocate new object):
|
||||
double totalDelay = 0;
|
||||
long timeMark = System.currentTimeMillis();
|
||||
try {
|
||||
for (; index < poolSize; index++) {
|
||||
//-------------------------
|
||||
pool[index] = new Object();
|
||||
long nextTimeMark = System.currentTimeMillis();
|
||||
long elapsed = nextTimeMark - timeMark;
|
||||
timeMark = nextTimeMark;
|
||||
//----------------------
|
||||
if (elapsed > 1000) {
|
||||
double seconds = elapsed / 1000.0;
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"pool[" + index + "]=new Object(); // elapsed " + seconds + "s");
|
||||
totalDelay += seconds;
|
||||
if (totalDelay > 60) {
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"Memory allocation became slow; so, heap seems exhausted.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Heap seems exhausted - OutOfMemoryError thrown.";
|
||||
}
|
||||
|
||||
if (index > poolSize - 1000) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Warning: pool[] is full; so, checks would not be enough hard...";
|
||||
}
|
||||
|
||||
// Check NoSuchFieldException (positive):
|
||||
try {
|
||||
Field valid = Zoo.class.getField("PUBLIC_FIELD"); // should pass
|
||||
// Field wrong = Zoo.class.getField("PRIVATE_FIELD"); // should fail
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: NoSuchFieldException not thrown as expected";
|
||||
} catch (NoSuchFieldException nsfe) {
|
||||
pool[index++] = nsfe;
|
||||
log[messages++] = "Failure: NoSuchFieldException thrown unexpectedly";
|
||||
exitCode = 2;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] =
|
||||
"Skipped: NoSuchFieldException positive check - OutOfMemoryError thrown";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
// Check NoSuchFieldException (negative):
|
||||
try {
|
||||
// Field valid = Zoo.class.getField("PUBLIC_FIELD"); // should pass
|
||||
Field wrong = Zoo.class.getField("PRIVATE_FIELD"); // should fail
|
||||
log[messages++] = "Failure: NoSuchFieldException incorrectly not thrown";
|
||||
exitCode = 2;
|
||||
} catch (NoSuchFieldException nsfe) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: NoSuchFieldException thrown as expected";
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] =
|
||||
"NoSuchFieldException negative check - OutOfMemoryError thrown";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
// Check NoSuchMethodException (positive):
|
||||
try {
|
||||
Method valid = Zoo.class.getMethod("PUBLIC_METHOD", noArgs); // should pass
|
||||
// Method wrong = Zoo.class.getMethod("PRIVATE_METHOD",noArgs); // should fail
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: NoSuchFieldException not thrown as expected";
|
||||
} catch (NoSuchMethodException nsme) {
|
||||
pool[index++] = nsme;
|
||||
log[messages++] = "Failure: NoSuchMethodException thrown unexpectedly";
|
||||
exitCode = 2;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] =
|
||||
"Skipped: NoSuchMethodException positive check - OutOfMemoryError thrown";
|
||||
pool[index++] = oome;
|
||||
skipped++;
|
||||
}
|
||||
|
||||
// Check NoSuchMethodException (negative):
|
||||
try {
|
||||
// Method valid = Zoo.class.getMethod("PUBLIC_METHOD",noArgs); // should pass
|
||||
Method wrong = Zoo.class.getMethod("PRIVATE_METHOD", noArgs); // should fail
|
||||
log[messages++] = "Failure: NoSuchMethodException incorrectly not thrown";
|
||||
exitCode = 2;
|
||||
} catch (NoSuchMethodException nsme) {
|
||||
pool[index++] = nsme;
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: NoSuchFieldException thrown as expected";
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] =
|
||||
"Skipped: NoSuchMethodException negative check - OutOfMemoryError thrown";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Several items used to check reflections.
|
||||
*/
|
||||
private static class Zoo {
|
||||
public String PUBLIC_FIELD = "Accessible via reflection";
|
||||
private String PRIVATE_FIELD = "Inaccessible via reflection";
|
||||
|
||||
public String PUBLIC_METHOD() {
|
||||
return "Accessible via reflection";
|
||||
}
|
||||
|
||||
private String PRIVATE_METHOD() {
|
||||
return "Inaccessible via reflection";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-call to <code>run(args,out)</code>, and return JCK-like exit status.
|
||||
* (The stream <code>out</code> is assigned to <code>System.out</code> here.)
|
||||
*
|
||||
* @see #run(String[], PrintStream)
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||
// Last try. If there is some exception outside the code, test should end correctly
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
try {
|
||||
pool = null;
|
||||
log = null;
|
||||
System.gc();
|
||||
if (e instanceof OutOfMemoryError) {
|
||||
try {
|
||||
System.out.println("OOME : Test Skipped");
|
||||
System.exit(0);
|
||||
} catch (Throwable ignore) {
|
||||
} // No code in the handler can provoke correct exceptions.
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
throw (RuntimeException) e;
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
}
|
||||
});
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status.
|
||||
}
|
||||
|
||||
}
|
||||
288
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except009.java
Normal file
288
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except009.java
Normal file
@ -0,0 +1,288 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/except/except009.
|
||||
* VM testbase keywords: [stress, diehard, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* Throwable instance.
|
||||
* The test tries to occupy all of memory available in the heap by allocating
|
||||
* lots of new Object() instances. Instances of the type Object are the smallest
|
||||
* objects, so they apparently should occupy most fine-grained fragments in the
|
||||
* heap and leave no free space for new Throwable instance. After that, the test
|
||||
* provokes various exceptions (e.g.: by executing integer division by 0 and so
|
||||
* on), and checks if appropriate exceptions are thrown.
|
||||
* COMMENTS
|
||||
* The test needs a lot of memory to start up, so it should not run under older
|
||||
* JDK 1.1.x release due to its poorer heap utilization. Also, some checks are
|
||||
* skipped when testing classic VM, because OutOfMemoryError is correctly thrown
|
||||
* instead of target exception.
|
||||
* When the test is being self-initiating (i.e.: eating heap), memory occupation
|
||||
* is terminated if memory allocation slows down crucially. This is a workaround
|
||||
* intended to avoid the HotSpot bug:
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance (HotSpot bug)
|
||||
* #4245060 (P4/S5) poor garbage collector performance (Classic VM bug)
|
||||
* However, printing of the test's error messages, warnings, and of execution
|
||||
* trace fails under JDK 1.2 for Win32 even so. If the test fails due to this
|
||||
* problem, exit status 96 is returned instead of 97.
|
||||
* JDK 1.3 classic VM for Sparc may crash (core dump) due to the known bug:
|
||||
* #4245057 (P2/S3) VM crashes when heap is exhausted
|
||||
*
|
||||
* @run main/othervm -Xms50M -Xmx200M nsk.stress.except.except009
|
||||
*/
|
||||
|
||||
package nsk.stress.except;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* <code>Throwable</code> instance.
|
||||
* <p>
|
||||
* <p>The test tries to occupy all of memory available in the heap by
|
||||
* allocating lots of new <code>Object()</code> instances. Instances of the
|
||||
* type <code>Object</code> are the smallest objects, so they apparently should
|
||||
* occupy most fine-grained fragments in the heap and leave no free space for
|
||||
* new <code>Throwable</code> instance. After that, the test provokes various
|
||||
* exceptions (e.g.: by executing integer division by 0 and so on), and checks
|
||||
* if appropriate exceptions are thrown.
|
||||
* <p>
|
||||
* <p>Note, that memory occupation is terminated if memory allocation slows
|
||||
* down crucially. This is a workaround intended to avoid the HotSpot bug:
|
||||
* <br>
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* <p>
|
||||
* <p>There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* <br>
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance
|
||||
* <br>
|
||||
* #4245060 (P4/S5) poor garbage collector performance
|
||||
* <br>However, printing of the test's error messages, warnings, and of
|
||||
* execution trace may fail even so. If the test fails due to poor GC
|
||||
* performance, exit status 96 is returned instead of 97.
|
||||
* <p>
|
||||
* <p>Also note, that the test needs a lot of memory to start up, so it should
|
||||
* not run under older JDK 1.1.x release due to its poor heap utilization.
|
||||
*/
|
||||
public class except009 {
|
||||
/**
|
||||
* Either allow or supress printing of execution trace.
|
||||
*/
|
||||
private static boolean TRACE_ON = false;
|
||||
/**
|
||||
* Either allow or supress printing of warning messages.
|
||||
*/
|
||||
private static final boolean WARN_ON = true;
|
||||
/*
|
||||
* Storage for a lot of tiny objects
|
||||
* "static volatile" keywords are for preventing heap optimization
|
||||
*/
|
||||
private static volatile Object pool[] = null;
|
||||
/**
|
||||
* Temporary <code>log</code> for error messages, warnings and/or execution trace.
|
||||
*
|
||||
* @see #messages
|
||||
*/
|
||||
private static String log[] = new String[1000]; // up to 1000 messages
|
||||
/**
|
||||
* How many <code>messages</code> were submitted to the <code>log</code>.
|
||||
*
|
||||
* @see #log
|
||||
*/
|
||||
private static int messages = 0;
|
||||
|
||||
/**
|
||||
* Re-call to the method <code>run(out)</code> (ignore <code>args[]</code>),
|
||||
* and print the test summary - either test passed of failed.
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
if (args.length > 0) {
|
||||
if (args[0].toLowerCase().startsWith("-v"))
|
||||
TRACE_ON = true;
|
||||
}
|
||||
|
||||
int exitCode = run(out);
|
||||
pool = null;
|
||||
System.gc();
|
||||
// Print the log[] and the test summary:
|
||||
try {
|
||||
for (int i = 0; i < messages; i++)
|
||||
out.println(log[i]);
|
||||
if (exitCode == 0) {
|
||||
if (TRACE_ON)
|
||||
out.println("Test passed.");
|
||||
} else
|
||||
out.println("Test failed.");
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Poor performance of garbage collector:
|
||||
exitCode = 1;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate as much <code>Object</code> instances as possible to bring JVM
|
||||
* into stress, and then check if exceptions are correctly thrown accordingly
|
||||
* to various situations like integer division by 0, etc.
|
||||
*/
|
||||
private static int run(PrintStream out) {
|
||||
out.println("# While printing this message, JVM seems to initiate the output");
|
||||
out.println("# stream, so that it will not need more memory to print later,");
|
||||
out.println("# when the heap would fail to provide more memory.");
|
||||
out.println("# ");
|
||||
out.println("# Note, that the test maintains especial static log[] field in");
|
||||
out.println("# order to avoid printing when the heap seems exhausted.");
|
||||
out.println("# Nevertheless, printing could arise OutOfMemoryError even");
|
||||
out.println("# after all the memory allocated by the test is released.");
|
||||
out.println("# ");
|
||||
out.println("# That problem is caused by the known JDK/HotSpot bugs:");
|
||||
out.println("# 4239841 (P1/S5) 1.1: poor garbage collector performance");
|
||||
out.println("# 4245060 (P4/S5) poor garbage collector performance");
|
||||
out.println("# ");
|
||||
out.println("# This message is just intended to work-around that problem.");
|
||||
out.println("# If printing should fail even so, the test will try to return");
|
||||
out.println("# the exit status 96 instead of 97 to indicate the problem.");
|
||||
out.println("# However, the test may fail or even crash on some platforms");
|
||||
out.println("# suffering the bug 4239841 or 4245060.");
|
||||
|
||||
// Sum up exit code:
|
||||
int exitCode = 0; // apparently PASSED
|
||||
int skipped = 0; // some checks may correctly suffer OutOfMemoryError
|
||||
String s = "qwerty";
|
||||
char c;
|
||||
// Allocate repository for a lots of tiny objects:
|
||||
for (int size = 1 << 30; size > 0 && pool == null; size >>= 1)
|
||||
try {
|
||||
pool = new Object[size];
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
if (pool == null)
|
||||
throw new Error("HS bug: cannot allocate new Object[1]");
|
||||
int poolSize = pool.length;
|
||||
|
||||
int index = 0;
|
||||
pool[index++] = new Object();
|
||||
|
||||
// Sum up time spent, when it was hard to JVM to allocate next object
|
||||
// (i.e.: when JVM has spent more than 1 second to allocate new object):
|
||||
double totalDelay = 0;
|
||||
long timeMark = System.currentTimeMillis();
|
||||
try {
|
||||
for (; index < poolSize; index++) {
|
||||
//-------------------------
|
||||
pool[index] = new Object();
|
||||
long nextTimeMark = System.currentTimeMillis();
|
||||
long elapsed = nextTimeMark - timeMark;
|
||||
timeMark = nextTimeMark;
|
||||
//----------------------
|
||||
if (elapsed > 1000) {
|
||||
double seconds = elapsed / 1000.0;
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"pool[" + index + "]=new Object(); // elapsed " + seconds + "s");
|
||||
totalDelay += seconds;
|
||||
if (totalDelay > 60) {
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"Memory allocation became slow; so, heap seems exhausted.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Heap seems exhausted - OutOfMemoryError thrown.";
|
||||
}
|
||||
|
||||
if (index > poolSize - 1000) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Warning: pool[] is full; so, checks would not be enough hard...";
|
||||
}
|
||||
|
||||
// Check StringIndexOutOfBoundsException:
|
||||
try {
|
||||
c = s.charAt(6); // should fail
|
||||
log[messages++] = "Failure: StringIndexOutOfBoundsException incorrectly not thrown";
|
||||
exitCode = 2;
|
||||
} catch (StringIndexOutOfBoundsException sioobe) {
|
||||
pool[index++] = sioobe;
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: StringIndexOutOfBoundsException thrown as expected";
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] =
|
||||
"Skipped: StringIndexOutOfBoundsException: thrown OutOfMemoryError";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-call to <code>run(args,out)</code>, and return JCK-like exit status.
|
||||
* (The stream <code>out</code> is assigned to <code>System.out</code> here.)
|
||||
*
|
||||
* @see #run(String[], PrintStream)
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||
// Last try. If there is some exceprions outside the code, test should end correctly
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
try {
|
||||
pool = null;
|
||||
log = null;
|
||||
System.gc();
|
||||
if (e instanceof OutOfMemoryError) {
|
||||
try {
|
||||
System.out.println("OOME : Test Skipped");
|
||||
System.exit(0);
|
||||
} catch (Throwable ignore) {
|
||||
} // No code in the handler can provoke correct exceptions.
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
throw (RuntimeException) e;
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
}
|
||||
});
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status.
|
||||
}
|
||||
|
||||
}
|
||||
291
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except010.java
Normal file
291
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except010.java
Normal file
@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/except/except010.
|
||||
* VM testbase keywords: [stress, diehard, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* Throwable instance.
|
||||
* The test tries to occupy all of memory available in the heap by allocating
|
||||
* lots of new Object() instances. Instances of the type Object are the smallest
|
||||
* objects, so they apparently should occupy most fine-grained fragments in the
|
||||
* heap and leave no free space for new Throwable instance. After that, the test
|
||||
* provokes various exceptions (e.g.: by executing integer division by 0 and so
|
||||
* on), and checks if appropriate exceptions are thrown.
|
||||
* COMMENTS
|
||||
* The test needs a lot of memory to start up, so it should not run under older
|
||||
* JDK 1.1.x release due to its poorer heap utilization. Also, some checks are
|
||||
* skipped when testing classic VM, because OutOfMemoryError is correctly thrown
|
||||
* instead of target exception.
|
||||
* When the test is being self-initiating (i.e.: eating heap), memory occupation
|
||||
* is terminated if memory allocation slows down crucially. This is a workaround
|
||||
* intended to avoid the HotSpot bug:
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance (HotSpot bug)
|
||||
* #4245060 (P4/S5) poor garbage collector performance (Classic VM bug)
|
||||
* However, printing of the test's error messages, warnings, and of execution
|
||||
* trace fails under JDK 1.2 for Win32 even so. If the test fails due to this
|
||||
* problem, exit status 96 is returned instead of 97.
|
||||
* JDK 1.3 classic VM for Sparc may crash (core dump) due to the known bug:
|
||||
* #4245057 (P2/S3) VM crashes when heap is exhausted
|
||||
*
|
||||
* @run main/othervm -Xms50M -Xmx200M nsk.stress.except.except010
|
||||
*/
|
||||
|
||||
package nsk.stress.except;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* <code>Throwable</code> instance.
|
||||
* <p>
|
||||
* <p>The test tries to occupy all of memory available in the heap by
|
||||
* allocating lots of new <code>Object()</code> instances. Instances of the
|
||||
* type <code>Object</code> are the smallest objects, so they apparently should
|
||||
* occupy most fine-grained fragments in the heap and leave no free space for
|
||||
* new <code>Throwable</code> instance. After that, the test provokes various
|
||||
* exceptions (e.g.: by executing integer division by 0 and so on), and checks
|
||||
* if appropriate exceptions are thrown.
|
||||
* <p>
|
||||
* <p>Note, that memory occupation is terminated if memory allocation slows
|
||||
* down crucially. This is a workaround intended to avoid the HotSpot bug:
|
||||
* <br>
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* <p>
|
||||
* <p>There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* <br>
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance
|
||||
* <br>
|
||||
* #4245060 (P4/S5) poor garbage collector performance
|
||||
* <br>However, printing of the test's error messages, warnings, and of
|
||||
* execution trace may fail even so. If the test fails due to poor GC
|
||||
* performance, exit status 96 is returned instead of 97.
|
||||
* <p>
|
||||
* <p>Also note, that the test needs a lot of memory to start up, so it should
|
||||
* not run under older JDK 1.1.x release due to its poor heap utilization.
|
||||
*/
|
||||
public class except010 {
|
||||
/**
|
||||
* Either allow or supress printing of execution trace.
|
||||
*/
|
||||
private static boolean TRACE_ON = false;
|
||||
/**
|
||||
* Either allow or supress printing of warning messages.
|
||||
*/
|
||||
private static final boolean WARN_ON = true;
|
||||
/*
|
||||
* Storage for a lot of tiny objects
|
||||
* "static volatile" keywords are for preventing heap optimization
|
||||
*/
|
||||
private static volatile Object pool[] = null;
|
||||
/**
|
||||
* Temporary <code>log</code> for error messages, warnings and/or execution trace.
|
||||
*
|
||||
* @see #messages
|
||||
*/
|
||||
private static String log[] = new String[1000]; // up to 1000 messages
|
||||
/**
|
||||
* How many <code>messages</code> were submitted to the <code>log</code>.
|
||||
*
|
||||
* @see #log
|
||||
*/
|
||||
private static int messages = 0;
|
||||
|
||||
/**
|
||||
* Re-call to the method <code>run(out)</code> (ignore <code>args[]</code>),
|
||||
* and print the test summary - either test passed of failed.
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
if (args.length > 0) {
|
||||
if (args[0].toLowerCase().startsWith("-v"))
|
||||
TRACE_ON = true;
|
||||
}
|
||||
|
||||
int exitCode = run(out);
|
||||
pool = null;
|
||||
System.gc();
|
||||
// Print the log[] and the test summary:
|
||||
try {
|
||||
for (int i = 0; i < messages; i++)
|
||||
out.println(log[i]);
|
||||
if (exitCode == 0) {
|
||||
if (TRACE_ON)
|
||||
out.println("Test passed.");
|
||||
} else
|
||||
out.println("Test failed.");
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Poor performance of garbage collector:
|
||||
exitCode = 1;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate as much <code>Object</code> instances as possible to bring JVM
|
||||
* into stress, and then check if exceptions are correctly thrown accordingly
|
||||
* to various situations like integer division by 0, etc.
|
||||
*/
|
||||
private static int run(PrintStream out) {
|
||||
out.println("# While printing this message, JVM seems to initiate the output");
|
||||
out.println("# stream, so that it will not need more memory to print later,");
|
||||
out.println("# when the heap would fail to provide more memory.");
|
||||
out.println("# ");
|
||||
out.println("# Note, that the test maintains especial static log[] field in");
|
||||
out.println("# order to avoid printing when the heap seems exhausted.");
|
||||
out.println("# Nevertheless, printing could arise OutOfMemoryError even");
|
||||
out.println("# after all the memory allocated by the test is released.");
|
||||
out.println("# ");
|
||||
out.println("# That problem is caused by the known JDK/HotSpot bugs:");
|
||||
out.println("# 4239841 (P1/S5) 1.1: poor garbage collector performance");
|
||||
out.println("# 4245060 (P4/S5) poor garbage collector performance");
|
||||
out.println("# ");
|
||||
out.println("# This message is just intended to work-around that problem.");
|
||||
out.println("# If printing should fail even so, the test will try to return");
|
||||
out.println("# the exit status 96 instead of 97 to indicate the problem.");
|
||||
out.println("# However, the test may fail or even crash on some platforms");
|
||||
out.println("# suffering the bug 4239841 or 4245060.");
|
||||
|
||||
// Sum up exit code:
|
||||
int exitCode = 0; // apparently PASSED
|
||||
int skipped = 0; // some checks may correctly suffer OutOfMemoryError
|
||||
|
||||
// Allocate repository for a lots of tiny objects:
|
||||
for (int size = 1 << 30; size > 0 && pool == null; size >>= 1)
|
||||
try {
|
||||
pool = new Object[size];
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
if (pool == null)
|
||||
throw new Error("HS bug: cannot allocate new Object[1]");
|
||||
int poolSize = pool.length;
|
||||
|
||||
int index = 0;
|
||||
pool[index++] = new Object();
|
||||
|
||||
// Sum up time spent, when it was hard to JVM to allocate next object
|
||||
// (i.e.: when JVM has spent more than 1 second to allocate new object):
|
||||
double totalDelay = 0;
|
||||
long timeMark = System.currentTimeMillis();
|
||||
try {
|
||||
for (; index < poolSize; index++) {
|
||||
//-------------------------
|
||||
pool[index] = new Object();
|
||||
long nextTimeMark = System.currentTimeMillis();
|
||||
long elapsed = nextTimeMark - timeMark;
|
||||
timeMark = nextTimeMark;
|
||||
//----------------------
|
||||
if (elapsed > 1000) {
|
||||
double seconds = elapsed / 1000.0;
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"pool[" + index + "]=new Object(); // elapsed " + seconds + "s");
|
||||
totalDelay += seconds;
|
||||
if (totalDelay > 60) {
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"Memory allocation became slow; so, heap seems exhausted.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Heap seems exhausted - OutOfMemoryError thrown.";
|
||||
}
|
||||
|
||||
if (index > poolSize - 1000) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Warning: pool[] is full; so, checks would not be enough hard...";
|
||||
}
|
||||
|
||||
// Check StackOverflowError:
|
||||
try {
|
||||
goIntoInfiniteRecursion();
|
||||
log[messages++] = "Failure: StackOverflowError failed to throw";
|
||||
exitCode = 2;
|
||||
} catch (StackOverflowError soe) {
|
||||
pool[index++] = soe;
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: StackOverflowError thrown as expected";
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] =
|
||||
"Skipped: StackOverflowError: thrown OutOfMemoryError";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
private static void goIntoInfiniteRecursion() {
|
||||
goIntoInfiniteRecursion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-call to <code>run(args,out)</code>, and return JCK-like exit status.
|
||||
* (The stream <code>out</code> is assigned to <code>System.out</code> here.)
|
||||
*
|
||||
* @see #run(String[], PrintStream)
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||
// Last try. If there is some exceptions outside the code, test should end correctly
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
try {
|
||||
pool = null;
|
||||
log = null;
|
||||
System.gc();
|
||||
if (e instanceof OutOfMemoryError) {
|
||||
try {
|
||||
System.out.println("OOME : Test Skipped");
|
||||
System.exit(0);
|
||||
} catch (Throwable ignore) {
|
||||
} // No code in the handler can provoke correct exceptions.
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
throw (RuntimeException) e;
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
}
|
||||
});
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status.
|
||||
}
|
||||
|
||||
}
|
||||
296
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except011.java
Normal file
296
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except011.java
Normal file
@ -0,0 +1,296 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/except/except011.
|
||||
* VM testbase keywords: [stress, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* Throwable instance.
|
||||
* The test tries to occupy all of memory available in the heap by allocating
|
||||
* lots of new Object() instances. Instances of the type Object are the smallest
|
||||
* objects, so they apparently should occupy most fine-grained fragments in the
|
||||
* heap and leave no free space for new Throwable instance. After that, the test
|
||||
* provokes various exceptions (e.g.: by executing integer division by 0 and so
|
||||
* on), and checks if appropriate exceptions are thrown.
|
||||
* COMMENTS
|
||||
* The test needs a lot of memory to start up, so it should not run under older
|
||||
* JDK 1.1.x release due to its poorer heap utilization. Also, some checks are
|
||||
* skipped when testing classic VM, because OutOfMemoryError is correctly thrown
|
||||
* instead of target exception.
|
||||
* When the test is being self-initiating (i.e.: eating heap), memory occupation
|
||||
* is terminated if memory allocation slows down crucially. This is a workaround
|
||||
* intended to avoid the HotSpot bug:
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance (HotSpot bug)
|
||||
* #4245060 (P4/S5) poor garbage collector performance (Classic VM bug)
|
||||
* However, printing of the test's error messages, warnings, and of execution
|
||||
* trace fails under JDK 1.2 for Win32 even so. If the test fails due to this
|
||||
* problem, exit status 96 is returned instead of 97.
|
||||
* JDK 1.3 classic VM for Sparc may crash (core dump) due to the known bug:
|
||||
* #4245057 (P2/S3) VM crashes when heap is exhausted
|
||||
*
|
||||
* @run main/othervm -Xms50M -Xmx200M nsk.stress.except.except011
|
||||
*/
|
||||
|
||||
package nsk.stress.except;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* <code>Throwable</code> instance.
|
||||
* <p>
|
||||
* <p>The test tries to occupy all of memory available in the heap by
|
||||
* allocating lots of new <code>Object()</code> instances. Instances of the
|
||||
* type <code>Object</code> are the smallest objects, so they apparently should
|
||||
* occupy most fine-grained fragments in the heap and leave no free space for
|
||||
* new <code>Throwable</code> instance. After that, the test provokes various
|
||||
* exceptions (e.g.: by executing integer division by 0 and so on), and checks
|
||||
* if appropriate exceptions are thrown.
|
||||
* <p>
|
||||
* <p>Note, that memory occupation is terminated if memory allocation slows
|
||||
* down crucially. This is a workaround intended to avoid the HotSpot bug:
|
||||
* <br>
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* <p>
|
||||
* <p>There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* <br>
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance
|
||||
* <br>
|
||||
* #4245060 (P4/S5) poor garbage collector performance
|
||||
* <br>However, printing of the test's error messages, warnings, and of
|
||||
* execution trace may fail even so. If the test fails due to poor GC
|
||||
* performance, exit status 96 is returned instead of 97.
|
||||
* <p>
|
||||
* <p>Also note, that the test needs a lot of memory to start up, so it should
|
||||
* not run under older JDK 1.1.x release due to its poor heap utilization.
|
||||
*/
|
||||
public class except011 {
|
||||
/**
|
||||
* Either allow or supress printing of execution trace.
|
||||
*/
|
||||
private static boolean TRACE_ON = false;
|
||||
/**
|
||||
* Either allow or supress printing of warning messages.
|
||||
*/
|
||||
private static final boolean WARN_ON = true;
|
||||
/*
|
||||
* Storage for a lot of tiny objects
|
||||
* "static volatile" keywords are for preventing heap optimization
|
||||
*/
|
||||
private static volatile Object pool[] = null;
|
||||
/**
|
||||
* Temporary <code>log</code> for error messages, warnings and/or execution trace.
|
||||
*
|
||||
* @see #messages
|
||||
*/
|
||||
private static String log[] = new String[1000]; // up to 1000 messages
|
||||
/**
|
||||
* How many <code>messages</code> were submitted to the <code>log</code>.
|
||||
*
|
||||
* @see #log
|
||||
*/
|
||||
private static int messages = 0;
|
||||
|
||||
private static final String className = "nsk.stress.except.except011.except011oops";
|
||||
|
||||
/**
|
||||
* Re-call to the method <code>run(out)</code> (ignore <code>args[]</code>),
|
||||
* and print the test summary - either test passed of failed.
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
if (args.length > 0) {
|
||||
if (args[0].toLowerCase().startsWith("-v"))
|
||||
TRACE_ON = true;
|
||||
}
|
||||
|
||||
int exitCode = run(out);
|
||||
pool = null;
|
||||
System.gc();
|
||||
// Print the log[] and the test summary:
|
||||
try {
|
||||
for (int i = 0; i < messages; i++)
|
||||
out.println(log[i]);
|
||||
if (exitCode == 0) {
|
||||
if (TRACE_ON)
|
||||
out.println("Test passed.");
|
||||
} else
|
||||
out.println("Test failed.");
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Poor performance of garbage collector:
|
||||
exitCode = 1;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate as much <code>Object</code> instances as possible to bring JVM
|
||||
* into stress, and then check if exceptions are correctly thrown accordingly
|
||||
* to various situations like integer division by 0, etc.
|
||||
*/
|
||||
private static int run(PrintStream out) {
|
||||
out.println("# While printing this message, JVM seems to initiate the output");
|
||||
out.println("# stream, so that it will not need more memory to print later,");
|
||||
out.println("# when the heap would fail to provide more memory.");
|
||||
out.println("# ");
|
||||
out.println("# Note, that the test maintains especial static log[] field in");
|
||||
out.println("# order to avoid printing when the heap seems exhausted.");
|
||||
out.println("# Nevertheless, printing could arise OutOfMemoryError even");
|
||||
out.println("# after all the memory allocated by the test is released.");
|
||||
out.println("# ");
|
||||
out.println("# That problem is caused by the known JDK/HotSpot bugs:");
|
||||
out.println("# 4239841 (P1/S5) 1.1: poor garbage collector performance");
|
||||
out.println("# 4245060 (P4/S5) poor garbage collector performance");
|
||||
out.println("# ");
|
||||
out.println("# This message is just intended to work-around that problem.");
|
||||
out.println("# If printing should fail even so, the test will try to return");
|
||||
out.println("# the exit status 96 instead of 97 to indicate the problem.");
|
||||
out.println("# However, the test may fail or even crash on some platforms");
|
||||
out.println("# suffering the bug 4239841 or 4245060.");
|
||||
|
||||
// Sum up exit code:
|
||||
int exitCode = 0; // apparently PASSED
|
||||
int skipped = 0; // some checks may correctly suffer OutOfMemoryError
|
||||
Class oops;
|
||||
// Allocate repository for a lots of tiny objects:
|
||||
for (int size = 1 << 30; size > 0 && pool == null; size >>= 1)
|
||||
try {
|
||||
pool = new Object[size];
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
if (pool == null)
|
||||
throw new Error("HS bug: cannot allocate new Object[1]");
|
||||
int poolSize = pool.length;
|
||||
|
||||
int index = 0;
|
||||
pool[index++] = new Object();
|
||||
|
||||
// Sum up time spent, when it was hard to JVM to allocate next object
|
||||
// (i.e.: when JVM has spent more than 1 second to allocate new object):
|
||||
double totalDelay = 0;
|
||||
long timeMark = System.currentTimeMillis();
|
||||
try {
|
||||
for (; index < poolSize; index++) {
|
||||
//-------------------------
|
||||
pool[index] = new Object();
|
||||
long nextTimeMark = System.currentTimeMillis();
|
||||
long elapsed = nextTimeMark - timeMark;
|
||||
timeMark = nextTimeMark;
|
||||
//----------------------
|
||||
if (elapsed > 1000) {
|
||||
double seconds = elapsed / 1000.0;
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"pool[" + index + "]=new Object(); // elapsed " + seconds + "s");
|
||||
totalDelay += seconds;
|
||||
if (totalDelay > 60) {
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"Memory allocation became slow; so, heap seems exhausted.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Heap seems exhausted - OutOfMemoryError thrown.";
|
||||
}
|
||||
|
||||
if (index > poolSize - 1000) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Warning: pool[] is full; so, checks would not be enough hard...";
|
||||
}
|
||||
|
||||
// Check ExceptionInInitializerError:
|
||||
try {
|
||||
oops = Class.forName(className);
|
||||
log[messages++] = "Failure: ExceptionInInitializerError failed to throw";
|
||||
exitCode = 2;
|
||||
} catch (ExceptionInInitializerError eiie) {
|
||||
String message = eiie.getException().getMessage();
|
||||
if (!message.equals("except011oops")) {
|
||||
log[messages++] =
|
||||
"Failure: ExceptionInInitializerError: unexpected target exception";
|
||||
exitCode = 2;
|
||||
} else if (TRACE_ON)
|
||||
log[messages++] = "Success: ExceptionInInitializerError thrown as expected";
|
||||
} catch (ClassNotFoundException cnfe) {
|
||||
log[messages++] = "Failure: ExceptionInInitializerError: target class not found";
|
||||
exitCode = 2;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] =
|
||||
"Skipped: ExceptionInInitializerError: thrown OutOfMemoryError";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-call to <code>run(args,out)</code>, and return JCK-like exit status.
|
||||
* (The stream <code>out</code> is assigned to <code>System.out</code> here.)
|
||||
*
|
||||
* @see #run(String[], PrintStream)
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||
// Last try. If there is some OOME, test should end correctly
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
try {
|
||||
pool = null;
|
||||
log = null;
|
||||
System.gc(); // Empty memory to be able to write to the output
|
||||
if (e instanceof OutOfMemoryError) {
|
||||
try {
|
||||
System.out.println("OOME : Test Skipped");
|
||||
System.exit(0);
|
||||
} catch (Throwable ignore) {
|
||||
} // No code in the handler can provoke correct exceptions.
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
throw (RuntimeException) e;
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
}
|
||||
});
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status.
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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.
|
||||
*/
|
||||
|
||||
package nsk.stress.except;
|
||||
|
||||
/**
|
||||
* This class throws exception while static initialization.
|
||||
* The test should load this class via reflection in order
|
||||
* to hold the exception until runtime.
|
||||
*
|
||||
* @see nsk.stress.except.except011
|
||||
*/
|
||||
public class except011oops {
|
||||
static boolean truth = true;
|
||||
|
||||
static {
|
||||
if (truth)
|
||||
throw new RuntimeException("except011oops");
|
||||
}
|
||||
}
|
||||
366
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except012.java
Normal file
366
test/hotspot/jtreg/vmTestbase/nsk/stress/except/except012.java
Normal file
@ -0,0 +1,366 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/except/except012.
|
||||
* VM testbase keywords: [stress, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* Throwable instance.
|
||||
* The test tries to occupy all of memory available in the heap by allocating
|
||||
* lots of new Object() instances. Instances of the type Object are the smallest
|
||||
* objects, so they apparently should occupy most fine-grained fragments in the
|
||||
* heap and leave no free space for new Throwable instance. After that, the test
|
||||
* provokes various exceptions (e.g.: by executing integer division by 0 and so
|
||||
* on), and checks if appropriate exceptions are thrown.
|
||||
* COMMENTS
|
||||
* The test needs a lot of memory to start up, so it should not run under older
|
||||
* JDK 1.1.x release due to its poorer heap utilization. Also, some checks are
|
||||
* skipped when testing classic VM, because OutOfMemoryError is correctly thrown
|
||||
* instead of target exception.
|
||||
* When the test is being self-initiating (i.e.: eating heap), memory occupation
|
||||
* is terminated if memory allocation slows down crucially. This is a workaround
|
||||
* intended to avoid the HotSpot bug:
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance (HotSpot bug)
|
||||
* #4245060 (P4/S5) poor garbage collector performance (Classic VM bug)
|
||||
* However, printing of the test's error messages, warnings, and of execution
|
||||
* trace fails under JDK 1.2 for Win32 even so. If the test fails due to this
|
||||
* problem, exit status 96 is returned instead of 97.
|
||||
* JDK 1.3 classic VM for Sparc may crash (core dump) due to the known bug:
|
||||
* #4245057 (P2/S3) VM crashes when heap is exhausted
|
||||
*
|
||||
* @run main/othervm -Xms50M -Xmx200M nsk.stress.except.except012
|
||||
*/
|
||||
|
||||
package nsk.stress.except;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* This checks if various exceptions are thrown (and caught) correctly
|
||||
* when there apparently are no free space in the heap to allocate new
|
||||
* <code>Throwable</code> instance.
|
||||
* <p>
|
||||
* <p>The test tries to occupy all of memory available in the heap by
|
||||
* allocating lots of new <code>Object()</code> instances. Instances of the
|
||||
* type <code>Object</code> are the smallest objects, so they apparently should
|
||||
* occupy most fine-grained fragments in the heap and leave no free space for
|
||||
* new <code>Throwable</code> instance. After that, the test provokes various
|
||||
* exceptions (e.g.: by executing integer division by 0 and so on), and checks
|
||||
* if appropriate exceptions are thrown.
|
||||
* <p>
|
||||
* <p>Note, that memory occupation is terminated if memory allocation slows
|
||||
* down crucially. This is a workaround intended to avoid the HotSpot bug:
|
||||
* <br>
|
||||
* #4248801 (P1/S5) slow memory allocation when heap is almost exhausted
|
||||
* <p>
|
||||
* <p>There is also a workaround involved to avoid the following bugs known
|
||||
* for HotSpot and for classic VM:
|
||||
* <br>
|
||||
* #4239841 (P1/S5) 1.1: poor garbage collector performance
|
||||
* <br>
|
||||
* #4245060 (P4/S5) poor garbage collector performance
|
||||
* <br>However, printing of the test's error messages, warnings, and of
|
||||
* execution trace may fail even so. If the test fails due to poor GC
|
||||
* performance, exit status 96 is returned instead of 97.
|
||||
* <p>
|
||||
* <p>Also note, that the test needs a lot of memory to start up, so it should
|
||||
* not run under older JDK 1.1.x release due to its poor heap utilization.
|
||||
*/
|
||||
public class except012 {
|
||||
/**
|
||||
* Either allow or supress printing of execution trace.
|
||||
*/
|
||||
private static boolean TRACE_ON = false;
|
||||
/**
|
||||
* Either allow or supress printing of warning messages.
|
||||
*/
|
||||
private static final boolean WARN_ON = true;
|
||||
|
||||
/**
|
||||
* Temporary <code>log</code> for error messages, warnings and/or execution trace.
|
||||
*
|
||||
* @see #messages
|
||||
*/
|
||||
private static String log[] = new String[1000]; // up to 1000 messages
|
||||
/**
|
||||
* How many <code>messages</code> were submitted to the <code>log</code>.
|
||||
*
|
||||
* @see #log
|
||||
*/
|
||||
private static int messages = 0;
|
||||
/*
|
||||
* Storage for a lot of tiny objects
|
||||
* "static volatile" keywords are for preventing heap optimization
|
||||
*/
|
||||
private static volatile Object pool[] = null;
|
||||
|
||||
/**
|
||||
* Re-call to the method <code>run(out)</code> (ignore <code>args[]</code>),
|
||||
* and print the test summary - either test passed of failed.
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
if (args.length > 0) {
|
||||
if (args[0].toLowerCase().startsWith("-v"))
|
||||
TRACE_ON = true;
|
||||
}
|
||||
|
||||
int exitCode = run(out);
|
||||
pool = null;
|
||||
System.gc();
|
||||
// Print the log[] and the test summary:
|
||||
try {
|
||||
for (int i = 0; i < messages; i++)
|
||||
out.println(log[i]);
|
||||
if (exitCode == 0) {
|
||||
if (TRACE_ON)
|
||||
out.println("Test passed.");
|
||||
} else
|
||||
out.println("Test failed.");
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Poor performance of garbage collector:
|
||||
exitCode = 1;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate as much <code>Object</code> instances as possible to bring JVM
|
||||
* into stress, and then check if exceptions are correctly thrown accordingly
|
||||
* to various situations like integer division by 0, etc.
|
||||
*/
|
||||
private static int run(PrintStream out) {
|
||||
out.println("# While printing this message, JVM seems to initiate the output");
|
||||
out.println("# stream, so that it will not need more memory to print later,");
|
||||
out.println("# when the heap would fail to provide more memory.");
|
||||
out.println("# ");
|
||||
out.println("# Note, that the test maintains especial static log[] field in");
|
||||
out.println("# order to avoid printing when the heap seems exhausted.");
|
||||
out.println("# Nevertheless, printing could arise OutOfMemoryError even");
|
||||
out.println("# after all the memory allocated by the test is released.");
|
||||
out.println("# ");
|
||||
out.println("# That problem is caused by the known JDK/HotSpot bugs:");
|
||||
out.println("# 4239841 (P1/S5) 1.1: poor garbage collector performance");
|
||||
out.println("# 4245060 (P4/S5) poor garbage collector performance");
|
||||
out.println("# ");
|
||||
out.println("# This message is just intended to work-around that problem.");
|
||||
out.println("# If printing should fail even so, the test will try to return");
|
||||
out.println("# the exit status 96 instead of 97 to indicate the problem.");
|
||||
out.println("# However, the test may fail or even crash on some platforms");
|
||||
out.println("# suffering the bug 4239841 or 4245060.");
|
||||
|
||||
// Allocate items necessary for the test:
|
||||
CrazyClassLoader crazyClassLoader = new CrazyClassLoader();
|
||||
MustDie threadToDie = new MustDie();
|
||||
|
||||
// Sum up exit code:
|
||||
int exitCode = 0; // apparently PASSED
|
||||
int skipped = 0; // some checks may correctly suffer OutOfMemoryError
|
||||
// Allocate repository for a lots of tiny objects:
|
||||
for (int size = 1 << 30; size > 0 && pool == null; size >>= 1)
|
||||
try {
|
||||
pool = new Object[size];
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
if (pool == null)
|
||||
throw new Error("HS bug: cannot allocate new Object[1]");
|
||||
int poolSize = pool.length;
|
||||
|
||||
int index = 0;
|
||||
pool[index++] = new Object();
|
||||
|
||||
// Sum up time spent, when it was hard to JVM to allocate next object
|
||||
// (i.e.: when JVM has spent more than 1 second to allocate new object):
|
||||
double totalDelay = 0;
|
||||
long timeMark = System.currentTimeMillis();
|
||||
try {
|
||||
for (; index < poolSize; index++) {
|
||||
//-------------------------
|
||||
pool[index] = new Object();
|
||||
long nextTimeMark = System.currentTimeMillis();
|
||||
long elapsed = nextTimeMark - timeMark;
|
||||
timeMark = nextTimeMark;
|
||||
//----------------------
|
||||
if (elapsed > 1000) {
|
||||
double seconds = elapsed / 1000.0;
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"pool[" + index + "]=new Object(); // elapsed " + seconds + "s");
|
||||
totalDelay += seconds;
|
||||
if (totalDelay > 60) {
|
||||
if (TRACE_ON)
|
||||
out.println(
|
||||
"Memory allocation became slow; so, heap seems exhausted.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Heap seems exhausted - OutOfMemoryError thrown.";
|
||||
}
|
||||
|
||||
if (index > poolSize - 1000) {
|
||||
if (WARN_ON)
|
||||
log[messages++] = "Warning: pool[] is full; so, checks would not be enough hard...";
|
||||
}
|
||||
|
||||
// Check ClassFormatError:
|
||||
try {
|
||||
Class oops = crazyClassLoader.loadClass("name doesn't matter");
|
||||
log[messages++] = "Failure: ClassFormatError failed to throw";
|
||||
exitCode = 2;
|
||||
} catch (ClassFormatError cfe) {
|
||||
if (TRACE_ON)
|
||||
log[messages++] = "Success: ClassFormatError thrown as expected";
|
||||
} catch (ClassNotFoundException cnfe) {
|
||||
log[messages++] =
|
||||
"Failure: ClassFormatError: unexpectedly thrown ClassNotFoundException";
|
||||
exitCode = 2;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] =
|
||||
"Skipped: ClassFormatError: thrown OutOfMemoryError";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
// Check ThreadDeath:
|
||||
try {
|
||||
threadToDie.start();
|
||||
while (threadToDie.isAlive())
|
||||
threadToDie.join();
|
||||
Throwable exception = threadToDie.exception;
|
||||
if (exception == null) {
|
||||
log[messages++] = "Failure: ThreadDeath failed to throw";
|
||||
exitCode = 2;
|
||||
} else if (exception instanceof OutOfMemoryError) {
|
||||
if (WARN_ON)
|
||||
log[messages++] =
|
||||
"Skipped: ThreadDeath: thrown OutOfMemoryError instead";
|
||||
} else if (!(exception instanceof ThreadDeath)) {
|
||||
log[messages++] =
|
||||
"Failure: ThreadDeath: unexpected exception thrown";
|
||||
exitCode = 2;
|
||||
} else if (TRACE_ON)
|
||||
log[messages++] = "Success: ThreadDeath thrown as expected";
|
||||
} catch (InterruptedException ie) {
|
||||
pool[index++] = ie;
|
||||
log[messages++] =
|
||||
"Failure: ThreadDeath: thrown InterruptedException instead";
|
||||
exitCode = 2;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
if (WARN_ON)
|
||||
log[messages++] =
|
||||
"Skipped: ThreadDeath: thrown OutOfMemoryError";
|
||||
skipped++;
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class loader provokes <code>ClassFormatError</code>.
|
||||
*/
|
||||
private static class CrazyClassLoader extends ClassLoader {
|
||||
public Class loadClass(String name) throws ClassNotFoundException {
|
||||
Class crazyClass = defineClass(null, crazyBytecode, 0, crazyBytecode.length);
|
||||
return crazyClass; // return is unreacable, due to ClassFormatError
|
||||
}
|
||||
|
||||
private static byte crazyBytecode[];
|
||||
|
||||
static {
|
||||
crazyBytecode = new byte[1000];
|
||||
Random random = new Random(0);
|
||||
for (int i = 0; i < crazyBytecode.length; i++)
|
||||
crazyBytecode[i] = (byte) random.nextInt(256);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This thread should die in order to check <code>ThreadDeath</code> error.
|
||||
*/
|
||||
private static class MustDie extends Thread {
|
||||
Throwable exception = null;
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
stop();
|
||||
} catch (Throwable throwable) {
|
||||
exception = throwable;
|
||||
if (throwable instanceof ThreadDeath)
|
||||
throw (ThreadDeath) throwable;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-call to <code>run(args,out)</code>, and return JCK-like exit status.
|
||||
* (The stream <code>out</code> is assigned to <code>System.out</code> here.)
|
||||
*
|
||||
* @see #run(String[], PrintStream)
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||
// Last try. If there is some OOME, test should end correctly
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
try {
|
||||
pool = null;
|
||||
System.gc(); // Empty memory to be able to write to the output
|
||||
if (e instanceof OutOfMemoryError) {
|
||||
try {
|
||||
System.out.println("OOME : Test Skipped");
|
||||
System.exit(0);
|
||||
} catch (Throwable ignore) {
|
||||
} // any of the test exceptions are handled in test.#
|
||||
// No code in the handler can provoke correct exceptions.
|
||||
} else if (e instanceof ThreadDeath) {
|
||||
} //ignore since it thrown as expected
|
||||
else {
|
||||
e.printStackTrace();
|
||||
throw (RuntimeException) e;
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
}
|
||||
});
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status.
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package nsk.stress.jni;
|
||||
|
||||
class GarbageGenerator extends Thread {
|
||||
class Garbage {
|
||||
Garbage() {
|
||||
this(1024);
|
||||
}
|
||||
|
||||
Garbage(int m) {
|
||||
memory = new byte[m];
|
||||
}
|
||||
|
||||
void setNext(Garbage n) {
|
||||
next = n;
|
||||
}
|
||||
|
||||
Garbage getNext() {
|
||||
return next;
|
||||
}
|
||||
|
||||
protected void finalize() {
|
||||
}
|
||||
|
||||
private Garbage next;
|
||||
private byte[] memory;
|
||||
}
|
||||
|
||||
class GarbageRing {
|
||||
GarbageRing() {
|
||||
attachment = new Garbage(0);
|
||||
}
|
||||
|
||||
void add(int size) {
|
||||
Garbage head = attachment.getNext();
|
||||
Garbage g = new Garbage(size);
|
||||
if (head != null) {
|
||||
Garbage oldNext = head.getNext();
|
||||
if (oldNext != null) {
|
||||
g.setNext(oldNext);
|
||||
head.setNext(g);
|
||||
attachment.setNext(g);
|
||||
} else {
|
||||
g.setNext(head);
|
||||
head.setNext(g);
|
||||
}
|
||||
} else
|
||||
attachment.setNext(g);
|
||||
}
|
||||
|
||||
void discard() {
|
||||
attachment.setNext(null);
|
||||
}
|
||||
|
||||
private byte[] memory;
|
||||
private Garbage attachment;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
GarbageRing gr = new GarbageRing();
|
||||
int g = 0;
|
||||
while (!done) {
|
||||
for (g = 0; g < ringSize; g++) {
|
||||
gr.add(allocSize);
|
||||
yield();
|
||||
}
|
||||
gr.discard();
|
||||
try {
|
||||
sleep(interval);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("GarbageRing::run(): done");
|
||||
}
|
||||
|
||||
public void setAllocSize(int i) {
|
||||
allocSize = i;
|
||||
}
|
||||
|
||||
public int getAllocSize() {
|
||||
return allocSize;
|
||||
}
|
||||
|
||||
public void setInterval(int i) {
|
||||
interval = i;
|
||||
}
|
||||
|
||||
public int getInterval() {
|
||||
return interval;
|
||||
}
|
||||
|
||||
public void halt() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
private int allocSize = 10000;
|
||||
private int ringSize = 50;
|
||||
private int interval = 1000;
|
||||
private boolean done = false;
|
||||
final private static boolean DEBUG = false;
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package nsk.stress.jni;
|
||||
|
||||
class Interrupter extends Thread {
|
||||
public Interrupter(
|
||||
Thread[] alloc,
|
||||
Synchronizer[] s
|
||||
) {
|
||||
targets = alloc;
|
||||
sync = s;
|
||||
if (DEBUG) System.out.println("Interrupter created.");
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (!done) {
|
||||
synchronized (sync[2]) {
|
||||
targets[turn].interrupt();
|
||||
}
|
||||
turn = (turn + 1) % targets.length;
|
||||
try {
|
||||
sleep(interval);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("Interrupter::run(): done");
|
||||
}
|
||||
|
||||
public void setInterval(int i) {
|
||||
interval = i;
|
||||
}
|
||||
|
||||
public int getInterval() {
|
||||
return interval;
|
||||
}
|
||||
|
||||
public void halt() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
Thread[] targets;
|
||||
Synchronizer[] sync;
|
||||
private int turn = 0;
|
||||
private int interval = 1000;
|
||||
private boolean done = false;
|
||||
final private static boolean DEBUG = false;
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package nsk.stress.jni;
|
||||
|
||||
class Synchronizer {
|
||||
}
|
||||
24
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/TEST.properties
Normal file
24
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/TEST.properties
Normal file
@ -0,0 +1,24 @@
|
||||
#
|
||||
# Copyright (c) 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.
|
||||
#
|
||||
|
||||
exclusiveAccess.dirs=.
|
||||
@ -0,0 +1,499 @@
|
||||
/*
|
||||
* 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: JDK-8199562
|
||||
* 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 JDK-8199562
|
||||
* @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);
|
||||
}
|
||||
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#include <jni.h>
|
||||
#include <stdlib.h>
|
||||
#include "jnihelper.h"
|
||||
|
||||
// compare most java primitive value types
|
||||
#define COMP(type) \
|
||||
int type##comp(const void *s1, const void *s2)\
|
||||
{\
|
||||
type st1 = *((type *)s1);\
|
||||
type st2 = *((type *)s2);\
|
||||
if (st1 < st2)\
|
||||
return -1;\
|
||||
else if (st1 > st2)\
|
||||
return 1;\
|
||||
else\
|
||||
return 0;\
|
||||
}
|
||||
|
||||
// basic routine: provide critical sections and calculations
|
||||
// enter array CS
|
||||
// check isCopy for native referencing
|
||||
// enter first string CS
|
||||
// leave first string CS
|
||||
// enter second string CS
|
||||
// leave array CS
|
||||
// enter second string CS
|
||||
|
||||
#define BODY(type) \
|
||||
int hash = 0; int i; jboolean isCopy = JNI_FALSE; jchar *nativeStr; jsize size; type *nativeArray; \
|
||||
size = (*env)->GetArrayLength(env, array); CE \
|
||||
nativeArray = (type *)(*env)->GetPrimitiveArrayCritical(env, array, &isCopy); CE \
|
||||
EnterCS(env); \
|
||||
if (isCopy == JNI_TRUE) return 0;\
|
||||
qsort(nativeArray, size, sizeof(type), *type##comp);\
|
||||
\
|
||||
size = (*env)->GetStringLength(env, str); CE \
|
||||
nativeStr = (jchar *)(*env)->GetStringCritical(env, str, &isCopy); CE \
|
||||
if (isCopy == JNI_TRUE) return 0;\
|
||||
for (i = 0; i < size; ++i)\
|
||||
hash += (int)nativeStr[i];\
|
||||
\
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, array, nativeArray, 0); CE \
|
||||
LeaveCS(env); \
|
||||
(*env)->ReleaseStringCritical(env, str, nativeStr); CE \
|
||||
\
|
||||
hash = 0;\
|
||||
size = (*env)->GetStringLength(env, str); CE \
|
||||
nativeStr = (jchar *)(*env)->GetStringCritical(env, str, &isCopy); CE \
|
||||
EnterCS(env); \
|
||||
if (isCopy == JNI_TRUE) return 0;\
|
||||
for (i = 0; i < size; ++i)\
|
||||
hash += (int)nativeStr[i];\
|
||||
LeaveCS(env); \
|
||||
(*env)->ReleaseStringCritical(env, str, nativeStr); CE \
|
||||
return hash;
|
||||
|
||||
static int CSEntered = 0;
|
||||
static int CSLeft = 0;
|
||||
|
||||
void EnterCS(JNIEnv *env)
|
||||
{
|
||||
// unsafe but where are no better ideas
|
||||
//++CSEntered;
|
||||
//printf("CS Entered -> Entered: %d\n", CSEntered);
|
||||
// jclass trace = 0; jmethodID method = 0;
|
||||
// trace = (*env)->FindClass(env, "nsk/stress/jni/gclocker/Trace"); CE
|
||||
// method = (*env)->GetStaticMethodID(env, trace, "EnterCS", "()V"); CE
|
||||
// (*env)->CallStaticVoidMethod(env, trace, method); CE
|
||||
}
|
||||
|
||||
void LeaveCS(JNIEnv *env)
|
||||
{
|
||||
// unsafe but where are no better ideas
|
||||
//++CSLeft;
|
||||
//printf("CS Left -> Completed: %d\tActive: %d\n", CSLeft, CSEntered - CSLeft);
|
||||
// jclass trace = 0; jmethodID method = 0;
|
||||
// trace = (*env)->FindClass(env, "nsk/stress/jni/gclocker/Trace"); CE
|
||||
// method = (*env)->GetStaticMethodID(env, trace, "LeaveCS", "()V"); CE
|
||||
// (*env)->CallStaticVoidMethod(env, trace, method); CE
|
||||
}
|
||||
|
||||
COMP(jint)
|
||||
COMP(jboolean)
|
||||
COMP(jchar)
|
||||
COMP(jshort)
|
||||
COMP(jbyte)
|
||||
COMP(jdouble)
|
||||
COMP(jfloat)
|
||||
COMP(jlong)
|
||||
|
||||
/*
|
||||
* Class: JNIWorker
|
||||
* Method: NativeCall
|
||||
* Signature: ([ZLjava/lang/String;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_nsk_stress_jni_gclocker_JNIWorker_NativeCall___3ZLjava_lang_String_2
|
||||
(JNIEnv * env, jobject obj, jbooleanArray array, jstring str)
|
||||
{
|
||||
BODY(jboolean)
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: JNIWorker
|
||||
* Method: NativeCall
|
||||
* Signature: ([BLjava/lang/String;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_nsk_stress_jni_gclocker_JNIWorker_NativeCall___3BLjava_lang_String_2
|
||||
(JNIEnv * env, jobject obj, jbyteArray array, jstring str)
|
||||
{
|
||||
BODY(jbyte)
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: JNIWorker
|
||||
* Method: NativeCall
|
||||
* Signature: ([CLjava/lang/String;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_nsk_stress_jni_gclocker_JNIWorker_NativeCall___3CLjava_lang_String_2
|
||||
(JNIEnv *env, jobject obj, jcharArray array, jstring str)
|
||||
{
|
||||
BODY(jchar)
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: JNIWorker
|
||||
* Method: NativeCall
|
||||
* Signature: ([SLjava/lang/String;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_nsk_stress_jni_gclocker_JNIWorker_NativeCall___3SLjava_lang_String_2
|
||||
(JNIEnv *env, jobject obj, jshortArray array, jstring str)
|
||||
{
|
||||
BODY(jshort)
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: JNIWorker
|
||||
* Method: NativeCall
|
||||
* Signature: ([ILjava/lang/String;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_nsk_stress_jni_gclocker_JNIWorker_NativeCall___3ILjava_lang_String_2
|
||||
(JNIEnv *env, jobject obj, jintArray array, jstring str)
|
||||
{
|
||||
BODY(jint)
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: JNIWorker
|
||||
* Method: NativeCall
|
||||
* Signature: ([JLjava/lang/String;)I
|
||||
*/
|
||||
|
||||
JNIEXPORT jint JNICALL Java_nsk_stress_jni_gclocker_JNIWorker_NativeCall___3JLjava_lang_String_2
|
||||
(JNIEnv *env, jobject obj, jlongArray array, jstring str)
|
||||
{
|
||||
BODY(jlong)
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: JNIWorker
|
||||
* Method: NativeCall
|
||||
* Signature: ([FLjava/lang/String;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_nsk_stress_jni_gclocker_JNIWorker_NativeCall___3FLjava_lang_String_2
|
||||
(JNIEnv *env, jobject obj, jfloatArray array, jstring str)
|
||||
{
|
||||
BODY(jfloat)
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: JNIWorker
|
||||
* Method: NativeCall
|
||||
* Signature: ([DLjava/lang/String;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_nsk_stress_jni_gclocker_JNIWorker_NativeCall___3DLjava_lang_String_2
|
||||
(JNIEnv *env, jobject obj, jdoubleArray array, jstring str)
|
||||
{
|
||||
BODY(jdouble)
|
||||
}
|
||||
33
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/jnihelper.h
Normal file
33
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/jnihelper.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Asserts every exception as fatal one
|
||||
#define CE {\
|
||||
if ((*env)->ExceptionOccurred(env))\
|
||||
{\
|
||||
puts("Unexpected JNI exception. TEST FAIL."); \
|
||||
(*env)->ExceptionDescribe(env); \
|
||||
(*env)->ExceptionClear(env);\
|
||||
(*env)->FatalError(env, "Unexpected JNI Exception. TEST FAIL."); \
|
||||
}\
|
||||
}
|
||||
492
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/jnistress001.java
Normal file
492
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/jnistress001.java
Normal file
@ -0,0 +1,492 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* jnistress001 is a class that sets up classes that do the work
|
||||
* for the test.
|
||||
*
|
||||
* The Interrupter objects send interrupts to the JNIters.
|
||||
* The GarbageGenerator objects generate garbage.
|
||||
*
|
||||
* sync[0] synchronizes the test cycles.
|
||||
* sync[1] synchronizes access to exception counters.
|
||||
* sync[2] synchronizes the cycle count update. It also insures that
|
||||
* the interrupts do not interfere with the cycle count updates.
|
||||
* This is because cycle count updates are used to define cycles.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @key stress
|
||||
*
|
||||
* @summary converted from VM testbase nsk/stress/jni/jnistress001.
|
||||
* VM testbase keywords: [stress, quick, feature_283, nonconcurrent]
|
||||
*
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @run driver jdk.test.lib.FileInstaller . .
|
||||
* @run main/othervm/native
|
||||
* nsk.stress.jni.jnistress001
|
||||
* -numTHREADer 20
|
||||
* -threadInterval 200
|
||||
* -numInterrupter 2
|
||||
* -interruptInterval 500
|
||||
* -numGarbage 80
|
||||
* -garbageInterval 5
|
||||
* -numIteration 200
|
||||
*/
|
||||
|
||||
package nsk.stress.jni;
|
||||
|
||||
import nsk.share.Consts;
|
||||
import nsk.share.Debug;
|
||||
import nsk.share.test.StressOptions;
|
||||
|
||||
public class jnistress001 extends Thread {
|
||||
|
||||
/* Maximum number of iterations. Ignored if <= 0L */
|
||||
static long numIteration = 0L;
|
||||
/* Timeout */
|
||||
static long timeOut;
|
||||
/* Number of test class objects */
|
||||
static int numJNIter = 1;
|
||||
/* Time between JNI stressing by the threads under test */
|
||||
/* (in milliseconds) */
|
||||
static int jniInterval = 10000;
|
||||
/* Number of interrupting threads */
|
||||
static int numInterrupter = 1;
|
||||
/* Time between interrupts in milliseconds */
|
||||
static int interruptInterval = 1000;
|
||||
/* Number of garbage generating threads */
|
||||
static int numGarbage = 1;
|
||||
/* Time between garbage allocations in milliseconds */
|
||||
static int garbageInterval = 1000;
|
||||
// Size of string's array in native method
|
||||
static int jniStringAllocSize = 1000;
|
||||
// Print period for native method
|
||||
static int printPeriod = 200;
|
||||
|
||||
private static StressOptions stressOptions;
|
||||
|
||||
public static void main(String[] argv) {
|
||||
try {
|
||||
int i = 0;
|
||||
int nJNISync = 10;
|
||||
jnistress001 dm = null;
|
||||
boolean errArg = false;
|
||||
|
||||
stressOptions = new StressOptions(argv);
|
||||
|
||||
/* Process arguments */
|
||||
while (!errArg && i < argv.length) {
|
||||
/* Number of iterations. Ignored if <= 0. */
|
||||
if (i < argv.length && argv[i].equals("-numIteration")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numIteration = Long.parseLong(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numTHREADer")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numJNIter = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
if (numJNIter <= 0) errArg = true;
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-threadInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
jniInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numInterrupter")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numInterrupter = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-interruptInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
interruptInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numGarbage")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numGarbage = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-garbageInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
garbageInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-jniStringAllocSize")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
jniStringAllocSize = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-printperiod")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
printPeriod = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].startsWith("-stress")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
++i;
|
||||
}
|
||||
} else System.out.println("Argument #" + i++ + " is incorrect");
|
||||
|
||||
}
|
||||
|
||||
numIteration *= stressOptions.getIterationsFactor();
|
||||
numJNIter *= stressOptions.getThreadsFactor();
|
||||
numInterrupter *= stressOptions.getThreadsFactor();
|
||||
numGarbage *= stressOptions.getThreadsFactor();
|
||||
timeOut = stressOptions.getTime() * 1000;
|
||||
|
||||
sync = new Synchronizer[10];
|
||||
for (i = 0; i < nJNISync; i++)
|
||||
sync[i] = new Synchronizer();
|
||||
dm = new jnistress001(numIteration, numJNIter, jniInterval,
|
||||
numInterrupter, interruptInterval, numGarbage, garbageInterval);
|
||||
dm.start();
|
||||
|
||||
try {
|
||||
dm.join(timeOut);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("TESTER THREAD WAS INTERRUPTED");
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
}
|
||||
|
||||
if (DEBUG) System.out.println("jnistress001::main(): halt!");
|
||||
|
||||
if (dm.isAlive()) {
|
||||
System.out.println("TIME LIMIT EXCEEDED");
|
||||
dm.halt();
|
||||
if (DEBUG) System.out.println("jnistress001::main(): join!");
|
||||
try {
|
||||
dm.join(10000L);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("TESTER THREAD WAS INTERRUPTED");
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
}
|
||||
} else {
|
||||
System.out.println("TESTER THREAD FINISHED");
|
||||
}
|
||||
|
||||
if (DEBUG) System.out.println("jnistress001::main(): zzzz...");
|
||||
|
||||
if (!JNIter001.passed())
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
|
||||
} catch (Throwable e) {
|
||||
Debug.Fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
jnistress001(
|
||||
long iters,
|
||||
int nJNI,
|
||||
int jniInterval,
|
||||
int nInter,
|
||||
int iruptInterval,
|
||||
int nGarb,
|
||||
int garbInterval
|
||||
) {
|
||||
int i = 0;
|
||||
nCycles = iters;
|
||||
/* Should have at least one of nCycles>0 */
|
||||
if (nCycles <= 0) nCycles = Long.MAX_VALUE;
|
||||
jniter = new JNIter001[nJNI];
|
||||
interval = jniInterval;
|
||||
irupt = new Interrupter[nInter];
|
||||
garb = new GarbageGenerator[nGarb];
|
||||
for (i = 0; i < nJNI; i++)
|
||||
jniter[i] = new JNIter001(sync);
|
||||
for (i = 0; i < nInter; i++) {
|
||||
irupt[i] = new Interrupter(jniter, sync);
|
||||
irupt[i].setInterval(iruptInterval);
|
||||
}
|
||||
for (i = 0; i < nGarb; i++) {
|
||||
garb[i] = new GarbageGenerator();
|
||||
garb[i].setInterval(garbInterval);
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
int i = 0;
|
||||
long iCycle = 0L;
|
||||
JNIter001.clearCount();
|
||||
JNIter001.clearInterruptCount();
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
jniter[i].start();
|
||||
|
||||
while (JNIter001.getCount() < jniter.length) {
|
||||
try {
|
||||
sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
JNIter001.clearCount();
|
||||
// JNIter001.clearInterruptCount();
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
|
||||
for (i = 0; i < garb.length; i++)
|
||||
garb[i].start();
|
||||
for (i = 0; i < irupt.length; i++)
|
||||
irupt[i].start();
|
||||
|
||||
if (DEBUG) System.out.println("Cycles=" + nCycles);
|
||||
for (iCycle = 0; iCycle < nCycles && !done && JNIter001.passed(); iCycle++) {
|
||||
System.out.print("Cycle: " + iCycle);
|
||||
try {
|
||||
sleep(interval);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
synchronized (sync[1]) {
|
||||
System.out.println(" Interrupt count=" +
|
||||
JNIter001.getInterruptCount());
|
||||
}
|
||||
JNIter001.clearCount();
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
int n = 0;
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
if (jniter[i].finished()) n++;
|
||||
if (n == jniter.length) break;
|
||||
}
|
||||
if (JNIter001.passed()) { /* Use of setpass was backwards */
|
||||
System.out.println("JNI TEST PASSED");
|
||||
} else {
|
||||
System.out.println("JNI TEST FAILED");
|
||||
}
|
||||
for (i = 0; i < irupt.length; i++)
|
||||
irupt[i].halt();
|
||||
for (i = 0; i < garb.length; i++)
|
||||
garb[i].halt();
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
jniter[i].halt();
|
||||
/* Flush any waiters */
|
||||
if (DEBUG) System.out.println("jnistress001::run(): before sync[0]");
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress001::run(): after sync[0]");
|
||||
for (i = 0; i < irupt.length; i++) {
|
||||
try {
|
||||
irupt[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress001::run(): X");
|
||||
for (i = 0; i < garb.length; i++) {
|
||||
try {
|
||||
garb[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress001::run(): Y");
|
||||
System.out.println("jniter.length is " + jniter.length);
|
||||
for (i = 0; i < jniter.length; i++) {
|
||||
try {
|
||||
if (jniter[i].isAlive()) {
|
||||
jniter[i].join();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress001::run(): Z");
|
||||
}
|
||||
|
||||
public void halt() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
public boolean finished() {
|
||||
return done;
|
||||
}
|
||||
|
||||
long nCycles = 0;
|
||||
JNIter001[] jniter;
|
||||
static Synchronizer[] sync;
|
||||
private int interval = 100;
|
||||
Interrupter[] irupt;
|
||||
GarbageGenerator[] garb;
|
||||
private boolean done = false;
|
||||
final private static boolean DEBUG = false;
|
||||
}
|
||||
|
||||
class JNIter001 extends Thread {
|
||||
|
||||
// The native method for testing JNI UTF-8 calls
|
||||
public native String jnistress(String threadName, int nstr, int printPeriod);
|
||||
|
||||
// The native method for testing JNI Unicode calls
|
||||
public native String jnistress1(String threadName, int nstr, int printPeriod);
|
||||
|
||||
static {
|
||||
System.loadLibrary("jnistress001");
|
||||
}
|
||||
|
||||
public JNIter001(Synchronizer[] aSync) {
|
||||
sync = aSync;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
int iter = 0;
|
||||
|
||||
/* Synchronize start of work */
|
||||
incCount();
|
||||
synchronized (sync[0]) {
|
||||
try {
|
||||
sync[0].wait();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
while (!done && pass) {
|
||||
try {
|
||||
/* Synchronized the JNI stressing */
|
||||
synchronized (sync[2]) {
|
||||
incCount();
|
||||
}
|
||||
synchronized (sync[0]) {
|
||||
try {
|
||||
sync[0].wait();
|
||||
} catch (InterruptedException e) {
|
||||
synchronized (sync[1]) {
|
||||
JNIter001.incInterruptCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
synchronized (sync[0]) {
|
||||
String s1 = jnistress(getName(),
|
||||
jnistress001.jniStringAllocSize,
|
||||
jnistress001.printPeriod);
|
||||
String s2 = jnistress1(getName(),
|
||||
jnistress001.jniStringAllocSize,
|
||||
jnistress001.printPeriod);
|
||||
if (!s1.equals(s2))
|
||||
System.out.println("Wrong compare in thread " + getName());
|
||||
}
|
||||
if (DEBUG)
|
||||
System.out.println("We have " + activeCount() +
|
||||
" threads now.");
|
||||
} catch (Exception e) {
|
||||
synchronized (sync[1]) {
|
||||
JNIter001.incInterruptCount();
|
||||
}
|
||||
}
|
||||
iter++;
|
||||
iter = iter % CASECOUNT;
|
||||
}
|
||||
if (DEBUG) System.out.println("JNITer::run(): done=" + done);
|
||||
done = true;
|
||||
if (DEBUG) System.out.println("JNITer::run(): pass=" + JNIter001.pass);
|
||||
if (DEBUG) System.out.println("JNITer::run(): done");
|
||||
}
|
||||
|
||||
private synchronized static void incCount() {
|
||||
count++;
|
||||
}
|
||||
|
||||
public static int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public synchronized static void clearCount() {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
private synchronized static void incInterruptCount() {
|
||||
interruptCount++;
|
||||
}
|
||||
|
||||
public static int getInterruptCount() {
|
||||
return interruptCount;
|
||||
}
|
||||
|
||||
public synchronized static void clearInterruptCount() {
|
||||
interruptCount = 0;
|
||||
}
|
||||
|
||||
public static void halt() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
public boolean finished() {
|
||||
return done;
|
||||
}
|
||||
|
||||
public static boolean passed() {
|
||||
return pass;
|
||||
}
|
||||
|
||||
public static void setpass(boolean value) {
|
||||
pass = value;
|
||||
}
|
||||
|
||||
Synchronizer[] sync;
|
||||
private static int count = 0;
|
||||
private static int interruptCount = 0;
|
||||
private static boolean done = false;
|
||||
private static boolean pass = true;
|
||||
final private static int CASECOUNT = 2;
|
||||
final private static boolean DEBUG = false;
|
||||
}
|
||||
582
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/jnistress002.java
Normal file
582
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/jnistress002.java
Normal file
@ -0,0 +1,582 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* jnistress002 is a class that sets up classes that do the work
|
||||
* for the test.
|
||||
*
|
||||
* The Interrupter objects send interrupts to the JNIters.
|
||||
* The GarbageGenerator objects generate garbage.
|
||||
*
|
||||
* sync[0] synchronizes the test cycles.
|
||||
* sync[1] synchronizes access to exception counters.
|
||||
* sync[2] synchronizes the cycle count update. It also insures that
|
||||
* the interrupts do not interfere with the cycle count updates.
|
||||
* This is because cycle count updates are used to define cycles.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @key stress
|
||||
*
|
||||
* @summary converted from VM testbase nsk/stress/jni/jnistress002.
|
||||
* VM testbase keywords: [stress, quick, feature_283, nonconcurrent]
|
||||
*
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @run driver jdk.test.lib.FileInstaller . .
|
||||
* @run main/othervm/native
|
||||
* nsk.stress.jni.jnistress002
|
||||
* -numTHREADer 20
|
||||
* -threadInterval 200
|
||||
* -numInterrupter 2
|
||||
* -interruptInterval 500
|
||||
* -numGarbage 80
|
||||
* -garbageInterval 5
|
||||
* -numIteration 260
|
||||
*/
|
||||
|
||||
package nsk.stress.jni;
|
||||
|
||||
import nsk.share.Consts;
|
||||
import nsk.share.Debug;
|
||||
import nsk.share.test.StressOptions;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Random;
|
||||
|
||||
public class jnistress002 extends Thread {
|
||||
|
||||
/* Maximum number of iterations. Ignored if <= 0L */
|
||||
static long numIteration = 0L;
|
||||
/* Timeout */
|
||||
static long timeOut;
|
||||
/* Number of test class objects */
|
||||
static int numJNIter = 1;
|
||||
/* Time between JNI stressing by the threads under test */
|
||||
/* (in milliseconds) */
|
||||
static int jniInterval = 10000;
|
||||
/* Number of interrupting threads */
|
||||
static int numInterrupter = 1;
|
||||
/* Time between interrupts in milliseconds */
|
||||
static int interruptInterval = 100;
|
||||
/* Number of garbage generating threads */
|
||||
static int numGarbage = 1;
|
||||
/* Time between garbage allocations in milliseconds */
|
||||
static int garbageInterval = 100;
|
||||
// The number of classes for creates via JNI
|
||||
static int jniStringAllocSize = 10000;
|
||||
|
||||
private static StressOptions stressOptions;
|
||||
|
||||
public static void main(String[] argv) {
|
||||
try {
|
||||
int i = 0;
|
||||
int nJNISync = 10;
|
||||
jnistress002 dm = null;
|
||||
boolean errArg = false;
|
||||
|
||||
stressOptions = new StressOptions(argv);
|
||||
|
||||
/* Process arguments */
|
||||
while (!errArg && i < argv.length) {
|
||||
/* Number of iterations. Ignored if <= 0. */
|
||||
if (i < argv.length && argv[i].equals("-numIteration")) {
|
||||
++i;
|
||||
if (i < argv.length) {
|
||||
try {
|
||||
numIteration = Long.parseLong(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numTHREADer")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numJNIter = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
if (numJNIter <= 0) errArg = true;
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-threadInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
jniInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numInterrupter")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numInterrupter = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-interruptInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
interruptInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numGarbage")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numGarbage = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-garbageInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
garbageInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-jniStringAllocSize")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
jniStringAllocSize = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].startsWith("-stress")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
++i;
|
||||
}
|
||||
} else System.out.println("Argument #" + i++ + " is incorrect");
|
||||
}
|
||||
|
||||
numIteration *= stressOptions.getIterationsFactor();
|
||||
numJNIter *= stressOptions.getThreadsFactor();
|
||||
numInterrupter *= stressOptions.getThreadsFactor();
|
||||
numGarbage *= stressOptions.getThreadsFactor();
|
||||
timeOut = stressOptions.getTime() * 1000;
|
||||
|
||||
sync = new Synchronizer[10];
|
||||
for (i = 0; i < nJNISync; i++)
|
||||
sync[i] = new Synchronizer();
|
||||
dm = new jnistress002(numIteration, numJNIter, jniInterval,
|
||||
numInterrupter, interruptInterval, numGarbage, garbageInterval);
|
||||
dm.start();
|
||||
|
||||
try {
|
||||
dm.join(timeOut);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("TESTER THREAD WAS INTERRUPTED");
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
}
|
||||
|
||||
if (DEBUG) System.out.println("jnistress002::main(): halt!");
|
||||
|
||||
if (dm.isAlive()) {
|
||||
System.out.println("TIME LIMIT EXCEEDED");
|
||||
dm.halt();
|
||||
if (DEBUG) System.out.println("jnistress002::main(): join!");
|
||||
try {
|
||||
dm.join(10000L);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("TESTER THREAD WAS INTERRUPTED");
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
}
|
||||
} else {
|
||||
System.out.println("TESTER THREAD FINISHED");
|
||||
}
|
||||
|
||||
if (DEBUG) System.out.println("jnistress002::main(): zzzz...");
|
||||
|
||||
if (!JNIter002.passed())
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
} catch (Throwable e) {
|
||||
Debug.Fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
jnistress002(
|
||||
long iters,
|
||||
int nJNI,
|
||||
int jniInterval,
|
||||
int nInter,
|
||||
int iruptInterval,
|
||||
int nGarb,
|
||||
int garbInterval
|
||||
) {
|
||||
int i = 0;
|
||||
nCycles = iters;
|
||||
/* Should have at least one of nCycles>0 */
|
||||
if (nCycles <= 0) nCycles = Long.MAX_VALUE;
|
||||
jniter = new JNIter002[nJNI];
|
||||
interval = jniInterval;
|
||||
irupt = new Interrupter[nInter];
|
||||
garb = new GarbageGenerator[nGarb];
|
||||
for (i = 0; i < nJNI; i++)
|
||||
jniter[i] = new JNIter002(sync);
|
||||
for (i = 0; i < nInter; i++) {
|
||||
irupt[i] = new Interrupter(jniter, sync);
|
||||
irupt[i].setInterval(iruptInterval);
|
||||
}
|
||||
for (i = 0; i < nGarb; i++) {
|
||||
garb[i] = new GarbageGenerator();
|
||||
garb[i].setInterval(garbInterval);
|
||||
|
||||
}
|
||||
|
||||
// premtive special class loading
|
||||
objectsJNI clStub = new objectsJNI(null, 0, 0, null, 0, 0);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
int i = 0;
|
||||
long iCycle = 0L;
|
||||
JNIter002.clearCount();
|
||||
JNIter002.clearInterruptCount();
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
jniter[i].start();
|
||||
|
||||
while (JNIter002.getCount() < jniter.length) {
|
||||
try {
|
||||
sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
JNIter002.clearCount();
|
||||
// JNIter002.clearInterruptCount();
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
|
||||
for (i = 0; i < garb.length; i++)
|
||||
garb[i].start();
|
||||
for (i = 0; i < irupt.length - 1; i++)
|
||||
irupt[i].start();
|
||||
|
||||
if (DEBUG) System.out.println("Cycles=" + nCycles);
|
||||
for (iCycle = 0; iCycle < nCycles && !done && JNIter002.passed(); iCycle++) {
|
||||
System.out.print("Cycle: " + iCycle);
|
||||
try {
|
||||
sleep(interval);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
synchronized (sync[1]) {
|
||||
System.out.println(" Interrupt count=" +
|
||||
JNIter002.getInterruptCount());
|
||||
}
|
||||
JNIter002.clearCount();
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
int n = 0;
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
if (jniter[i].finished()) n++;
|
||||
if (n == jniter.length) break;
|
||||
}
|
||||
if (JNIter002.passed()) {
|
||||
System.out.println("JNI TEST PASSED");
|
||||
} else {
|
||||
System.out.println("JNI TEST FAILED");
|
||||
}
|
||||
for (i = 0; i < irupt.length; i++)
|
||||
irupt[i].halt();
|
||||
for (i = 0; i < garb.length; i++)
|
||||
garb[i].halt();
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
jniter[i].halt();
|
||||
/* Flush any waiters */
|
||||
if (DEBUG) System.out.println("jnistress002::run(): before sync[0]");
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress002::run(): after sync[0]");
|
||||
for (i = 0; i < irupt.length; i++) {
|
||||
try {
|
||||
irupt[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress002::run(): X");
|
||||
for (i = 0; i < garb.length; i++) {
|
||||
try {
|
||||
garb[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress002::run(): Y");
|
||||
System.out.println("jniter.length is " + jniter.length);
|
||||
for (i = 0; i < jniter.length; i++) {
|
||||
try {
|
||||
if (jniter[i].isAlive()) {
|
||||
jniter[i].join();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress002::run(): Z");
|
||||
} catch (Throwable e) {
|
||||
Debug.Fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void halt() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
public boolean finished() {
|
||||
return done;
|
||||
}
|
||||
|
||||
long nCycles = 0;
|
||||
JNIter002[] jniter;
|
||||
static Synchronizer[] sync;
|
||||
private int interval = 100;
|
||||
Interrupter[] irupt;
|
||||
GarbageGenerator[] garb;
|
||||
private boolean done = false;
|
||||
final private static boolean DEBUG = false;
|
||||
}
|
||||
|
||||
class objectsJNI {
|
||||
public String instName;
|
||||
public int i;
|
||||
public long l;
|
||||
public char[] c;
|
||||
public float f;
|
||||
public double d;
|
||||
|
||||
public objectsJNI(String name,
|
||||
int intgr,
|
||||
long lng,
|
||||
char[] charr,
|
||||
float flt,
|
||||
double dbl
|
||||
) {
|
||||
instName = name;
|
||||
i = intgr;
|
||||
l = lng;
|
||||
f = flt;
|
||||
d = dbl;
|
||||
c = charr;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
|
||||
if (this.getClass() != o.getClass())
|
||||
return false;
|
||||
|
||||
Field[] fields = o.getClass().getFields();
|
||||
try {
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
if (fields[i].get(o) instanceof char[]) {
|
||||
for (int j = 0; j < ((char[]) fields[i].get(this)).length; j++)
|
||||
if (((char[]) fields[i].get(this))[j] !=
|
||||
((char[]) fields[i].get(o))[j]) {
|
||||
System.out.println(
|
||||
"Char arrays have difference in " + j);
|
||||
return false;
|
||||
}
|
||||
} else if (!fields[i].get(this).equals(fields[i].get(o))) {
|
||||
System.out.println(
|
||||
"The fields No. " + i + " are different");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error : " + e);
|
||||
}
|
||||
;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class JNIter002 extends Thread {
|
||||
|
||||
// The native method for testing JNI Object's calls
|
||||
public native objectsJNI[] jniobjects(String s, int i, long l,
|
||||
char[] c, float f, double d);
|
||||
|
||||
static {
|
||||
System.loadLibrary("jnistress002");
|
||||
}
|
||||
|
||||
static Random myRandom = new Random();
|
||||
|
||||
public JNIter002(Synchronizer[] aSync) {
|
||||
sync = aSync;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
String s;
|
||||
int i;
|
||||
long l;
|
||||
char[] c;
|
||||
float f;
|
||||
double d;
|
||||
int iter = 0;
|
||||
|
||||
/* Synchronize start of work */
|
||||
incCount();
|
||||
synchronized (sync[0]) {
|
||||
try {
|
||||
sync[0].wait();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
while (!done && pass) {
|
||||
try {
|
||||
/* Synchronized the JNI stressing */
|
||||
synchronized (sync[2]) {
|
||||
incCount();
|
||||
}
|
||||
synchronized (sync[0]) {
|
||||
try {
|
||||
sync[0].wait();
|
||||
} catch (InterruptedException e) {
|
||||
synchronized (sync[1]) {
|
||||
JNIter002.incInterruptCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
synchronized (sync[0]) {
|
||||
i = myRandom.nextInt(Integer.MAX_VALUE);
|
||||
l = myRandom.nextLong();
|
||||
f = myRandom.nextFloat();
|
||||
d = myRandom.nextDouble();
|
||||
s = getName();
|
||||
c = s.toCharArray();
|
||||
objectsJNI test = new objectsJNI(s, i, l, c, f, d);
|
||||
Object[] testJNI = jniobjects(s, i, l, c, f, d);
|
||||
|
||||
for (int j = 0; j < testJNI.length; j++)
|
||||
if (!testJNI[j].equals(test)) {
|
||||
System.out.println("Objects are different");
|
||||
fieldprint("JNI object", testJNI[j]);
|
||||
fieldprint("Java object", test);
|
||||
pass = false;
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("We have " + activeCount() +
|
||||
" threads now.");
|
||||
synchronized (this) {
|
||||
try {
|
||||
wait(1L);
|
||||
} catch (InterruptedException e) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
synchronized (sync[1]) {
|
||||
JNIter002.incInterruptCount();
|
||||
}
|
||||
}
|
||||
iter++;
|
||||
iter = iter % CASECOUNT;
|
||||
}
|
||||
if (DEBUG) System.out.println("JNITer::run(): done=" + done);
|
||||
done = true;
|
||||
if (DEBUG) System.out.println("JNITer::run(): pass=" + JNIter002.pass);
|
||||
if (DEBUG) System.out.println("JNIter002::run(): done");
|
||||
} catch (Throwable e) {
|
||||
Debug.Fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized static void incCount() {
|
||||
count++;
|
||||
}
|
||||
|
||||
public static int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public synchronized static void clearCount() {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
private synchronized static void incInterruptCount() {
|
||||
interruptCount++;
|
||||
}
|
||||
|
||||
public static int getInterruptCount() {
|
||||
return interruptCount;
|
||||
}
|
||||
|
||||
public synchronized static void clearInterruptCount() {
|
||||
interruptCount = 0;
|
||||
}
|
||||
|
||||
public static void halt() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
public boolean finished() {
|
||||
return done;
|
||||
}
|
||||
|
||||
public static boolean passed() {
|
||||
return pass;
|
||||
}
|
||||
|
||||
Synchronizer[] sync;
|
||||
private static int count = 0;
|
||||
private static int interruptCount = 0;
|
||||
private static boolean done = false;
|
||||
private static boolean pass = true;
|
||||
final private static int CASECOUNT = 2;
|
||||
final private static boolean DEBUG = false;
|
||||
|
||||
static void fieldprint(String s, Object obj) {
|
||||
Field[] fields = obj.getClass().getFields();
|
||||
System.out.println(s);
|
||||
try {
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
if (fields[i].get(obj) instanceof java.lang.String)
|
||||
System.out.println(
|
||||
fields[i] + " = \"" + fields[i].get(obj) + "\"");
|
||||
else if (fields[i].get(obj) instanceof char[])
|
||||
System.out.println(fields[i] + " = \"" +
|
||||
new String((char[]) fields[i].get(obj)) + "\"");
|
||||
else
|
||||
System.out.println(
|
||||
fields[i] + " = " + fields[i].get(obj));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
514
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/jnistress003.java
Normal file
514
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/jnistress003.java
Normal file
@ -0,0 +1,514 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* jnistress003 is a class that sets up classes that do the work
|
||||
* for the test.
|
||||
*
|
||||
* The Interrupter objects send interrupts to the JNIters.
|
||||
* The GarbageGenerator objects generate garbage.
|
||||
*
|
||||
* sync[0] synchronizes the test cycles.
|
||||
* sync[1] synchronizes access to exception counters.
|
||||
* sync[2] synchronizes the cycle count update. It also insures that
|
||||
* the interrupts do not interfere with the cycle count updates.
|
||||
* This is because cycle count updates are used to define cycles.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @key stress
|
||||
*
|
||||
* @summary converted from VM testbase nsk/stress/jni/jnistress003.
|
||||
* VM testbase keywords: [stress, quick, feature_283, nonconcurrent]
|
||||
*
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @run driver jdk.test.lib.FileInstaller . .
|
||||
* @run main/othervm/native
|
||||
* nsk.stress.jni.jnistress003
|
||||
* -numTHREADer 20
|
||||
* -threadInterval 200
|
||||
* -numInterrupter 2
|
||||
* -interruptInterval 500
|
||||
* -numGarbage 80
|
||||
* -garbageInterval 5
|
||||
* -numIteration 260
|
||||
*/
|
||||
|
||||
package nsk.stress.jni;
|
||||
|
||||
import nsk.share.Consts;
|
||||
import nsk.share.Debug;
|
||||
import nsk.share.test.StressOptions;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
public class jnistress003 extends Thread {
|
||||
|
||||
/* Maximum number of iterations. Ignored if <= 0L */
|
||||
static long numIteration = 0L;
|
||||
/* Timeout */
|
||||
static long timeOut;
|
||||
/* Number of test class objects */
|
||||
static int numJNIter = 1;
|
||||
/* Time between JNI stressing by the threads under test */
|
||||
/* (in milliseconds) */
|
||||
static int jniInterval = 10000;
|
||||
/* Number of interrupting threads */
|
||||
static int numInterrupter = 1;
|
||||
/* Time between interrupts in milliseconds */
|
||||
static int interruptInterval = 100;
|
||||
/* Number of garbage generating threads */
|
||||
static int numGarbage = 1;
|
||||
/* Time between garbage allocations in milliseconds */
|
||||
static int garbageInterval = 100;
|
||||
// The size of arrays creates via JNI
|
||||
static int SIZE = 5000;
|
||||
// The MAX quantity of creates arrays
|
||||
static int jniStringAllocSize = 100000;
|
||||
|
||||
private static StressOptions stressOptions;
|
||||
|
||||
public static void main(String[] argv) {
|
||||
try {
|
||||
int i = 0;
|
||||
int nJNISync = 10;
|
||||
jnistress003 dm = null;
|
||||
boolean errArg = false;
|
||||
|
||||
stressOptions = new StressOptions(argv);
|
||||
|
||||
/* Process arguments */
|
||||
while (!errArg && i < argv.length) {
|
||||
/* Number of iterations. Ignored if <= 0. */
|
||||
if (i < argv.length && argv[i].equals("-numIteration")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numIteration = Long.parseLong(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numTHREADer")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numJNIter = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
if (numJNIter <= 0) errArg = true;
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-threadInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
jniInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numInterrupter")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numInterrupter = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-interruptInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
interruptInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numGarbage")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numGarbage = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-garbageInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
garbageInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-arraysize")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
SIZE = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-jniStringAllocSize")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
jniStringAllocSize = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].startsWith("-stress")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
++i;
|
||||
}
|
||||
} else System.out.println("Argument #" + i++ + " is incorrect");
|
||||
}
|
||||
|
||||
numIteration *= stressOptions.getIterationsFactor();
|
||||
numJNIter *= stressOptions.getThreadsFactor();
|
||||
numInterrupter *= stressOptions.getThreadsFactor();
|
||||
numGarbage *= stressOptions.getThreadsFactor();
|
||||
timeOut = stressOptions.getTime() * 1000;
|
||||
|
||||
sync = new Synchronizer[10];
|
||||
for (i = 0; i < nJNISync; i++)
|
||||
sync[i] = new Synchronizer();
|
||||
dm = new jnistress003(numIteration, numJNIter, jniInterval,
|
||||
numInterrupter, interruptInterval,
|
||||
numGarbage, garbageInterval);
|
||||
|
||||
dm.start();
|
||||
|
||||
try {
|
||||
dm.join(timeOut);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("TESTER THREAD WAS INTERRUPTED");
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
}
|
||||
|
||||
if (DEBUG) System.out.println("jnistress003::main(): halt!");
|
||||
|
||||
if (dm.isAlive()) {
|
||||
System.out.println("TIME LIMIT EXCEEDED");
|
||||
dm.halt();
|
||||
if (DEBUG) System.out.println("jnistress003::main(): join!");
|
||||
try {
|
||||
dm.join(10000L);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("TESTER THREAD WAS INTERRUPTED");
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
}
|
||||
} else {
|
||||
System.out.println("TESTER THREAD FINISHED");
|
||||
}
|
||||
|
||||
if (DEBUG) System.out.println("jnistress003::main(): zzzz...");
|
||||
|
||||
if (!JNIter003.passed())
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
} catch (Throwable e) {
|
||||
Debug.Fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
jnistress003(
|
||||
long iters,
|
||||
int nJNI,
|
||||
int jniInterval,
|
||||
int nInter,
|
||||
int iruptInterval,
|
||||
int nGarb,
|
||||
int garbInterval
|
||||
) {
|
||||
int i = 0;
|
||||
nCycles = iters;
|
||||
/* Should have at least one of nCycles>0 */
|
||||
if (nCycles <= 0) nCycles = Long.MAX_VALUE;
|
||||
jniter = new JNIter003[nJNI];
|
||||
interval = jniInterval;
|
||||
irupt = new Interrupter[nInter];
|
||||
garb = new GarbageGenerator[nGarb];
|
||||
for (i = 0; i < nJNI; i++)
|
||||
jniter[i] = new JNIter003(sync);
|
||||
for (i = 0; i < nInter; i++) {
|
||||
irupt[i] = new Interrupter(jniter, sync);
|
||||
irupt[i].setInterval(iruptInterval);
|
||||
}
|
||||
for (i = 0; i < nGarb; i++) {
|
||||
garb[i] = new GarbageGenerator();
|
||||
garb[i].setInterval(garbInterval);
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
int i = 0;
|
||||
long iCycle = 0L;
|
||||
JNIter003.clearCount();
|
||||
JNIter003.clearInterruptCount();
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
jniter[i].start();
|
||||
|
||||
while (!done && JNIter003.getCount() < jniter.length) {
|
||||
try {
|
||||
sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
JNIter003.clearCount();
|
||||
// JNIter003.clearInterruptCount();
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
|
||||
for (i = 0; i < garb.length; i++)
|
||||
garb[i].start();
|
||||
for (i = 0; i < irupt.length; i++)
|
||||
irupt[i].start();
|
||||
|
||||
if (DEBUG) System.out.println("Cycles=" + nCycles);
|
||||
for (iCycle = 0; iCycle < nCycles && !done && JNIter003.passed(); iCycle++) {
|
||||
System.out.print("Cycle: " + iCycle);
|
||||
try {
|
||||
sleep(interval);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
synchronized (sync[1]) {
|
||||
System.out.println(" Interrupt count=" +
|
||||
JNIter003.getInterruptCount());
|
||||
}
|
||||
JNIter003.clearCount();
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
int n = 0;
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
if (jniter[i].finished()) n++;
|
||||
if (n == jniter.length) break;
|
||||
}
|
||||
if (JNIter003.passed()) {
|
||||
System.out.println("JNI TEST PASSED");
|
||||
} else {
|
||||
System.out.println("JNI TEST FAILED");
|
||||
}
|
||||
for (i = 0; i < irupt.length; i++)
|
||||
irupt[i].halt();
|
||||
for (i = 0; i < garb.length; i++)
|
||||
garb[i].halt();
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
jniter[i].halt();
|
||||
/* Flush any waiters */
|
||||
if (DEBUG) System.out.println("jnistress003::run(): before sync[0]");
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress003::run(): after sync[0]");
|
||||
for (i = 0; i < irupt.length; i++) {
|
||||
try {
|
||||
irupt[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress003::run(): X");
|
||||
for (i = 0; i < garb.length; i++) {
|
||||
try {
|
||||
garb[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress003::run(): Y");
|
||||
for (i = 0; i < jniter.length; i++) {
|
||||
try {
|
||||
if (jniter[i].isAlive()) {
|
||||
jniter[i].join();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress003::run(): Z");
|
||||
} catch (Throwable e) {
|
||||
Debug.Fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void halt() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
public boolean finished() {
|
||||
return done;
|
||||
}
|
||||
|
||||
long nCycles = 0;
|
||||
JNIter003[] jniter;
|
||||
static Synchronizer[] sync;
|
||||
private int interval = 100;
|
||||
Interrupter[] irupt;
|
||||
GarbageGenerator[] garb;
|
||||
private boolean done = false;
|
||||
final private static boolean DEBUG = false;
|
||||
}
|
||||
|
||||
class JNIter003 extends Thread {
|
||||
|
||||
// The native methods for testing JNI Arrays calls
|
||||
|
||||
public native Object[] jniInitArrays(int size);
|
||||
|
||||
public native boolean jniBodyChangeArray(Object[] orig,
|
||||
Object[] clone, int jniStringAllocSize);
|
||||
|
||||
static {
|
||||
System.loadLibrary("jnistress003");
|
||||
}
|
||||
|
||||
public JNIter003(Synchronizer[] aSync) {
|
||||
sync = aSync;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
Object[] mainArray;
|
||||
Object[] clonedArray;
|
||||
|
||||
int i, j;
|
||||
int iter = 0;
|
||||
|
||||
/* Synchronize start of work */
|
||||
incCount();
|
||||
synchronized (sync[0]) {
|
||||
try {
|
||||
sync[0].wait();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
while (!done && pass) {
|
||||
try {
|
||||
/* Synchronized the JNI stressing */
|
||||
synchronized (sync[2]) {
|
||||
incCount();
|
||||
}
|
||||
synchronized (sync[0]) {
|
||||
try {
|
||||
sync[0].wait();
|
||||
} catch (InterruptedException e) {
|
||||
synchronized (sync[1]) {
|
||||
JNIter003.incInterruptCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
// synchronized(sync[0]) {
|
||||
try {
|
||||
mainArray = jniInitArrays(jnistress003.SIZE);
|
||||
clonedArray = (Object[]) mainArray.clone();
|
||||
JNIter003.pass = jniBodyChangeArray(mainArray, clonedArray,
|
||||
jnistress003.jniStringAllocSize);
|
||||
for (i = 0; i < 8; i++)
|
||||
compared &= Array.get(mainArray, i).equals(Array.get(clonedArray, i));
|
||||
} catch (OutOfMemoryError e) {
|
||||
System.out.println("Error: " + e);
|
||||
}
|
||||
// }
|
||||
if (DEBUG)
|
||||
System.out.println("We have " + activeCount() + " threads now.");
|
||||
JNIter003.pass = JNIter003.pass && compared;
|
||||
synchronized (this) {
|
||||
try {
|
||||
wait(1L);
|
||||
} catch (InterruptedException e) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
synchronized (sync[1]) {
|
||||
JNIter003.incInterruptCount();
|
||||
}
|
||||
}
|
||||
iter++;
|
||||
iter = iter % CASECOUNT;
|
||||
}
|
||||
if (DEBUG) System.out.println("JNITer::run(): done=" + done);
|
||||
done = true;
|
||||
if (DEBUG) System.out.println("JNITer::run(): pass=" + JNIter003.pass);
|
||||
if (DEBUG) System.out.println("JNIter003::run(): done");
|
||||
} catch (Throwable e) {
|
||||
Debug.Fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized static void incCount() {
|
||||
count++;
|
||||
}
|
||||
|
||||
public static int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public synchronized static void clearCount() {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
private synchronized static void incInterruptCount() {
|
||||
interruptCount++;
|
||||
}
|
||||
|
||||
public static int getInterruptCount() {
|
||||
return interruptCount;
|
||||
}
|
||||
|
||||
public synchronized static void clearInterruptCount() {
|
||||
interruptCount = 0;
|
||||
}
|
||||
|
||||
public void halt() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
public boolean finished() {
|
||||
return done;
|
||||
}
|
||||
|
||||
public static boolean passed() {
|
||||
return pass;
|
||||
}
|
||||
|
||||
Synchronizer[] sync;
|
||||
private static int count = 0;
|
||||
private static int interruptCount = 0;
|
||||
private boolean done = false;
|
||||
private static boolean pass = true;
|
||||
private static boolean compared = true;
|
||||
final private static int CASECOUNT = 2;
|
||||
final private static boolean DEBUG = false;
|
||||
}
|
||||
498
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/jnistress004.java
Normal file
498
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/jnistress004.java
Normal file
@ -0,0 +1,498 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* jnistress004 is a class that sets up classes that do the work
|
||||
* for the test.
|
||||
*
|
||||
* The Interrupter objects send interrupts to the JNIters.
|
||||
* The GarbageGenerator objects generate garbage.
|
||||
*
|
||||
* sync[0] synchronizes the test cycles.
|
||||
* sync[1] synchronizes access to exception counters.
|
||||
* sync[2] synchronizes the cycle count update. It also insures that
|
||||
* the interrupts do not interfere with the cycle count updates.
|
||||
* This is because cycle count updates are used to define cycles.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @key stress
|
||||
*
|
||||
* @summary converted from VM testbase nsk/stress/jni/jnistress004.
|
||||
* VM testbase keywords: [stress, quick, feature_283, nonconcurrent]
|
||||
*
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @run driver jdk.test.lib.FileInstaller . .
|
||||
* @run main/othervm/native
|
||||
* nsk.stress.jni.jnistress004
|
||||
* -numTHREADer 20
|
||||
* -threadInterval 200
|
||||
* -numInterrupter 2
|
||||
* -interruptInterval 500
|
||||
* -numGarbage 80
|
||||
* -garbageInterval 5
|
||||
* -numIteration 260
|
||||
*/
|
||||
|
||||
package nsk.stress.jni;
|
||||
|
||||
import nsk.share.Consts;
|
||||
import nsk.share.Debug;
|
||||
import nsk.share.test.StressOptions;
|
||||
|
||||
public class jnistress004 extends Thread {
|
||||
|
||||
/* Maximum number of iterations. Ignored if <= 0L */
|
||||
static long numIteration = 2L;
|
||||
/* Timeout */
|
||||
static long timeOut;
|
||||
/* Number of test class objects */
|
||||
static int numJNIter = 100;
|
||||
/* Time between JNI stressing by the threads under test */
|
||||
/* (in milliseconds) */
|
||||
static int jniInterval = 25;
|
||||
/* Number of interrupting threads */
|
||||
static int numInterrupter = 10;
|
||||
/* Time between interrupts in milliseconds */
|
||||
static int interruptInterval = 45;
|
||||
/* Number of garbage generating threads */
|
||||
static int numGarbage = 1;
|
||||
/* Time between garbage allocations in milliseconds */
|
||||
static int garbageInterval = 100;
|
||||
// The MAX quantity of critical operations
|
||||
static int jniStringAllocSize = 50000;
|
||||
|
||||
private static StressOptions stressOptions;
|
||||
|
||||
public static void main(String[] argv) {
|
||||
try {
|
||||
int i = 0;
|
||||
int nJNISync = 10;
|
||||
jnistress004 dm = null;
|
||||
boolean errArg = false;
|
||||
|
||||
stressOptions = new StressOptions(argv);
|
||||
|
||||
/* Process arguments */
|
||||
while (!errArg && i < argv.length) {
|
||||
/* Number of iterations. Ignored if <= 0. */
|
||||
if (i < argv.length && argv[i].equals("-numIteration")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numIteration = Long.parseLong(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numTHREADer")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numJNIter = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
if (numJNIter <= 0) errArg = true;
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-threadInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
jniInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numInterrupter")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numInterrupter = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-interruptInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
interruptInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numGarbage")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numGarbage = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-garbageInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
garbageInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-jniStringAllocSize")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
jniStringAllocSize = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].startsWith("-stress")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
++i;
|
||||
}
|
||||
} else System.out.println("Argument #" + i++ + " is incorrect");
|
||||
}
|
||||
|
||||
numIteration *= stressOptions.getIterationsFactor();
|
||||
numJNIter *= stressOptions.getThreadsFactor();
|
||||
numInterrupter *= stressOptions.getThreadsFactor();
|
||||
numGarbage *= stressOptions.getThreadsFactor();
|
||||
timeOut = stressOptions.getTime() * 1000;
|
||||
|
||||
sync = new Synchronizer[10];
|
||||
for (i = 0; i < nJNISync; i++)
|
||||
sync[i] = new Synchronizer();
|
||||
dm = new jnistress004(numIteration, numJNIter, jniInterval,
|
||||
numInterrupter, interruptInterval, numGarbage, garbageInterval);
|
||||
dm.start();
|
||||
|
||||
try {
|
||||
dm.join(timeOut);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("TESTER THREAD WAS INTERRUPTED");
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
}
|
||||
|
||||
if (DEBUG) System.out.println("jnistress004::main(): halt!");
|
||||
|
||||
if (dm.isAlive()) {
|
||||
System.out.println("TIME LIMIT EXCEEDED");
|
||||
dm.halt();
|
||||
if (DEBUG) System.out.println("jnistress004::main(): join!");
|
||||
try {
|
||||
dm.join(10000L);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("TESTER THREAD WAS INTERRUPTED");
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
}
|
||||
} else {
|
||||
System.out.println("TESTER THREAD FINISHED");
|
||||
}
|
||||
|
||||
if (DEBUG) System.out.println("jnistress004::main(): zzzz...");
|
||||
|
||||
if (!JNIter004.passed())
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
|
||||
} catch (Throwable e) {
|
||||
Debug.Fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
jnistress004(
|
||||
long iters,
|
||||
int nJNI,
|
||||
int jniInterval,
|
||||
int nInter,
|
||||
int iruptInterval,
|
||||
int nGarb,
|
||||
int garbInterval
|
||||
) {
|
||||
int i = 0;
|
||||
nCycles = iters;
|
||||
/* Should have at least one of nCycles>0 */
|
||||
if (nCycles <= 0) nCycles = Long.MAX_VALUE;
|
||||
jniter = new JNIter004[nJNI];
|
||||
interval = jniInterval;
|
||||
irupt = new Interrupter[nInter];
|
||||
garb = new GarbageGenerator[nGarb];
|
||||
for (i = 0; i < nJNI; i++)
|
||||
jniter[i] = new JNIter004(sync);
|
||||
for (i = 0; i < nInter; i++) {
|
||||
irupt[i] = new Interrupter(jniter, sync);
|
||||
irupt[i].setInterval(iruptInterval);
|
||||
}
|
||||
for (i = 0; i < nGarb; i++) {
|
||||
garb[i] = new GarbageGenerator();
|
||||
garb[i].setInterval(garbInterval);
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
int i = 0;
|
||||
long iCycle = 0L;
|
||||
JNIter004.clearCount();
|
||||
JNIter004.clearInterruptCount();
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
jniter[i].start();
|
||||
|
||||
while (JNIter004.getCount() < jniter.length) {
|
||||
try {
|
||||
sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
JNIter004.clearCount();
|
||||
// JNIter004.clearInterruptCount();
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
|
||||
for (i = 0; i < garb.length; i++)
|
||||
garb[i].start();
|
||||
for (i = 0; i < irupt.length; i++)
|
||||
irupt[i].start();
|
||||
|
||||
if (DEBUG) System.out.println("Cycles=" + nCycles);
|
||||
for (iCycle = 0; iCycle < nCycles && !done && JNIter004.passed(); iCycle++) {
|
||||
System.out.print("Cycle: " + iCycle);
|
||||
try {
|
||||
sleep(interval);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
synchronized (sync[1]) {
|
||||
System.out.println(" Interrupt count=" +
|
||||
JNIter004.getInterruptCount());
|
||||
}
|
||||
JNIter004.clearCount();
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
int n = 0;
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
if (jniter[i].finished()) n++;
|
||||
if (n == jniter.length) break;
|
||||
}
|
||||
if (JNIter004.passed())
|
||||
System.out.println("JNI TEST PASSED");
|
||||
else
|
||||
System.out.println("JNI TEST FAILED");
|
||||
for (i = 0; i < irupt.length; i++)
|
||||
irupt[i].halt();
|
||||
for (i = 0; i < garb.length; i++)
|
||||
garb[i].halt();
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
jniter[i].halt();
|
||||
/* Flush any waiters */
|
||||
if (DEBUG) System.out.println("jnistress004::run(): before sync[0]");
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress004::run(): after sync[0]");
|
||||
for (i = 0; i < irupt.length; i++) {
|
||||
try {
|
||||
irupt[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress004::run(): X");
|
||||
for (i = 0; i < garb.length; i++) {
|
||||
try {
|
||||
garb[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress004::run(): Y");
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
for (i = 0; i < jniter.length; i++) {
|
||||
try {
|
||||
if (jniter[i].isAlive()) {
|
||||
jniter[i].join();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress004::run(): Z");
|
||||
} catch (Throwable e) {
|
||||
Debug.Fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void halt() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
public boolean finished() {
|
||||
return done;
|
||||
}
|
||||
|
||||
long nCycles = 0;
|
||||
JNIter004[] jniter;
|
||||
static Synchronizer[] sync;
|
||||
private int interval = 100;
|
||||
Interrupter[] irupt;
|
||||
GarbageGenerator[] garb;
|
||||
private boolean done = false;
|
||||
final private static boolean DEBUG = false;
|
||||
}
|
||||
|
||||
class JNIter004 extends Thread {
|
||||
|
||||
// The native methods for testing JNI critical calls
|
||||
public native char[] CheckSum(String str);
|
||||
|
||||
public native boolean CheckCompare(String name, char[] sum, int upper);
|
||||
|
||||
static {
|
||||
System.loadLibrary("jnistress004");
|
||||
}
|
||||
|
||||
Runtime myRT = Runtime.getRuntime();
|
||||
static int Count = 0;
|
||||
|
||||
public JNIter004(Synchronizer[] aSync) {
|
||||
sync = aSync;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
char[] Sum;
|
||||
int iter = 0;
|
||||
|
||||
/* Synchronize start of work */
|
||||
incCount();
|
||||
synchronized (sync[0]) {
|
||||
try {
|
||||
sync[0].wait();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
while (!done && pass) {
|
||||
try {
|
||||
/* Synchronized the JNI stressing */
|
||||
synchronized (sync[2]) {
|
||||
incCount();
|
||||
}
|
||||
synchronized (sync[0]) {
|
||||
try {
|
||||
sync[0].wait();
|
||||
} catch (InterruptedException e) {
|
||||
synchronized (sync[1]) {
|
||||
JNIter004.incInterruptCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
synchronized (sync[0]) {
|
||||
try {
|
||||
if (Count++ < jnistress004.jniStringAllocSize) {
|
||||
System.out.println("JAVA: comparing " + (getName()) + " with " + CheckSum(getName()));
|
||||
if (!CheckCompare(getName(), CheckSum(getName()), jnistress004.jniStringAllocSize))
|
||||
pass = true;
|
||||
}
|
||||
} catch (OutOfMemoryError e) {
|
||||
System.out.println("Error in Java code" + e);
|
||||
}
|
||||
}
|
||||
if (DEBUG)
|
||||
System.out.println(getName() + "\t\t" + myRT.freeMemory());
|
||||
synchronized (this) {
|
||||
try {
|
||||
wait(1L);
|
||||
} catch (InterruptedException e) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
synchronized (sync[1]) {
|
||||
JNIter004.incInterruptCount();
|
||||
}
|
||||
}
|
||||
iter++;
|
||||
iter = iter % CASECOUNT;
|
||||
}
|
||||
if (DEBUG) System.out.println("JNITer::run(): done=" + done);
|
||||
done = true;
|
||||
if (DEBUG) System.out.println("JNITer::run(): pass=" + JNIter004.pass);
|
||||
if (DEBUG) System.out.println("JNIter004::run(): done");
|
||||
} catch (Throwable e) {
|
||||
Debug.Fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized static void incCount() {
|
||||
count++;
|
||||
}
|
||||
|
||||
public static int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public synchronized static void clearCount() {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
private synchronized static void incInterruptCount() {
|
||||
interruptCount++;
|
||||
}
|
||||
|
||||
public static int getInterruptCount() {
|
||||
return interruptCount;
|
||||
}
|
||||
|
||||
public synchronized static void clearInterruptCount() {
|
||||
interruptCount = 0;
|
||||
}
|
||||
|
||||
public static void halt() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
public boolean finished() {
|
||||
return done;
|
||||
}
|
||||
|
||||
public static boolean passed() {
|
||||
return pass;
|
||||
}
|
||||
|
||||
public static void setpass(boolean value) {
|
||||
pass = value;
|
||||
}
|
||||
|
||||
Synchronizer[] sync;
|
||||
private static int count = 0;
|
||||
private static int interruptCount = 0;
|
||||
private static boolean done = false;
|
||||
private static boolean pass = true;
|
||||
final private static int CASECOUNT = 2;
|
||||
final private static boolean DEBUG = false;
|
||||
}
|
||||
506
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/jnistress005.java
Normal file
506
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/jnistress005.java
Normal file
@ -0,0 +1,506 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* jnistress005 is a class that sets up classes that do the work
|
||||
* for the test.
|
||||
*
|
||||
* The Interrupter objects send interrupts to the JNIters.
|
||||
* The GarbageGenerator objects generate garbage.
|
||||
*
|
||||
* sync[0] synchronizes the test cycles.
|
||||
* sync[1] synchronizes access to exception counters.
|
||||
* sync[2] synchronizes the cycle count update. It also insures that
|
||||
* the interrupts do not interfere with the cycle count updates.
|
||||
* This is because cycle count updates are used to define cycles.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @key stress
|
||||
*
|
||||
* @summary converted from VM testbase nsk/stress/jni/jnistress005.
|
||||
* VM testbase keywords: [stress, quick, feature_283, nonconcurrent]
|
||||
*
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @run driver jdk.test.lib.FileInstaller . .
|
||||
* @run main/othervm/native
|
||||
* nsk.stress.jni.jnistress005
|
||||
* -numTHREADer 20
|
||||
* -threadInterval 200
|
||||
* -numInterrupter 2
|
||||
* -interruptInterval 500
|
||||
* -numGarbage 80
|
||||
* -garbageInterval 5
|
||||
* -numIteration 260
|
||||
*/
|
||||
|
||||
package nsk.stress.jni;
|
||||
|
||||
import nsk.share.Consts;
|
||||
import nsk.share.Debug;
|
||||
import nsk.share.test.StressOptions;
|
||||
|
||||
public class jnistress005 extends Thread {
|
||||
|
||||
/* Maximum number of iterations. Ignored if <= 0L */
|
||||
static long numIteration = 0L;
|
||||
/* Timeout */
|
||||
static long timeOut;
|
||||
/* Number of test class objects */
|
||||
static int numJNIter = 1;
|
||||
/* Time between JNI stressing by the threads under test */
|
||||
/* (in milliseconds) */
|
||||
static int jniInterval = 10000;
|
||||
/* Number of interrupting threads */
|
||||
static int numInterrupter = 1;
|
||||
/* Time between interrupts in milliseconds */
|
||||
static int interruptInterval = 100;
|
||||
/* Number of garbage generating threads */
|
||||
static int numGarbage = 1;
|
||||
/* Time between garbage allocations in milliseconds */
|
||||
static int garbageInterval = 100;
|
||||
// The MAX quantity of creates exceptions
|
||||
static int jniStringAllocSize = 15000;
|
||||
|
||||
private static StressOptions stressOptions;
|
||||
|
||||
public static void main(String[] argv) {
|
||||
try {
|
||||
int i = 0;
|
||||
int nJNISync = 10;
|
||||
jnistress005 dm = null;
|
||||
boolean errArg = false;
|
||||
|
||||
stressOptions = new StressOptions(argv);
|
||||
|
||||
/* Process arguments */
|
||||
while (!errArg && i < argv.length) {
|
||||
/* Number of iterations. Ignored if <= 0. */
|
||||
if (i < argv.length && argv[i].equals("-numIteration")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numIteration = Long.parseLong(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numTHREADer")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numJNIter = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
if (numJNIter <= 0) errArg = true;
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-threadInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
jniInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numInterrupter")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numInterrupter = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-interruptInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
interruptInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numGarbage")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numGarbage = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-garbageInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
garbageInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-jniStringAllocSize")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
jniStringAllocSize = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].startsWith("-stress")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
++i;
|
||||
}
|
||||
} else System.out.println("Argument #" + i++ + " is incorrect");
|
||||
}
|
||||
|
||||
numIteration *= stressOptions.getIterationsFactor();
|
||||
numJNIter *= stressOptions.getThreadsFactor();
|
||||
numInterrupter *= stressOptions.getThreadsFactor();
|
||||
numGarbage *= stressOptions.getThreadsFactor();
|
||||
timeOut = stressOptions.getTime() * 1000;
|
||||
|
||||
sync = new Synchronizer[10];
|
||||
for (i = 0; i < nJNISync; i++)
|
||||
sync[i] = new Synchronizer();
|
||||
dm = new jnistress005(numIteration, numJNIter, jniInterval,
|
||||
numInterrupter, interruptInterval, numGarbage, garbageInterval);
|
||||
dm.start();
|
||||
|
||||
try {
|
||||
dm.join(timeOut);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("TESTER THREAD WAS INTERRUPTED");
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
}
|
||||
|
||||
if (DEBUG) System.out.println("jnistress005::main(): halt!");
|
||||
|
||||
if (dm.isAlive()) {
|
||||
System.out.println("TIME LIMIT EXCEEDED");
|
||||
dm.halt();
|
||||
if (DEBUG) System.out.println("jnistress005::main(): join!");
|
||||
try {
|
||||
dm.join(10000L);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("TESTER THREAD WAS INTERRUPTED");
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
}
|
||||
} else {
|
||||
System.out.println("TESTER THREAD FINISHED");
|
||||
}
|
||||
|
||||
if (DEBUG) System.out.println("jnistress005::main(): zzzz...");
|
||||
|
||||
if (!JNIter005.passed())
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
|
||||
} catch (Throwable e) {
|
||||
Debug.Fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
jnistress005(
|
||||
long iters,
|
||||
int nJNI,
|
||||
int jniInterval,
|
||||
int nInter,
|
||||
int iruptInterval,
|
||||
int nGarb,
|
||||
int garbInterval
|
||||
) {
|
||||
int i = 0;
|
||||
nCycles = iters;
|
||||
/* Should have at least one of nCycles>0 */
|
||||
if (nCycles <= 0) nCycles = Long.MAX_VALUE;
|
||||
jniter = new JNIter005[nJNI];
|
||||
interval = jniInterval;
|
||||
irupt = new Interrupter[nInter];
|
||||
garb = new GarbageGenerator[nGarb];
|
||||
for (i = 0; i < nJNI; i++)
|
||||
jniter[i] = new JNIter005(sync);
|
||||
for (i = 0; i < nInter; i++) {
|
||||
irupt[i] = new Interrupter(jniter, sync);
|
||||
irupt[i].setInterval(iruptInterval);
|
||||
}
|
||||
for (i = 0; i < nGarb; i++) {
|
||||
garb[i] = new GarbageGenerator();
|
||||
garb[i].setInterval(garbInterval);
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
int i = 0;
|
||||
long iCycle = 0L;
|
||||
// JNIter005.clearCount();
|
||||
JNIter005.clearInterruptCount();
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
jniter[i].start();
|
||||
|
||||
while (JNIter005.getCount() < jniter.length) {
|
||||
try {
|
||||
sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
// JNIter005.clearCount();
|
||||
// JNIter005.clearInterruptCount();
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
|
||||
for (i = 0; i < garb.length; i++)
|
||||
garb[i].start();
|
||||
for (i = 0; i < irupt.length; i++)
|
||||
irupt[i].start();
|
||||
|
||||
if (DEBUG) System.out.println("Cycles=" + nCycles);
|
||||
for (iCycle = 0; iCycle < nCycles && !done && JNIter005.passed(); iCycle++) {
|
||||
System.out.print("Cycle: " + iCycle);
|
||||
try {
|
||||
sleep(interval);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
synchronized (sync[1]) {
|
||||
System.out.println(
|
||||
" Interrupt count=" + JNIter005.getInterruptCount() +
|
||||
" Native interrupt count=" + JNIter005.CountException);
|
||||
}
|
||||
// JNIter005.clearCount();
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
int n = 0;
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
if (jniter[i].finished()) n++;
|
||||
if (n == jniter.length) break;
|
||||
}
|
||||
if (JNIter005.passed())
|
||||
System.out.println("JNI TEST PASSED");
|
||||
else
|
||||
System.out.println("JNI TEST FAILED");
|
||||
for (i = 0; i < irupt.length; i++)
|
||||
irupt[i].halt();
|
||||
for (i = 0; i < garb.length; i++)
|
||||
garb[i].halt();
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
jniter[i].halt();
|
||||
/* Flush any waiters */
|
||||
if (DEBUG) System.out.println("jnistress005::run(): before sync[0]");
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress005::run(): after sync[0]");
|
||||
for (i = 0; i < irupt.length; i++) {
|
||||
try {
|
||||
irupt[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress005::run(): X");
|
||||
for (i = 0; i < garb.length; i++) {
|
||||
try {
|
||||
garb[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress005::run(): Y");
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
for (i = 0; i < jniter.length; i++) {
|
||||
try {
|
||||
if (jniter[i].isAlive()) {
|
||||
jniter[i].join();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress005::run(): Z");
|
||||
} catch (Throwable e) {
|
||||
Debug.Fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void halt() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
public boolean finished() {
|
||||
return done;
|
||||
}
|
||||
|
||||
long nCycles = 0;
|
||||
JNIter005[] jniter;
|
||||
static Synchronizer[] sync;
|
||||
private int interval = 100;
|
||||
Interrupter[] irupt;
|
||||
GarbageGenerator[] garb;
|
||||
private boolean done = false;
|
||||
final private static boolean DEBUG = false;
|
||||
}
|
||||
|
||||
class JNIter005 extends Thread {
|
||||
|
||||
// The native methods for testing JNI exception calls
|
||||
public native void except(Throwable tobj);
|
||||
|
||||
// public native int count();
|
||||
static {
|
||||
System.loadLibrary("jnistress005");
|
||||
}
|
||||
|
||||
Exception nobj = new Exception();
|
||||
static int CountException = 0;
|
||||
static int counts = 0;
|
||||
|
||||
public JNIter005(Synchronizer[] aSync) {
|
||||
sync = aSync;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
char[] Sum;
|
||||
int iter = 0;
|
||||
|
||||
/* Synchronize start of work */
|
||||
incCount();
|
||||
synchronized (sync[0]) {
|
||||
try {
|
||||
sync[0].wait();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
while (!done && pass) {
|
||||
try {
|
||||
/* Synchronized the JNI stressing */
|
||||
synchronized (sync[2]) {
|
||||
incCount();
|
||||
}
|
||||
synchronized (sync[0]) {
|
||||
try {
|
||||
sync[0].wait();
|
||||
} catch (InterruptedException e) {
|
||||
synchronized (sync[1]) {
|
||||
JNIter005.incInterruptCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
synchronized (sync[0]) {
|
||||
if (CountException < jnistress005.jniStringAllocSize) {
|
||||
try {
|
||||
except(nobj);
|
||||
} catch (Exception e) {
|
||||
if ((CountException % 1000) == 0)
|
||||
System.out.println("JAVA: " + e);
|
||||
System.out.println("Here");
|
||||
System.out.println("counts " + counts +
|
||||
" CountException " + CountException);
|
||||
|
||||
++CountException;
|
||||
}
|
||||
} else
|
||||
// if (CountException==counts) halt();
|
||||
if (CountException == jnistress005.jniStringAllocSize) halt();
|
||||
}
|
||||
if (DEBUG)
|
||||
System.out.println("We have " + activeCount() + " threads now.");
|
||||
synchronized (this) {
|
||||
try {
|
||||
wait(1L);
|
||||
} catch (InterruptedException e) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
synchronized (sync[1]) {
|
||||
JNIter005.incInterruptCount();
|
||||
}
|
||||
}
|
||||
iter++;
|
||||
iter = iter % CASECOUNT;
|
||||
}
|
||||
if (DEBUG) System.out.println("JNITer::run(): done=" + done);
|
||||
done = true;
|
||||
if (DEBUG) System.out.println("JNITer::run(): pass=" + JNIter005.pass);
|
||||
if (DEBUG) System.out.println("JNIter005::run(): done");
|
||||
} catch (Throwable e) {
|
||||
Debug.Fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized static void incCount() {
|
||||
count++;
|
||||
}
|
||||
|
||||
public static int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public synchronized static void clearCount() {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
private synchronized static void incInterruptCount() {
|
||||
interruptCount++;
|
||||
}
|
||||
|
||||
public static int getInterruptCount() {
|
||||
return interruptCount;
|
||||
}
|
||||
|
||||
public synchronized static void clearInterruptCount() {
|
||||
interruptCount = 0;
|
||||
}
|
||||
|
||||
public void halt() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
public boolean finished() {
|
||||
return done;
|
||||
}
|
||||
|
||||
public static boolean passed() {
|
||||
return pass;
|
||||
}
|
||||
|
||||
public static void setpass(boolean value) {
|
||||
pass = value;
|
||||
}
|
||||
|
||||
Synchronizer[] sync;
|
||||
private static int count = 0;
|
||||
private static int interruptCount = 0;
|
||||
private boolean done = false;
|
||||
private static boolean pass = true;
|
||||
final private static int CASECOUNT = 2;
|
||||
final private static boolean DEBUG = false;
|
||||
}
|
||||
502
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/jnistress006.java
Normal file
502
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/jnistress006.java
Normal file
@ -0,0 +1,502 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* jnistress006 is a class that sets up classes that do the work
|
||||
* for the test.
|
||||
*
|
||||
* The Interrupter objects send interrupts to the JNIters.
|
||||
* The GarbageGenerator objects generate garbage.
|
||||
*
|
||||
* sync[0] synchronizes the test cycles.
|
||||
* sync[1] synchronizes access to exception counters.
|
||||
* sync[2] synchronizes the cycle count update. It also insures that
|
||||
* the interrupts do not interfere with the cycle count updates.
|
||||
* This is because cycle count updates are used to define cycles.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @key stress
|
||||
*
|
||||
* @summary converted from VM testbase nsk/stress/jni/jnistress006.
|
||||
* VM testbase keywords: [stress, quick, feature_283, nonconcurrent]
|
||||
*
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @run driver jdk.test.lib.FileInstaller . .
|
||||
* @run main/othervm/native
|
||||
* nsk.stress.jni.jnistress006
|
||||
* -numTHREADer 20
|
||||
* -threadInterval 200
|
||||
* -numInterrupter 2
|
||||
* -interruptInterval 500
|
||||
* -numGarbage 80
|
||||
* -garbageInterval 5
|
||||
* -numIteration 260
|
||||
*/
|
||||
|
||||
package nsk.stress.jni;
|
||||
|
||||
import nsk.share.Consts;
|
||||
import nsk.share.Debug;
|
||||
import nsk.share.test.StressOptions;
|
||||
|
||||
public class jnistress006 extends Thread {
|
||||
|
||||
/* Maximum number of iterations. Ignored if <= 0L */
|
||||
static long numIteration = 0L;
|
||||
/* Timeout */
|
||||
static long timeOut;
|
||||
/* Number of test class objects */
|
||||
static int numJNIter = 1;
|
||||
/* Time between JNI stressing by the threads under test */
|
||||
/* (in milliseconds) */
|
||||
static int jniInterval = 10000;
|
||||
/* Number of interrupting threads */
|
||||
static int numInterrupter = 1;
|
||||
/* Time between interrupts in milliseconds */
|
||||
static int interruptInterval = 100;
|
||||
/* Number of garbage generating threads */
|
||||
static int numGarbage = 1;
|
||||
/* Time between garbage allocations in milliseconds */
|
||||
static int garbageInterval = 100;
|
||||
// The MAX quantity of creates global refs
|
||||
static int jniStringAllocSize = 30000;
|
||||
|
||||
private static StressOptions stressOptions;
|
||||
|
||||
public static void main(String[] argv) {
|
||||
try {
|
||||
int i = 0;
|
||||
int nJNISync = 10;
|
||||
jnistress006 dm = null;
|
||||
boolean errArg = false;
|
||||
|
||||
stressOptions = new StressOptions(argv);
|
||||
|
||||
/* Process arguments */
|
||||
while (!errArg && i < argv.length) {
|
||||
/* Number of iterations. Ignored if <= 0. */
|
||||
if (i < argv.length && argv[i].equals("-numIteration")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numIteration = Long.parseLong(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numTHREADer")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numJNIter = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
if (numJNIter <= 0) errArg = true;
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-threadInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
jniInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numInterrupter")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numInterrupter = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-interruptInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
interruptInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numGarbage")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numGarbage = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-garbageInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
garbageInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-jniStringAllocSize")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
jniStringAllocSize = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].startsWith("-stress")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
++i;
|
||||
}
|
||||
} else System.out.println("Argument #" + i++ + " is incorrect");
|
||||
}
|
||||
|
||||
numIteration *= stressOptions.getIterationsFactor();
|
||||
numJNIter *= stressOptions.getThreadsFactor();
|
||||
numInterrupter *= stressOptions.getThreadsFactor();
|
||||
numGarbage *= stressOptions.getThreadsFactor();
|
||||
timeOut = stressOptions.getTime() * 1000;
|
||||
|
||||
sync = new Synchronizer[10];
|
||||
for (i = 0; i < nJNISync; i++)
|
||||
sync[i] = new Synchronizer();
|
||||
dm = new jnistress006(numIteration, numJNIter, jniInterval,
|
||||
numInterrupter, interruptInterval, numGarbage, garbageInterval);
|
||||
|
||||
dm.start();
|
||||
|
||||
try {
|
||||
dm.join(timeOut);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("TESTER THREAD WAS INTERRUPTED");
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
}
|
||||
|
||||
if (DEBUG) System.out.println("jnistress006::main(): halt!");
|
||||
|
||||
if (dm.isAlive()) {
|
||||
System.out.println("TIME LIMIT EXCEEDED");
|
||||
dm.halt();
|
||||
if (DEBUG) System.out.println("jnistress006::main(): join!");
|
||||
try {
|
||||
dm.join(10000L);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("TESTER THREAD WAS INTERRUPTED");
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
}
|
||||
} else {
|
||||
System.out.println("TESTER THREAD FINISHED");
|
||||
}
|
||||
|
||||
if (DEBUG) System.out.println("jnistress006::main(): zzzz...");
|
||||
|
||||
if (!JNIter006.passed())
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
|
||||
} catch (Throwable e) {
|
||||
Debug.Fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
jnistress006(
|
||||
long iters,
|
||||
int nJNI,
|
||||
int jniInterval,
|
||||
int nInter,
|
||||
int iruptInterval,
|
||||
int nGarb,
|
||||
int garbInterval
|
||||
) {
|
||||
int i = 0;
|
||||
nCycles = iters;
|
||||
/* Should have at least one of nCycles>0 */
|
||||
if (nCycles <= 0) nCycles = Long.MAX_VALUE;
|
||||
jniter = new JNIter006[nJNI];
|
||||
interval = jniInterval;
|
||||
irupt = new Interrupter[nInter];
|
||||
garb = new GarbageGenerator[nGarb];
|
||||
for (i = 0; i < nJNI; i++)
|
||||
jniter[i] = new JNIter006(sync);
|
||||
for (i = 0; i < nInter; i++) {
|
||||
irupt[i] = new Interrupter(jniter, sync);
|
||||
irupt[i].setInterval(iruptInterval);
|
||||
}
|
||||
for (i = 0; i < nGarb; i++) {
|
||||
garb[i] = new GarbageGenerator();
|
||||
garb[i].setInterval(garbInterval);
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
int i = 0;
|
||||
long iCycle = 0L;
|
||||
JNIter006.clearCount();
|
||||
JNIter006.clearInterruptCount();
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
jniter[i].start();
|
||||
|
||||
while (JNIter006.getCount() < jniter.length) {
|
||||
try {
|
||||
sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
JNIter006.clearCount();
|
||||
// JNIter006.clearInterruptCount();
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
|
||||
for (i = 0; i < garb.length; i++)
|
||||
garb[i].start();
|
||||
for (i = 0; i < irupt.length; i++)
|
||||
irupt[i].start();
|
||||
|
||||
if (DEBUG) System.out.println("Cycles=" + nCycles);
|
||||
for (iCycle = 0; iCycle < nCycles && !done && JNIter006.passed(); iCycle++) {
|
||||
System.out.print("Cycle: " + iCycle);
|
||||
try {
|
||||
sleep(interval);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
synchronized (sync[1]) {
|
||||
System.out.println(" Interrupt count=" +
|
||||
JNIter006.getInterruptCount());
|
||||
}
|
||||
JNIter006.clearCount();
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
int n = 0;
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
if (jniter[i].finished()) n++;
|
||||
if (n == jniter.length) break;
|
||||
}
|
||||
if (JNIter006.passed())
|
||||
System.out.println("JNI TEST PASSED");
|
||||
else
|
||||
System.out.println("JNI TEST FAILED");
|
||||
for (i = 0; i < irupt.length; i++)
|
||||
irupt[i].halt();
|
||||
for (i = 0; i < garb.length; i++)
|
||||
garb[i].halt();
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
jniter[i].halt();
|
||||
/* Flush any waiters */
|
||||
if (DEBUG) System.out.println("jnistress006::run(): before sync[0]");
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress006::run(): after sync[0]");
|
||||
for (i = 0; i < irupt.length; i++) {
|
||||
try {
|
||||
irupt[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress006::run(): X");
|
||||
for (i = 0; i < garb.length; i++) {
|
||||
try {
|
||||
garb[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress006::run(): Y");
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
for (i = 0; i < jniter.length; i++) {
|
||||
try {
|
||||
if (jniter[i].isAlive()) {
|
||||
jniter[i].join();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress006::run(): Z");
|
||||
} catch (Throwable e) {
|
||||
Debug.Fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void halt() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
public boolean finished() {
|
||||
return done;
|
||||
}
|
||||
|
||||
long nCycles = 0;
|
||||
JNIter006[] jniter;
|
||||
static Synchronizer[] sync;
|
||||
private int interval = 100;
|
||||
Interrupter[] irupt;
|
||||
GarbageGenerator[] garb;
|
||||
private boolean done = false;
|
||||
final private static boolean DEBUG = false;
|
||||
}
|
||||
|
||||
class JNIter006 extends Thread {
|
||||
|
||||
// The native methods for testing JNI exception calls
|
||||
public native boolean refs(Object tobj, int jniStringAllocSize);
|
||||
|
||||
static {
|
||||
System.loadLibrary("jnistress006");
|
||||
}
|
||||
|
||||
Referenced tobj = new Referenced();
|
||||
static int CountRefs;
|
||||
|
||||
public JNIter006(Synchronizer[] aSync) {
|
||||
sync = aSync;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
int iter = 0;
|
||||
|
||||
/* Synchronize start of work */
|
||||
incCount();
|
||||
synchronized (sync[0]) {
|
||||
try {
|
||||
sync[0].wait();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
while (!done && pass) {
|
||||
try {
|
||||
/* Synchronized the JNI stressing */
|
||||
synchronized (sync[2]) {
|
||||
incCount();
|
||||
}
|
||||
synchronized (sync[0]) {
|
||||
try {
|
||||
sync[0].wait();
|
||||
} catch (InterruptedException e) {
|
||||
synchronized (sync[1]) {
|
||||
JNIter006.incInterruptCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
synchronized (sync[0]) {
|
||||
try {
|
||||
tobj.set_i(123456);
|
||||
pass = refs(tobj, jnistress006.jniStringAllocSize);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error: " + e);
|
||||
}
|
||||
}
|
||||
if (DEBUG)
|
||||
System.out.println("We have " + activeCount() + " threads now.");
|
||||
synchronized (this) {
|
||||
try {
|
||||
wait(1L);
|
||||
} catch (InterruptedException e) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
synchronized (sync[1]) {
|
||||
JNIter006.incInterruptCount();
|
||||
}
|
||||
}
|
||||
iter++;
|
||||
iter = iter % CASECOUNT;
|
||||
}
|
||||
if (DEBUG) System.out.println("JNITer::run(): done=" + done);
|
||||
done = true;
|
||||
if (DEBUG) System.out.println("JNITer::run(): pass=" + JNIter006.pass);
|
||||
if (DEBUG) System.out.println("JNIter006::run(): done");
|
||||
} catch (Throwable e) {
|
||||
Debug.Fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized static void incCount() {
|
||||
count++;
|
||||
}
|
||||
|
||||
public static int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public synchronized static void clearCount() {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
private synchronized static void incInterruptCount() {
|
||||
interruptCount++;
|
||||
}
|
||||
|
||||
public static int getInterruptCount() {
|
||||
return interruptCount;
|
||||
}
|
||||
|
||||
public synchronized static void clearInterruptCount() {
|
||||
interruptCount = 0;
|
||||
}
|
||||
|
||||
public void halt() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
public boolean finished() {
|
||||
return done;
|
||||
}
|
||||
|
||||
public static boolean passed() {
|
||||
return pass;
|
||||
}
|
||||
|
||||
Synchronizer[] sync;
|
||||
private static int count = 0;
|
||||
private static int interruptCount = 0;
|
||||
private static boolean done = false;
|
||||
private static boolean pass = true;
|
||||
final private static int CASECOUNT = 2;
|
||||
final private static boolean DEBUG = false;
|
||||
}
|
||||
|
||||
class Referenced {
|
||||
private static int i;
|
||||
|
||||
public static void set_i(int value) {
|
||||
i = value;
|
||||
}
|
||||
|
||||
public static int get_i() {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
499
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/jnistress007.java
Normal file
499
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/jnistress007.java
Normal file
@ -0,0 +1,499 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* jnistress007 is a class that sets up classes that do the work
|
||||
* for the test.
|
||||
*
|
||||
* The Interrupter objects send interrupts to the JNIters.
|
||||
* The GarbageGenerator objects generate garbage.
|
||||
*
|
||||
* sync[0] synchronizes the test cycles.
|
||||
* sync[1] synchronizes access to exception counters.
|
||||
* sync[2] synchronizes the cycle count update. It also insures that
|
||||
* the interrupts do not interfere with the cycle count updates.
|
||||
* This is because cycle count updates are used to define cycles.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @key stress
|
||||
*
|
||||
* @summary converted from VM testbase nsk/stress/jni/jnistress007.
|
||||
* VM testbase keywords: [stress, quick, feature_283, nonconcurrent]
|
||||
*
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @run driver jdk.test.lib.FileInstaller . .
|
||||
* @run main/othervm/native
|
||||
* nsk.stress.jni.jnistress007
|
||||
* -numTHREADer 10
|
||||
* -threadInterval 20
|
||||
* -numInterrupter 2
|
||||
* -interruptInterval 50
|
||||
* -numGarbage 80
|
||||
* -garbageInterval 5
|
||||
* -numIteration 130
|
||||
*/
|
||||
|
||||
package nsk.stress.jni;
|
||||
|
||||
import nsk.share.Consts;
|
||||
import nsk.share.Debug;
|
||||
import nsk.share.test.StressOptions;
|
||||
|
||||
public class jnistress007 extends Thread {
|
||||
|
||||
/* Maximum number of iterations. Ignored if <= 0L */
|
||||
static long numIteration = 0L;
|
||||
/* Timeout */
|
||||
static long timeOut;
|
||||
/* Number of test class objects */
|
||||
static int numJNIter = 1;
|
||||
/* Time between JNI stressing by the threads under test */
|
||||
/* (in milliseconds) */
|
||||
static int jniInterval = 10000;
|
||||
/* Number of interrupting threads */
|
||||
static int numInterrupter = 1;
|
||||
/* Time between interrupts in milliseconds */
|
||||
static int interruptInterval = 1000;
|
||||
/* Number of garbage generating threads */
|
||||
static int numGarbage = 1;
|
||||
/* Time between garbage allocations in milliseconds */
|
||||
static int garbageInterval = 1000;
|
||||
// The MAX quantity of monitor's call
|
||||
static int jniStringAllocSize = 300;
|
||||
|
||||
private static StressOptions stressOptions;
|
||||
|
||||
public static void main(String[] argv) {
|
||||
try {
|
||||
int i = 0;
|
||||
int nJNISync = 10;
|
||||
jnistress007 dm = null;
|
||||
boolean errArg = false;
|
||||
|
||||
stressOptions = new StressOptions(argv);
|
||||
|
||||
/* Process arguments */
|
||||
while (!errArg && i < argv.length) {
|
||||
/* Number of iterations. Ignored if <= 0. */
|
||||
if (i < argv.length && argv[i].equals("-numIteration")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numIteration = Long.parseLong(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numTHREADer")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numJNIter = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
if (numJNIter <= 0) errArg = true;
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-threadInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
jniInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numInterrupter")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numInterrupter = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-interruptInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
interruptInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-numGarbage")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
numGarbage = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-garbageInterval")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
garbageInterval = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].equals("-jniStringAllocSize")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
try {
|
||||
jniStringAllocSize = Integer.parseInt(argv[i++]);
|
||||
} catch (NumberFormatException e) {
|
||||
errArg = true;
|
||||
}
|
||||
}
|
||||
} else if (i < argv.length && argv[i].startsWith("-stress")) {
|
||||
++i;
|
||||
if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
|
||||
++i;
|
||||
}
|
||||
} else System.out.println("Argument #" + i++ + " is incorrect");
|
||||
}
|
||||
|
||||
numIteration *= stressOptions.getIterationsFactor();
|
||||
numJNIter *= stressOptions.getThreadsFactor();
|
||||
numInterrupter *= stressOptions.getThreadsFactor();
|
||||
numGarbage *= stressOptions.getThreadsFactor();
|
||||
timeOut = stressOptions.getTime() * 1000;
|
||||
|
||||
sync = new Synchronizer[10];
|
||||
for (i = 0; i < nJNISync; i++)
|
||||
sync[i] = new Synchronizer();
|
||||
dm = new jnistress007(numIteration, numJNIter, jniInterval,
|
||||
numInterrupter, interruptInterval, numGarbage, garbageInterval);
|
||||
dm.start();
|
||||
|
||||
try {
|
||||
dm.join(timeOut);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("TESTER THREAD WAS INTERRUPTED");
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
}
|
||||
|
||||
if (DEBUG) System.out.println("jnistress007::main(): halt!");
|
||||
|
||||
if (dm.isAlive()) {
|
||||
System.out.println("TIME LIMIT EXCEEDED");
|
||||
dm.halt();
|
||||
if (DEBUG) System.out.println("jnistress007::main(): join!");
|
||||
try {
|
||||
dm.join(10000L);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("TESTER THREAD WAS INTERRUPTED");
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
}
|
||||
} else {
|
||||
System.out.println("TESTER THREAD FINISHED");
|
||||
}
|
||||
|
||||
if (DEBUG) System.out.println("jnistress007::main(): zzzz...");
|
||||
|
||||
if (JNIter007.passed())
|
||||
System.exit(Consts.TEST_FAILED);
|
||||
|
||||
} catch (Throwable e) {
|
||||
Debug.Fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
jnistress007(
|
||||
long iters,
|
||||
int nJNI,
|
||||
int jniInterval,
|
||||
int nInter,
|
||||
int iruptInterval,
|
||||
int nGarb,
|
||||
int garbInterval
|
||||
) {
|
||||
int i = 0;
|
||||
nCycles = iters;
|
||||
/* Should have at least one of nCycles>0 */
|
||||
if (nCycles <= 0) nCycles = Long.MAX_VALUE;
|
||||
jniter = new JNIter007[nJNI];
|
||||
interval = jniInterval;
|
||||
irupt = new Interrupter[nInter];
|
||||
garb = new GarbageGenerator[nGarb];
|
||||
for (i = 0; i < nJNI; i++)
|
||||
jniter[i] = new JNIter007(sync);
|
||||
for (i = 0; i < nInter; i++) {
|
||||
irupt[i] = new Interrupter(jniter, sync);
|
||||
irupt[i].setInterval(iruptInterval);
|
||||
}
|
||||
for (i = 0; i < nGarb; i++) {
|
||||
garb[i] = new GarbageGenerator();
|
||||
garb[i].setInterval(garbInterval);
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
int i = 0;
|
||||
long iCycle = 0L;
|
||||
JNIter007.clearCount();
|
||||
JNIter007.clearInterruptCount();
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
jniter[i].start();
|
||||
|
||||
while (JNIter007.getCount() < jniter.length) {
|
||||
try {
|
||||
sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
JNIter007.clearCount();
|
||||
// JNIter007.clearInterruptCount();
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
|
||||
for (i = 0; i < garb.length; i++)
|
||||
garb[i].start();
|
||||
for (i = 0; i < irupt.length; i++)
|
||||
irupt[i].start();
|
||||
|
||||
if (DEBUG) System.out.println("Cycles=" + nCycles);
|
||||
for (iCycle = 0; iCycle < nCycles && !done && !JNIter007.passed(); iCycle++) {
|
||||
System.out.print("Cycle: " + iCycle);
|
||||
try {
|
||||
sleep(interval);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
synchronized (sync[1]) {
|
||||
System.out.println("\tInterrupt count=" +
|
||||
JNIter007.getInterruptCount());
|
||||
}
|
||||
JNIter007.clearCount();
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
int n = 0;
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
if (jniter[i].finished()) n++;
|
||||
if (n == jniter.length) break;
|
||||
}
|
||||
for (i = 0; i < irupt.length; i++)
|
||||
irupt[i].halt();
|
||||
for (i = 0; i < garb.length; i++)
|
||||
garb[i].halt();
|
||||
for (i = 0; i < jniter.length; i++)
|
||||
jniter[i].halt();
|
||||
/* Flush any waiters */
|
||||
if (DEBUG) System.out.println("jnistress007::run(): before sync[0]");
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress007::run(): after sync[0]");
|
||||
for (i = 0; i < irupt.length; i++) {
|
||||
try {
|
||||
irupt[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress007::run(): X");
|
||||
for (i = 0; i < garb.length; i++) {
|
||||
try {
|
||||
garb[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress007::run(): Y");
|
||||
synchronized (sync[0]) {
|
||||
sync[0].notifyAll();
|
||||
}
|
||||
for (i = 0; i < jniter.length; i++) {
|
||||
try {
|
||||
jniter[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (JNIter007.passed()) {
|
||||
System.out.println("JNI TEST PASSED");
|
||||
} else {
|
||||
System.out.println("JNI TEST FAILED");
|
||||
}
|
||||
if (DEBUG) System.out.println("jnistress007::run(): Z");
|
||||
} catch (Throwable e) {
|
||||
Debug.Fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void halt() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
public boolean finished() {
|
||||
return done;
|
||||
}
|
||||
|
||||
long nCycles = 0;
|
||||
JNIter007[] jniter;
|
||||
static Synchronizer[] sync;
|
||||
private int interval = 100;
|
||||
Interrupter[] irupt;
|
||||
GarbageGenerator[] garb;
|
||||
private boolean done = false;
|
||||
final private static boolean DEBUG = false;
|
||||
}
|
||||
|
||||
class JNIter007 extends Thread {
|
||||
|
||||
// The native methods for testing JNI monitors calls
|
||||
public native void incCount(String name);
|
||||
|
||||
static {
|
||||
System.loadLibrary("jnistress007");
|
||||
}
|
||||
|
||||
public static int nativeCount, javaCount = 0;
|
||||
|
||||
public JNIter007(Synchronizer[] aSync) {
|
||||
sync = aSync;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
int iter = 0;
|
||||
|
||||
/* Synchronize start of work */
|
||||
incCount();
|
||||
synchronized (sync[0]) {
|
||||
try {
|
||||
sync[0].wait();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
while (!done && !pass) {
|
||||
try {
|
||||
/* Synchronized the JNI stressing */
|
||||
synchronized (sync[2]) {
|
||||
incCount();
|
||||
}
|
||||
synchronized (sync[0]) {
|
||||
try {
|
||||
sync[0].wait();
|
||||
} catch (InterruptedException e) {
|
||||
synchronized (sync[1]) {
|
||||
JNIter007.incInterruptCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
synchronized (sync[0]) {
|
||||
try {
|
||||
if ((javaCount < jnistress007.jniStringAllocSize) &&
|
||||
(nativeCount < jnistress007.jniStringAllocSize)) {
|
||||
javaCount++;
|
||||
incCount(getName());
|
||||
if ((javaCount % 1000) == 0)
|
||||
System.out.println("Count in java " +
|
||||
getName() + " " + javaCount);
|
||||
} else if (javaCount == nativeCount) {
|
||||
done = true;
|
||||
} else {
|
||||
System.out.println("Native: " + nativeCount +
|
||||
"\t" + "Java: " + javaCount);
|
||||
pass = true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error: " + e);
|
||||
}
|
||||
}
|
||||
if (DEBUG)
|
||||
System.out.println("We have " + activeCount() + " threads now.");
|
||||
synchronized (this) {
|
||||
try {
|
||||
wait(1L);
|
||||
} catch (InterruptedException e) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
synchronized (sync[1]) {
|
||||
JNIter007.incInterruptCount();
|
||||
}
|
||||
}
|
||||
iter++;
|
||||
iter = iter % CASECOUNT;
|
||||
}
|
||||
if (DEBUG) System.out.println("JNITer::run(): done=" + done);
|
||||
done = true;
|
||||
if (DEBUG) System.out.println("JNITer::run(): pass=" + JNIter007.pass);
|
||||
if (DEBUG) System.out.println("JNIter::run(): done");
|
||||
} catch (Throwable e) {
|
||||
Debug.Fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized static void incCount() {
|
||||
count++;
|
||||
}
|
||||
|
||||
public static int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public synchronized static void clearCount() {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
private synchronized static void incInterruptCount() {
|
||||
interruptCount++;
|
||||
}
|
||||
|
||||
public static int getInterruptCount() {
|
||||
return interruptCount;
|
||||
}
|
||||
|
||||
public synchronized static void clearInterruptCount() {
|
||||
interruptCount = 0;
|
||||
}
|
||||
|
||||
public void halt() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
public boolean finished() {
|
||||
return done;
|
||||
}
|
||||
|
||||
public static boolean passed() {
|
||||
return pass;
|
||||
}
|
||||
|
||||
Synchronizer[] sync;
|
||||
private static int count = 0;
|
||||
private static int interruptCount = 0;
|
||||
private boolean done = false;
|
||||
private static boolean pass = false;
|
||||
final private static int CASECOUNT = 2;
|
||||
final private static boolean DEBUG = false;
|
||||
}
|
||||
239
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress001.c
Normal file
239
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress001.c
Normal file
@ -0,0 +1,239 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include <stdio.h>
|
||||
/* Changed from strings.h to string.h for Windows. */
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "jnihelper.h"
|
||||
|
||||
#define DIGESTLENGTH 16
|
||||
|
||||
typedef struct {
|
||||
const char **str;
|
||||
char **checkstr;
|
||||
} CHAR_ARRAY;
|
||||
|
||||
typedef struct {
|
||||
const jchar **str;
|
||||
char **checkstr;
|
||||
int *size;
|
||||
} JCHAR_ARRAY;
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_nsk_stress_jni_JNIter001_jnistress (JNIEnv *env, jobject jobj, jstring jstr,
|
||||
jint nstr, jint printperiod) {
|
||||
|
||||
int i,j;
|
||||
size_t k;
|
||||
static CHAR_ARRAY *element;
|
||||
unsigned char digest[DIGESTLENGTH];
|
||||
static int allocs=0;
|
||||
static size_t strsize=0;
|
||||
static unsigned int compared=1;
|
||||
|
||||
const char *clsName = "nsk/stress/jni/JNIter001";
|
||||
const char *name="setpass";
|
||||
const char *sig="(Z)V";
|
||||
const char *halt="halt";
|
||||
const char *haltSig="()V";
|
||||
jstring tmpstr;
|
||||
jclass clazz;
|
||||
jmethodID methodID;
|
||||
|
||||
(*env)->MonitorEnter(env, jobj); CE
|
||||
if (!allocs) {
|
||||
element = (CHAR_ARRAY *)malloc(sizeof(CHAR_ARRAY));
|
||||
element->str = (const char **)malloc(nstr*sizeof(const char *));
|
||||
element->checkstr = (char **)malloc(nstr*sizeof(char *));
|
||||
for (j=0;j<nstr;j++)
|
||||
element->checkstr[j] = (char *)malloc(DIGESTLENGTH*sizeof(char));
|
||||
}
|
||||
for(j=0;j<DIGESTLENGTH;j++) {
|
||||
digest[j]=0;
|
||||
}
|
||||
element->str[allocs] = (*env)->GetStringUTFChars(env,jstr,0); CE
|
||||
if (strlen(element->str[allocs]) !=
|
||||
(size_t) (*env)->GetStringUTFLength(env, jstr))
|
||||
printf("Length is wrong in string No. %d\n",allocs);
|
||||
else
|
||||
strsize += strlen(element->str[allocs])+1;
|
||||
for (k = 0; k < strlen(element->str[allocs]); k++) {
|
||||
digest[k % DIGESTLENGTH] += element->str[allocs][k];
|
||||
}
|
||||
memcpy(element->checkstr[allocs],digest,DIGESTLENGTH);
|
||||
allocs++;
|
||||
if (allocs%printperiod==0) {
|
||||
printf("Check string for thread %s is ", element->str[allocs-1]);
|
||||
for (j=0;j<DIGESTLENGTH;j++)
|
||||
printf("%02x", digest[j]);
|
||||
printf("\n");
|
||||
}
|
||||
if (allocs==nstr) {
|
||||
printf("JNI UTF8 strings memory=%zd\n", strsize);
|
||||
tmpstr=(*env)->NewStringUTF(env,element->str[allocs-1]); CE
|
||||
for (j=0; j<nstr; j++) {
|
||||
|
||||
for(i=0;i<DIGESTLENGTH;i++) {
|
||||
digest[i]=0;
|
||||
}
|
||||
for (k=0; k < strlen(element->str[j]); k++) {
|
||||
digest[k % DIGESTLENGTH] += element->str[j][k];
|
||||
}
|
||||
if (memcmp(digest,element->checkstr[j],DIGESTLENGTH)==0) {
|
||||
(*env)->ReleaseStringUTFChars(env,jstr,element->str[j]); CE
|
||||
element->str[j] = NULL;
|
||||
element->checkstr[j] = NULL;
|
||||
}
|
||||
else {
|
||||
compared=0;
|
||||
printf("The element No. %d has been corrupted %s vs %s\n",j, element->str[j],element->checkstr[j]);
|
||||
printf("Digest string is %s [", element->str[j]);
|
||||
for (i=0;i<DIGESTLENGTH;i++)
|
||||
printf("ch[%d]=%02x", i, digest[i]);
|
||||
printf("Digest end\n");
|
||||
}
|
||||
}
|
||||
allocs=0;
|
||||
strsize = 0;
|
||||
for (j=0;j<nstr;j++)
|
||||
free(element->checkstr[j]);
|
||||
free(element->checkstr);
|
||||
free((void *)(element->str));
|
||||
free(element);
|
||||
clazz=(*env)->FindClass(env, clsName); CE
|
||||
if (!compared) {
|
||||
methodID=(*env)->GetStaticMethodID(env, clazz, name, sig); CE
|
||||
(*env)->CallStaticVoidMethod(env, clazz, methodID, JNI_FALSE); CE
|
||||
}
|
||||
//methodID=(*env)->GetStaticMethodID(env, clazz, halt, haltSig); CE
|
||||
//(*env)->CallStaticVoidMethod(env, clazz, methodID); CE
|
||||
return(tmpstr);
|
||||
}
|
||||
(*env)->MonitorExit(env, jobj); CE
|
||||
return ((*env)->NewStringUTF(env,element->str[allocs-1]));
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_nsk_stress_jni_JNIter001_jnistress1(JNIEnv *env, jobject jobj, jstring jstr,
|
||||
jint nstr, jint printperiod) {
|
||||
|
||||
int i,j;
|
||||
static JCHAR_ARRAY *javachars;
|
||||
unsigned char digest[DIGESTLENGTH];
|
||||
static int index=0;
|
||||
static long len=0;
|
||||
static unsigned int equal=1;
|
||||
char *elem;
|
||||
|
||||
const char *clsName = "nsk/stress/jni/JNIter001";
|
||||
const char *name="setpass";
|
||||
const char *sig="(Z)V";
|
||||
const char *halt="halt";
|
||||
const char *haltSig="()V";
|
||||
jstring tmpstr;
|
||||
jclass clazz;
|
||||
jmethodID methodID;
|
||||
|
||||
(*env)->MonitorEnter(env, jobj); CE
|
||||
if (!index) {
|
||||
javachars = (JCHAR_ARRAY *)malloc(sizeof(JCHAR_ARRAY));
|
||||
javachars->str = (const jchar **)malloc(nstr*sizeof(const jchar *));
|
||||
javachars->checkstr = (char **)malloc(nstr*sizeof(char *));
|
||||
javachars->size = (int *)malloc(nstr*sizeof(int));
|
||||
for (j=0;j<nstr;j++)
|
||||
javachars->checkstr[j] = (char *)malloc(DIGESTLENGTH*sizeof(char));
|
||||
}
|
||||
for(j=0;j<DIGESTLENGTH;j++) {
|
||||
digest[j]=0;
|
||||
}
|
||||
javachars->str[index] = (*env)->GetStringChars(env,jstr,0); CE
|
||||
javachars->size[index] = (*env)->GetStringUTFLength(env, jstr); CE
|
||||
len += javachars->size[index];
|
||||
elem = (char*) malloc(javachars->size[index]*sizeof(char));
|
||||
for (j=0; j < javachars->size[index]; j++) {
|
||||
elem[j] = (char) javachars->str[index][j];
|
||||
}
|
||||
//memcpy(digest, elem, javachars->size[index]);
|
||||
for(j=0;j<javachars->size[index]; j++) {
|
||||
digest[j % DIGESTLENGTH]+=elem[j];
|
||||
}
|
||||
memcpy(javachars->checkstr[index++],digest,DIGESTLENGTH);
|
||||
if (index%printperiod==0) {
|
||||
printf("Check string sum for thread %s is ",elem);
|
||||
for (j=0;j<DIGESTLENGTH;j++)
|
||||
printf("%02x", digest[j]);
|
||||
printf("\n");
|
||||
}
|
||||
free(elem);
|
||||
if (index==nstr) {
|
||||
printf("JNI Unicode strings memory=%ld\n",len);
|
||||
tmpstr=(*env)->NewString(env,javachars->str[index-1],javachars->size[index-1]); CE
|
||||
for (j=0; j<nstr; j++) {
|
||||
elem = (char*) malloc(javachars->size[j]*sizeof(char));
|
||||
for (i=0; i < javachars->size[j]; i++) {
|
||||
elem[i] = (char) javachars->str[j][i];
|
||||
}
|
||||
//memcpy(digest, elem, javachars->size[j]);
|
||||
for(i=0;i<DIGESTLENGTH;i++) {
|
||||
digest[i]=0;
|
||||
}
|
||||
for(i=0;i<javachars->size[j]; i++) {
|
||||
digest[i % DIGESTLENGTH]+=elem[i];
|
||||
}
|
||||
free(elem);
|
||||
if (memcmp(digest,javachars->checkstr[j],javachars->size[j])==0) {
|
||||
(*env)->ReleaseStringChars(env,jstr,javachars->str[j]); CE
|
||||
javachars->str[j] = NULL;
|
||||
javachars->checkstr[j] = NULL;
|
||||
javachars->size[j] = 0;
|
||||
}
|
||||
else {
|
||||
equal=0;
|
||||
printf("The Unicode element No. %d has been corrupted\n",j);
|
||||
for(i=0;i<DIGESTLENGTH;i++) {
|
||||
printf("digest[%d]=%02x checkstr[%d]=%02x\n",i,digest[i],i,javachars->checkstr[j][i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
index=0;
|
||||
len = 0;
|
||||
for (j=0;j<nstr;j++)
|
||||
free(javachars->checkstr[j]);
|
||||
free(javachars->checkstr);
|
||||
free((void *)(javachars->str));
|
||||
free(javachars->size);
|
||||
free(javachars);
|
||||
clazz=(*env)->FindClass(env, clsName); CE
|
||||
if (!equal) {
|
||||
methodID=(*env)->GetStaticMethodID(env, clazz, name, sig); CE
|
||||
(*env)->CallStaticVoidMethod(env, clazz, methodID, JNI_FALSE); CE
|
||||
}
|
||||
//methodID=(*env)->GetStaticMethodID(env, clazz, halt, haltSig); CE
|
||||
//(*env)->CallStaticVoidMethod(env, clazz, methodID); CE
|
||||
return(tmpstr);
|
||||
}
|
||||
(*env)->MonitorExit(env, jobj); CE
|
||||
return((*env)->NewString(env,javachars->str[index-1],javachars->size[index-1]));
|
||||
}
|
||||
102
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress002.c
Normal file
102
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress002.c
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include <stdio.h>
|
||||
#include "jnihelper.h"
|
||||
|
||||
jobject NewObjectWrapper(JNIEnv *env, jclass clazz, jmethodID methodID, ...) {
|
||||
va_list ap;
|
||||
jobject tmp;
|
||||
|
||||
va_start(ap,methodID);
|
||||
tmp=(*env)->NewObjectV(env, clazz, methodID, ap);
|
||||
va_end(ap);
|
||||
return(tmp);
|
||||
}
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_nsk_stress_jni_JNIter002_jniobjects (JNIEnv *env, jobject jobj, jstring jstr, jint intgr,
|
||||
jlong lng, jcharArray jChArr, jfloat flt, jdouble dbl) {
|
||||
|
||||
static int classCount = 0;
|
||||
jobjectArray obj;
|
||||
jobject element;
|
||||
jclass clazz, clazzUp;
|
||||
jmethodID methodID;
|
||||
const char *classname="nsk/stress/jni/objectsJNI";
|
||||
const char *name="<init>";
|
||||
const char *sig="(Ljava/lang/String;IJ[CFD)V";
|
||||
const char *upperClassName="nsk/stress/jni/jnistress002";
|
||||
const char *fieldName="jniStringAllocSize";
|
||||
const char *fieldSig="I";
|
||||
const char *setpass="halt";
|
||||
const char *setpassSig="()V";
|
||||
jvalue paramArr [6];
|
||||
|
||||
(*env)->MonitorEnter(env, jobj); CE
|
||||
++classCount;
|
||||
(*env)->MonitorExit(env, jobj); CE
|
||||
paramArr[0].l=jstr;
|
||||
paramArr[1].i=intgr;
|
||||
paramArr[2].j=lng;
|
||||
paramArr[3].l=jChArr;
|
||||
paramArr[4].f=flt;
|
||||
paramArr[5].d=dbl;
|
||||
|
||||
clazz=(*env)->FindClass(env,classname); CE
|
||||
obj=(*env)->NewObjectArray(env,(jsize)3,clazz,
|
||||
(*env)->AllocObject(env, clazz)); CE
|
||||
if (obj==NULL) {
|
||||
fprintf(stderr,"Can not construct the object Array for %s\n", classname);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
methodID=(*env)->GetMethodID(env,clazz,name,sig); CE
|
||||
if (methodID==NULL) {
|
||||
fprintf(stderr,"Can not get the ID of <init> for %s\n", classname);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
element=(*env)->NewObject(env,clazz,methodID,
|
||||
jstr, intgr, lng, jChArr, flt, dbl); CE
|
||||
(*env)->SetObjectArrayElement(env,obj,0,element); CE
|
||||
element=(*env)->NewObjectA(env,clazz,methodID,paramArr); CE
|
||||
(*env)->SetObjectArrayElement(env,obj,1,element); CE
|
||||
element= NewObjectWrapper(env, clazz, methodID,
|
||||
jstr, intgr, lng, jChArr, flt, dbl); CE
|
||||
(*env)->SetObjectArrayElement(env,obj,2,element); CE
|
||||
|
||||
clazzUp=(*env)->FindClass(env, upperClassName); CE
|
||||
if (classCount == (*env)->GetStaticIntField(env, clazzUp,
|
||||
(*env)->GetStaticFieldID(env,clazzUp,fieldName,fieldSig))) {
|
||||
classname="nsk/stress/jni/JNIter002";
|
||||
clazz=(*env)->FindClass(env, classname); CE
|
||||
methodID=(*env)->GetStaticMethodID(env,clazz, setpass, setpassSig); CE
|
||||
(*env)->CallStaticVoidMethod(env, clazz, methodID); CE
|
||||
}
|
||||
|
||||
CE
|
||||
|
||||
return obj;
|
||||
}
|
||||
260
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress003.c
Normal file
260
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress003.c
Normal file
@ -0,0 +1,260 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "jnihelper.h"
|
||||
|
||||
#define BOOL 0
|
||||
#define BYTE 1
|
||||
#define CHAR 2
|
||||
#define SHORT 3
|
||||
#define INT 4
|
||||
#define LONG 5
|
||||
#define FLOAT 6
|
||||
#define DOUBLE 7
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_nsk_stress_jni_JNIter003_jniInitArrays (JNIEnv *env, jobject jobj, jint size) {
|
||||
|
||||
jobject *arrayArray;
|
||||
jboolean *boolBuf;
|
||||
jbyte *byteBuf;
|
||||
jchar *charBuf;
|
||||
jshort *shortBuf;
|
||||
jint *intBuf;
|
||||
jlong *longBuf;
|
||||
jfloat *floatBuf;
|
||||
jdouble *doubleBuf;
|
||||
jobjectArray objectsArray;
|
||||
|
||||
int i;
|
||||
int SIZE=size;
|
||||
const char *classname="java/lang/Object";
|
||||
jclass clazz = (*env)->FindClass(env,classname); CE
|
||||
objectsArray = (*env)->NewObjectArray(env,8,clazz,(*env)->AllocObject(env,clazz));
|
||||
|
||||
arrayArray=(jobject *)malloc(8*sizeof(jobject)); CE
|
||||
arrayArray[BOOL]=(*env)->NewBooleanArray(env,SIZE); CE
|
||||
arrayArray[BYTE]=(*env)->NewByteArray(env, SIZE); CE
|
||||
arrayArray[CHAR]=(*env)->NewCharArray(env, SIZE); CE
|
||||
arrayArray[SHORT]=(*env)->NewShortArray(env, SIZE); CE
|
||||
arrayArray[INT]=(*env)->NewIntArray(env, SIZE); CE
|
||||
arrayArray[LONG]=(*env)->NewLongArray(env, SIZE); CE
|
||||
arrayArray[FLOAT]=(*env)->NewFloatArray(env, SIZE); CE
|
||||
arrayArray[DOUBLE]=(*env)->NewDoubleArray(env, SIZE); CE
|
||||
|
||||
for(i=0;i<8;i++)
|
||||
{(*env)->SetObjectArrayElement(env,objectsArray,i,arrayArray[i]); CE }
|
||||
|
||||
boolBuf=(jboolean *)malloc(SIZE*sizeof(jboolean));
|
||||
byteBuf=(jbyte *)malloc(SIZE*sizeof(jbyte));
|
||||
charBuf=(jchar *)malloc(SIZE*sizeof(jchar));
|
||||
shortBuf=(jshort *)malloc(SIZE*sizeof(jshort));
|
||||
intBuf=(jint *)malloc(SIZE*sizeof(jint));
|
||||
longBuf=(jlong *)malloc(SIZE*sizeof(jlong));
|
||||
floatBuf=(jfloat *)malloc(SIZE*sizeof(jfloat));
|
||||
doubleBuf=(jdouble *)malloc(SIZE*sizeof(jdouble));
|
||||
|
||||
for (i=0;i<SIZE;i++) {
|
||||
if (i%2==0) boolBuf[i]=JNI_TRUE;
|
||||
else boolBuf[i]=JNI_FALSE;
|
||||
/*
|
||||
byteBuf[i]=(jbyte)random();
|
||||
charBuf[i]=(jchar)random();
|
||||
shortBuf[i]=(jshort)random();
|
||||
intBuf[i]=(jint)random();
|
||||
longBuf[i]=(jlong)random();
|
||||
floatBuf[i]=(jfloat)((random()));
|
||||
doubleBuf[i]=(jdouble)((random()));
|
||||
*/
|
||||
byteBuf[i]=(jbyte)109;
|
||||
charBuf[i]=(jchar)214;
|
||||
shortBuf[i]=(jshort)9223;
|
||||
intBuf[i]=(jint)872634;
|
||||
longBuf[i]=(jlong)276458276;
|
||||
floatBuf[i]=(jfloat)235.4576284;
|
||||
doubleBuf[i]=(jdouble)98275.716253567;
|
||||
}
|
||||
(*env)->SetBooleanArrayRegion(env,arrayArray[BOOL],0,i,boolBuf); CE
|
||||
(*env)->SetByteArrayRegion(env,arrayArray[BYTE],0,i,byteBuf); CE
|
||||
(*env)->SetCharArrayRegion(env,arrayArray[CHAR],0,i,charBuf); CE
|
||||
(*env)->SetShortArrayRegion(env,arrayArray[SHORT],0,i,shortBuf); CE
|
||||
(*env)->SetIntArrayRegion(env,arrayArray[INT],0,i,intBuf); CE
|
||||
(*env)->SetLongArrayRegion(env,arrayArray[LONG],0,i,longBuf); CE
|
||||
(*env)->SetFloatArrayRegion(env,arrayArray[FLOAT],0,i,floatBuf); CE
|
||||
(*env)->SetDoubleArrayRegion(env,arrayArray[DOUBLE],0,i,doubleBuf); CE
|
||||
|
||||
free(doubleBuf);
|
||||
free(floatBuf);
|
||||
free(longBuf);
|
||||
free(intBuf);
|
||||
free(shortBuf);
|
||||
free(byteBuf);
|
||||
free(charBuf);
|
||||
free(boolBuf);
|
||||
free(arrayArray);
|
||||
|
||||
return objectsArray;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_nsk_stress_jni_JNIter003_jniBodyChangeArray (JNIEnv *env, jobject jobj,
|
||||
jobjectArray orig, jobjectArray clone, jint limit) {
|
||||
|
||||
#define SWAP(param1, param2) tmparr=param2; param2=param1; param1=tmparr;
|
||||
#define SIZE(type) (*env)->GetArrayLength(env,arrayClone[type])
|
||||
|
||||
static volatile long count=0;
|
||||
jobject *arrayOrig, *arrayClone;
|
||||
jboolean *boolOrig, *boolClone;
|
||||
jbyte *byteOrig, *byteClone;
|
||||
jchar *charOrig, *charClone;
|
||||
jshort *shortOrig, *shortClone;
|
||||
jint *intOrig, *intClone;
|
||||
jlong *longOrig, *longClone;
|
||||
jfloat *floatOrig, *floatClone;
|
||||
jdouble *doubleOrig, *doubleClone;
|
||||
int i;
|
||||
|
||||
if ((orig==NULL) || (clone==NULL)) {
|
||||
fprintf(stderr,"JNI received a NULL array from Java\n");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
if (count == limit) {
|
||||
jclass clazz;
|
||||
const char *classname = "nsk/stress/jni/JNIter003";
|
||||
const char *setdone = "halt";
|
||||
const char *setdonesig = "()V";
|
||||
jmethodID jmethod;
|
||||
|
||||
fprintf(stderr, "Count and limit are: %ld\t%d cons.\n", count, limit);
|
||||
clazz=(*env)->FindClass(env, classname); CE
|
||||
jmethod=(*env)->GetMethodID(env, clazz, setdone, setdonesig); CE
|
||||
(*env)->CallVoidMethod(env, jobj, jmethod); CE
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
(*env)->MonitorEnter(env, jobj); CE
|
||||
++count;
|
||||
(*env)->MonitorExit(env, jobj); CE
|
||||
arrayOrig=(jobject *)malloc(8*sizeof(jobject));
|
||||
arrayClone=(jobject *)malloc(8*sizeof(jobject));
|
||||
for(i=0;i<8;i++) {
|
||||
arrayOrig[i]=(*env)->GetObjectArrayElement(env,orig,i); CE
|
||||
arrayClone[i]=(*env)->GetObjectArrayElement(env,clone,i); CE
|
||||
}
|
||||
|
||||
/* Take the elements from Java arrays into native buffers */
|
||||
/* Use Get<Type>ArrayElements */
|
||||
boolOrig = (*env)->GetBooleanArrayElements(env,arrayOrig[BOOL],0); CE
|
||||
byteOrig = (*env)->GetByteArrayElements(env,arrayOrig[BYTE],0); CE
|
||||
charOrig = (*env)->GetCharArrayElements(env,arrayOrig[CHAR],0); CE
|
||||
shortOrig = (*env)->GetShortArrayElements(env,arrayOrig[SHORT],0); CE
|
||||
intOrig = (*env)->GetIntArrayElements(env,arrayOrig[INT],0); CE
|
||||
longOrig = (*env)->GetLongArrayElements(env,arrayOrig[LONG],0); CE
|
||||
floatOrig = (*env)->GetFloatArrayElements(env,arrayOrig[FLOAT],0); CE
|
||||
doubleOrig = (*env)->GetDoubleArrayElements(env,arrayOrig[DOUBLE],0); CE
|
||||
|
||||
/* Alloc some memory for cloned arrays buffers */
|
||||
boolClone=(jboolean *)malloc(SIZE(BOOL)*sizeof(jboolean));
|
||||
byteClone=(jbyte *)malloc(SIZE(BYTE)*sizeof(jbyte));
|
||||
charClone=(jchar *)malloc(SIZE(CHAR)*sizeof(jchar));
|
||||
shortClone=(jshort *)malloc(SIZE(SHORT)*sizeof(jshort));
|
||||
intClone=(jint *)malloc(SIZE(INT)*sizeof(jint));
|
||||
longClone=(jlong *)malloc(SIZE(LONG)*sizeof(jlong));
|
||||
floatClone=(jfloat *)malloc(SIZE(FLOAT)*sizeof(jfloat));
|
||||
doubleClone=(jdouble *)malloc(SIZE(DOUBLE)*sizeof(jdouble));
|
||||
|
||||
/* Take the elements from cloned Java arrays into native buffers */
|
||||
/* Use Get<Type>ArrayRegion */
|
||||
(*env)->GetBooleanArrayRegion(env,arrayClone[BOOL],0,SIZE(BOOL),boolClone); CE
|
||||
(*env)->GetByteArrayRegion(env,arrayClone[BYTE],0,SIZE(BYTE),byteClone); CE
|
||||
(*env)->GetCharArrayRegion(env,arrayClone[CHAR],0,SIZE(CHAR),charClone); CE
|
||||
(*env)->GetShortArrayRegion(env,arrayClone[SHORT],0,SIZE(SHORT),shortClone); CE
|
||||
(*env)->GetIntArrayRegion(env,arrayClone[INT],0,SIZE(INT),intClone); CE
|
||||
(*env)->GetLongArrayRegion(env,arrayClone[LONG],0,SIZE(LONG),longClone); CE
|
||||
(*env)->GetFloatArrayRegion(env,arrayClone[FLOAT],0,SIZE(FLOAT),floatClone); CE
|
||||
(*env)->GetDoubleArrayRegion(env,arrayClone[DOUBLE],0,SIZE(DOUBLE),doubleClone); CE
|
||||
|
||||
/* In this code section I should make some changes for elements into both */
|
||||
/* (original and cloned) arrays and than copied new values back to Java */
|
||||
|
||||
/*
|
||||
Can't change the pointer into the Java structure. It's illegal JNI.
|
||||
SWAP(boolOrig,boolClone)
|
||||
SWAP(byteOrig,byteClone)
|
||||
SWAP(charOrig,charClone)
|
||||
SWAP(shortOrig,shortClone)
|
||||
SWAP(intOrig,intClone)
|
||||
SWAP(longOrig,longClone)
|
||||
SWAP(floatOrig,floatClone)
|
||||
SWAP(doubleOrig,doubleClone)
|
||||
*/
|
||||
|
||||
/* Coping new values of elements back to Java and releasing native buffers */
|
||||
/* Use Set<Type>ArrayRegion */
|
||||
/*
|
||||
Use Orig pointers to get the original effect of the test.
|
||||
(*env)->SetBooleanArrayRegion(env,arrayClone[BOOL],0,SIZE(BOOL),boolClone);
|
||||
(*env)->SetByteArrayRegion(env,arrayClone[BYTE],0,SIZE(BYTE),byteClone);
|
||||
(*env)->SetCharArrayRegion(env,arrayClone[CHAR],0,SIZE(CHAR),charClone);
|
||||
(*env)->SetShortArrayRegion(env,arrayClone[SHORT],0,SIZE(SHORT),shortClone);
|
||||
(*env)->SetIntArrayRegion(env,arrayClone[INT],0,SIZE(INT),intClone);
|
||||
(*env)->SetLongArrayRegion(env,arrayClone[LONG],0,SIZE(LONG),longClone);
|
||||
(*env)->SetFloatArrayRegion(env,arrayClone[FLOAT],0,SIZE(FLOAT),floatClone);
|
||||
(*env)->SetDoubleArrayRegion(env,arrayClone[DOUBLE],0,SIZE(DOUBLE),doubleClone);
|
||||
*/
|
||||
(*env)->SetBooleanArrayRegion(env,arrayClone[BOOL],0,SIZE(BOOL),boolOrig); CE
|
||||
(*env)->SetByteArrayRegion(env,arrayClone[BYTE],0,SIZE(BYTE),byteOrig); CE
|
||||
(*env)->SetCharArrayRegion(env,arrayClone[CHAR],0,SIZE(CHAR),charOrig); CE
|
||||
(*env)->SetShortArrayRegion(env,arrayClone[SHORT],0,SIZE(SHORT),shortOrig); CE
|
||||
(*env)->SetIntArrayRegion(env,arrayClone[INT],0,SIZE(INT),intOrig); CE
|
||||
(*env)->SetLongArrayRegion(env,arrayClone[LONG],0,SIZE(LONG),longOrig); CE
|
||||
(*env)->SetFloatArrayRegion(env,arrayClone[FLOAT],0,SIZE(FLOAT),floatOrig); CE
|
||||
(*env)->SetDoubleArrayRegion(env,arrayClone[DOUBLE],0,SIZE(DOUBLE),doubleOrig); CE
|
||||
|
||||
/* Use Release<Type>ArrayElements */
|
||||
(*env)->ReleaseDoubleArrayElements(env,arrayOrig[DOUBLE],doubleOrig,0); CE
|
||||
(*env)->ReleaseFloatArrayElements(env,arrayOrig[FLOAT],floatOrig,0); CE
|
||||
(*env)->ReleaseLongArrayElements(env,arrayOrig[LONG],longOrig,0); CE
|
||||
(*env)->ReleaseIntArrayElements(env,arrayOrig[INT],intOrig,0); CE
|
||||
(*env)->ReleaseShortArrayElements(env,arrayOrig[SHORT],shortOrig,0); CE
|
||||
(*env)->ReleaseCharArrayElements(env,arrayOrig[CHAR],charOrig,0); CE
|
||||
(*env)->ReleaseByteArrayElements(env,arrayOrig[BYTE],byteOrig,0); CE
|
||||
(*env)->ReleaseBooleanArrayElements(env,arrayOrig[BOOL],boolOrig,0); CE
|
||||
free(arrayOrig);
|
||||
|
||||
free(doubleClone);
|
||||
free(floatClone);
|
||||
free(longClone);
|
||||
free(intClone);
|
||||
free(shortClone);
|
||||
free(byteClone);
|
||||
free(charClone);
|
||||
free(boolClone);
|
||||
free(arrayClone);
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
168
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress004.c
Normal file
168
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress004.c
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "jnihelper.h"
|
||||
|
||||
#define DIGESTLENGTH 16
|
||||
|
||||
JNIEXPORT jcharArray JNICALL
|
||||
Java_nsk_stress_jni_JNIter004_CheckSum (JNIEnv *env, jobject jobj, jstring jstr) {
|
||||
|
||||
unsigned char digest[DIGESTLENGTH];
|
||||
jchar *tmp;
|
||||
static jint upper = 0;
|
||||
jcharArray jArr;
|
||||
int i;
|
||||
const jchar *critstr;
|
||||
char *str;
|
||||
jint len=(*env)->GetStringUTFLength(env,jstr); CE
|
||||
|
||||
for(i=0;i<DIGESTLENGTH;i++) {
|
||||
digest[i]=0;
|
||||
}
|
||||
str=(char *)malloc(len*sizeof(char));
|
||||
/* const char *threadName=(*env)->GetStringUTFChars(env, jstr, 0); */
|
||||
|
||||
(*env)->MonitorEnter(env, jobj); CE
|
||||
if (upper==0) tmp=(jchar *)malloc(DIGESTLENGTH*sizeof(char));
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
(*env)->ExceptionDescribe(env);
|
||||
(*env)->ExceptionClear(env);
|
||||
}
|
||||
critstr=(*env)->GetStringCritical(env, jstr, 0); CE
|
||||
for(i=0;i<len;i++)
|
||||
str[i] = (char) critstr[i];
|
||||
(*env)->ReleaseStringCritical(env,jstr,critstr); CE
|
||||
for(i=0;i<len;i++) {
|
||||
digest[i % DIGESTLENGTH]+=str[i];
|
||||
}
|
||||
free(str);
|
||||
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
(*env)->ExceptionDescribe(env);
|
||||
(*env)->ExceptionClear(env);
|
||||
}
|
||||
memcpy(tmp,digest,DIGESTLENGTH);
|
||||
jArr=(*env)->NewCharArray(env,DIGESTLENGTH/sizeof(jchar)); CE
|
||||
len=(*env)->GetArrayLength(env,jArr); CE
|
||||
(*env)->SetCharArrayRegion(env,jArr,0,len,tmp); CE
|
||||
/* ++upper; */
|
||||
(*env)->MonitorExit(env, jobj); CE
|
||||
return jArr;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_nsk_stress_jni_JNIter004_CheckCompare (JNIEnv *env, jobject jobj, jstring jstr,
|
||||
jcharArray cArr, jint limit) {
|
||||
|
||||
unsigned char digest[DIGESTLENGTH];
|
||||
jchar *tmp;
|
||||
/* jcharArray jArr; */
|
||||
const jchar *critstr;
|
||||
jint strlen;
|
||||
char *str;
|
||||
jboolean ret=JNI_TRUE;
|
||||
int i;
|
||||
static jint upper = 0;
|
||||
jint len;
|
||||
jchar *ch;
|
||||
|
||||
for(i=0;i<DIGESTLENGTH;i++) {
|
||||
digest[i]=0;
|
||||
}
|
||||
strlen = (*env)->GetStringUTFLength(env,jstr); CE
|
||||
str = (char *)malloc(strlen*sizeof(char));
|
||||
|
||||
len =(*env)->GetArrayLength(env,cArr); CE
|
||||
|
||||
(*env)->MonitorEnter(env, jobj); CE
|
||||
if (upper>limit) {
|
||||
(*env)->MonitorExit(env, jobj); CE
|
||||
return JNI_FALSE;
|
||||
}
|
||||
tmp=(jchar *)malloc(DIGESTLENGTH*sizeof(char));
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
(*env)->ExceptionDescribe(env);
|
||||
(*env)->ExceptionClear(env);
|
||||
}
|
||||
critstr=(*env)->GetStringCritical(env, jstr, 0); CE
|
||||
for(i=0;i<strlen;i++)
|
||||
str[i] = (char) critstr[i];
|
||||
(*env)->ReleaseStringCritical(env,jstr,critstr); CE
|
||||
for(i=0;i<strlen; i++) {
|
||||
digest[i % DIGESTLENGTH]+=str[i % DIGESTLENGTH];
|
||||
}
|
||||
|
||||
free(str);
|
||||
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
(*env)->ExceptionDescribe(env);
|
||||
(*env)->ExceptionClear(env);
|
||||
}
|
||||
memcpy(tmp,digest,DIGESTLENGTH);
|
||||
|
||||
/* jArr=(*env)->NewCharArray(env,DIGESTLENGTH/sizeof(jchar)); */
|
||||
/* len=(*env)->GetArrayLength(env,jArr); */
|
||||
/* (*env)->SetCharArrayRegion(env,jArr,0,len,tmp); */
|
||||
/* ++upper; */
|
||||
/* (*env)->MonitorExit(env, jobj); */
|
||||
|
||||
/* Compare */
|
||||
/* (*env)->MonitorEnter(env, jobj); */
|
||||
|
||||
ch=(jchar *)(*env)->GetPrimitiveArrayCritical(env,cArr,0); CE
|
||||
|
||||
printf("Comparing: ");
|
||||
for(i=0;i<len;i++)
|
||||
if(ch[i]!=tmp[i]) {
|
||||
printf("Error in %d\n",i);
|
||||
printf("ch[%d]=%02x tmp[%d]=%02x\n",i,ch[i],i,tmp[i]);
|
||||
ret=JNI_FALSE;
|
||||
}
|
||||
else {
|
||||
printf("ch[%d]=%02x tmp[%d]=%02x\n",i,ch[i],i,tmp[i]);
|
||||
}
|
||||
printf("\n");
|
||||
(*env)->ReleasePrimitiveArrayCritical(env,cArr,ch,0); CE
|
||||
++upper;
|
||||
if (!(upper % 500))
|
||||
fprintf(stderr,"There are %d elements now.\n", upper);
|
||||
if (upper==limit) {
|
||||
jclass clazz;
|
||||
jmethodID methodID;
|
||||
char *name="halt";
|
||||
char *sig="()V";
|
||||
|
||||
clazz=(*env)->GetObjectClass(env, jobj); CE
|
||||
methodID=(*env)->GetStaticMethodID(env, clazz, name, sig); CE
|
||||
(*env)->CallStaticVoidMethod(env, clazz, methodID); CE
|
||||
free(tmp);
|
||||
ret=JNI_TRUE;
|
||||
}
|
||||
(*env)->MonitorExit(env, jobj); CE
|
||||
return ret;
|
||||
}
|
||||
111
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress005.c
Normal file
111
test/hotspot/jtreg/vmTestbase/nsk/stress/jni/libjnistress005.c
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define CHECK_EXCEPTION { if ((*env)->ExceptionOccurred(env)) { fprintf(stderr, "Unexpected exception:\n"); (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); exit(97); } }
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_nsk_stress_jni_JNIter005_except (JNIEnv *env, jobject jobj, jthrowable tobj) {
|
||||
jclass clazz;
|
||||
static int Exceptcalls=0;
|
||||
const char *name;
|
||||
const char *mess;
|
||||
jmethodID jmethod;
|
||||
const char *iter = "nsk/stress/jni/JNIter005";
|
||||
// const char *inc = "nsk/stress/jni/jnistress005/incCount";
|
||||
const char *incSig = "()V";
|
||||
const char *fldName = "counts";
|
||||
const char *fldSig = "I";
|
||||
|
||||
/* incClazz = (*env)->FindClass(env, iter); */
|
||||
/* CHECK_EXCEPTION */
|
||||
/* jmethod=(*env)->GetStaticMethodID(env, incClazz, inc, incSig); */
|
||||
/* CHECK_EXCEPTION */
|
||||
/* (*env)->CallStaticVoidMethod(env, incClazz, jmethod); */
|
||||
/* CHECK_EXCEPTION */
|
||||
/* jfld = (*env)->GetFieldID(env, incClazz, fldName, fldSig); */
|
||||
/* printf("JNI: Count is %d\n", (*env)->GetIntField(env, jobj, jfld)); */
|
||||
/* CHECK_EXCEPTION */
|
||||
|
||||
(*env)->MonitorEnter(env, jobj);
|
||||
CHECK_EXCEPTION
|
||||
if (!(*env)->Throw(env, tobj)) {
|
||||
if((*env)->ExceptionOccurred(env))
|
||||
if (Exceptcalls%1000==0)
|
||||
fprintf(stderr, "NATIVE: Throw has been catched in native\n");
|
||||
(*env)->ExceptionClear(env);
|
||||
++Exceptcalls;
|
||||
} else fprintf(stderr, "Throw failed\n");
|
||||
|
||||
(*env)->MonitorExit(env, jobj);
|
||||
CHECK_EXCEPTION
|
||||
|
||||
switch (Exceptcalls%23) {
|
||||
case 0: name="java/lang/ArithmeticException"; break;
|
||||
case 1: name="java/lang/ArrayIndexOutOfBoundsException"; break;
|
||||
case 2: name="java/lang/ArrayStoreException"; break;
|
||||
case 3: name="java/lang/ClassCastException"; break;
|
||||
case 4: name="java/lang/ClassNotFoundException"; break;
|
||||
case 5: name="java/lang/CloneNotSupportedException"; break;
|
||||
case 6: name="java/lang/IllegalAccessException"; break;
|
||||
case 7: name="java/lang/IllegalArgumentException"; break;
|
||||
case 8: name="java/lang/IllegalMonitorStateException"; break;
|
||||
case 9: name="java/lang/IllegalStateException"; break;
|
||||
case 10: name="java/lang/IllegalThreadStateException"; break;
|
||||
case 11: name="java/lang/IndexOutOfBoundsException"; break;
|
||||
case 12: name="java/lang/InstantiationException"; break;
|
||||
case 13: name="java/lang/InterruptedException"; break;
|
||||
case 14: name="java/lang/NegativeArraySizeException"; break;
|
||||
case 15: name="java/lang/NoSuchFieldException"; break;
|
||||
case 16: name="java/lang/NoSuchMethodException"; break;
|
||||
case 17: name="java/lang/NullPointerException"; break;
|
||||
case 18: name="java/lang/NumberFormatException"; break;
|
||||
case 19: name="java/lang/RuntimeException"; break;
|
||||
case 20: name="java/lang/SecurityException"; break;
|
||||
case 21: name="java/lang/StringIndexOutOfBoundsException"; break;
|
||||
case 22: name="java/lang/UnsupportedOperationException"; break;
|
||||
default: name="java/lang/Exception";
|
||||
}
|
||||
mess=name;
|
||||
|
||||
CHECK_EXCEPTION
|
||||
clazz = (*env)->FindClass(env, name);
|
||||
CHECK_EXCEPTION
|
||||
if ((*env)->ThrowNew(env, clazz, mess)) {
|
||||
const char *pass = "setpass";
|
||||
const char *passSig = "(Z)V";
|
||||
jclass incClazz;
|
||||
fprintf(stderr, "ThrowNew failed\n");
|
||||
CHECK_EXCEPTION;
|
||||
incClazz = (*env)->FindClass(env, iter);
|
||||
CHECK_EXCEPTION;
|
||||
jmethod=(*env)->GetStaticMethodID(env, incClazz, pass, passSig);
|
||||
CHECK_EXCEPTION
|
||||
(*env)->CallStaticVoidMethod(env, incClazz, jmethod, JNI_FALSE);
|
||||
CHECK_EXCEPTION
|
||||
}
|
||||
/* printf("JNI: count %d\n", Exceptcalls); */
|
||||
}
|
||||
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "jnihelper.h"
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_nsk_stress_jni_JNIter006_refs (JNIEnv *env, jobject jobj, jobject tobj, jint LIMIT) {
|
||||
|
||||
static jobject *globRefsArray = 0;
|
||||
static int upper = 0;
|
||||
|
||||
jclass clazz;
|
||||
jmethodID jmethod;
|
||||
jboolean res=JNI_FALSE;
|
||||
const char *classname = "nsk/stress/jni/JNIter006";
|
||||
const char *getmethodname="get_i";
|
||||
const char *setmethodname="set_i";
|
||||
const char *getsig="()I";
|
||||
const char *setsig="(I)V";
|
||||
const char *setdone = "halt";
|
||||
const char *setdonesig = "()V";
|
||||
int i = 0;
|
||||
|
||||
if (upper >= LIMIT) return JNI_TRUE;
|
||||
|
||||
if (upper==0)
|
||||
globRefsArray=(jobject*)(malloc(LIMIT*sizeof(jobject)));
|
||||
|
||||
globRefsArray[upper]=(*env)->NewGlobalRef(env, tobj); CE
|
||||
if ((*env)->IsSameObject(env, tobj, globRefsArray[upper])) {
|
||||
(*env)->DeleteLocalRef(env, tobj); CE
|
||||
clazz=(*env)->GetObjectClass(env, globRefsArray[upper]); CE
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,"Objects are different\n");
|
||||
(*env)->MonitorExit(env, jobj); CE
|
||||
return res;
|
||||
}
|
||||
jmethod=(*env)->GetStaticMethodID(env, clazz, setmethodname, setsig); CE
|
||||
(*env)->CallStaticVoidMethod(env, clazz, jmethod, (jint)upper); CE
|
||||
(*env)->MonitorEnter(env, jobj); CE
|
||||
++upper;
|
||||
res=JNI_TRUE;
|
||||
(*env)->MonitorExit(env, jobj); CE
|
||||
/* If upper == LIMIT than flush ref's array and set */
|
||||
/* 'done' flag in JNIter006 class to JNI_TRUE */
|
||||
if (upper == LIMIT) {
|
||||
fprintf(stderr,"\n\tTotal memory allocated: %zd bytes\n",
|
||||
LIMIT*sizeof(jobject));
|
||||
clazz=(*env)->FindClass(env, classname); CE
|
||||
jmethod=(*env)->GetMethodID(env, clazz, setdone, setdonesig); CE
|
||||
(*env)->CallVoidMethod(env, jobj, jmethod); CE
|
||||
|
||||
for (i=0;i<LIMIT;i++) {
|
||||
(*env)->DeleteGlobalRef(env, globRefsArray[i]); CE
|
||||
}
|
||||
free(globRefsArray);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include <stdio.h>
|
||||
#include "jnihelper.h"
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_nsk_stress_jni_JNIter007_incCount (JNIEnv *env, jobject jobj, jstring name) {
|
||||
jclass clazz;
|
||||
jfieldID fld;
|
||||
jint value;
|
||||
const char *str = (*env)->GetStringUTFChars(env, name, 0); CE
|
||||
|
||||
if ((*env)->MonitorEnter(env, jobj))
|
||||
printf("Error in monitor lock\n");
|
||||
clazz = (*env)->GetObjectClass(env, jobj); CE
|
||||
fld = (*env)->GetStaticFieldID(env, clazz, "nativeCount", "I"); CE
|
||||
value = (*env)->GetStaticIntField(env, clazz, fld); CE
|
||||
(*env)->SetStaticIntField(env, clazz, fld, (jint)(++value)); CE
|
||||
(*env)->MonitorExit(env, jobj); CE
|
||||
if (value%1000 == 0 )
|
||||
printf("in %s Count after %u\n", str, value);
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
#
|
||||
# Copyright (c) 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.
|
||||
#
|
||||
|
||||
exclusiveAccess.dirs=.
|
||||
544
test/hotspot/jtreg/vmTestbase/nsk/stress/network/network001.java
Normal file
544
test/hotspot/jtreg/vmTestbase/nsk/stress/network/network001.java
Normal file
@ -0,0 +1,544 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/network/network001.
|
||||
* VM testbase keywords: [stress, diehard, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test transfers huge amount of data between server and client
|
||||
* TCP/IP sockets, and checks if those data are transfered correctly.
|
||||
* Both sockets are attached to local host name, or to the loopback
|
||||
* "localhost" (having IP address 127.0.0.1).
|
||||
* Information transfer is synchronized in this test. Client passes
|
||||
* a large data parcel to server, and server reads that parcel and checks
|
||||
* if it is same as expected (byte-to-byte equality). Then server passes
|
||||
* (some other) parcel to client, and client reads and verifies those bytes.
|
||||
* This ping-pong game is repeated 2000 times; and after that both sockets
|
||||
* check if there are no extra bytes accudentally passed through their
|
||||
* connection.
|
||||
* Parcels lengths and contents are chosen randomly, and average parcel
|
||||
* length is 125 bytes. So totally, each of the 2 sockets passes ~250Kb of
|
||||
* data to its partner, and thus ~500Kb of data are transfered by this test.
|
||||
* COMMENTS
|
||||
* Note, that HotSpot 1.3beta-H fails to start this test due to the bug:
|
||||
* #4245704 (P1/S1) Fails to launch with: jre/bin/net.dll ...
|
||||
*
|
||||
* @run main/othervm nsk.stress.network.network001
|
||||
*/
|
||||
|
||||
package nsk.stress.network;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* This test transfers huge amount of data between server and client
|
||||
* TCP/IP sockets, and checks if those data are transfered correctly.
|
||||
* Both sockets are attached to local host name, or to the loopback
|
||||
* ``localhost'' (having IP address 127.0.0.1).
|
||||
* <p>
|
||||
* <p>Information transfer is synchronized in this test. Client passes
|
||||
* a large data parcel to server, and server reads that parcel and checks
|
||||
* if it is same as expected (byte-to-byte equality). Then server passes
|
||||
* (some other) parcel to client, and client reads and verifies those bytes.
|
||||
* This ping-pong game is repeated 2000 times; and after that both sockets
|
||||
* check if there are no extra bytes accudentally passed through their
|
||||
* connection.
|
||||
* <p>
|
||||
* <p>Parcels lengths and contents are chosen randomly, and average parcel
|
||||
* length is 125 bytes. So totally, each of the 2 sockets passes ~250Kb of
|
||||
* data to its partner, and thus ~500Kb of data are transfered by this test.
|
||||
*/
|
||||
public class network001 {
|
||||
/**
|
||||
* Number of parcels to be sent/recieve.
|
||||
*/
|
||||
private static final int DATA_PARCELS = 2000;
|
||||
|
||||
/**
|
||||
* Maximal length of data parcel to be sent/recieved
|
||||
* (now it equals to 250 bytes).
|
||||
*/
|
||||
private static final int MAX_PARCEL = 250;
|
||||
|
||||
/**
|
||||
* Either actually display optional reports or not.
|
||||
*/
|
||||
static private final boolean DEBUG_MODE = false;
|
||||
|
||||
/**
|
||||
* Errors and optional reports log. Usually <code>System.out</code>.
|
||||
*/
|
||||
static private PrintStream out = System.out;
|
||||
|
||||
/**
|
||||
* Print error message: both client and server may print
|
||||
* concurently.
|
||||
*/
|
||||
static private synchronized void println(Object message) {
|
||||
out.println(message.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Display optional report: comment ca va.
|
||||
*/
|
||||
static private void display(Object report) {
|
||||
if (DEBUG_MODE)
|
||||
println(report.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Server thread intended to reply to data parcels sent by Client thread.
|
||||
*/
|
||||
static private class Server extends Thread {
|
||||
/**
|
||||
* This server thread listens the single socket.
|
||||
*/
|
||||
private ServerSocket serverSocket;
|
||||
|
||||
/**
|
||||
* Address and port of this server socket.
|
||||
*/
|
||||
public String toString() {
|
||||
return serverSocket.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Did the thread failed? If yes, what is the failure's reason.
|
||||
*/
|
||||
Exception exception = null;
|
||||
|
||||
/**
|
||||
* Which port does this socket is listening.
|
||||
*/
|
||||
int getPort() {
|
||||
return serverSocket.getLocalPort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find some free port at the given <code>address</code>
|
||||
* and attach new server to hear that port.
|
||||
*/
|
||||
Server(InetAddress address) throws IOException {
|
||||
int someFreePort = 0;
|
||||
int backlog = 50; // default for new ServerSocket(port)
|
||||
serverSocket = new ServerSocket(someFreePort, backlog, address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept connection, read the string "abra", and respond "cadabra".
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
Socket socket = serverSocket.accept();
|
||||
display("Server socket: " + socket);
|
||||
|
||||
InputStream istream = socket.getInputStream();
|
||||
OutputStream ostream = socket.getOutputStream();
|
||||
|
||||
Random random = new Random(0);
|
||||
|
||||
for (int i = 0; i < DATA_PARCELS; i++) {
|
||||
Parcel etalon = new Parcel(random);
|
||||
|
||||
Parcel sample = new Parcel(istream); // read
|
||||
if (!sample.equals(etalon)) {
|
||||
println("Server thread got unexpected parcel:");
|
||||
println("sample=" + sample);
|
||||
println("etalon=" + etalon);
|
||||
throw new TestFailure(
|
||||
"server has read unexpected parcel");
|
||||
}
|
||||
|
||||
etalon.send(ostream);
|
||||
ostream.flush();
|
||||
}
|
||||
|
||||
int datum = istream.read(); // wait for client close()
|
||||
if (datum >= 0)
|
||||
throw new TestFailure(
|
||||
"server has read ambigous byte: " + datum);
|
||||
|
||||
ostream.close(); // implies: socket.close();
|
||||
|
||||
} catch (Exception oops) {
|
||||
exception = oops;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Client thread intended to send data parcels to Server thread and
|
||||
* to recieve the server's replies.
|
||||
*/
|
||||
static private class Client extends Thread {
|
||||
/**
|
||||
* This thread uses the single client socket.
|
||||
*/
|
||||
private Socket socket;
|
||||
|
||||
/**
|
||||
* Address and port of this socket.
|
||||
*/
|
||||
public String toString() {
|
||||
return socket.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Did the thread failed? If yes, what is the failure's reason.
|
||||
*/
|
||||
Exception exception = null;
|
||||
|
||||
/**
|
||||
* Connect client socket on the given <code>address</code>
|
||||
* and <code>port</code>.
|
||||
*/
|
||||
Client(InetAddress address, int port) throws IOException {
|
||||
socket = new Socket(address, port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept connection, read the string "abra", and respond "cadabra".
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
InputStream istream = socket.getInputStream();
|
||||
OutputStream ostream = socket.getOutputStream();
|
||||
|
||||
Random random = new Random(0);
|
||||
|
||||
for (int i = 0; i < DATA_PARCELS; i++) {
|
||||
Parcel etalon = new Parcel(random);
|
||||
etalon.send(ostream);
|
||||
ostream.flush();
|
||||
|
||||
Parcel sample = new Parcel(istream); // read
|
||||
if (!sample.equals(etalon)) {
|
||||
println("Client thread got unexpected parcel:");
|
||||
println("sample=" + sample);
|
||||
println("etalon=" + etalon);
|
||||
throw new TestFailure(
|
||||
"parcel context is unexpected to client");
|
||||
}
|
||||
}
|
||||
|
||||
if (istream.available() > 0) {
|
||||
int datum = istream.read();
|
||||
throw new TestFailure(
|
||||
"client has read ambigous byte: " + datum);
|
||||
}
|
||||
ostream.close(); // implies: socket.close()
|
||||
|
||||
} catch (Exception oops) {
|
||||
exception = oops;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A data parcel to sent/recieved between Client and Server threads.
|
||||
* When data parcel is sent, first 4 bytes transfered encode the size
|
||||
* of the parcel (i.e.: number of data bytes in the parcel's contents).
|
||||
* Then the parcel's contents bytes are transered.
|
||||
*/
|
||||
static class Parcel {
|
||||
private byte[] parcel;
|
||||
|
||||
/**
|
||||
* Display all bytes as integer values from 0 to 255;
|
||||
* or return ``<tt>null</tt>'' if this Parcel is not
|
||||
* yet initialized.
|
||||
*/
|
||||
public String toString() {
|
||||
if (parcel == null)
|
||||
return "null";
|
||||
String s = "{";
|
||||
for (int i = 0; i < parcel.length; i++)
|
||||
s += (i > 0 ? ", " : "") + ((int) parcel[i] & 0xFF);
|
||||
return s + "}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate new <code>parcel[]</code> array using the given
|
||||
* <code>random</code> numbers generator. Client and Server
|
||||
* threads should use identical <code>random</code> generators,
|
||||
* so that those threads could generate equal data parcels and
|
||||
* check the parcel just transfered.
|
||||
*/
|
||||
public Parcel(Random random) {
|
||||
int size = random.nextInt(MAX_PARCEL) + 1;
|
||||
parcel = new byte[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
parcel[i] = (byte) random.nextInt(256);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read exactly <code>size</code> bytes from the <code>istream</code>
|
||||
* if possible, or throw <code>TestFailure</code> if unexpected end of
|
||||
* <code>istream</code> occurs.
|
||||
*/
|
||||
private static byte[] readBytes(int size, InputStream istream)
|
||||
throws IOException {
|
||||
|
||||
byte data[] = new byte[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
int datum = istream.read();
|
||||
if (datum < 0)
|
||||
throw new TestFailure(
|
||||
"unexpected EOF: have read: " + i + " bytes of " + size);
|
||||
data[i] = (byte) datum;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 4 bytes from <code>istream</code> and threat them to encode
|
||||
* size of data parcel following these 4 bytes.
|
||||
*/
|
||||
private static int getSize(InputStream istream) throws IOException {
|
||||
byte data[] = readBytes(4, istream);
|
||||
int data0 = (int) data[0] & 0xFF;
|
||||
int data1 = (int) data[1] & 0xFF;
|
||||
int data2 = (int) data[2] & 0xFF;
|
||||
int data3 = (int) data[3] & 0xFF;
|
||||
int sizeWord = data0 + (data1 << 8) + (data2 << 16) + (data3 << 24);
|
||||
int size = sizeWord + 1;
|
||||
if (size <= 0)
|
||||
throw new TestFailure("illegal size: " + size);
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send 4 bytes encoding actual size of the parcel just to be transfered.
|
||||
*/
|
||||
private static void putSize(OutputStream ostream, int size)
|
||||
throws IOException {
|
||||
|
||||
if (size <= 0)
|
||||
throw new TestFailure("illegal size: " + size);
|
||||
|
||||
int sizeWord = size - 1;
|
||||
byte data[] = new byte[4];
|
||||
data[0] = (byte) sizeWord;
|
||||
data[1] = (byte) (sizeWord >> 8);
|
||||
data[2] = (byte) (sizeWord >> 16);
|
||||
data[3] = (byte) (sizeWord >> 24);
|
||||
ostream.write(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recieve data parcel.
|
||||
*/
|
||||
public Parcel(InputStream istream) throws IOException {
|
||||
int size = getSize(istream);
|
||||
parcel = readBytes(size, istream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send <code>this</code> data parcel.
|
||||
*/
|
||||
public void send(OutputStream ostream) throws IOException {
|
||||
int size = parcel.length;
|
||||
putSize(ostream, size);
|
||||
ostream.write(parcel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check byte-to-byte equality between <code>this</code> and the
|
||||
* <code>other</code> parcels.
|
||||
*/
|
||||
public boolean equals(Parcel other) {
|
||||
if (this.parcel.length != other.parcel.length)
|
||||
return false;
|
||||
int size = parcel.length;
|
||||
for (int i = 0; i < size; i++)
|
||||
if (this.parcel[i] != other.parcel[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Server or Client thread may throw this exception to report the test
|
||||
* failure.
|
||||
*/
|
||||
static class TestFailure extends RuntimeException {
|
||||
/**
|
||||
* Report particular <code>purpose</code> of the test failure.
|
||||
*/
|
||||
public TestFailure(String purpose) {
|
||||
super(purpose);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach client and server sockets to the local host, and check if
|
||||
* huge amount of data could be correctly transfered between these
|
||||
* sockets.
|
||||
* <p>
|
||||
* <p>Command-line parameters provided with <code>args[]</code> may
|
||||
* prompt the local host IP address or domain name. Execute:
|
||||
* <br>
|
||||
* <code>java network001 [<i>IP-address</i> | <i>host_name</i> |
|
||||
* localhost ]</code>
|
||||
* <br>where parameters are:
|
||||
* <br>
|
||||
* <code><i>IP-address</i></code> - local hots's address, or 127.0.0.1
|
||||
* <br>
|
||||
* <code><i>host_name</i></code> - local host's domain name, or the
|
||||
* keyword ``<code>localhost</code>''
|
||||
* <br>
|
||||
* <code>localhost</code> - placeholder for the IP-address 127.0.0.1
|
||||
* <br>By default, the test uses the Internet address available via
|
||||
* the method <code>InetAddress.getLocalHost()</code>
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
network001.out = out;
|
||||
|
||||
//
|
||||
// Get IP address of the local machine.
|
||||
//
|
||||
|
||||
InetAddress address = null;
|
||||
try {
|
||||
switch (args.length) {
|
||||
case 0:
|
||||
address = InetAddress.getLocalHost();
|
||||
break;
|
||||
case 1:
|
||||
String hostName = args[0];
|
||||
address = InetAddress.getByName(args[0]);
|
||||
break;
|
||||
default:
|
||||
println("Use:");
|
||||
println(" java network001");
|
||||
println("or:");
|
||||
println(" java network001 ${IP_ADDRESS}");
|
||||
println("or:");
|
||||
println(" java network001 ${HOST_NAME}");
|
||||
println("or:");
|
||||
println(" java network001 localhost");
|
||||
return 2; // FAILED
|
||||
}
|
||||
} catch (UnknownHostException exception) {
|
||||
println(exception);
|
||||
return 2; // FAILED
|
||||
}
|
||||
display("Host: " + address);
|
||||
|
||||
//
|
||||
// Incarnate the server & the client sockets.
|
||||
//
|
||||
|
||||
Server server = null;
|
||||
try {
|
||||
server = new Server(address);
|
||||
} catch (IOException io) {
|
||||
println("Failed to create server: " + io);
|
||||
return 2;
|
||||
}
|
||||
display("Server: " + server);
|
||||
|
||||
int port = server.getPort();
|
||||
|
||||
Client client = null;
|
||||
try {
|
||||
client = new Client(address, port);
|
||||
} catch (IOException io) {
|
||||
out.println("Failed to create client: " + io);
|
||||
return 2;
|
||||
}
|
||||
display("Client socket: " + client);
|
||||
|
||||
//
|
||||
// Execute the server and client threads.
|
||||
//
|
||||
|
||||
Exception exception = null;
|
||||
try {
|
||||
server.start();
|
||||
client.start();
|
||||
while (client.isAlive() || server.isAlive())
|
||||
if (client.exception == null && server.exception == null)
|
||||
Thread.yield();
|
||||
else
|
||||
break;
|
||||
} catch (TestFailure failure) {
|
||||
exception = failure;
|
||||
}
|
||||
|
||||
// Failure diagnostics, if needed.
|
||||
|
||||
Exception problem[] = new Exception[3];
|
||||
problem[0] = exception;
|
||||
problem[1] = server.exception;
|
||||
problem[2] = client.exception;
|
||||
|
||||
int exitCode = 0;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
if (problem[i] != null) {
|
||||
out.println("#### OOPS ! ####");
|
||||
problem[i].printStackTrace(out);
|
||||
exitCode = 2;
|
||||
}
|
||||
|
||||
if (exitCode != 0) {
|
||||
out.println("#### OOPS ! ####");
|
||||
out.println("# Test failed.");
|
||||
return 2; // FAILED
|
||||
}
|
||||
display("Test passed.");
|
||||
return 0; // PASSED
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-calls to the method <code>run(args[],out)</code> actually
|
||||
* performing the test; and stop with exit code 95 if the test
|
||||
* has passed, or with code 97 if the test has failed.
|
||||
* (This is JCK-like exit codes convention.)
|
||||
*
|
||||
* @see #run(String[], PrintStream)
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit code.
|
||||
}
|
||||
|
||||
}
|
||||
697
test/hotspot/jtreg/vmTestbase/nsk/stress/network/network002.java
Normal file
697
test/hotspot/jtreg/vmTestbase/nsk/stress/network/network002.java
Normal file
@ -0,0 +1,697 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/network/network002.
|
||||
* VM testbase keywords: [stress, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test transfers huge amount of data between 2 Java virtual machines
|
||||
* using the TCP/IP protocol, and checks if those data are transfered correctly.
|
||||
* Both client and server VMs run on the same local computer and attach TCP/IP
|
||||
* sockets to the local host, or to the loopback domain "localhost" (having IP
|
||||
* address 127.0.0.1).
|
||||
* Information transfer is synchronized in this test. Client VM passes
|
||||
* a large data parcel to server VM, and server reads that parcel and checks
|
||||
* if it is same as expected (byte-to-byte equality). Then server passes
|
||||
* (some other) parcel to client, and client reads and verifies those data.
|
||||
* This ping-pong game is repeated 2000 times; and after that both VMs check
|
||||
* if there are no extra bytes accudentally passed through their connection.
|
||||
* Parcels lengths and contents are chosen randomly, and average parcel
|
||||
* length is 125 bytes. So totally, each of the 2 VMs passes ~250Kb of data
|
||||
* to its partner, and thus ~500Kb of data are transfered by this test.
|
||||
* COMMENTS
|
||||
* HotSpot 1.3beta-H fails to start this test due to the hotspot bug:
|
||||
* #4245704 (P1/S1) Fails to launch with: jre/bin/net.dll ...
|
||||
* Test was fixed:
|
||||
* added WAITTIME parameter defined timeout for TCP/IP sockets in minutes
|
||||
*
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @run driver jdk.test.lib.FileInstaller . .
|
||||
* @build nsk.stress.network.network002
|
||||
* @run main/othervm PropertyResolvingWrapper
|
||||
* nsk.stress.network.network002
|
||||
* "${test.jdk}/bin/java ${test.vm.opts} ${test.java.opts}" 5
|
||||
*/
|
||||
|
||||
package nsk.stress.network;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* This test transfers huge amount of data between 2 Java virtual machines
|
||||
* using the TCP/IP protocol, and checks if those data are transfered correctly.
|
||||
* Both client and server VMs run on the same local computer and attach TCP/IP
|
||||
* sockets to the local host, or to the loopback domain ``<code>localhost</code>''
|
||||
* (having IP address <code>127.0.0.1</code>).
|
||||
* <p>
|
||||
* <p>Information transfer is synchronized in this test. Client VM passes
|
||||
* a large data parcel to server VM, and server reads that parcel and checks
|
||||
* if it is same as expected (byte-to-byte equality). Then server passes
|
||||
* (some other) parcel to client, and client reads and verifies those data.
|
||||
* This ping-pong game is repeated 2000 times; and after that both VMs check
|
||||
* if there are no extra bytes accudentally passed through their connection.
|
||||
* <p>
|
||||
* <p>Parcels lengths and contents are chosen randomly, and average parcel
|
||||
* length is 125 bytes. So totally, each of the 2 VMs passes ~250Kb of data
|
||||
* to its partner, and thus ~500Kb of data are transfered by this test.
|
||||
*/
|
||||
public class network002 {
|
||||
/**
|
||||
* Timeout for TCP/IP sockets (currently set to 1 min).
|
||||
*/
|
||||
private static int SO_TIMEOUT;
|
||||
|
||||
/**
|
||||
* Number of parcels to be sent/recieved.
|
||||
*/
|
||||
private static final int DATA_PARCELS = 2000;
|
||||
|
||||
/**
|
||||
* Maximal length of data parcel to be sent/recieved.
|
||||
*/
|
||||
private static final int MAX_PARCEL = 250;
|
||||
|
||||
/**
|
||||
* Either actually display optional reports or not.
|
||||
*/
|
||||
static private final boolean DEBUG_MODE = false;
|
||||
|
||||
//----------------------------------------------------------------//
|
||||
|
||||
/**
|
||||
* Re-calls to the method <code>run(args[],out)</code> actually
|
||||
* performing the test. After <code>run(args[],out)</code> stops,
|
||||
* follow JDK-like convention for exit codes. I.e.: stop with
|
||||
* exit status 95 if the test has passed, or with status 97 if
|
||||
* the test has failed.
|
||||
*
|
||||
* @see #run(String[], PrintStream)
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status.
|
||||
}
|
||||
|
||||
/**
|
||||
* Incarnate new <code>network002</code> instance reporting to the given
|
||||
* <code>out</code> stream, and invoke the method <code>run(args)</code>
|
||||
* for that instance to perform the test.
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
network002 test = new network002(out);
|
||||
int exitCode = test.run(args);
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line parameters stored into <code>args[]</code> array,
|
||||
* then perform the test. I.e.: start the server thread at the same VM
|
||||
* this method runs, then start the other client VM, and verify data
|
||||
* transfer through TCP/IP connection between those different virtual
|
||||
* machines.
|
||||
* <p>
|
||||
* <p>There should be 1 or 2 command-line parameters:
|
||||
* <br>
|
||||
* <code>java network002 <i>java_command</i> <i>waittime</i>
|
||||
* [<i>IP-address</i> | <i>host_name</i> | localhost ]</code>
|
||||
* <br>where parameters are:
|
||||
* <br>
|
||||
* <code><i>java_command</i></code> - how to start java,
|
||||
* e.g.: ``<code>c:\jdk1.3\bin\java -classic</code>''
|
||||
* <br>
|
||||
* <code>waittime</code> - timeout for TCP/IP sockets in minutes
|
||||
* <br>
|
||||
* <code><i>IP-address</i></code> - local hots's address, or 127.0.0.1
|
||||
* <br>
|
||||
* <code><i>host_name</i></code> - local host's domain name, or the
|
||||
* keyword ``<code>localhost</code>''
|
||||
* <br>
|
||||
* <code>localhost</code> - placeholder for the IP-address 127.0.0.1
|
||||
* <p>
|
||||
* <p>Usually, <code><i>java_command</i></code> should point to the same
|
||||
* Java machine just executing this test. However, every compatible Java 2
|
||||
* implementation is appropriate.
|
||||
* <p>
|
||||
* <p>If optional parameter is ommited, the test invokes the method
|
||||
* <code>InetAddress.getLocalHost()</code> to get the domain name and
|
||||
* IP-address of the local computer.
|
||||
*/
|
||||
private int run(String args[]) {
|
||||
//
|
||||
// Get the Internet address of the local machine.
|
||||
//
|
||||
InetAddress address = null;
|
||||
try {
|
||||
switch (args.length) {
|
||||
case 2:
|
||||
address = InetAddress.getLocalHost();
|
||||
break;
|
||||
case 3:
|
||||
address = InetAddress.getByName(args[2]);
|
||||
break;
|
||||
default:
|
||||
complain("Illegal arguments number; execute:");
|
||||
complain(" java network002 $JAVA_COMMAND " +
|
||||
"[$IP_ADDRESS | $HOST_NAME | localhost]");
|
||||
return 2; // FAILED
|
||||
}
|
||||
} catch (UnknownHostException exception) {
|
||||
complain(exception.toString());
|
||||
return 2; // FAILED
|
||||
}
|
||||
display("Host: " + address);
|
||||
|
||||
//
|
||||
// Start the server thread on the same VM this method just runs.
|
||||
//
|
||||
Server server = null;
|
||||
try {
|
||||
server = new Server(address);
|
||||
server.start();
|
||||
} catch (Exception exception) {
|
||||
complain("Failed to start server: " + exception);
|
||||
return 2;
|
||||
}
|
||||
display("Server: " + server);
|
||||
|
||||
//
|
||||
// Start the client process on different VM.
|
||||
//
|
||||
String IPAddress = server.getIPAddress(); // e.g.: 127.0.0.1
|
||||
int port = server.getPort();
|
||||
String command = args[0] + " " + network002.class.getName() + "$Client " + IPAddress + " " + port;
|
||||
try {
|
||||
SO_TIMEOUT = Integer.parseInt(args[1]) * 60 * 1000;
|
||||
} catch (NumberFormatException e) {
|
||||
complain("Wrong timeout argument: " + e);
|
||||
return 2;
|
||||
}
|
||||
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
|
||||
Process client = null;
|
||||
IORedirector redirectOut = null;
|
||||
IORedirector redirectErr = null;
|
||||
|
||||
try {
|
||||
client = runtime.exec(command);
|
||||
|
||||
InputStream clientOut = client.getInputStream();
|
||||
InputStream clientErr = client.getErrorStream();
|
||||
redirectOut = new IORedirector(clientOut, DEBUG_MODE ? out : null);
|
||||
redirectErr = new IORedirector(clientErr, out);
|
||||
redirectOut.start();
|
||||
redirectErr.start();
|
||||
|
||||
} catch (Exception exception) {
|
||||
complain("Failed to start client: " + exception);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Wait until the server and client both stop.
|
||||
//
|
||||
try {
|
||||
client.waitFor();
|
||||
if (redirectOut.isAlive())
|
||||
redirectOut.join();
|
||||
if (redirectErr.isAlive())
|
||||
redirectErr.join();
|
||||
|
||||
// If client has crashed, also terminate the server (to avoid hangup).
|
||||
int clientStatus = client.exitValue();
|
||||
if (clientStatus != 95) {
|
||||
complain("");
|
||||
complain("Client VM has crashed: exit status=" + clientStatus);
|
||||
if (server.isAlive())
|
||||
complain("Server also should be terminated.");
|
||||
complain("Test failed.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
// Client has finished OK; wait for the server.
|
||||
if (server.isAlive())
|
||||
server.join();
|
||||
|
||||
} catch (Exception exception) {
|
||||
complain("Test interrupted: " + exception);
|
||||
complain("Test failed.");
|
||||
return 2; // FAILURE
|
||||
}
|
||||
|
||||
//
|
||||
// Complain failure, if occured.
|
||||
//
|
||||
|
||||
if (server.exception != null) {
|
||||
complain("Server exception: " + server.exception);
|
||||
complain("Test failed.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
display("Test passed.");
|
||||
return 0; // Ok
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------//
|
||||
|
||||
/**
|
||||
* The test should report to the given <code>out</code> stream.
|
||||
*/
|
||||
private network002(PrintStream out) {
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log stream for error messages and/or (optional) execution trace.
|
||||
*/
|
||||
private PrintStream out;
|
||||
|
||||
/**
|
||||
* Print error message.
|
||||
*/
|
||||
private void complain(Object message) {
|
||||
out.println("# " + message);
|
||||
out.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display optional report: comment ca va?
|
||||
*/
|
||||
private void display(Object report) {
|
||||
if (DEBUG_MODE)
|
||||
out.println(report.toString());
|
||||
out.flush();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------//
|
||||
|
||||
/**
|
||||
* Server thread should reply to data parcels sent by Client VM.
|
||||
*/
|
||||
private class Server extends Thread {
|
||||
/**
|
||||
* The socket to listen for a client.
|
||||
*/
|
||||
private ServerSocket serverSocket;
|
||||
|
||||
/**
|
||||
* Display the server socket.
|
||||
*/
|
||||
public String toString() {
|
||||
return serverSocket.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Server's IP-address in the form ``<code><i>x.y.u.z</i></code>'',
|
||||
* or ``<code>127.0.0.1</code>'' for loopback connection.
|
||||
*/
|
||||
public String getIPAddress() {
|
||||
return serverSocket.getInetAddress().getHostAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
* Which port is this socket listening?
|
||||
*/
|
||||
int getPort() {
|
||||
return serverSocket.getLocalPort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find some free port at the given <code>address</code>
|
||||
* and attach new server to hear that port.
|
||||
*/
|
||||
public Server(InetAddress address) throws IOException {
|
||||
int someFreePort = 0;
|
||||
int backlog = 50; // default for new ServerSocket(port)
|
||||
serverSocket = new ServerSocket(someFreePort, backlog, address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception just arisen while the server was working,
|
||||
* or <code>null</code> if it was OK with the server.
|
||||
*/
|
||||
Exception exception = null;
|
||||
|
||||
/**
|
||||
* Accept connection, then reply to client's parcels.
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
Socket socket = serverSocket.accept();
|
||||
socket.setSoTimeout(SO_TIMEOUT);
|
||||
|
||||
InputStream istream = socket.getInputStream();
|
||||
OutputStream ostream = socket.getOutputStream();
|
||||
|
||||
Random random = new Random(0);
|
||||
|
||||
for (int i = 0; i < DATA_PARCELS; i++) {
|
||||
display("Server: i=" + i);
|
||||
Parcel etalon = new Parcel(random);
|
||||
|
||||
Parcel sample = new Parcel(istream); // read
|
||||
if (!sample.equals(etalon)) {
|
||||
complain("Server got unexpected parcel:\n"
|
||||
+ "sample=" + sample + "\n"
|
||||
+ "etalon=" + etalon);
|
||||
throw new TestFailure(
|
||||
"the parcel just read seems wrong for server");
|
||||
}
|
||||
|
||||
etalon.send(ostream);
|
||||
ostream.flush();
|
||||
}
|
||||
|
||||
int datum = istream.read(); // wait for client close()
|
||||
if (datum >= 0)
|
||||
throw new TestFailure(
|
||||
"server has read ambigous byte: " + datum);
|
||||
|
||||
ostream.close(); // implies: socket.close();
|
||||
|
||||
} catch (Exception oops) {
|
||||
exception = oops;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------//
|
||||
|
||||
/**
|
||||
* Client VM should send data parcels to Server VM and
|
||||
* recieve and verify the server's replies.
|
||||
*/
|
||||
private static class Client {
|
||||
/**
|
||||
* Print error message.
|
||||
*/
|
||||
private static void complain(Object message) {
|
||||
System.err.println("# " + message);
|
||||
System.err.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display execution trace.
|
||||
*/
|
||||
private static void display(Object message) {
|
||||
System.out.println(message.toString());
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit with JCK-like status.
|
||||
*/
|
||||
private static void exit(int exitCode) {
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atack server with huge data parcels, and check if it replies correctly.
|
||||
* The command-line parameters prescribe the server's IP-address and port:
|
||||
* <br>
|
||||
* <code>java network002$Client <i>IP-address</i> <i>port</i></code>
|
||||
* <br>where:
|
||||
* <br>
|
||||
* <code><i>IP-address</i></code> - local host's address,
|
||||
* or <code>127.0.0.1</code>
|
||||
* <br>
|
||||
* <code><i>port</i></code> - some port assigned by server
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
if (args.length != 2) {
|
||||
complain("Illegal number of client paramenets, try:");
|
||||
complain(" java network002$Client IP-address port");
|
||||
exit(2); // FAILED
|
||||
}
|
||||
|
||||
try {
|
||||
InetAddress address = InetAddress.getByName(args[0]);
|
||||
int port = Integer.parseInt(args[1]);
|
||||
|
||||
Socket socket = new Socket(address, port);
|
||||
socket.setSoTimeout(SO_TIMEOUT);
|
||||
display("Client: " + socket);
|
||||
|
||||
InputStream istream = socket.getInputStream();
|
||||
OutputStream ostream = socket.getOutputStream();
|
||||
|
||||
Random random = new Random(0);
|
||||
|
||||
for (int i = 0; i < DATA_PARCELS; i++) {
|
||||
display("Client: i=" + i);
|
||||
Parcel etalon = new Parcel(random);
|
||||
etalon.send(ostream);
|
||||
ostream.flush();
|
||||
|
||||
Parcel sample = new Parcel(istream); // read
|
||||
if (!sample.equals(etalon)) {
|
||||
complain("Client got unexpected parcel:\n"
|
||||
+ "sample=" + sample + "\n"
|
||||
+ "etalon=" + etalon);
|
||||
throw new TestFailure(
|
||||
"parcel context is unexpected to client");
|
||||
}
|
||||
}
|
||||
|
||||
if (istream.available() > 0) {
|
||||
int datum = istream.read();
|
||||
throw new TestFailure(
|
||||
"client has read ambigous byte: " + datum);
|
||||
}
|
||||
ostream.close(); // implies: socket.close()
|
||||
|
||||
} catch (Exception exception) {
|
||||
complain("Client exception: " + exception);
|
||||
exit(2); // FAILED
|
||||
}
|
||||
exit(0); // PASSED, at least at the client side.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Two of such threads should redirect <code>out</code> and <code>err</code>
|
||||
* streams of client VM.
|
||||
*/
|
||||
private static class IORedirector extends Thread {
|
||||
/**
|
||||
* Source stream.
|
||||
*/
|
||||
InputStream in;
|
||||
/**
|
||||
* Destination stream.
|
||||
*/
|
||||
OutputStream out;
|
||||
|
||||
/**
|
||||
* Redirect <code>in</code> to <code>out</code>.
|
||||
*/
|
||||
public IORedirector(InputStream in, OutputStream out) {
|
||||
this.in = in;
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read input stream until the EOF, and write everithing to output stream.
|
||||
* If output stream is assigned to <code>null</code>, do not print anything,
|
||||
* but read the input stream anywhere.
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
for (; ; ) {
|
||||
int symbol = in.read();
|
||||
if (symbol < 0)
|
||||
break; // EOF
|
||||
if (out != null)
|
||||
out.write(symbol);
|
||||
}
|
||||
|
||||
if (out != null)
|
||||
out.flush();
|
||||
|
||||
} catch (Exception exception) {
|
||||
throw new TestFailure("IORedirector exception: " + exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------//
|
||||
|
||||
/**
|
||||
* A data parcel to be sent/recieved between Client VM and Server thread.
|
||||
* When data parcel is sent, first 4 bytes are transfered which encode the
|
||||
* <code>int</code> number equal to size of the parcel minus 1. I.e.: if
|
||||
* number of data bytes in the parcel's contents is <code>N</code>, then
|
||||
* the first 4 bytes encode the number <code>N-1</code>. After that, the
|
||||
* parcel's contents bytes are transered.
|
||||
*/
|
||||
static class Parcel {
|
||||
private byte[] parcel;
|
||||
|
||||
/**
|
||||
* Display all bytes as integer values from 0 to 255;
|
||||
* or return ``<tt>null</tt>'' if this Parcel is not
|
||||
* yet initialized.
|
||||
*/
|
||||
public String toString() {
|
||||
if (parcel == null)
|
||||
return "null";
|
||||
String s = "{";
|
||||
for (int i = 0; i < parcel.length; i++)
|
||||
s += (i > 0 ? ", " : "") + ((int) parcel[i] & 0xFF);
|
||||
return s + "}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate new <code>parcel[]</code> array using the given
|
||||
* <code>random</code> numbers generator. Client and Server
|
||||
* threads should use identical <code>random</code> generators,
|
||||
* so that those threads could generate equal data parcels and
|
||||
* check the parcel just transfered.
|
||||
*/
|
||||
public Parcel(Random random) {
|
||||
int size = random.nextInt(MAX_PARCEL) + 1;
|
||||
parcel = new byte[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
parcel[i] = (byte) random.nextInt(256);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read exactly <code>size</code> bytes from the <code>istream</code>
|
||||
* if possible, or throw <code>TestFailure</code> if unexpected end of
|
||||
* <code>istream</code> occurs.
|
||||
*/
|
||||
private static byte[] readBytes(int size, InputStream istream)
|
||||
throws IOException {
|
||||
|
||||
byte data[] = new byte[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
int datum = istream.read();
|
||||
if (datum < 0)
|
||||
throw new TestFailure(
|
||||
"unexpected EOF: have read: " + i + " bytes of " + size);
|
||||
data[i] = (byte) datum;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 4 bytes from <code>istream</code> and threat them to encode
|
||||
* size of data parcel following these 4 bytes.
|
||||
*/
|
||||
private static int getSize(InputStream istream) throws IOException {
|
||||
byte data[] = readBytes(4, istream);
|
||||
int data0 = (int) data[0] & 0xFF;
|
||||
int data1 = (int) data[1] & 0xFF;
|
||||
int data2 = (int) data[2] & 0xFF;
|
||||
int data3 = (int) data[3] & 0xFF;
|
||||
int sizeWord = data0 + (data1 << 8) + (data2 << 16) + (data3 << 24);
|
||||
int size = sizeWord + 1;
|
||||
if (size <= 0)
|
||||
throw new TestFailure("illegal size: " + size);
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send 4 bytes encoding actual size of the parcel just to be transfered.
|
||||
*/
|
||||
private static void putSize(OutputStream ostream, int size)
|
||||
throws IOException {
|
||||
|
||||
if (size <= 0)
|
||||
throw new TestFailure("illegal size: " + size);
|
||||
|
||||
int sizeWord = size - 1;
|
||||
byte data[] = new byte[4];
|
||||
data[0] = (byte) sizeWord;
|
||||
data[1] = (byte) (sizeWord >> 8);
|
||||
data[2] = (byte) (sizeWord >> 16);
|
||||
data[3] = (byte) (sizeWord >> 24);
|
||||
ostream.write(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recieve data parcel.
|
||||
*/
|
||||
public Parcel(InputStream istream) throws IOException {
|
||||
int size = getSize(istream);
|
||||
parcel = readBytes(size, istream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send <code>this</code> data parcel.
|
||||
*/
|
||||
public void send(OutputStream ostream) throws IOException {
|
||||
int size = parcel.length;
|
||||
putSize(ostream, size);
|
||||
ostream.write(parcel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check byte-to-byte equality between <code>this</code> and the
|
||||
* <code>other</code> parcels.
|
||||
*/
|
||||
public boolean equals(Parcel other) {
|
||||
if (this.parcel.length != other.parcel.length)
|
||||
return false;
|
||||
int size = parcel.length;
|
||||
for (int i = 0; i < size; i++)
|
||||
if (this.parcel[i] != other.parcel[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Server or Client may throw this exception to report the test failure.
|
||||
*/
|
||||
static class TestFailure extends RuntimeException {
|
||||
/**
|
||||
* Report particular <code>purpose</code> of the test failure.
|
||||
*/
|
||||
public TestFailure(String purpose) {
|
||||
super(purpose);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
658
test/hotspot/jtreg/vmTestbase/nsk/stress/network/network003.java
Normal file
658
test/hotspot/jtreg/vmTestbase/nsk/stress/network/network003.java
Normal file
@ -0,0 +1,658 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/network/network003.
|
||||
* VM testbase keywords: [stress, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test transfers huge amount of data between one server and multiple
|
||||
* clients communicating via TCP/IP sockets, and checks if those data are
|
||||
* transfered correctly. All TCP/IP sockets are attached to local host
|
||||
* (by its domain name), or to the ``localhost'' loopback (having the IP
|
||||
* address 127.0.0.1).
|
||||
* In this test, 128 client/server connections are established. Once a
|
||||
* connection is established, client passes a large data parcel to server,
|
||||
* and server reads that parcel and checks if it is same as expected
|
||||
* (byte-to-byte equality is desired). Then server passes (some other) parcel
|
||||
* to the client, and client reads and verifies those bytes. This ping-pong
|
||||
* game is repeated 128 times; and after that each pair of sockets checks if
|
||||
* there are no extra bytes accudentally passed through their connection.
|
||||
* Parcels lengths and contents are chosen randomly, and average parcel
|
||||
* length is 128 bytes. So totally, each pair of sockets passes ~16Kb of
|
||||
* data to each other, and thus ~32Kb of data are transfered by each sockets
|
||||
* pair. Totally, ~4Mb of data are transfered by all client/server pairs.
|
||||
* COMMENTS
|
||||
* The production Solaris_JDK_1.3-b12 Server VM crashes under this test:
|
||||
* #
|
||||
* # HotSpot Virtual Machine Error, Unexpected Signal 10
|
||||
* # Please report this error at
|
||||
* # http://java.sun.com/cgi-bin/bugreport.cgi
|
||||
* #
|
||||
* # Error ID: 4F533F534F4C415249530E43505007D9 01
|
||||
* #
|
||||
* # Problematic Thread: prio=5 tid=0x214418 nid=0x103 runnable
|
||||
* #
|
||||
* (ErrorID == "os_solaris.cpp, 2009")
|
||||
*
|
||||
* @run main/othervm nsk.stress.network.network003
|
||||
*/
|
||||
|
||||
package nsk.stress.network;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* This test transfers huge amount of data between one server and multiple
|
||||
* clients communicating via TCP/IP sockets, and checks if those data are
|
||||
* transfered correctly. All TCP/IP sockets are attached to local host
|
||||
* (by its domain name), or to the ``localhost'' loopback (having the IP
|
||||
* address 127.0.0.1).
|
||||
* <p>
|
||||
* <p>In this test, 128 client/server connections are established. Once a
|
||||
* connection is established, client passes a large data parcel to server,
|
||||
* and server reads that parcel and checks if it is same as expected
|
||||
* (byte-to-byte equality is desired). Then server passes (some other) parcel
|
||||
* to the client, and client reads and verifies those bytes. This ping-pong
|
||||
* game is repeated 128 times; and after that each pair of sockets checks if
|
||||
* there are no extra bytes accudentally passed through their connection.
|
||||
* <p>
|
||||
* <p>Parcels lengths and contents are chosen randomly, and average parcel
|
||||
* length is 128 bytes. So totally, each pair of sockets passes ~16Kb of
|
||||
* data to each other, and thus ~32Kb of data are transfered by each sockets
|
||||
* pair. Totally, ~4Mb of data are transfered by all client/server pairs.
|
||||
*/
|
||||
public class network003 {
|
||||
/**
|
||||
* Do actually display optional reports?
|
||||
*/
|
||||
static private final boolean DEBUG_MODE = false;
|
||||
|
||||
/**
|
||||
* Errors and optional reports log. Usually <code>System.out</code>.
|
||||
*/
|
||||
static private PrintStream out = System.out;
|
||||
|
||||
/**
|
||||
* Print error message: all clients and servers may print concurently.
|
||||
*/
|
||||
static private synchronized void println(Object message) {
|
||||
out.println(message.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Display optional report: comment ca va.
|
||||
*/
|
||||
static private void display(Object report) {
|
||||
if (DEBUG_MODE)
|
||||
println(report.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximal number of connections this test should open simultaneously.
|
||||
*/
|
||||
private final static int MAX_CONNECTIONS = 128;
|
||||
|
||||
/**
|
||||
* Check few more connections to make sure that MAX_CONNECTIONS are safe.
|
||||
*/
|
||||
private final static int CONNECTIONS_RESERVE = 10;
|
||||
|
||||
/**
|
||||
* Number of client/server connections to establish.
|
||||
*/
|
||||
private static final int CONNECTIONS = detectOSLimitation();
|
||||
|
||||
/**
|
||||
* Number of parcels to be sent/recieved.
|
||||
*/
|
||||
private static final int DATA_PARCELS = 128;
|
||||
|
||||
/**
|
||||
* Maximal length of data parcel to be sent/recieved
|
||||
* (it equals to 256 bytes now).
|
||||
*/
|
||||
private static final int MAX_PARCEL = 1 << 8;
|
||||
|
||||
/**
|
||||
* How many IP sockets can we open simultaneously?
|
||||
* Check if <code>MAX_CONNECTIONS</code> connections
|
||||
* can be open simultaneously.
|
||||
*/
|
||||
private static int detectOSLimitation() {
|
||||
final int CONNECTIONS_TO_TRY = MAX_CONNECTIONS + CONNECTIONS_RESERVE;
|
||||
ServerSocket ssoc[] = new ServerSocket[CONNECTIONS_TO_TRY];
|
||||
display("--- Trying to open " + CONNECTIONS_TO_TRY + " connections:");
|
||||
int i;
|
||||
for (i = 0; i < CONNECTIONS_TO_TRY; i++)
|
||||
try {
|
||||
ssoc[i] = new ServerSocket(0);
|
||||
display("--- Open: ssoc[" + i + "] = " + ssoc[i]);
|
||||
} catch (IOException ioe) {
|
||||
display("--- OOPS! -- failed to open connection #" + i);
|
||||
break;
|
||||
}
|
||||
display("--- Could open " +
|
||||
(i < CONNECTIONS_TO_TRY ? "only " : "") + i + " connections.");
|
||||
display("--- Closing them:");
|
||||
for (int j = 0; j < i; j++)
|
||||
try {
|
||||
ssoc[j].close();
|
||||
} catch (IOException ioe) {
|
||||
throw new Error("FATAL error while loading the test: " + ioe);
|
||||
}
|
||||
display("--- OK.");
|
||||
int safeConnections = i - CONNECTIONS_RESERVE;
|
||||
if (safeConnections < 1)
|
||||
safeConnections = 1;
|
||||
if (safeConnections < MAX_CONNECTIONS) {
|
||||
println("# ------------------------- CAUTION: -------------------");
|
||||
println("# While checking the OS limitations, the test found that");
|
||||
println("# only " + i + " TCP/IP socket connections could be safely open");
|
||||
println("# simultaneously. However, possibility to open at least");
|
||||
println("# " + MAX_CONNECTIONS + "+" + CONNECTIONS_RESERVE
|
||||
+ " connections were expected.");
|
||||
println("# ");
|
||||
println("# So, the test will check only " + safeConnections + " connection"
|
||||
+ (safeConnections == 1 ? "" : "s") + " which seem");
|
||||
println("# safe to be open simultaneously.");
|
||||
println("# ------------------------------------------------------");
|
||||
}
|
||||
return safeConnections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Server thread intended to reply to data parcels sent by Client thread.
|
||||
*/
|
||||
static private class Server extends Thread {
|
||||
/**
|
||||
* This server thread listens the single socket.
|
||||
*/
|
||||
private ServerSocket serverSocket;
|
||||
|
||||
/**
|
||||
* Address and port of this server socket.
|
||||
*/
|
||||
public String toString() {
|
||||
return serverSocket.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Did the thread failed? If yes, what is the failure's reason.
|
||||
*/
|
||||
Exception exception = null;
|
||||
|
||||
/**
|
||||
* What is the port number this socket is listening for?
|
||||
*/
|
||||
int getPort() {
|
||||
return serverSocket.getLocalPort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find some free port at the given <code>address</code>
|
||||
* and attach new server to hear that port.
|
||||
*/
|
||||
Server(InetAddress address) throws IOException {
|
||||
int someFreePort = 0;
|
||||
int backlog = 50; // default for new ServerSocket(port)
|
||||
serverSocket = new ServerSocket(someFreePort, backlog, address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept connection, then read/respond <code>DATA_PARCELS</code> parcels
|
||||
* of random data. Set initial seed for pseudo-random numbers generator
|
||||
* to the value of the local port number.
|
||||
*
|
||||
* @see #DATA_PARCELS
|
||||
* @see #getPort()
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
Socket socket = serverSocket.accept();
|
||||
display("Server socket: " + socket);
|
||||
|
||||
InputStream istream = socket.getInputStream();
|
||||
OutputStream ostream = socket.getOutputStream();
|
||||
|
||||
Random random = new Random(getPort());
|
||||
|
||||
for (int i = 0; i < DATA_PARCELS; i++) {
|
||||
Parcel etalon = new Parcel(random);
|
||||
|
||||
Parcel sample = new Parcel(istream); // read
|
||||
if (!sample.equals(etalon)) {
|
||||
println("Server thread for port #"
|
||||
+ getPort() + " got unexpected parcel:\n"
|
||||
+ "sample=" + sample + "\n"
|
||||
+ "etalon=" + etalon);
|
||||
throw new TestFailure(
|
||||
"server has read unexpected parcel");
|
||||
}
|
||||
|
||||
etalon.send(ostream);
|
||||
ostream.flush();
|
||||
}
|
||||
|
||||
int datum = istream.read(); // wait for client close()
|
||||
if (datum >= 0)
|
||||
throw new TestFailure(
|
||||
"server has read ambigous byte: " + datum);
|
||||
|
||||
ostream.close(); // implies: socket.close();
|
||||
|
||||
} catch (Exception oops) {
|
||||
exception = oops;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Client thread intended to send data parcels to Server thread and
|
||||
* to recieve the server's replies.
|
||||
*/
|
||||
static private class Client extends Thread {
|
||||
/**
|
||||
* This thread uses the single client socket.
|
||||
*/
|
||||
private Socket socket;
|
||||
|
||||
/**
|
||||
* Address and port of this socket.
|
||||
*/
|
||||
public String toString() {
|
||||
return socket.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Did the thread failed? If yes, what is the failure's reason.
|
||||
*/
|
||||
Exception exception = null;
|
||||
|
||||
/**
|
||||
* Connect client socket on the given <code>address</code>
|
||||
* and <code>port</code>.
|
||||
*/
|
||||
Client(InetAddress address, int port) throws IOException {
|
||||
socket = new Socket(address, port);
|
||||
}
|
||||
|
||||
/**
|
||||
* What is the port number this socket is listening for?
|
||||
*/
|
||||
int getPort() {
|
||||
return socket.getPort();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Establish connection, then read/respond <code>DATA_PARCELS</code> parcels
|
||||
* of random data. Set initial seed for pseudo-random numbers generator
|
||||
* to the value of the local port number.
|
||||
*
|
||||
* @see #DATA_PARCELS
|
||||
* @see #getPort()
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
InputStream istream = socket.getInputStream();
|
||||
OutputStream ostream = socket.getOutputStream();
|
||||
|
||||
Random random = new Random(getPort());
|
||||
|
||||
for (int i = 0; i < DATA_PARCELS; i++) {
|
||||
Parcel etalon = new Parcel(random);
|
||||
etalon.send(ostream);
|
||||
ostream.flush();
|
||||
|
||||
Parcel sample = new Parcel(istream); // read
|
||||
if (!sample.equals(etalon)) {
|
||||
println("Client thread for port #"
|
||||
+ getPort() + " got unexpected parcel:\n"
|
||||
+ "sample=" + sample + "\n"
|
||||
+ "etalon=" + etalon);
|
||||
throw new TestFailure(
|
||||
"parcel context is unexpected to client");
|
||||
}
|
||||
}
|
||||
|
||||
if (istream.available() > 0) {
|
||||
int datum = istream.read();
|
||||
throw new TestFailure(
|
||||
"client has read ambigous byte: " + datum);
|
||||
}
|
||||
ostream.close(); // implies: socket.close()
|
||||
|
||||
} catch (Exception oops) {
|
||||
exception = oops;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A data parcel to sent/recieved between Client and Server threads.
|
||||
* When data parcel is sent, first 4 bytes transfered encode the size
|
||||
* of the parcel (i.e.: number of data bytes in the parcel's contents).
|
||||
* Then the parcel's contents bytes are transered.
|
||||
*/
|
||||
static class Parcel {
|
||||
private byte[] parcel;
|
||||
|
||||
/**
|
||||
* Display all bytes as integer values from 0 to 255;
|
||||
* or return ``<tt>null</tt>'' if this Parcel is not
|
||||
* yet initialized.
|
||||
*/
|
||||
public String toString() {
|
||||
if (parcel == null)
|
||||
return "null";
|
||||
String s = "{";
|
||||
for (int i = 0; i < parcel.length; i++)
|
||||
s += (i > 0 ? ", " : "") + ((int) parcel[i] & 0xFF);
|
||||
return s + "}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate new <code>parcel[]</code> array using the given
|
||||
* <code>random</code> numbers generator. Client and Server
|
||||
* threads should use identical <code>random</code> generators,
|
||||
* so that those threads could generate equal data parcels and
|
||||
* check the parcel just transfered.
|
||||
*/
|
||||
public Parcel(Random random) {
|
||||
int size = random.nextInt(MAX_PARCEL) + 1;
|
||||
parcel = new byte[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
parcel[i] = (byte) random.nextInt(256);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read exactly <code>size</code> bytes from the <code>istream</code>
|
||||
* if possible, or throw <code>TestFailure</code> if unexpected end of
|
||||
* <code>istream</code> occurs.
|
||||
*/
|
||||
private static byte[] readBytes(int size, InputStream istream)
|
||||
throws IOException {
|
||||
|
||||
byte data[] = new byte[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
int datum = istream.read();
|
||||
if (datum < 0)
|
||||
throw new TestFailure(
|
||||
"unexpected EOF: have read: " + i + " bytes of " + size);
|
||||
data[i] = (byte) datum;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 4 bytes from <code>istream</code> and threat them to encode
|
||||
* size of data parcel following these 4 bytes.
|
||||
*/
|
||||
private static int getSize(InputStream istream) throws IOException {
|
||||
byte data[] = readBytes(4, istream);
|
||||
int data0 = (int) data[0] & 0xFF;
|
||||
int data1 = (int) data[1] & 0xFF;
|
||||
int data2 = (int) data[2] & 0xFF;
|
||||
int data3 = (int) data[3] & 0xFF;
|
||||
int sizeWord = data0 + (data1 << 8) + (data2 << 16) + (data3 << 24);
|
||||
int size = sizeWord + 1;
|
||||
if (size <= 0)
|
||||
throw new TestFailure("illegal size: " + size);
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send 4 bytes encoding actual size of the parcel just to be transfered.
|
||||
*/
|
||||
private static void putSize(OutputStream ostream, int size)
|
||||
throws IOException {
|
||||
|
||||
if (size <= 0)
|
||||
throw new TestFailure("illegal size: " + size);
|
||||
|
||||
int sizeWord = size - 1;
|
||||
byte data[] = new byte[4];
|
||||
data[0] = (byte) sizeWord;
|
||||
data[1] = (byte) (sizeWord >> 8);
|
||||
data[2] = (byte) (sizeWord >> 16);
|
||||
data[3] = (byte) (sizeWord >> 24);
|
||||
ostream.write(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recieve data parcel.
|
||||
*/
|
||||
public Parcel(InputStream istream) throws IOException {
|
||||
int size = getSize(istream);
|
||||
parcel = readBytes(size, istream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send <code>this</code> data parcel.
|
||||
*/
|
||||
public void send(OutputStream ostream) throws IOException {
|
||||
int size = parcel.length;
|
||||
putSize(ostream, size);
|
||||
ostream.write(parcel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check byte-to-byte equality between <code>this</code> and the
|
||||
* <code>other</code> parcels.
|
||||
*/
|
||||
public boolean equals(Parcel other) {
|
||||
if (this.parcel.length != other.parcel.length)
|
||||
return false;
|
||||
int size = parcel.length;
|
||||
for (int i = 0; i < size; i++)
|
||||
if (this.parcel[i] != other.parcel[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Server or Client thread may throw this exception to report the test
|
||||
* failure.
|
||||
*/
|
||||
static class TestFailure extends RuntimeException {
|
||||
/**
|
||||
* Report particular <code>purpose</code> of the test failure.
|
||||
*/
|
||||
public TestFailure(String purpose) {
|
||||
super(purpose);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach client and server sockets to the local host, and check if
|
||||
* huge amount of data could be correctly transfered between these
|
||||
* sockets.
|
||||
* <p>
|
||||
* <p>Command-line parameters provided with <code>args[]</code> may
|
||||
* prompt the local host IP address or domain name. Execute:
|
||||
* <br>
|
||||
* <code>java network003 [<i>IP-address</i> | <i>host_name</i> |
|
||||
* localhost ]</code>
|
||||
* <br>where parameters are:
|
||||
* <br>
|
||||
* <code><i>IP-address</i></code> - local hots's address, or 127.0.0.1
|
||||
* <br>
|
||||
* <code><i>host_name</i></code> - local host's domain name, or the
|
||||
* keyword ``<code>localhost</code>''
|
||||
* <br>
|
||||
* <code>localhost</code> - placeholder for the IP-address 127.0.0.1
|
||||
* <br>By default, the test uses the Internet address available via
|
||||
* the method <code>InetAddress.getLocalHost()</code>
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
network003.out = out;
|
||||
|
||||
//
|
||||
// Get IP address of the local machine.
|
||||
//
|
||||
|
||||
InetAddress address = null;
|
||||
try {
|
||||
switch (args.length) {
|
||||
case 0:
|
||||
address = InetAddress.getLocalHost();
|
||||
break;
|
||||
case 1:
|
||||
String hostName = args[0];
|
||||
address = InetAddress.getByName(args[0]);
|
||||
break;
|
||||
default:
|
||||
println("Use:");
|
||||
println(" java network003");
|
||||
println("or:");
|
||||
println(" java network003 ${IP_ADDRESS}");
|
||||
println("or:");
|
||||
println(" java network003 ${HOST_NAME}");
|
||||
println("or:");
|
||||
println(" java network003 localhost");
|
||||
return 2; // FAILED
|
||||
}
|
||||
} catch (UnknownHostException exception) {
|
||||
println(exception);
|
||||
return 2; // FAILED
|
||||
}
|
||||
display("Host: " + address);
|
||||
|
||||
//
|
||||
// Incarnate the server & the client sockets.
|
||||
//
|
||||
|
||||
Server server[] = new Server[CONNECTIONS];
|
||||
Client client[] = new Client[CONNECTIONS];
|
||||
|
||||
for (int i = 0; i < CONNECTIONS; i++) {
|
||||
try {
|
||||
server[i] = new Server(address);
|
||||
} catch (IOException io) {
|
||||
println("Failed to create server #" + i + ": " + io);
|
||||
return 2;
|
||||
}
|
||||
display("Server #" + i + ": " + server[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < CONNECTIONS; i++) {
|
||||
int port = server[i].getPort();
|
||||
try {
|
||||
client[i] = new Client(address, port);
|
||||
} catch (IOException io) {
|
||||
out.println("Failed to create client #" + i + ": " + io);
|
||||
return 2;
|
||||
}
|
||||
display("Client socket #" + i + ": " + client[i]);
|
||||
}
|
||||
|
||||
//
|
||||
// Execute the server and client threads.
|
||||
//
|
||||
|
||||
Exception exception = null;
|
||||
try {
|
||||
for (int i = 0; i < CONNECTIONS; i++)
|
||||
server[i].start();
|
||||
for (int i = 0; i < CONNECTIONS; i++)
|
||||
client[i].start();
|
||||
boolean someIsAlive = true;
|
||||
while (someIsAlive) {
|
||||
boolean aliveFound = false;
|
||||
boolean someBroken = false;
|
||||
for (int i = 0; i < CONNECTIONS; i++)
|
||||
if (client[i].isAlive() || server[i].isAlive()) {
|
||||
if ((client[i].exception != null) ||
|
||||
(server[i].exception != null))
|
||||
someBroken = true;
|
||||
aliveFound = true;
|
||||
Thread.yield();
|
||||
}
|
||||
someIsAlive = aliveFound;
|
||||
if (someBroken)
|
||||
break;
|
||||
}
|
||||
} catch (TestFailure failure) {
|
||||
exception = failure;
|
||||
}
|
||||
|
||||
// Failure diagnostics, if needed.
|
||||
|
||||
Exception problem[] = new Exception[2 * CONNECTIONS + 1];
|
||||
problem[0] = exception;
|
||||
for (int i = 0; i < CONNECTIONS; i++) {
|
||||
problem[2 * i + 1] = server[i].exception;
|
||||
problem[2 * i + 2] = client[i].exception;
|
||||
}
|
||||
|
||||
int exitCode = 0;
|
||||
|
||||
for (int i = 0; i < 2 * CONNECTIONS + 1; i++)
|
||||
if (problem[i] != null) {
|
||||
out.println("#### OOPS ! ####");
|
||||
problem[i].printStackTrace(out);
|
||||
exitCode = 2;
|
||||
}
|
||||
|
||||
if (exitCode != 0) {
|
||||
out.println("#### OOPS ! ####");
|
||||
out.println("# Test failed.");
|
||||
return 2; // FAILED
|
||||
}
|
||||
display("Test passed.");
|
||||
return 0; // PASSED
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-calls to the method <code>run(args[],out)</code> actually
|
||||
* performing the test; and stop with exit code 95 if the test
|
||||
* has passed, or with code 97 if the test has failed.
|
||||
* (This is JCK-like exit codes convention.)
|
||||
*
|
||||
* @see #run(String[], PrintStream)
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit code.
|
||||
}
|
||||
|
||||
}
|
||||
878
test/hotspot/jtreg/vmTestbase/nsk/stress/network/network004.java
Normal file
878
test/hotspot/jtreg/vmTestbase/nsk/stress/network/network004.java
Normal file
@ -0,0 +1,878 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/network/network004.
|
||||
* VM testbase keywords: [stress, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test transfers huge amount of data between 2 Java virtual machines
|
||||
* using the TCP/IP protocol, and checks if those data are transfered correctly.
|
||||
* Both client and server VMs run on the same local computer and attach TCP/IP
|
||||
* sockets to the local host, or to the loopback domain ``localhost''
|
||||
* (having IP address 127.0.0.1).
|
||||
* In this test, 128 client/server connections are established. Once a
|
||||
* connection is established, client passes a large data parcel to server,
|
||||
* and server reads that parcel and checks if it is same as expected
|
||||
* (byte-to-byte equality is desired). Then server passes (some other) parcel
|
||||
* to the client, and client reads and verifies those bytes. This ping-pong
|
||||
* game is repeated 128 times; and after that each pair of sockets checks if
|
||||
* there are no extra bytes accudentally passed through their connection.
|
||||
* Parcels lengths and contents are chosen randomly, and average
|
||||
* parcel length is 128 bytes. So totally, each pair of sockets passes ~16Kb of
|
||||
* data to each other, and thus ~32Kb of data are transfered by each sockets
|
||||
* pair. Totally, ~4Mb of data are transfered by all client/server pairs.
|
||||
* COMMENTS
|
||||
* The production Solaris_JDK_1.3-b12 Server VM intermittently crashes under
|
||||
* this test, even when client part of the test is executed with Client HS:
|
||||
* >>>> java -server network004 java
|
||||
* #
|
||||
* # HotSpot Virtual Machine Error, Unexpected Signal 10
|
||||
* # Please report this error at
|
||||
* # http://java.sun.com/cgi-bin/bugreport.cgi
|
||||
* #
|
||||
* # Error ID: 4F533F534F4C415249530E43505007D9 01
|
||||
* #
|
||||
* # Problematic Thread: prio=5 tid=0x214418 nid=0x103 runnable
|
||||
* #
|
||||
* (ErrorID == "os_solaris.cpp, 2009")
|
||||
* If the client part of the test is executed with Server HS, the
|
||||
* production Solaris_JDK_1.3-b12 Server VM intermittently fails
|
||||
* this test due to timeout:
|
||||
* >>>> time java -server network004 'java -server -showversion'
|
||||
* java version "1.3"
|
||||
* Java(TM) 2 Runtime Environment, Standard Edition (build Solaris_JDK_1.3-b12)
|
||||
* Java HotSpot(TM) Server VM (build 1.3-b12, mixed mode)
|
||||
* # Client #96: java.io.InterruptedIOException: Read timed out
|
||||
* # Client VM has crashed: exit status=97
|
||||
* # Test failed.
|
||||
* 156.0u 117.0s 7:06 63% 0+0k 0+0io 0pf+0w
|
||||
* Test was fixed:
|
||||
* added WAITTIME parameter defined timeout for TCP/IP sockets in minutes
|
||||
*
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @run driver jdk.test.lib.FileInstaller . .
|
||||
* @build nsk.stress.network.network004
|
||||
* @run main/othervm PropertyResolvingWrapper
|
||||
* nsk.stress.network.network004
|
||||
* "${test.jdk}/bin/java ${test.vm.opts} ${test.java.opts}" 5
|
||||
*/
|
||||
|
||||
package nsk.stress.network;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Random;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* This test transfers huge amount of data between 2 Java virtual machines
|
||||
* using the TCP/IP protocol, and checks if those data are transfered correctly.
|
||||
* Both client and server VMs run on the same local computer and attach TCP/IP
|
||||
* sockets to the local host, or to the loopback domain ``<code>localhost</code>''
|
||||
* (having IP address <code>127.0.0.1</code>).
|
||||
* <p>
|
||||
* <p>In this test, 128 client/server connections are established. Once a
|
||||
* connection is established, client passes a large data parcel to server,
|
||||
* and server reads that parcel and checks if it is same as expected
|
||||
* (byte-to-byte equality is desired). Then server passes (some other) parcel
|
||||
* to the client, and client reads and verifies those bytes. This ping-pong
|
||||
* game is repeated 128 times; and after that each pair of sockets checks if
|
||||
* there are no extra bytes accudentally passed through their connection.
|
||||
* <p>
|
||||
* <p>Parcels lengths and contents are chosen randomly, and average
|
||||
* parcel length is 128 bytes. So totally, each pair of sockets passes ~16Kb of
|
||||
* data to each other, and thus ~32Kb of data are transfered by each sockets
|
||||
* pair. Totally, ~4Mb of data are transfered by all client/server pairs.
|
||||
*/
|
||||
public class network004 {
|
||||
/**
|
||||
* Timeout for TCP/IP sockets (currently set to 1 min).
|
||||
*/
|
||||
private static int SO_TIMEOUT;// = 2*60*1000;
|
||||
|
||||
/**
|
||||
* Maximal number of connections this test should open simultaneously.
|
||||
*/
|
||||
private final static int MAX_CONNECTIONS = 128;
|
||||
|
||||
/**
|
||||
* Check few more connections to make sure that MAX_CONNECTIONS are safe.
|
||||
*/
|
||||
private final static int CONNECTIONS_RESERVE = 10;
|
||||
|
||||
/**
|
||||
* Number of parcels to be sent/recieved.
|
||||
*/
|
||||
private final static int DATA_PARCELS = 128;
|
||||
|
||||
/**
|
||||
* Maximal length of data parcel to be sent/recieved
|
||||
* (it equals to 256 bytes now).
|
||||
*/
|
||||
private final static int MAX_PARCEL = 1 << 8;
|
||||
|
||||
/**
|
||||
* Either actually display optional reports or not.
|
||||
*/
|
||||
static private final boolean DEBUG_MODE = false;
|
||||
|
||||
/**
|
||||
* How many IP sockets can we open simultaneously?
|
||||
* Check if <code>MAX_CONNECTIONS</code> connections
|
||||
* can be open simultaneously.
|
||||
*/
|
||||
private static int detectOSLimitation() {
|
||||
final int CONNECTIONS_TO_TRY = MAX_CONNECTIONS + CONNECTIONS_RESERVE;
|
||||
ServerSocket ssoc[] = new ServerSocket[CONNECTIONS_TO_TRY];
|
||||
display("--- Trying to open " + CONNECTIONS_TO_TRY + " connections:");
|
||||
int i;
|
||||
for (i = 0; i < CONNECTIONS_TO_TRY; i++)
|
||||
try {
|
||||
ssoc[i] = new ServerSocket(0);
|
||||
display("--- Open: ssoc[" + i + "] = " + ssoc[i]);
|
||||
} catch (IOException ioe) {
|
||||
display("--- OOPS! -- failed to open connection #" + i);
|
||||
break;
|
||||
}
|
||||
display("--- Could open " +
|
||||
(i < CONNECTIONS_TO_TRY ? "only " : "") + i + " connections.");
|
||||
display("--- Closing them:");
|
||||
for (int j = 0; j < i; j++)
|
||||
try {
|
||||
ssoc[j].close();
|
||||
} catch (IOException ioe) {
|
||||
throw new Error("FATAL error while loading the test: " + ioe);
|
||||
}
|
||||
display("--- OK.");
|
||||
int safeConnections = i - CONNECTIONS_RESERVE;
|
||||
if (safeConnections < 1)
|
||||
safeConnections = 1;
|
||||
if (safeConnections < MAX_CONNECTIONS) {
|
||||
complain("------------------------- CAUTION: -------------------");
|
||||
complain("While checking the OS limitations, the test found that");
|
||||
complain("only " + i + " TCP/IP socket connections could be safely open");
|
||||
complain("simultaneously. However, possibility to open at least");
|
||||
complain("" + MAX_CONNECTIONS + "+" + CONNECTIONS_RESERVE
|
||||
+ " connections were expected.");
|
||||
complain("");
|
||||
complain("So, the test will check only " + safeConnections + " connection"
|
||||
+ (safeConnections == 1 ? "" : "s") + " which seem");
|
||||
complain("safe to be open simultaneously.");
|
||||
complain("------------------------------------------------------");
|
||||
}
|
||||
return safeConnections;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------//
|
||||
|
||||
/**
|
||||
* Re-calls to the method <code>run(args[],out)</code> actually
|
||||
* performing the test. After <code>run(args[],out)</code> stops,
|
||||
* follow JDK-like convention for exit codes. I.e.: stop with
|
||||
* exit status 95 if the test has passed, or with status 97 if
|
||||
* the test has failed.
|
||||
*
|
||||
* @see #run(String[], PrintStream)
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status.
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line parameters stored into <code>args[]</code> array,
|
||||
* then perform the test. I.e.: start the server thread at the same VM
|
||||
* this method runs, then start the other client VM, and verify data
|
||||
* transfer through TCP/IP connection between those different virtual
|
||||
* machines.
|
||||
* <p>
|
||||
* <p>There should be 1 or 2 command-line parameters:
|
||||
* <br>
|
||||
* <code>java network004 <i>java_command</i>
|
||||
* [<i>IP-address</i> | <i>host_name</i> | localhost ]</code>
|
||||
* <br>where parameters are:
|
||||
* <br>
|
||||
* <code><i>java_command</i></code> - how to start java,
|
||||
* e.g.: ``<code>c:\jdk1.3\bin\java -classic</code>''
|
||||
* <br>
|
||||
* <code>waittime</code> - timeout for TCP/IP sockets in minutes
|
||||
* <br>
|
||||
* <code><i>IP-address</i></code> - local hots's address, or 127.0.0.1
|
||||
* <br>
|
||||
* <code><i>host_name</i></code> - local host's domain name, or the
|
||||
* keyword ``<code>localhost</code>''
|
||||
* <br>
|
||||
* <code>localhost</code> - placeholder for the IP-address 127.0.0.1
|
||||
* <p>
|
||||
* <p>Usually, <code><i>java_command</i></code> should point to the same
|
||||
* Java machine just executing this test. However, every compatible Java 2
|
||||
* implementation is appropriate.
|
||||
* <p>
|
||||
* <p>If optional parameter is ommited, the test invokes the method
|
||||
* <code>InetAddress.getLocalHost()</code> to get the domain name and
|
||||
* IP-address of the local computer.
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
network004.out = out;
|
||||
|
||||
//
|
||||
// Get the Internet address of the local machine.
|
||||
//
|
||||
InetAddress address = null;
|
||||
try {
|
||||
switch (args.length) {
|
||||
case 2:
|
||||
address = InetAddress.getLocalHost();
|
||||
break;
|
||||
case 3:
|
||||
address = InetAddress.getByName(args[2]);
|
||||
break;
|
||||
default:
|
||||
complain("Illegal arguments number; execute:");
|
||||
complain(" java network004 $JAVA_COMMAND " +
|
||||
"[$IP_ADDRESS | $HOST_NAME | localhost]");
|
||||
return 2; // FAILED
|
||||
}
|
||||
} catch (UnknownHostException exception) {
|
||||
complain(exception.toString());
|
||||
return 2; // FAILED
|
||||
}
|
||||
display("Host: " + address);
|
||||
|
||||
//
|
||||
// Detect if it is safe to open MAX_CONNETIONS simultaneously:
|
||||
//
|
||||
final int CONNECTIONS = detectOSLimitation();
|
||||
|
||||
//
|
||||
// Start the server thread on the same VM (which executes this method).
|
||||
//
|
||||
Server server[] = new Server[CONNECTIONS];
|
||||
for (int i = 0; i < CONNECTIONS; i++) {
|
||||
try {
|
||||
server[i] = new Server(address);
|
||||
} catch (Exception exception) {
|
||||
complain("Server #" + i + ": " + exception);
|
||||
return 2;
|
||||
}
|
||||
display("Server #" + i + ": " + server[i]);
|
||||
server[i].start();
|
||||
}
|
||||
|
||||
//
|
||||
// Start the client process on different VM.
|
||||
//
|
||||
String command = args[0] + " " + network004.class.getName() + "$Client";
|
||||
try {
|
||||
SO_TIMEOUT = Integer.parseInt(args[1]) * 60 * 1000;
|
||||
} catch (NumberFormatException e) {
|
||||
complain("Wrong timeout argument: " + e);
|
||||
return 2;
|
||||
}
|
||||
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
|
||||
Process client = null;
|
||||
IORedirector redirectOut = null;
|
||||
IORedirector redirectErr = null;
|
||||
|
||||
try {
|
||||
// Start clients on different JVM:
|
||||
client = runtime.exec(command);
|
||||
|
||||
// Provide clients with access to stderr and stdout:
|
||||
InputStream clientOut = client.getInputStream();
|
||||
InputStream clientErr = client.getErrorStream();
|
||||
redirectOut = new IORedirector(clientOut, DEBUG_MODE ? out : null);
|
||||
redirectErr = new IORedirector(clientErr, out);
|
||||
redirectOut.start();
|
||||
redirectErr.start();
|
||||
|
||||
// Pass parameters to clients (number of connections, and IP adresses and ports):
|
||||
PrintStream clientIn = new PrintStream(client.getOutputStream());
|
||||
clientIn.println(CONNECTIONS);
|
||||
for (int i = 0; i < CONNECTIONS; i++)
|
||||
clientIn.println(server[i].getIPAddress() + " " + server[i].getPort());
|
||||
clientIn.flush();
|
||||
clientIn.close();
|
||||
|
||||
} catch (Exception exception) {
|
||||
complain("Failed to start client: " + exception);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Wait until the server and client both stop.
|
||||
//
|
||||
boolean testFailed = false;
|
||||
try {
|
||||
client.waitFor();
|
||||
// Let I/O redirectors to flush:
|
||||
if (redirectOut.isAlive())
|
||||
redirectOut.join();
|
||||
if (redirectErr.isAlive())
|
||||
redirectErr.join();
|
||||
|
||||
// If client has crashed, also terminate the server (to avoid hangup).
|
||||
int clientStatus = client.exitValue();
|
||||
if (clientStatus != 95) {
|
||||
complain("Client VM has failed: exit status=" + clientStatus);
|
||||
testFailed = true;
|
||||
}
|
||||
|
||||
// Client has finished OK; wait for the server.
|
||||
for (int i = 0; i < CONNECTIONS; i++) {
|
||||
display("Server: waiting for #" + i);
|
||||
while (server[i].isAlive())
|
||||
server[i].join();
|
||||
if (server[i].exception != null) {
|
||||
complain("Server thread #" + i + ": " + server[i].exception);
|
||||
testFailed = true;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception exception) {
|
||||
complain("Test interrupted: " + exception);
|
||||
testFailed = true;
|
||||
}
|
||||
|
||||
if (testFailed)
|
||||
complain("Test failed.");
|
||||
else
|
||||
display("Test passed.");
|
||||
return testFailed ? 2 : 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------//
|
||||
|
||||
/**
|
||||
* Log stream for error messages and/or (optional) execution trace.
|
||||
*/
|
||||
private static PrintStream out;
|
||||
|
||||
/**
|
||||
* Print error message.
|
||||
*/
|
||||
private static synchronized void complain(Object message) {
|
||||
out.println("# " + message);
|
||||
out.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display optional report: comment ca va?
|
||||
*/
|
||||
private static synchronized void display(Object report) {
|
||||
if (DEBUG_MODE)
|
||||
out.println(report.toString());
|
||||
out.flush();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------//
|
||||
|
||||
/**
|
||||
* Server thread should reply to data parcels sent by Client VM.
|
||||
*/
|
||||
private static class Server extends Thread {
|
||||
/**
|
||||
* The socket to listen for a client.
|
||||
*/
|
||||
private ServerSocket serverSocket;
|
||||
|
||||
/**
|
||||
* Display the server socket.
|
||||
*/
|
||||
public String toString() {
|
||||
return serverSocket.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Server's IP-address in the form ``<code><i>x.y.u.z</i></code>'',
|
||||
* or ``<code>127.0.0.1</code>'' for loopback connection.
|
||||
*/
|
||||
public String getIPAddress() {
|
||||
return serverSocket.getInetAddress().getHostAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
* Which port is this socket listening?
|
||||
*/
|
||||
int getPort() {
|
||||
return serverSocket.getLocalPort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find some free port at the given <code>address</code>
|
||||
* and attach new server to hear that port.
|
||||
*/
|
||||
public Server(InetAddress address) throws IOException {
|
||||
int someFreePort = 0;
|
||||
int backlog = 50; // default for new ServerSocket(port)
|
||||
serverSocket = new ServerSocket(someFreePort, backlog, address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception just arisen while the server was working,
|
||||
* or <code>null</code> if it was OK with the server.
|
||||
*/
|
||||
Exception exception = null;
|
||||
|
||||
/**
|
||||
* Accept connection, then reply to client's parcels.
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
Socket socket = serverSocket.accept();
|
||||
socket.setSoTimeout(SO_TIMEOUT);
|
||||
// display("Server: " + socket);
|
||||
|
||||
InputStream istream = socket.getInputStream();
|
||||
OutputStream ostream = socket.getOutputStream();
|
||||
|
||||
Random random = new Random(getPort());
|
||||
|
||||
for (int i = 0; i < DATA_PARCELS; i++) {
|
||||
Parcel etalon = new Parcel(random);
|
||||
|
||||
Parcel sample = new Parcel(istream); // read
|
||||
if (!sample.equals(etalon)) {
|
||||
complain("Server thread for port #"
|
||||
+ getPort() + " got unexpected parcel:\n"
|
||||
+ "sample=" + sample + "\n"
|
||||
+ "etalon=" + etalon);
|
||||
throw new TestFailure(
|
||||
"server has read unexpected parcel");
|
||||
}
|
||||
|
||||
etalon.send(ostream);
|
||||
ostream.flush();
|
||||
}
|
||||
|
||||
int datum = istream.read(); // wait for client close()
|
||||
if (datum >= 0)
|
||||
throw new TestFailure(
|
||||
"server has read ambigous byte: " + datum);
|
||||
|
||||
ostream.close(); // implies: socket.close();
|
||||
|
||||
} catch (Exception oops) {
|
||||
exception = oops;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------//
|
||||
|
||||
/**
|
||||
* Client VM should send data parcels to Server VM and
|
||||
* recieve and verify the server's replies.
|
||||
*/
|
||||
private static class Client extends Thread {
|
||||
/**
|
||||
* This thread uses the single client socket.
|
||||
*/
|
||||
private Socket socket;
|
||||
|
||||
/**
|
||||
* Address and port of this socket.
|
||||
*/
|
||||
public String toString() {
|
||||
return socket.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Did the thread failed? If yes, what is the failure's reason.
|
||||
*/
|
||||
Exception exception = null;
|
||||
|
||||
/**
|
||||
* Connect client socket on the given <code>address</code>
|
||||
* and <code>port</code>.
|
||||
*/
|
||||
Client(InetAddress address, int port) throws IOException {
|
||||
socket = new Socket(address, port);
|
||||
socket.setSoTimeout(SO_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* What is the port number this socket is listening for?
|
||||
*/
|
||||
int getPort() {
|
||||
return socket.getPort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish connection, then read/respond <code>DATA_PARCELS</code> parcels
|
||||
* of random data. Set initial seed for pseudo-random numbers generator
|
||||
* to the value of the local port number.
|
||||
*
|
||||
* @see #DATA_PARCELS
|
||||
* @see #getPort()
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
InputStream istream = socket.getInputStream();
|
||||
OutputStream ostream = socket.getOutputStream();
|
||||
|
||||
Random random = new Random(getPort());
|
||||
|
||||
for (int i = 0; i < DATA_PARCELS; i++) {
|
||||
Parcel etalon = new Parcel(random);
|
||||
etalon.send(ostream);
|
||||
ostream.flush();
|
||||
|
||||
Parcel sample = new Parcel(istream); // read
|
||||
if (!sample.equals(etalon)) {
|
||||
complain("Client thread for port #"
|
||||
+ getPort() + " got unexpected parcel:\n"
|
||||
+ "sample=" + sample + "\n"
|
||||
+ "etalon=" + etalon);
|
||||
throw new TestFailure(
|
||||
"parcel context is unexpected to client");
|
||||
}
|
||||
}
|
||||
|
||||
if (istream.available() > 0) {
|
||||
int datum = istream.read();
|
||||
throw new TestFailure(
|
||||
"client has read ambigous byte: " + datum);
|
||||
}
|
||||
ostream.close(); // implies: socket.close()
|
||||
|
||||
} catch (Exception oops) {
|
||||
exception = oops;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish connections to lots of server sockets, atack servers with
|
||||
* huge data parcels, and check if it replies correctly. The addresses
|
||||
* and port numbers for server sockets are passed through <code>stdin</code>.
|
||||
* The input stream must consist of the stipulated number (up to 128+1) of
|
||||
* lines containing the pair of symbolic server domain name and the port number,
|
||||
* like:
|
||||
* <br> actual_number_of_sockets
|
||||
* <br> address_1 port_1
|
||||
* <br> address_2 port_2
|
||||
* <br> . . .
|
||||
* <br> address_N port_N
|
||||
* <br>where N must equal to the actual_number_of_sockets.
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
// ---- Parse stdin for the list of server sockets: ---- //
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
|
||||
|
||||
final int CONNECTIONS;
|
||||
try {
|
||||
String line = in.readLine();
|
||||
if (line == null) {
|
||||
complain("Client expects paramenets passed through stdin:");
|
||||
complain(" actual_number_of_sockets");
|
||||
complain(" IP-address_1 port_1");
|
||||
complain(" IP-address_2 port_2");
|
||||
complain(" . . .");
|
||||
complain(" IP-address_N port_N");
|
||||
exit(2); // FAILED
|
||||
}
|
||||
CONNECTIONS = Integer.parseInt(line);
|
||||
} catch (IOException ioe) {
|
||||
complain("Client failed to read the actual number of CONNECTIONS");
|
||||
throw new RuntimeException(ioe.toString());
|
||||
}
|
||||
|
||||
Client client[] = new Client[CONNECTIONS];
|
||||
for (int i = 0; i < CONNECTIONS; i++)
|
||||
try {
|
||||
String line = in.readLine();
|
||||
if (line == null) {
|
||||
complain("Client: failed to read address/port for client #" + i);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
StringTokenizer tokenz = new StringTokenizer(line);
|
||||
if (tokenz.countTokens() != 2) {
|
||||
complain("Client: illegal input string: " + line);
|
||||
exit(3);
|
||||
}
|
||||
String serverName = (String) tokenz.nextElement();
|
||||
InetAddress address = InetAddress.getByName(serverName);
|
||||
int port = Integer.parseInt((String) tokenz.nextElement());
|
||||
|
||||
client[i] = new Client(address, port);
|
||||
|
||||
display("Client #" + i + ": " + client[i]);
|
||||
|
||||
} catch (IOException ioe) {
|
||||
complain("Client #" + i + ": " + ioe);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
// ---- Start testing: ---- //
|
||||
|
||||
for (int i = 0; i < CONNECTIONS; i++)
|
||||
client[i].start();
|
||||
|
||||
int status = 0;
|
||||
for (int i = 0; i < CONNECTIONS; i++) {
|
||||
display("Client: waiting for #" + i);
|
||||
while (client[i].isAlive())
|
||||
yield();
|
||||
if (client[i].exception != null) {
|
||||
complain("Client #" + i + ": " + client[i].exception);
|
||||
status = 2;
|
||||
}
|
||||
}
|
||||
|
||||
exit(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print error message.
|
||||
*/
|
||||
private static synchronized void complain(Object message) {
|
||||
System.err.println("# " + message);
|
||||
System.err.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display execution trace.
|
||||
*/
|
||||
private static synchronized void display(Object message) {
|
||||
if (!DEBUG_MODE)
|
||||
return;
|
||||
System.out.println(message.toString());
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit with JCK-like status.
|
||||
*/
|
||||
private static void exit(int exitCode) {
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Two of such threads should redirect <code>out</code> and <code>err</code>
|
||||
* streams of client VM.
|
||||
*/
|
||||
private static class IORedirector extends Thread {
|
||||
/**
|
||||
* Source stream.
|
||||
*/
|
||||
InputStream in;
|
||||
/**
|
||||
* Destination stream.
|
||||
*/
|
||||
OutputStream out;
|
||||
|
||||
/**
|
||||
* Redirect <code>in</code> to <code>out</code>.
|
||||
*/
|
||||
public IORedirector(InputStream in, OutputStream out) {
|
||||
this.in = in;
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read input stream until the EOF, and write everithing to output stream.
|
||||
* If output stream is assigned to <code>null</code>, do not print anything,
|
||||
* but read the input stream anywhere.
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
for (; ; ) {
|
||||
int symbol = in.read();
|
||||
if (symbol < 0)
|
||||
break; // EOF
|
||||
if (out != null)
|
||||
out.write(symbol);
|
||||
}
|
||||
|
||||
if (out != null)
|
||||
out.flush();
|
||||
|
||||
} catch (Exception exception) {
|
||||
throw new TestFailure("IORedirector exception: " + exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------//
|
||||
|
||||
/**
|
||||
* A data parcel to be sent/recieved between Client VM and Server thread.
|
||||
* When data parcel is sent, first 4 bytes are transfered which encode the
|
||||
* <code>int</code> number equal to size of the parcel minus 1. I.e.: if
|
||||
* number of data bytes in the parcel's contents is <code>N</code>, then
|
||||
* the first 4 bytes encode the number <code>N-1</code>. After that, the
|
||||
* parcel's contents bytes are transered.
|
||||
*/
|
||||
static class Parcel {
|
||||
private byte[] parcel;
|
||||
|
||||
/**
|
||||
* Display all bytes as integer values from 0 to 255;
|
||||
* or return ``<tt>null</tt>'' if this Parcel is not
|
||||
* yet initialized.
|
||||
*/
|
||||
public String toString() {
|
||||
if (parcel == null)
|
||||
return "null";
|
||||
String s = "{";
|
||||
for (int i = 0; i < parcel.length; i++)
|
||||
s += (i > 0 ? ", " : "") + ((int) parcel[i] & 0xFF);
|
||||
return s + "}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate new <code>parcel[]</code> array using the given
|
||||
* <code>random</code> numbers generator. Client and Server
|
||||
* threads should use identical <code>random</code> generators,
|
||||
* so that those threads could generate equal data parcels and
|
||||
* check the parcel just transfered.
|
||||
*/
|
||||
public Parcel(Random random) {
|
||||
int size = random.nextInt(MAX_PARCEL) + 1;
|
||||
parcel = new byte[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
parcel[i] = (byte) random.nextInt(256);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read exactly <code>size</code> bytes from the <code>istream</code>
|
||||
* if possible, or throw <code>TestFailure</code> if unexpected end of
|
||||
* <code>istream</code> occurs.
|
||||
*/
|
||||
private static byte[] readBytes(int size, InputStream istream)
|
||||
throws IOException {
|
||||
|
||||
byte data[] = new byte[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
int datum = istream.read();
|
||||
if (datum < 0)
|
||||
throw new TestFailure(
|
||||
"unexpected EOF: have read: " + i + " bytes of " + size);
|
||||
data[i] = (byte) datum;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 4 bytes from <code>istream</code> and threat them to encode
|
||||
* size of data parcel following these 4 bytes.
|
||||
*/
|
||||
private static int getSize(InputStream istream) throws IOException {
|
||||
byte data[] = readBytes(4, istream);
|
||||
int data0 = (int) data[0] & 0xFF;
|
||||
int data1 = (int) data[1] & 0xFF;
|
||||
int data2 = (int) data[2] & 0xFF;
|
||||
int data3 = (int) data[3] & 0xFF;
|
||||
int sizeWord = data0 + (data1 << 8) + (data2 << 16) + (data3 << 24);
|
||||
int size = sizeWord + 1;
|
||||
if (size <= 0)
|
||||
throw new TestFailure("illegal size: " + size);
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send 4 bytes encoding actual size of the parcel just to be transfered.
|
||||
*/
|
||||
private static void putSize(OutputStream ostream, int size)
|
||||
throws IOException {
|
||||
|
||||
if (size <= 0)
|
||||
throw new TestFailure("illegal size: " + size);
|
||||
|
||||
int sizeWord = size - 1;
|
||||
byte data[] = new byte[4];
|
||||
data[0] = (byte) sizeWord;
|
||||
data[1] = (byte) (sizeWord >> 8);
|
||||
data[2] = (byte) (sizeWord >> 16);
|
||||
data[3] = (byte) (sizeWord >> 24);
|
||||
ostream.write(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recieve data parcel.
|
||||
*/
|
||||
public Parcel(InputStream istream) throws IOException {
|
||||
int size = getSize(istream);
|
||||
parcel = readBytes(size, istream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send <code>this</code> data parcel.
|
||||
*/
|
||||
public void send(OutputStream ostream) throws IOException {
|
||||
int size = parcel.length;
|
||||
putSize(ostream, size);
|
||||
ostream.write(parcel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check byte-to-byte equality between <code>this</code> and the
|
||||
* <code>other</code> parcels.
|
||||
*/
|
||||
public boolean equals(Parcel other) {
|
||||
if (this.parcel.length != other.parcel.length)
|
||||
return false;
|
||||
int size = parcel.length;
|
||||
for (int i = 0; i < size; i++)
|
||||
if (this.parcel[i] != other.parcel[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Server or Client may throw this exception to report the test failure.
|
||||
*/
|
||||
static class TestFailure extends RuntimeException {
|
||||
/**
|
||||
* Report particular <code>purpose</code> of the test failure.
|
||||
*/
|
||||
public TestFailure(String purpose) {
|
||||
super(purpose);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
635
test/hotspot/jtreg/vmTestbase/nsk/stress/network/network005.java
Normal file
635
test/hotspot/jtreg/vmTestbase/nsk/stress/network/network005.java
Normal file
@ -0,0 +1,635 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/network/network005.
|
||||
* VM testbase keywords: [stress, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test make huge number of data transers between one server and
|
||||
* multiple clients communicating via TCP/IP sockets, and checks if those
|
||||
* data are transfered correctly. All TCP/IP sockets are attached to local
|
||||
* host (by its domain name), or to the ``localhost'' loopback (having the
|
||||
* IP address 127.0.0.1).
|
||||
* In this test, 128 client/server connections are established. Once a
|
||||
* connection is established, client passes a large data parcel to server,
|
||||
* and server reads that parcel and checks if it is same as expected
|
||||
* (byte-to-byte equality is desired). Then server passes (some other) parcel
|
||||
* to the client, and client reads and verifies those bytes. This ping-pong
|
||||
* game is repeated 128 times; and after that each pair of sockets checks if
|
||||
* there are no extra bytes accudentally passed through their connection.
|
||||
* Parcels lengths and contents are chosen randomly, and average parcel
|
||||
* length is 128 bytes. So totally, each pair of sockets passes ~16Kb of
|
||||
* data to each other, and thus ~32Kb of data are transfered by each sockets
|
||||
* pair. Totally, ~4Mb of data are transfered by all client/server pairs.
|
||||
* COMMENTS
|
||||
*
|
||||
* @run main/othervm nsk.stress.network.network005
|
||||
*/
|
||||
|
||||
package nsk.stress.network;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* This test make huge number of data transers between one server and
|
||||
* multiple clients communicating via TCP/IP sockets, and checks if those
|
||||
* data are transfered correctly. All TCP/IP sockets are attached to local
|
||||
* host (by its domain name), or to the ``localhost'' loopback (having the
|
||||
* IP address 127.0.0.1).
|
||||
* <p>
|
||||
* <p>In this test, 128 client/server connections are established. Once a
|
||||
* connection is established, client passes a large data parcel to server,
|
||||
* and server reads that parcel and checks if it is same as expected
|
||||
* (byte-to-byte equality is desired). Then server passes (some other) parcel
|
||||
* to the client, and client reads and verifies those bytes. This ping-pong
|
||||
* game is repeated 128 times; and after that each pair of sockets checks if
|
||||
* there are no extra bytes accudentally passed through their connection.
|
||||
* <p>
|
||||
* <p>Parcels lengths and contents are chosen randomly, and average parcel
|
||||
* length is 128 bytes. So totally, each pair of sockets passes ~16Kb of
|
||||
* data to each other, and thus ~32Kb of data are transfered by each sockets
|
||||
* pair. Totally, ~4Mb of data are transfered by all client/server pairs.
|
||||
*/
|
||||
public class network005 {
|
||||
/**
|
||||
* Do actually display optional reports?
|
||||
*/
|
||||
static private final boolean DEBUG_MODE = false;
|
||||
|
||||
/**
|
||||
* Errors and optional reports log. Usually <code>System.out</code>.
|
||||
*/
|
||||
static private PrintStream out = System.out;
|
||||
|
||||
/**
|
||||
* Print error message: all clients and servers may print concurently.
|
||||
*/
|
||||
static private synchronized void println(Object message) {
|
||||
out.println(message.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Display optional report: comment ca va.
|
||||
*/
|
||||
static private void display(Object report) {
|
||||
if (DEBUG_MODE)
|
||||
println(report.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximal number of connections this test should open simultaneously.
|
||||
*/
|
||||
private final static int MAX_CONNECTIONS = 128;
|
||||
|
||||
/**
|
||||
* Check few more connections to make sure that MAX_CONNECTIONS are safe.
|
||||
*/
|
||||
private final static int CONNECTIONS_RESERVE = 10;
|
||||
|
||||
/**
|
||||
* Number of client/server connections to establish.
|
||||
*/
|
||||
private static final int CONNECTIONS = detectOSLimitation();
|
||||
|
||||
/**
|
||||
* Number of parcels to be sent/recieved.
|
||||
*/
|
||||
private static final int DATA_PARCELS = 128;
|
||||
|
||||
/**
|
||||
* Maximal length of data parcel to be sent/recieved
|
||||
* (it equals to 256 bytes now).
|
||||
*/
|
||||
private static final int MAX_PARCEL = 1 << 8;
|
||||
|
||||
/**
|
||||
* How many IP sockets can we open simultaneously?
|
||||
* Check if <code>MAX_CONNECTIONS</code> connections
|
||||
* can be open simultaneously.
|
||||
*/
|
||||
private static int detectOSLimitation() {
|
||||
final int CONNECTIONS_TO_TRY = MAX_CONNECTIONS + CONNECTIONS_RESERVE;
|
||||
display("--- Trying to open " + CONNECTIONS_TO_TRY + " connections:");
|
||||
|
||||
InetAddress address;
|
||||
ServerSocket serverSocket;
|
||||
try {
|
||||
address = InetAddress.getLocalHost();
|
||||
int anyPort = 0;
|
||||
int defaultBacklog = 50;
|
||||
serverSocket = new ServerSocket(anyPort, defaultBacklog, address);
|
||||
} catch (IOException ioe) {
|
||||
throw new Error("FATAL error while loading the test: " + ioe);
|
||||
}
|
||||
display(serverSocket.toString());
|
||||
|
||||
Socket server[] = new Socket[CONNECTIONS_TO_TRY];
|
||||
Socket client[] = new Socket[CONNECTIONS_TO_TRY];
|
||||
|
||||
int i, port = serverSocket.getLocalPort();
|
||||
for (i = 0; i < CONNECTIONS_TO_TRY; i++)
|
||||
try {
|
||||
client[i] = new Socket(address, port);
|
||||
display("--- Open: client[" + i + "] = " + client[i]);
|
||||
server[i] = serverSocket.accept();
|
||||
display("--- Open: server[" + i + "] = " + server[i]);
|
||||
} catch (IOException ioe) {
|
||||
display("--- OOPS! -- failed to open connection #" + i);
|
||||
break;
|
||||
}
|
||||
display("--- Could open " +
|
||||
(i < CONNECTIONS_TO_TRY ? "only " : "") + i + " connections.");
|
||||
display("--- Closing them:");
|
||||
for (int j = 0; j < i; j++)
|
||||
try {
|
||||
server[j].close();
|
||||
client[j].close();
|
||||
} catch (IOException ioe) {
|
||||
throw new Error("FATAL error while loading the test: " + ioe);
|
||||
}
|
||||
display("--- OK.");
|
||||
int safeConnections = i - CONNECTIONS_RESERVE;
|
||||
if (safeConnections < 1)
|
||||
safeConnections = 1;
|
||||
if (safeConnections < MAX_CONNECTIONS) {
|
||||
println("# ------------------------- CAUTION: -------------------");
|
||||
println("# While checking the OS limitations, the test found that");
|
||||
println("# only " + i + " TCP/IP socket connections could be safely open");
|
||||
println("# simultaneously. However, possibility to open at least");
|
||||
println("# " + MAX_CONNECTIONS + "+" + CONNECTIONS_RESERVE
|
||||
+ " connections were expected.");
|
||||
println("# ");
|
||||
println("# So, the test will check only " + safeConnections + " connection"
|
||||
+ (safeConnections == 1 ? "" : "s") + " which seem");
|
||||
println("# safe to be open simultaneously.");
|
||||
println("# ------------------------------------------------------");
|
||||
}
|
||||
return safeConnections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Server (or client) thread intended to transfer data parcels to
|
||||
* another client (or server) Agent.
|
||||
*/
|
||||
static private class Agent extends Thread {
|
||||
/**
|
||||
* Agent's client mode.
|
||||
*/
|
||||
final static int CLIENT = 1;
|
||||
/**
|
||||
* Agen's server mode.
|
||||
*/
|
||||
final static int SERVER = 2;
|
||||
|
||||
/**
|
||||
* Is this agent is client or server one?
|
||||
*/
|
||||
private int mode;
|
||||
|
||||
/**
|
||||
* This server thread listens the single socket.
|
||||
*/
|
||||
private Socket socket;
|
||||
|
||||
/**
|
||||
* What is the port number this socket is listening for?
|
||||
*/
|
||||
int getPort() {
|
||||
if (mode == SERVER)
|
||||
return socket.getLocalPort();
|
||||
else
|
||||
return socket.getPort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Address and port of this server socket.
|
||||
*/
|
||||
public String toString() {
|
||||
String mode = (this.mode == CLIENT) ? "Client" : "Server";
|
||||
return mode + ": " + socket.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Did the thread failed? If yes, what is the failure's reason.
|
||||
*/
|
||||
Exception exception = null;
|
||||
|
||||
/**
|
||||
* Find some free port at the given <code>address</code>
|
||||
* and attach new server to hear that port.
|
||||
*/
|
||||
Agent(Socket socket, int mode) {
|
||||
if ((mode != SERVER) && (mode != CLIENT))
|
||||
throw new IllegalArgumentException("unknown mode=" + mode);
|
||||
this.socket = socket;
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer <code>DATA_PARCELS</code> parcels of random data.
|
||||
* Set initial seed for pseudo-random numbers generator
|
||||
* to the value of the local port number.
|
||||
*
|
||||
* @see #DATA_PARCELS
|
||||
* @see #getPort()
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
InputStream istream = socket.getInputStream();
|
||||
OutputStream ostream = socket.getOutputStream();
|
||||
|
||||
Random random = new Random(getPort());
|
||||
|
||||
for (int i = 0; i < DATA_PARCELS; i++) {
|
||||
Parcel etalon = new Parcel(random);
|
||||
|
||||
if (mode == SERVER) {
|
||||
Parcel sample = new Parcel(istream); // read
|
||||
if (!sample.equals(etalon)) {
|
||||
println("Server agent for port #"
|
||||
+ getPort() + " got unexpected parcel:\n"
|
||||
+ "sample=" + sample + "\n"
|
||||
+ "etalon=" + etalon);
|
||||
throw new TestFailure(
|
||||
"server has read unexpected parcel");
|
||||
}
|
||||
|
||||
etalon.send(ostream); // reply
|
||||
ostream.flush();
|
||||
|
||||
} else {
|
||||
etalon.send(ostream); // init transfer
|
||||
ostream.flush();
|
||||
|
||||
Parcel sample = new Parcel(istream); // read
|
||||
if (!sample.equals(etalon)) {
|
||||
println("Client agent for port #"
|
||||
+ getPort() + " got unexpected parcel:\n"
|
||||
+ "sample=" + sample + "\n"
|
||||
+ "etalon=" + etalon);
|
||||
throw new TestFailure(
|
||||
"parcel context is unexpected to client");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == SERVER) {
|
||||
int datum = istream.read(); // wait until client's close()
|
||||
if (datum >= 0)
|
||||
throw new TestFailure(
|
||||
"server has read ambigous byte: " + datum);
|
||||
|
||||
ostream.close(); // implies: socket.close();
|
||||
|
||||
} else {
|
||||
if (istream.available() > 0) {
|
||||
int datum = istream.read();
|
||||
throw new TestFailure(
|
||||
"client has read ambigous byte: " + datum);
|
||||
}
|
||||
ostream.close(); // implies: socket.close()
|
||||
}
|
||||
|
||||
} catch (Exception oops) {
|
||||
exception = oops;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A data parcel to sent/recieved between Client and Server threads.
|
||||
* When data parcel is sent, first 4 bytes transfered encode the size
|
||||
* of the parcel (i.e.: number of data bytes in the parcel's contents).
|
||||
* Then the parcel's contents bytes are transered.
|
||||
*/
|
||||
static class Parcel {
|
||||
private byte[] parcel;
|
||||
|
||||
/**
|
||||
* Display all bytes as integer values from 0 to 255;
|
||||
* or return ``<tt>null</tt>'' if this Parcel is not
|
||||
* yet initialized.
|
||||
*/
|
||||
public String toString() {
|
||||
if (parcel == null)
|
||||
return "null";
|
||||
String s = "{";
|
||||
for (int i = 0; i < parcel.length; i++)
|
||||
s += (i > 0 ? ", " : "") + ((int) parcel[i] & 0xFF);
|
||||
return s + "}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate new <code>parcel[]</code> array using the given
|
||||
* <code>random</code> numbers generator. Client and Server
|
||||
* threads should use identical <code>random</code> generators,
|
||||
* so that those threads could generate equal data parcels and
|
||||
* check the parcel just transfered.
|
||||
*/
|
||||
public Parcel(Random random) {
|
||||
int size = random.nextInt(MAX_PARCEL) + 1;
|
||||
parcel = new byte[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
parcel[i] = (byte) random.nextInt(256);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read exactly <code>size</code> bytes from the <code>istream</code>
|
||||
* if possible, or throw <code>TestFailure</code> if unexpected end of
|
||||
* <code>istream</code> occurs.
|
||||
*/
|
||||
private static byte[] readBytes(int size, InputStream istream)
|
||||
throws IOException {
|
||||
|
||||
byte data[] = new byte[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
int datum = istream.read();
|
||||
if (datum < 0)
|
||||
throw new TestFailure(
|
||||
"unexpected EOF: have read: " + i + " bytes of " + size);
|
||||
data[i] = (byte) datum;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 4 bytes from <code>istream</code> and threat them to encode
|
||||
* size of data parcel following these 4 bytes.
|
||||
*/
|
||||
private static int getSize(InputStream istream) throws IOException {
|
||||
byte data[] = readBytes(4, istream);
|
||||
int data0 = (int) data[0] & 0xFF;
|
||||
int data1 = (int) data[1] & 0xFF;
|
||||
int data2 = (int) data[2] & 0xFF;
|
||||
int data3 = (int) data[3] & 0xFF;
|
||||
int sizeWord = data0 + (data1 << 8) + (data2 << 16) + (data3 << 24);
|
||||
int size = sizeWord + 1;
|
||||
if (size <= 0)
|
||||
throw new TestFailure("illegal size: " + size);
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send 4 bytes encoding actual size of the parcel just to be transfered.
|
||||
*/
|
||||
private static void putSize(OutputStream ostream, int size)
|
||||
throws IOException {
|
||||
|
||||
if (size <= 0)
|
||||
throw new TestFailure("illegal size: " + size);
|
||||
|
||||
int sizeWord = size - 1;
|
||||
byte data[] = new byte[4];
|
||||
data[0] = (byte) sizeWord;
|
||||
data[1] = (byte) (sizeWord >> 8);
|
||||
data[2] = (byte) (sizeWord >> 16);
|
||||
data[3] = (byte) (sizeWord >> 24);
|
||||
ostream.write(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recieve data parcel.
|
||||
*/
|
||||
public Parcel(InputStream istream) throws IOException {
|
||||
int size = getSize(istream);
|
||||
parcel = readBytes(size, istream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send <code>this</code> data parcel.
|
||||
*/
|
||||
public void send(OutputStream ostream) throws IOException {
|
||||
int size = parcel.length;
|
||||
putSize(ostream, size);
|
||||
ostream.write(parcel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check byte-to-byte equality between <code>this</code> and the
|
||||
* <code>other</code> parcels.
|
||||
*/
|
||||
public boolean equals(Parcel other) {
|
||||
if (this.parcel.length != other.parcel.length)
|
||||
return false;
|
||||
int size = parcel.length;
|
||||
for (int i = 0; i < size; i++)
|
||||
if (this.parcel[i] != other.parcel[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Server or Client thread may throw this exception to report the test
|
||||
* failure.
|
||||
*/
|
||||
static class TestFailure extends RuntimeException {
|
||||
/**
|
||||
* Report particular <code>purpose</code> of the test failure.
|
||||
*/
|
||||
public TestFailure(String purpose) {
|
||||
super(purpose);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach client and server sockets to the local host, and check if
|
||||
* huge number of data transfers could be correctly transfered between
|
||||
* these sockets.
|
||||
* <p>
|
||||
* <p>Command-line parameters provided with <code>args[]</code> may
|
||||
* prompt the local host IP address or domain name. Execute:
|
||||
* <br>
|
||||
* <code>java network005 [<i>IP-address</i> | <i>host_name</i> |
|
||||
* localhost ]</code>
|
||||
* <br>where parameters are:
|
||||
* <br>
|
||||
* <code><i>IP-address</i></code> - local hots's address, or 127.0.0.1
|
||||
* <br>
|
||||
* <code><i>host_name</i></code> - local host's domain name, or the
|
||||
* keyword ``<code>localhost</code>''
|
||||
* <br>
|
||||
* <code>localhost</code> - placeholder for the IP-address 127.0.0.1
|
||||
* <br>By default, the test uses the Internet address available via
|
||||
* the method <code>InetAddress.getLocalHost()</code>
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
network005.out = out;
|
||||
|
||||
//
|
||||
// Get IP address of the local machine.
|
||||
//
|
||||
|
||||
InetAddress address = null;
|
||||
try {
|
||||
switch (args.length) {
|
||||
case 0:
|
||||
address = InetAddress.getLocalHost();
|
||||
break;
|
||||
case 1:
|
||||
String hostName = args[0];
|
||||
address = InetAddress.getByName(args[0]);
|
||||
break;
|
||||
default:
|
||||
println("Use:");
|
||||
println(" java network005");
|
||||
println("or:");
|
||||
println(" java network005 ${IP_ADDRESS}");
|
||||
println("or:");
|
||||
println(" java network005 ${HOST_NAME}");
|
||||
println("or:");
|
||||
println(" java network005 localhost");
|
||||
return 2; // FAILED
|
||||
}
|
||||
} catch (UnknownHostException exception) {
|
||||
println(exception);
|
||||
return 2; // FAILED
|
||||
}
|
||||
display("Host: " + address);
|
||||
|
||||
//
|
||||
// Assign ServerSocket to the local host:
|
||||
//
|
||||
|
||||
ServerSocket serverSocket;
|
||||
try {
|
||||
final int anyPort = 0;
|
||||
final int defaultBacklog = 50;
|
||||
serverSocket = new ServerSocket(anyPort, defaultBacklog, address);
|
||||
} catch (IOException ioe) {
|
||||
println("# Failed to assign ServerSocket on: " + address);
|
||||
return 2;
|
||||
}
|
||||
display(serverSocket.toString());
|
||||
|
||||
final int port = serverSocket.getLocalPort();
|
||||
|
||||
//
|
||||
// Incarnate the server & the client agents.
|
||||
//
|
||||
|
||||
Agent server[] = new Agent[CONNECTIONS];
|
||||
Agent client[] = new Agent[CONNECTIONS];
|
||||
|
||||
for (int i = 0; i < CONNECTIONS; i++)
|
||||
try {
|
||||
Socket socket;
|
||||
socket = new Socket(address, port);
|
||||
client[i] = new Agent(socket, Agent.CLIENT);
|
||||
display("Client #" + i + ": " + socket);
|
||||
socket = serverSocket.accept();
|
||||
server[i] = new Agent(socket, Agent.SERVER);
|
||||
display("Server #" + i + ": " + socket);
|
||||
} catch (IOException io) {
|
||||
println("Failed establish conection #" + i + ": " + io);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Execute the server and client threads.
|
||||
//
|
||||
|
||||
Exception exception = null;
|
||||
for (int i = 0; i < CONNECTIONS; i++) {
|
||||
server[i].start();
|
||||
client[i].start();
|
||||
}
|
||||
try {
|
||||
boolean someIsAlive = true;
|
||||
while (someIsAlive) {
|
||||
boolean aliveFound = false;
|
||||
boolean someBroken = false;
|
||||
for (int i = 0; i < CONNECTIONS; i++)
|
||||
if (client[i].isAlive() || server[i].isAlive()) {
|
||||
if ((client[i].exception != null) ||
|
||||
(server[i].exception != null))
|
||||
someBroken = true;
|
||||
aliveFound = true;
|
||||
Thread.yield();
|
||||
}
|
||||
someIsAlive = aliveFound;
|
||||
if (someBroken)
|
||||
break;
|
||||
}
|
||||
} catch (TestFailure failure) {
|
||||
exception = failure;
|
||||
}
|
||||
|
||||
// Failure diagnostics, if needed.
|
||||
|
||||
Exception problem[] = new Exception[2 * CONNECTIONS + 1];
|
||||
problem[0] = exception;
|
||||
for (int i = 0; i < CONNECTIONS; i++) {
|
||||
problem[2 * i + 1] = server[i].exception;
|
||||
problem[2 * i + 2] = client[i].exception;
|
||||
}
|
||||
|
||||
int exitCode = 0;
|
||||
|
||||
for (int i = 0; i < 2 * CONNECTIONS + 1; i++)
|
||||
if (problem[i] != null) {
|
||||
out.println("#### OOPS ! ####");
|
||||
problem[i].printStackTrace(out);
|
||||
exitCode = 2;
|
||||
}
|
||||
|
||||
if (exitCode != 0) {
|
||||
out.println("#### OOPS ! ####");
|
||||
out.println("# Test failed.");
|
||||
return 2; // FAILED
|
||||
}
|
||||
display("Test passed.");
|
||||
return 0; // PASSED
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-calls to the method <code>run(args[],out)</code> actually
|
||||
* performing the test; and stop with exit code 95 if the test
|
||||
* has passed, or with code 97 if the test has failed.
|
||||
* (This is JCK-like exit codes convention.)
|
||||
*
|
||||
* @see #run(String[], PrintStream)
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit code.
|
||||
}
|
||||
|
||||
}
|
||||
916
test/hotspot/jtreg/vmTestbase/nsk/stress/network/network006.java
Normal file
916
test/hotspot/jtreg/vmTestbase/nsk/stress/network/network006.java
Normal file
@ -0,0 +1,916 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/network/network006.
|
||||
* VM testbase keywords: [stress, slow, nonconcurrent, quick, quarantine]
|
||||
* VM testbase comments: 8185072
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test makes huge number of data transfers between 2 Java virtual
|
||||
* machines using the TCP/IP protocol, and checks if those data are transfered
|
||||
* correctly. Both client and server VMs run on the same local computer and
|
||||
* attach TCP/IP sockets to the local host, or to the loopback domain
|
||||
* ``localhost'' (having IP address 127.0.0.1).
|
||||
* In this test, 128 client/server connections are established. Once a
|
||||
* connection is established, client passes a data parcel to server, and server
|
||||
* reads that parcel and checks if it is same as expected (byte-to-byte equality
|
||||
* is desired). Then server passes (some other) parcel to the client, and client
|
||||
* reads and verifies those bytes. This ping-pong game is repeated 128 times; and
|
||||
* after that each pair of sockets checks if there are no extra bytes accudentally
|
||||
* passed through their connection.
|
||||
* Parcels lengths and contents are chosen randomly, and average parcel length
|
||||
* is 128 bytes. So totally, each pair of sockets passes ~16Kb of data to each other,
|
||||
* and thus ~32Kb of data are transfered by each sockets pair. Totally, ~4Mb of data
|
||||
* are transfered by all client/server pairs.
|
||||
* COMMENTS
|
||||
* Test was fixed:
|
||||
* added WAITTIME parameter defined timeout for TCP/IP sockets in minutes
|
||||
*
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @run driver jdk.test.lib.FileInstaller . .
|
||||
* @build nsk.stress.network.network006
|
||||
* @run main/othervm PropertyResolvingWrapper
|
||||
* nsk.stress.network.network006
|
||||
* "${test.jdk}/bin/java ${test.vm.opts} ${test.java.opts}" 5
|
||||
*/
|
||||
|
||||
package nsk.stress.network;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* This test makes huge number of data transfers between 2 Java virtual
|
||||
* machines using the TCP/IP protocol, and checks if those data are transfered
|
||||
* correctly. Both client and server VMs run on the same local computer and
|
||||
* attach TCP/IP sockets to the local host, or to the loopback domain
|
||||
* ``<code>localhost</code>'' (having IP address <code>127.0.0.1</code>).
|
||||
* <p>
|
||||
* <p>In this test, 128 client/server connections are established. Once a
|
||||
* connection is established, client passes a data parcel to server, and server
|
||||
* reads that parcel and checks if it is same as expected (byte-to-byte equality
|
||||
* is desired). Then server passes (some other) parcel to the client, and client
|
||||
* reads and verifies those bytes. This ping-pong game is repeated 128 times; and
|
||||
* after that each pair of sockets checks if there are no extra bytes accudentally
|
||||
* passed through their connection.
|
||||
* <p>
|
||||
* <p>Parcels lengths and contents are chosen randomly, and average parcel length
|
||||
* is 128 bytes. So totally, each pair of sockets passes ~16Kb of data to each other,
|
||||
* and thus ~32Kb of data are transfered by each sockets pair. Totally, ~4Mb of data
|
||||
* are transfered by all client/server pairs.
|
||||
*/
|
||||
public class network006 {
|
||||
/**
|
||||
* Timeout for TCP/IP sockets (currently set to 1 min).
|
||||
*/
|
||||
private static int SO_TIMEOUT;// = 2*60*1000;
|
||||
|
||||
/**
|
||||
* Maximal number of connections this test should open simultaneously.
|
||||
*/
|
||||
private final static int MAX_CONNECTIONS = 128;
|
||||
|
||||
/**
|
||||
* Check few more connections to make sure that MAX_CONNECTIONS are safe.
|
||||
*/
|
||||
private final static int CONNECTIONS_RESERVE = 10;
|
||||
|
||||
/**
|
||||
* The test used to fail with connection reset by peer set to 50.
|
||||
* (and once in a three if it was set to 10).
|
||||
* So now we set it to MAX_CONNECTIONS (128).
|
||||
*/
|
||||
private final static int BACKLOG_QUEUE_LENGTH = MAX_CONNECTIONS;
|
||||
|
||||
/**
|
||||
* Number of parcels to be sent/recieved.
|
||||
*/
|
||||
private final static int DATA_PARCELS = 128;
|
||||
|
||||
/**
|
||||
* Maximal length of data parcel to be sent/recieved
|
||||
* (it equals to 256 bytes now).
|
||||
*/
|
||||
private final static int MAX_PARCEL = 1 << 8;
|
||||
|
||||
/**
|
||||
* Either actually display optional reports or not.
|
||||
*/
|
||||
static private final boolean DEBUG_MODE = false;
|
||||
|
||||
/**
|
||||
* How many IP sockets can we open simultaneously?
|
||||
* Check if <code>MAX_CONNECTIONS</code> connections
|
||||
* can be open simultaneously.
|
||||
*/
|
||||
private static int detectOSLimitation() {
|
||||
final int CONNECTIONS_TO_TRY = MAX_CONNECTIONS + CONNECTIONS_RESERVE;
|
||||
display("--- Trying to open " + CONNECTIONS_TO_TRY + " connections:");
|
||||
|
||||
InetAddress address;
|
||||
ServerSocket serverSocket;
|
||||
try {
|
||||
address = InetAddress.getLocalHost();
|
||||
int anyPort = 0;
|
||||
int defaultBacklog = BACKLOG_QUEUE_LENGTH;
|
||||
serverSocket = new ServerSocket(anyPort, defaultBacklog, address);
|
||||
} catch (IOException ioe) {
|
||||
throw new Error("FATAL error while loading the test: " + ioe);
|
||||
}
|
||||
display(serverSocket.toString());
|
||||
|
||||
Socket server[] = new Socket[CONNECTIONS_TO_TRY];
|
||||
Socket client[] = new Socket[CONNECTIONS_TO_TRY];
|
||||
|
||||
int i, port = serverSocket.getLocalPort();
|
||||
for (i = 0; i < CONNECTIONS_TO_TRY; i++)
|
||||
try {
|
||||
client[i] = new Socket(address, port);
|
||||
display(">Open: client[" + i + "] = " + client[i]);
|
||||
server[i] = serverSocket.accept();
|
||||
display(">Open: server[" + i + "] = " + server[i]);
|
||||
} catch (IOException ioe) {
|
||||
display(">OOPS! -- failed to open connection #" + i);
|
||||
break;
|
||||
}
|
||||
display("> Could open " +
|
||||
(i < CONNECTIONS_TO_TRY ? "only " : "") + i + " connections.");
|
||||
display(">Closing them:");
|
||||
for (int j = 0; j < i; j++)
|
||||
try {
|
||||
server[j].close();
|
||||
client[j].close();
|
||||
} catch (IOException ioe) {
|
||||
throw new Error("FATAL error while loading the test: " + ioe);
|
||||
}
|
||||
display(">OK.");
|
||||
int safeConnections = i - CONNECTIONS_RESERVE;
|
||||
if (safeConnections < 1)
|
||||
safeConnections = 1;
|
||||
if (safeConnections < MAX_CONNECTIONS) {
|
||||
complain("------------------------- CAUTION: -------------------");
|
||||
complain("While checking the OS limitations, the test found that");
|
||||
complain("only " + i + " TCP/IP socket connections could be safely open");
|
||||
complain("simultaneously. However, possibility to open at least");
|
||||
complain("" + MAX_CONNECTIONS + "+" + CONNECTIONS_RESERVE
|
||||
+ " connections were expected.");
|
||||
complain("");
|
||||
complain("So, the test will check only " + safeConnections + " connection"
|
||||
+ (safeConnections == 1 ? "" : "s") + " which seem");
|
||||
complain("safe to be open simultaneously.");
|
||||
complain("------------------------------------------------------");
|
||||
}
|
||||
return safeConnections;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------//
|
||||
|
||||
/**
|
||||
* Re-calls to the method <code>run(args[],out)</code> actually
|
||||
* performing the test. After <code>run(args[],out)</code> stops,
|
||||
* follow JDK-like convention for exit codes. I.e.: stop with
|
||||
* exit status 95 if the test has passed, or with status 97 if
|
||||
* the test has failed.
|
||||
*
|
||||
* @see #run(String[], PrintStream)
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status.
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line parameters stored into <code>args[]</code> array,
|
||||
* then perform the test. I.e.: start the server thread at the same VM
|
||||
* this method runs, then start the other client VM, and verify data
|
||||
* transfer through TCP/IP connection between those different virtual
|
||||
* machines.
|
||||
* <p>
|
||||
* <p>There should be 2 or 3 command-line parameters:
|
||||
* <br>
|
||||
* <code>java network006 <i>java_command</i>
|
||||
* [<i>IP-address</i> | <i>host_name</i> | localhost ]</code>
|
||||
* <br>where parameters are:
|
||||
* <br>
|
||||
* <code><i>java_command</i></code> - how to start java,
|
||||
* e.g.: ``<code>c:\jdk1.3\bin\java -classic</code>''
|
||||
* <br>
|
||||
* <code>waittime</code> - timeout for TCP/IP sockets in minutes
|
||||
* <br>
|
||||
* <code><i>IP-address</i></code> - local hots's address, or 127.0.0.1
|
||||
* <br>
|
||||
* <code><i>host_name</i></code> - local host's domain name, or the
|
||||
* keyword ``<code>localhost</code>''
|
||||
* <br>
|
||||
* <code>localhost</code> - placeholder for the IP-address 127.0.0.1
|
||||
* <p>
|
||||
* <p>Usually, <code><i>java_command</i></code> should point to the same
|
||||
* Java machine just executing this test. However, every compatible Java 2
|
||||
* implementation is appropriate.
|
||||
* <p>
|
||||
* <p>If optional parameter is ommited, the test invokes the method
|
||||
* <code>InetAddress.getLocalHost()</code> to get the domain name and
|
||||
* IP-address of the local computer.
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
network006.out = out;
|
||||
|
||||
//
|
||||
// Get the Internet address of the local machine.
|
||||
//
|
||||
InetAddress address = null;
|
||||
try {
|
||||
switch (args.length) {
|
||||
case 2:
|
||||
address = InetAddress.getLocalHost();
|
||||
break;
|
||||
case 3:
|
||||
address = InetAddress.getByName(args[2]);
|
||||
break;
|
||||
default:
|
||||
complain("Illegal arguments number; execute:");
|
||||
complain(" java " + network006.class.getName() + " $JAVA_COMMAND " +
|
||||
"[$IP_ADDRESS | $HOST_NAME | localhost]");
|
||||
return 2; // FAILED
|
||||
}
|
||||
} catch (UnknownHostException exception) {
|
||||
complain(exception.toString());
|
||||
return 2; // FAILED
|
||||
}
|
||||
display("Host: " + address);
|
||||
|
||||
//
|
||||
// Detect if it is safe to open MAX_CONNETIONS simultaneously:
|
||||
//
|
||||
final int CONNECTIONS = detectOSLimitation();
|
||||
|
||||
//
|
||||
// Assign ServerSocket, and start client VM which should open
|
||||
// the prescribed number of CONNECTIONS to that ServerSocket.
|
||||
//
|
||||
|
||||
ServerSocket serverSocket;
|
||||
try {
|
||||
final int anyPort = 0;
|
||||
final int defaultBacklog = BACKLOG_QUEUE_LENGTH;
|
||||
serverSocket = new ServerSocket(anyPort, defaultBacklog, address);
|
||||
} catch (IOException exception) {
|
||||
complain("Cannot assign a ServerSocket on: " + address);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Start the client process on different VM.
|
||||
//
|
||||
|
||||
String IPAddress = address.getHostAddress();
|
||||
int localPort = serverSocket.getLocalPort();
|
||||
String arguments = " " + CONNECTIONS + " " + IPAddress + " " + localPort;
|
||||
//String command = args[0] + " " + network006.class.getName() + "$Client " + arguments;
|
||||
String command = args[0] + " " + Client.class.getName() + " " + arguments;
|
||||
try {
|
||||
SO_TIMEOUT = Integer.parseInt(args[1]) * 60 * 1000;
|
||||
} catch (NumberFormatException e) {
|
||||
complain("Wrong timeout argument: " + e);
|
||||
return 2;
|
||||
}
|
||||
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
|
||||
Process client = null;
|
||||
IORedirector redirectOut = null;
|
||||
IORedirector redirectErr = null;
|
||||
|
||||
try {
|
||||
// Start clients on different JVM:
|
||||
client = runtime.exec(command);
|
||||
|
||||
// Provide clients with access to stderr and stdout:
|
||||
InputStream clientOut = client.getInputStream();
|
||||
InputStream clientErr = client.getErrorStream();
|
||||
redirectOut = new IORedirector(clientOut, DEBUG_MODE ? out : null);
|
||||
redirectErr = new IORedirector(clientErr, out);
|
||||
redirectOut.start();
|
||||
redirectErr.start();
|
||||
|
||||
} catch (Exception exception) {
|
||||
complain("Failed to start client: " + exception);
|
||||
return 2;
|
||||
}
|
||||
//
|
||||
// Start the server threads (and let them establish connections):
|
||||
//
|
||||
|
||||
Server server[] = new Server[CONNECTIONS];
|
||||
for (int i = 0; i < CONNECTIONS; i++) {
|
||||
server[i] = new Server(serverSocket);
|
||||
display("Server #" + i + ": " + server[i]);
|
||||
server[i].start();
|
||||
}
|
||||
|
||||
//
|
||||
// Wait for the servers and the clients:
|
||||
//
|
||||
|
||||
boolean testFailed = false;
|
||||
|
||||
try {
|
||||
client.waitFor();
|
||||
int clientStatus = client.exitValue();
|
||||
display("Client VM exitCode=" + clientStatus);
|
||||
|
||||
// Let I/O redirectors to flush:
|
||||
if (redirectOut.isAlive())
|
||||
redirectOut.join();
|
||||
if (redirectErr.isAlive())
|
||||
redirectErr.join();
|
||||
|
||||
// If client has crashed, also terminate the server (to avoid hangup).
|
||||
if (clientStatus != 95) {
|
||||
complain("Client VM has crashed: exit status=" + clientStatus);
|
||||
testFailed = true;
|
||||
}
|
||||
|
||||
// Client has finished OK; wait for the server.
|
||||
for (int i = 0; i < CONNECTIONS; i++) {
|
||||
display("Server: waiting for #" + i);
|
||||
if (server[i].isAlive()) {
|
||||
display("Server #" + i + ": (joining...)" + server[i]);
|
||||
server[i].join();
|
||||
}
|
||||
if (server[i].exception != null) {
|
||||
if (server[i].message != null)
|
||||
complain("Server #" + i + "(finished): with message:" + server[i].message);
|
||||
|
||||
complain("Server #" + i + "(finished): " + server[i].exception);
|
||||
server[i].exception.printStackTrace(out);
|
||||
out.flush();
|
||||
// complain("Server #"+i+": "+server[i].exception.getStackTrace());
|
||||
testFailed = true;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception exception) {
|
||||
complain("Test interrupted: " + exception);
|
||||
testFailed = true;
|
||||
}
|
||||
|
||||
if (testFailed)
|
||||
complain("Test failed.");
|
||||
else
|
||||
display("Test passed.");
|
||||
return testFailed ? 2 : 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------//
|
||||
|
||||
/**
|
||||
* Log stream for error messages and/or (optional) execution trace.
|
||||
*/
|
||||
private static PrintStream out;
|
||||
|
||||
/**
|
||||
* Print error message.
|
||||
*/
|
||||
private static synchronized void complain(Object message) {
|
||||
out.println("# " + message);
|
||||
out.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display optional report: comment ca va?
|
||||
*/
|
||||
private static synchronized void display(Object report) {
|
||||
if (DEBUG_MODE)
|
||||
out.println(report.toString());
|
||||
out.flush(); //todo shouldn't this be inside if??
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------//
|
||||
|
||||
/**
|
||||
* Server thread should reply to data parcels sent by Client VM.
|
||||
*/
|
||||
private static class Server extends Thread {
|
||||
/**
|
||||
* The socket is assigned at the Server instantiation.
|
||||
*/
|
||||
private ServerSocket serverSocket;
|
||||
|
||||
/**
|
||||
* The socket is assigned at the Server runtime.
|
||||
*/
|
||||
private Socket socket;
|
||||
|
||||
/**
|
||||
* Display the server socket.
|
||||
*/
|
||||
public String toString() {
|
||||
|
||||
return "ServerSocket: " + serverSocket.toString();
|
||||
// + " socket: " + socket.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Which port is this socket listening?
|
||||
*/
|
||||
int getPort() {
|
||||
return serverSocket.getLocalPort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find some free port at the given <code>address</code>
|
||||
* and attach new server to hear that port. // lidsten to??
|
||||
*/
|
||||
public Server(ServerSocket serverSocket) {
|
||||
this.serverSocket = serverSocket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception just arisen while the server was working,
|
||||
* or <code>null</code> if it was OK with the server.
|
||||
*/
|
||||
Exception exception = null;
|
||||
String message = null;
|
||||
|
||||
/**
|
||||
* Accept connection, then reply to client's parcels.
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
socket = serverSocket.accept();
|
||||
socket.setSoTimeout(SO_TIMEOUT);
|
||||
|
||||
InputStream istream = socket.getInputStream();
|
||||
OutputStream ostream = socket.getOutputStream();
|
||||
|
||||
Random random = new Random(getPort());
|
||||
|
||||
for (int i = 0; i < DATA_PARCELS; i++) {
|
||||
Parcel etalon = new Parcel(random);
|
||||
message = "reading parcel number " + i;
|
||||
Parcel sample = new Parcel(istream); // read
|
||||
if (!sample.equals(etalon)) {
|
||||
complain("Server thread for port #"
|
||||
+ getPort() + " got unexpected parcel:\n"
|
||||
+ "sample=" + sample + "\n"
|
||||
+ "etalon=" + etalon);
|
||||
throw new TestFailure( //received??
|
||||
"server has read unexpected parcel");
|
||||
}
|
||||
message = "sending parcel number " + i;
|
||||
etalon.send(ostream);
|
||||
ostream.flush();
|
||||
}
|
||||
|
||||
int datum = istream.read(); // wait for client close()
|
||||
if (datum >= 0)
|
||||
throw new TestFailure(
|
||||
"server has read ambigous byte: " + datum);
|
||||
|
||||
ostream.close(); // implies: socket.close();
|
||||
|
||||
} catch (Exception oops) {
|
||||
exception = oops;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------//
|
||||
|
||||
/**
|
||||
* Client VM should send data parcels to Server VM and
|
||||
* recieve and verify the server's replies.
|
||||
*/
|
||||
private static class Client extends Thread {
|
||||
/**
|
||||
* This thread uses the single client socket.
|
||||
*/
|
||||
private Socket socket;
|
||||
|
||||
/**
|
||||
* Address and port of this socket.
|
||||
*/
|
||||
public String toString() {
|
||||
return socket.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Did the thread failed? If yes, what is the failure's reason.
|
||||
*/
|
||||
Exception exception = null;
|
||||
String message = null;
|
||||
|
||||
|
||||
public static java.io.PrintStream complainStream = System.out;
|
||||
public static java.io.PrintStream displayStream = System.err;
|
||||
|
||||
/**
|
||||
* Connect client socket on the given <code>address</code>
|
||||
* and <code>port</code>.
|
||||
*/
|
||||
Client(InetAddress address, int port) throws IOException {
|
||||
socket = new Socket(address, port);
|
||||
socket.setSoTimeout(SO_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* What is the port number this socket is listening for?
|
||||
*/
|
||||
int getPort() {
|
||||
return socket.getPort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish connection, then read/respond <code>DATA_PARCELS</code> parcels
|
||||
* of random data. Set initial seed for pseudo-random numbers generator
|
||||
* to the value of the local port number.
|
||||
*
|
||||
* @see #DATA_PARCELS
|
||||
* @see #getPort()
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
InputStream istream = socket.getInputStream();
|
||||
OutputStream ostream = socket.getOutputStream();
|
||||
|
||||
Random random = new Random(getPort());
|
||||
// suggested by Oleg -- to avoid race conditions
|
||||
/* try{
|
||||
Thread.sleep(500);
|
||||
}
|
||||
catch (java.lang.InterruptedException e)
|
||||
{
|
||||
}*/
|
||||
|
||||
for (int i = 0; i < DATA_PARCELS; i++) {
|
||||
Parcel etalon = new Parcel(random);
|
||||
message = "sending parcel number: " + i;
|
||||
etalon.send(ostream);
|
||||
ostream.flush();
|
||||
|
||||
message = "reading parcel number: " + i;
|
||||
Parcel sample = new Parcel(istream); // read
|
||||
if (!sample.equals(etalon)) {
|
||||
complain("Client thread for port #"
|
||||
+ getPort() + " got unexpected parcel:\n"
|
||||
+ "sample=" + sample + "\n"
|
||||
+ "etalon=" + etalon);
|
||||
throw new TestFailure(
|
||||
"parcel context is unexpected to client");
|
||||
}
|
||||
}
|
||||
|
||||
if (istream.available() > 0) {
|
||||
int datum = istream.read();
|
||||
throw new TestFailure(
|
||||
"client has read ambigous byte: " + datum);
|
||||
}
|
||||
ostream.close(); // implies: socket.close()
|
||||
|
||||
} catch (Exception oops) {
|
||||
exception = oops;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish lots of connections to server socket, attack servers with
|
||||
* huge data parcels, and check if they reply correctly. The number of
|
||||
* connections to try, the address and port number for the server socket
|
||||
* are passed through <code>args[]</code>, like:
|
||||
* <pre>
|
||||
* java network006$Client connections_to_try address port
|
||||
* </pre>
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
if (DEBUG_MODE) {
|
||||
try {
|
||||
String filename = "Client" + ((args.length == 3) ? args[2] : "new");
|
||||
displayStream = new PrintStream(filename + ".out");
|
||||
complainStream = new PrintStream(filename + ".err");
|
||||
} catch (FileNotFoundException exception) {
|
||||
complain(exception);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (args.length != 3) {
|
||||
complain("Client expects 3 paramenets:");
|
||||
complain(" java " + Client.class.getName() + " connections_to_try address port");
|
||||
exit(1); // FAILED
|
||||
}
|
||||
|
||||
int CONNECTIONS = Integer.parseInt(args[0]);
|
||||
display("Client VM: will try " + CONNECTIONS + " connections.");
|
||||
InetAddress address;
|
||||
try {
|
||||
address = InetAddress.getByName(args[1]);
|
||||
} catch (UnknownHostException exception) {
|
||||
address = null;
|
||||
complain("Client: cannot find host: \"" + args[1] + "\"");
|
||||
exit(4);
|
||||
}
|
||||
display("Client: host to contact: " + address);
|
||||
int port = Integer.parseInt(args[2]);
|
||||
display("Client: port to contact: " + port);
|
||||
|
||||
//
|
||||
// Establish connections, and start client processes:
|
||||
//
|
||||
|
||||
Client client[] = new Client[CONNECTIONS];
|
||||
for (int i = 0; i < CONNECTIONS; i++)
|
||||
try {
|
||||
client[i] = new Client(address, port);
|
||||
display("Client #" + i + ": " + client[i]);
|
||||
|
||||
} catch (IOException ioe) {
|
||||
complain("Client #" + i + "(creation): " + ioe);
|
||||
ioe.printStackTrace(complainStream);
|
||||
complainStream.flush();
|
||||
// complain("Client #" + i + "(creation): " + ioe.getStackTrace());
|
||||
exit(3);
|
||||
}
|
||||
|
||||
for (int i = 0; i < CONNECTIONS; i++)
|
||||
client[i].start();
|
||||
|
||||
//
|
||||
// Wait until testing is not finished:
|
||||
//
|
||||
|
||||
int status = 0;
|
||||
for (int i = 0; i < CONNECTIONS; i++) {
|
||||
display("Client: waiting for #" + i);
|
||||
if (client[i].isAlive()) {
|
||||
display("Client #" + i + ": (joining...)" + client[i]);
|
||||
|
||||
try {
|
||||
client[i].join();
|
||||
} catch (InterruptedException ie) {
|
||||
complain("Client #" + i + ": " + ie);
|
||||
status = 3;
|
||||
}
|
||||
}
|
||||
if (client[i].exception != null) {
|
||||
if (client[i].message != null)
|
||||
complain("Client #" + i + "(finished) with message: " + client[i].message);
|
||||
complain("Client #" + i + "(finished): " + client[i].exception);
|
||||
client[i].exception.printStackTrace(complainStream);
|
||||
complainStream.flush();
|
||||
if (status == 0)
|
||||
status = 2;
|
||||
}
|
||||
}
|
||||
|
||||
exit(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print error message.
|
||||
*/
|
||||
private static synchronized void complain(Object message) {
|
||||
complainStream.println("# " + message);
|
||||
complainStream.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display execution trace.
|
||||
*/
|
||||
private static synchronized void display(Object message) {
|
||||
if (!DEBUG_MODE)
|
||||
return;
|
||||
displayStream.println(message.toString());
|
||||
displayStream.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit with JCK-like status.
|
||||
*/
|
||||
private static void exit(int exitCode) {
|
||||
int status = exitCode + 95;
|
||||
// display("Client: exiting with code=" + status);
|
||||
System.exit(status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Two of such threads should redirect <code>out</code> and <code>err</code>
|
||||
* streams of client VM.
|
||||
*/
|
||||
private static class IORedirector extends Thread {
|
||||
/**
|
||||
* Source stream.
|
||||
*/
|
||||
InputStream in;
|
||||
/**
|
||||
* Destination stream.
|
||||
*/
|
||||
OutputStream out;
|
||||
|
||||
/**
|
||||
* Redirect <code>in</code> to <code>out</code>.
|
||||
*/
|
||||
public IORedirector(InputStream in, OutputStream out) {
|
||||
this.in = in;
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read input stream until the EOF, and write everithing to output stream.
|
||||
* If output stream is assigned to <code>null</code>, do not print anything,
|
||||
* but read the input stream anywhere.
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
for (; ; ) {
|
||||
int symbol = in.read();
|
||||
if (symbol < 0)
|
||||
break; // EOF
|
||||
if (out != null)
|
||||
out.write(symbol);
|
||||
}
|
||||
|
||||
if (out != null)
|
||||
out.flush();
|
||||
|
||||
} catch (Exception exception) {
|
||||
throw new TestFailure("IORedirector exception: " + exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------//
|
||||
|
||||
/**
|
||||
* A data parcel to be sent/recieved between Client VM and Server thread.
|
||||
* When data parcel is sent, first 4 bytes are transfered which encode the
|
||||
* <code>int</code> number equal to size of the parcel minus 1. I.e.: if
|
||||
* number of data bytes in the parcel's contents is <code>N</code>, then
|
||||
* the first 4 bytes encode the number <code>N-1</code>. After that, the
|
||||
* parcel's contents bytes are transered.
|
||||
*/
|
||||
static class Parcel {
|
||||
private byte[] parcel;
|
||||
|
||||
/**
|
||||
* Display all bytes as integer values from 0 to 255;
|
||||
* or return ``<tt>null</tt>'' if this Parcel is not
|
||||
* yet initialized.
|
||||
*/
|
||||
public String toString() {
|
||||
if (parcel == null)
|
||||
return "null";
|
||||
String s = "{";
|
||||
for (int i = 0; i < parcel.length; i++)
|
||||
s += (i > 0 ? ", " : "") + ((int) parcel[i] & 0xFF);
|
||||
return s + "}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate new <code>parcel[]</code> array using the given
|
||||
* <code>random</code> numbers generator. Client and Server
|
||||
* threads should use identical <code>random</code> generators,
|
||||
* so that those threads could generate equal data parcels and
|
||||
* check the parcel just transfered.
|
||||
*/
|
||||
public Parcel(Random random) {
|
||||
int size = random.nextInt(MAX_PARCEL) + 1;
|
||||
parcel = new byte[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
parcel[i] = (byte) random.nextInt(256);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read exactly <code>size</code> bytes from the <code>istream</code>
|
||||
* if possible, or throw <code>TestFailure</code> if unexpected end of
|
||||
* <code>istream</code> occurs.
|
||||
*/
|
||||
private static byte[] readBytes(int size, InputStream istream)
|
||||
throws IOException {
|
||||
|
||||
byte data[] = new byte[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
int datum = istream.read();
|
||||
if (datum < 0)
|
||||
throw new TestFailure(
|
||||
"unexpected EOF: have read: " + i + " bytes of " + size);
|
||||
data[i] = (byte) datum;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 4 bytes from <code>istream</code> and threat them to encode
|
||||
* size of data parcel following these 4 bytes.
|
||||
*/
|
||||
private static int getSize(InputStream istream) throws IOException {
|
||||
byte data[] = readBytes(4, istream);
|
||||
int data0 = (int) data[0] & 0xFF;
|
||||
int data1 = (int) data[1] & 0xFF;
|
||||
int data2 = (int) data[2] & 0xFF;
|
||||
int data3 = (int) data[3] & 0xFF;
|
||||
int sizeWord = data0 + (data1 << 8) + (data2 << 16) + (data3 << 24);
|
||||
int size = sizeWord + 1;
|
||||
if (size <= 0)
|
||||
throw new TestFailure("illegal size: " + size);
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send 4 bytes encoding actual size of the parcel just to be transfered.
|
||||
*/
|
||||
private static void putSize(OutputStream ostream, int size)
|
||||
throws IOException {
|
||||
|
||||
if (size <= 0)
|
||||
throw new TestFailure("illegal size: " + size);
|
||||
|
||||
int sizeWord = size - 1;
|
||||
byte data[] = new byte[4];
|
||||
data[0] = (byte) sizeWord;
|
||||
data[1] = (byte) (sizeWord >> 8);
|
||||
data[2] = (byte) (sizeWord >> 16);
|
||||
data[3] = (byte) (sizeWord >> 24);
|
||||
ostream.write(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recieve data parcel.
|
||||
*/
|
||||
public Parcel(InputStream istream) throws IOException {
|
||||
int size = getSize(istream);
|
||||
parcel = readBytes(size, istream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send <code>this</code> data parcel.
|
||||
*/
|
||||
public void send(OutputStream ostream) throws IOException {
|
||||
int size = parcel.length;
|
||||
putSize(ostream, size);
|
||||
ostream.write(parcel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check byte-to-byte equality between <code>this</code> and the
|
||||
* <code>other</code> parcels.
|
||||
*/
|
||||
public boolean equals(Parcel other) {
|
||||
if (this.parcel.length != other.parcel.length)
|
||||
return false;
|
||||
int size = parcel.length;
|
||||
for (int i = 0; i < size; i++)
|
||||
if (this.parcel[i] != other.parcel[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Server or Client may throw this exception to report the test failure.
|
||||
*/
|
||||
static class TestFailure extends RuntimeException {
|
||||
/**
|
||||
* Report particular <code>purpose</code> of the test failure.
|
||||
*/
|
||||
public TestFailure(String purpose) {
|
||||
super(purpose);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
#
|
||||
# Copyright (c) 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.
|
||||
#
|
||||
|
||||
exclusiveAccess.dirs=.
|
||||
369
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric001.java
Normal file
369
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric001.java
Normal file
@ -0,0 +1,369 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/numeric/numeric001.
|
||||
* VM testbase keywords: [stress, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test calculates the product A*A for a square matrix A of the type
|
||||
* double[][]. Elements of the matrix A are initiated with random numbers,
|
||||
* so that optimizing compiler could not eliminate any essential portion
|
||||
* of calculations.
|
||||
* That product A*A is calculated twice: in a single thread, and in N
|
||||
* separate threads, where NxN is the size of square matrix A. When executing
|
||||
* in N threads, each thread calculate distinct row of the resulting matrix.
|
||||
* The test checks if the resulting product A*A is the same when calculated
|
||||
* in single thread and in N threads.
|
||||
* By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if single-thread calculation is essentially
|
||||
* slower than N-threads calculation (surely, the number of CPUs installed
|
||||
* on the platform executing the test is taken into account for performance
|
||||
* testing). Note, that HotSpot may fail to adjust itself for better
|
||||
* performance in single-thread calculation.
|
||||
* COMMENTS
|
||||
* The bug was filed referencing to the same numeric algorithm,
|
||||
* which is used by this test:
|
||||
* 4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
*
|
||||
* @run main/othervm nsk.stress.numeric.numeric001.numeric001 300 300
|
||||
*/
|
||||
|
||||
package nsk.stress.numeric.numeric001;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* This test calculates the product <b>A</b><sup>.</sup><b>A</b> for
|
||||
* a square matrix <b>A</b> of the type <code>double[][]</code>.
|
||||
* Elements of the matrix <b>A</b> are initiated with random numbers,
|
||||
* so that optimizing compiler could not eliminate any essential portion
|
||||
* of calculations.
|
||||
* <p>
|
||||
* <p>That product <b>A</b><sup>.</sup><b>A</b> is calculated twice: in
|
||||
* a single thread, and in <i>N</i> separate threads, where <i>N</i>x<i>N</i>
|
||||
* is the size of square matrix <b>A</b>. When executing in <i>N</i> threads,
|
||||
* each thread calculate distinct row of the resulting matrix. The test checks
|
||||
* if the resulting product <b>A</b><sup>.</sup><b>A</b> is the same when
|
||||
* calculated in single thread and in <i>N</i> threads.
|
||||
* <p>
|
||||
* <p>By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if single-thread calculation is essentially
|
||||
* slower than <i>N</i>-threads calculation (surely, the number of CPUs
|
||||
* installed on the platform executing the test is taken into account for
|
||||
* performance testing). Note, that HotSpot may fail to adjust itself for
|
||||
* better performance in single-thread calculation.
|
||||
* <p>
|
||||
* <p>See the bug-report:
|
||||
* <br>
|
||||
* 4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
*/
|
||||
public class numeric001 {
|
||||
/**
|
||||
* When testing performance, single thread calculation is allowed to
|
||||
* be 10% slower than multi-threads calculation (<code>TOLERANCE</code>
|
||||
* is assigned to 10 now).
|
||||
*/
|
||||
public static final double TOLERANCE = 100; // 10;
|
||||
|
||||
/**
|
||||
* Re-assign this value to <code>true</code> for better
|
||||
* diagnostics.
|
||||
*/
|
||||
private static boolean verbose = false;
|
||||
|
||||
private static PrintStream out = null;
|
||||
|
||||
/**
|
||||
* Print error-message to the <code>out<code>.
|
||||
*/
|
||||
private static void complain(Object x) {
|
||||
out.println("# " + x);
|
||||
}
|
||||
|
||||
private static void print(Object x) {
|
||||
if (verbose)
|
||||
out.print(x);
|
||||
}
|
||||
|
||||
private static void println(Object x) {
|
||||
print(x + "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-invoke <code>run(args,out)</code> in order to simulate
|
||||
* JCK-like test interface.
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line parameters stored in <code>args[]</code> and run
|
||||
* the test.
|
||||
* <p>
|
||||
* <p>Command-line parameters are:
|
||||
* <br>
|
||||
* <code>java numeric001 [-verbose] [-performance] [-CPU:<i>number</i>]
|
||||
* <i>matrixSize</i> [<i>threads</i>]</code>
|
||||
* <p>
|
||||
* <p>Here:
|
||||
* <br> <code>-verbose</code> -
|
||||
* keyword, which alows to print execution trace
|
||||
* <br> <code>-performance</code> -
|
||||
* keyword, which alows performance testing
|
||||
* <br> <code><i>number</i></code> -
|
||||
* number of CPU installed on the computer just executing the test
|
||||
* <br> <code><i>matrixSize</i></code> -
|
||||
* number of rows (and columns) in square matrix to be tested
|
||||
* <br> <code><i>threads</i></code> -
|
||||
* for multi-thread calculation
|
||||
* (default: <code><i>matrixSize</i></code>)
|
||||
*
|
||||
* @param args strings array containing command-line parameters
|
||||
* @param out the test log, usually <code>System.out</code>
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
numeric001.out = out;
|
||||
|
||||
boolean testPerformance = false;
|
||||
int numberOfCPU = 1;
|
||||
|
||||
int argsShift = 0;
|
||||
for (; argsShift < args.length; argsShift++) {
|
||||
String argument = args[argsShift];
|
||||
|
||||
if (!argument.startsWith("-"))
|
||||
break;
|
||||
|
||||
if (argument.equals("-performance")) {
|
||||
testPerformance = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.equals("-verbose")) {
|
||||
verbose = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.startsWith("-CPU:")) {
|
||||
String value =
|
||||
argument.substring("-CPU:".length(), argument.length());
|
||||
numberOfCPU = Integer.parseInt(value);
|
||||
|
||||
if (numberOfCPU < 1) {
|
||||
complain("Illegal number of CPU: " + argument);
|
||||
return 2; // failure
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
complain("Cannot recognize argument: args[" + argsShift + "]: " + argument);
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
if ((args.length < argsShift + 1) || (args.length > argsShift + 2)) {
|
||||
complain("Illegal argument(s). Execute:");
|
||||
complain(
|
||||
" java numeric001 [-verbose] [-performance] [-CPU:number] " +
|
||||
"matrixSize [threads]");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int size = Integer.parseInt(args[argsShift]);
|
||||
if ((size < 100) || (size > 10000)) {
|
||||
complain("Matrix size should be 100 to 1000 lines & columns.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int threads = size;
|
||||
if (args.length >= argsShift + 2)
|
||||
threads = Integer.parseInt(args[argsShift + 1]);
|
||||
if ((threads < 1) || (threads > size)) {
|
||||
complain("Threads number should be 1 to matrix size.");
|
||||
return 2; // failure
|
||||
}
|
||||
if ((size % threads) != 0) {
|
||||
complain("Threads number should evenly divide matrix size.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
print("Preparing A[" + size + "," + size + "]:");
|
||||
SquareMatrix A = new SquareMatrix(size);
|
||||
SquareMatrix A1 = new SquareMatrix(size);
|
||||
SquareMatrix Am = new SquareMatrix(size);
|
||||
println(" done.");
|
||||
|
||||
double singleThread = elapsedTime(out, A, A1, size, 1);
|
||||
double multiThreads = elapsedTime(out, A, Am, size, threads);
|
||||
|
||||
print("Checking accuracy:");
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
if (A1.value[line][column] != Am.value[line][column]) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("Different results by single- and multi-threads:");
|
||||
complain(" line=" + line + ", column=" + column);
|
||||
complain("A1.value[line][column]=" + A1.value[line][column]);
|
||||
complain("Am.value[line][column]=" + Am.value[line][column]);
|
||||
return 2; // FAILED
|
||||
}
|
||||
println(" done.");
|
||||
|
||||
if (testPerformance) {
|
||||
print("Checking performance: ");
|
||||
double elapsed1 = singleThread;
|
||||
double elapsedM = multiThreads * numberOfCPU;
|
||||
if (elapsed1 > elapsedM * (1 + TOLERANCE / 100)) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("Single-thread calculation is essentially slower:");
|
||||
complain("Calculation time elapsed (seconds):");
|
||||
complain(" single thread: " + singleThread);
|
||||
complain(" multi-threads: " + multiThreads);
|
||||
complain(" number of CPU: " + numberOfCPU);
|
||||
complain(" tolerance: " + TOLERANCE + "%");
|
||||
return 2; // FAILED
|
||||
}
|
||||
println("done.");
|
||||
}
|
||||
|
||||
println("Test passed.");
|
||||
return 0; // PASSED
|
||||
}
|
||||
|
||||
private static double elapsedTime(PrintStream out,
|
||||
SquareMatrix A, SquareMatrix AA, int size, int threads) {
|
||||
|
||||
print("Computing A*A with " + threads + " thread(s):");
|
||||
long mark1 = System.currentTimeMillis();
|
||||
AA.setSquareOf(A, threads);
|
||||
long mark2 = System.currentTimeMillis();
|
||||
println(" done.");
|
||||
|
||||
double sec = (mark2 - mark1) / 1000.0;
|
||||
double perf = size * size * (size + size) / sec;
|
||||
println("Elapsed time: " + sec + " seconds");
|
||||
println("Performance: " + perf / 1e6 + " MFLOPS");
|
||||
|
||||
return sec;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class computes <code>A*A</code> for square matrix <code>A</code>.
|
||||
*/
|
||||
private static class SquareMatrix {
|
||||
volatile double value[][];
|
||||
|
||||
/**
|
||||
* New square matrix with random elements.
|
||||
*/
|
||||
public SquareMatrix(int size) {
|
||||
value = new double[size][size];
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
value[line][column] = Math.random() * size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update <code>value[][]</code> of <code>this</code> matrix.
|
||||
*
|
||||
* @param threads Split computation into the given number of threads.
|
||||
*/
|
||||
public void setSquareOf(SquareMatrix A, int threads) {
|
||||
if (this.value.length != A.value.length)
|
||||
throw new IllegalArgumentException(
|
||||
"this.value.length != A.value.length");
|
||||
|
||||
int size = value.length;
|
||||
if ((size % threads) != 0)
|
||||
throw new IllegalArgumentException("size%threads != 0");
|
||||
int bunch = size / threads;
|
||||
|
||||
Thread task[] = new Thread[threads];
|
||||
for (int t = 0; t < threads; t++) {
|
||||
int line0 = bunch * t;
|
||||
MatrixComputer computer =
|
||||
new MatrixComputer(value, A.value, line0, bunch);
|
||||
task[t] = new Thread(computer);
|
||||
}
|
||||
|
||||
for (int t = 0; t < threads; t++)
|
||||
task[t].start();
|
||||
|
||||
for (int t = 0; t < threads; t++)
|
||||
if (task[t].isAlive())
|
||||
try {
|
||||
task[t].join();
|
||||
} catch (InterruptedException exception) {
|
||||
throw new RuntimeException(exception.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread to compute a bunch of lines of matrix square.
|
||||
*/
|
||||
private static class MatrixComputer implements Runnable {
|
||||
private double result[][];
|
||||
private double source[][];
|
||||
private int line0;
|
||||
private int bunch;
|
||||
|
||||
/**
|
||||
* Register a task for matrix multiplication.
|
||||
*/
|
||||
public MatrixComputer(
|
||||
double result[][], double source[][], int line0, int bunch) {
|
||||
|
||||
this.result = result; // reference to resulting matrix value
|
||||
this.source = source; // reference to matrix to be squared
|
||||
this.line0 = line0; // compute lines from line0 to ...
|
||||
this.bunch = bunch; // number of resulting lines to compute
|
||||
}
|
||||
|
||||
/**
|
||||
* Do execute the task just registered for <code>this</code> thread.
|
||||
*/
|
||||
public void run() {
|
||||
int line1 = line0 + bunch;
|
||||
int size = result.length;
|
||||
for (int line = line0; line < line1; line++)
|
||||
for (int column = 0; column < size; column++) {
|
||||
double sum = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
sum += source[line][i] * source[i][column];
|
||||
result[line][column] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
400
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric002.java
Normal file
400
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric002.java
Normal file
@ -0,0 +1,400 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/numeric/numeric002.
|
||||
* VM testbase keywords: [stress, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test calculates the product A*A for a square matrix A of the type
|
||||
* float[][]. Elements of the matrix A are initiated with random numbers,
|
||||
* so that optimizing compiler could not eliminate any essential portion
|
||||
* of calculations.
|
||||
* That product A*A is calculated twice: in a single thread, and in N
|
||||
* separate threads, where NxN is the size of square matrix A. When executing
|
||||
* in N threads, each thread calculate distinct row of the resulting matrix.
|
||||
* The test checks if the resulting product A*A is the same when calculated
|
||||
* in single thread and in N threads.
|
||||
* By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if single-thread calculation is essentially
|
||||
* slower than N-threads calculation (surely, the number of CPUs installed
|
||||
* on the platform executing the test is taken into account for performance
|
||||
* testing). Note, that HotSpot may fail to adjust itself for better
|
||||
* performance in single-thread calculation.
|
||||
* COMMENTS
|
||||
* The bug was filed referencing to the same numeric algorithm,
|
||||
* which is used by this test:
|
||||
* 4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
*
|
||||
* @run main/othervm nsk.stress.numeric.numeric002.numeric002 300 300
|
||||
*/
|
||||
|
||||
package nsk.stress.numeric.numeric002;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* This test calculates the product <b>A</b><sup>.</sup><b>A</b> for
|
||||
* a square matrix <b>A</b> of the type <code>float[][]</code>.
|
||||
* Elements of the matrix <b>A</b> are initiated with random numbers,
|
||||
* so that optimizing compiler could not eliminate any essential portion
|
||||
* of calculations.
|
||||
* <p>
|
||||
* <p>That product <b>A</b><sup>.</sup><b>A</b> is calculated twice: in
|
||||
* a single thread, and in <i>N</i> separate threads, where <i>N</i>x<i>N</i>
|
||||
* is the size of square matrix <b>A</b>. When executing in <i>N</i> threads,
|
||||
* each thread calculate distinct row of the resulting matrix. The test checks
|
||||
* if the resulting product <b>A</b><sup>.</sup><b>A</b> is the same when
|
||||
* calculated in single thread and in <i>N</i> threads.
|
||||
* <p>
|
||||
* <p>By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if single-thread calculation is essentially
|
||||
* slower than <i>N</i>-threads calculation (surely, the number of CPUs
|
||||
* installed on the platform executing the test is taken into account for
|
||||
* performance testing). Note, that HotSpot may fail to adjust itself for
|
||||
* better performance in single-thread calculation.
|
||||
* <p>
|
||||
* <p>See the bug-report:
|
||||
* <br>
|
||||
* 4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
*/
|
||||
public class numeric002 {
|
||||
/**
|
||||
* When testing performance, single thread calculation is allowed to
|
||||
* be 10% slower than multi-threads calculation (<code>TOLERANCE</code>
|
||||
* is assigned to 10 now).
|
||||
*/
|
||||
public static final double TOLERANCE = 100; // 10;
|
||||
|
||||
/**
|
||||
* Re-assign this value to <code>true</code> for better
|
||||
* diagnostics.
|
||||
*/
|
||||
private static boolean verbose = false;
|
||||
|
||||
private static PrintStream out = null;
|
||||
|
||||
/**
|
||||
* Print error-message to the <code>out<code>.
|
||||
*/
|
||||
private static void complain(Object x) {
|
||||
out.println("# " + x);
|
||||
}
|
||||
|
||||
private static void print(Object x) {
|
||||
if (verbose)
|
||||
out.print(x);
|
||||
}
|
||||
|
||||
private static void println(Object x) {
|
||||
print(x + "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-invoke <code>run(args,out)</code> in order to simulate
|
||||
* JCK-like test interface.
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line parameters stored in <code>args[]</code> and run
|
||||
* the test.
|
||||
* <p>
|
||||
* <p>Command-line parameters are:
|
||||
* <br>
|
||||
* <code>java numeric002 [-verbose] [-performance] [-CPU:<i>number</i>]
|
||||
* <i>matrixSize</i> [<i>threads</i>]</code>
|
||||
* <p>
|
||||
* <p>Here:
|
||||
* <br> <code>-verbose</code> -
|
||||
* keyword, which alows to print execution trace
|
||||
* <br> <code>-performance</code> -
|
||||
* keyword, which alows performance testing
|
||||
* <br> <code><i>number</i></code> -
|
||||
* number of CPU installed on the computer just executing the test
|
||||
* <br> <code><i>matrixSize</i></code> -
|
||||
* number of rows (and columns) in square matrix to be tested
|
||||
* <br> <code><i>threads</i></code> -
|
||||
* for multi-thread calculation
|
||||
* (default: <code><i>matrixSize</i></code>)
|
||||
*
|
||||
* @param args strings array containing command-line parameters
|
||||
* @param out the test log, usually <code>System.out</code>
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
numeric002.out = out;
|
||||
|
||||
boolean testPerformance = false;
|
||||
int numberOfCPU = 1;
|
||||
|
||||
int argsShift = 0;
|
||||
for (; argsShift < args.length; argsShift++) {
|
||||
String argument = args[argsShift];
|
||||
|
||||
if (!argument.startsWith("-"))
|
||||
break;
|
||||
|
||||
if (argument.equals("-performance")) {
|
||||
testPerformance = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.equals("-verbose")) {
|
||||
verbose = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.startsWith("-CPU:")) {
|
||||
String value =
|
||||
argument.substring("-CPU:".length(), argument.length());
|
||||
numberOfCPU = Integer.parseInt(value);
|
||||
|
||||
if (numberOfCPU < 1) {
|
||||
complain("Illegal number of CPU: " + argument);
|
||||
return 2; // failure
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
complain("Cannot recognize argument: args[" + argsShift + "]: " + argument);
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
if ((args.length < argsShift + 1) || (args.length > argsShift + 2)) {
|
||||
complain("Illegal argument(s). Execute:");
|
||||
complain(
|
||||
" java numeric002 [-verbose] [-performance] [-CPU:number] " +
|
||||
"matrixSize [threads]");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int size = Integer.parseInt(args[argsShift]);
|
||||
if ((size < 100) || (size > 10000)) {
|
||||
complain("Matrix size should be 100 to 1000 lines & columns.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int threads = size;
|
||||
if (args.length >= argsShift + 2)
|
||||
threads = Integer.parseInt(args[argsShift + 1]);
|
||||
if ((threads < 1) || (threads > size)) {
|
||||
complain("Threads number should be 1 to matrix size.");
|
||||
return 2; // failure
|
||||
}
|
||||
if ((size % threads) != 0) {
|
||||
complain("Threads number should evenly divide matrix size.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
print("Preparing A[" + size + "," + size + "]:");
|
||||
SquareMatrix A = new SquareMatrix(size);
|
||||
SquareMatrix A1 = new SquareMatrix(size);
|
||||
SquareMatrix Am = new SquareMatrix(size);
|
||||
println(" done.");
|
||||
|
||||
double singleThread = elapsedTime(out, A, A1, size, 1);
|
||||
double multiThreads = elapsedTime(out, A, Am, size, threads);
|
||||
|
||||
if (!A1.isConsistent) {
|
||||
complain("Failed to execute 1-thread calculation.");
|
||||
return 2; // test FAILED
|
||||
}
|
||||
if (!Am.isConsistent) {
|
||||
complain("Failed to execute " + threads + "-threads calculation.");
|
||||
if (testPerformance) {
|
||||
complain("I.e.: VM failed to execute " + threads + " threads,");
|
||||
complain("and this looks like a performance bug.");
|
||||
return 2; // test FAILED
|
||||
} else {
|
||||
complain("This looks strange, but this is not a bug.");
|
||||
complain("The test is thought passed.");
|
||||
return 0; // test PASSED
|
||||
}
|
||||
}
|
||||
|
||||
print("Checking accuracy:");
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
if (A1.value[line][column] != Am.value[line][column]) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("Different results by single- and multi-threads:");
|
||||
complain(" line=" + line + ", column=" + column);
|
||||
complain("A1.value[line][column]=" + A1.value[line][column]);
|
||||
complain("Am.value[line][column]=" + Am.value[line][column]);
|
||||
return 2; // FAILED
|
||||
}
|
||||
println(" done.");
|
||||
|
||||
if (testPerformance) {
|
||||
print("Checking performance: ");
|
||||
double elapsed1 = singleThread;
|
||||
double elapsedM = multiThreads * numberOfCPU;
|
||||
if (elapsed1 > elapsedM * (1 + TOLERANCE / 100)) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("Single-thread calculation is essentially slower:");
|
||||
complain("Calculation time elapsed (seconds):");
|
||||
complain(" single thread: " + singleThread);
|
||||
complain(" multi-threads: " + multiThreads);
|
||||
complain(" number of CPU: " + numberOfCPU);
|
||||
complain(" tolerance: " + TOLERANCE + "%");
|
||||
return 2; // FAILED
|
||||
}
|
||||
println("done.");
|
||||
}
|
||||
|
||||
println("Test passed.");
|
||||
return 0; // PASSED
|
||||
}
|
||||
|
||||
private static double elapsedTime(PrintStream out,
|
||||
SquareMatrix A, SquareMatrix AA, int size, int threads) {
|
||||
|
||||
print("Computing A*A with " + threads + " thread(s):");
|
||||
long mark1 = System.currentTimeMillis();
|
||||
AA.setSquareOf(A, threads);
|
||||
long mark2 = System.currentTimeMillis();
|
||||
println(" done.");
|
||||
|
||||
double sec = (mark2 - mark1) / 1000.0;
|
||||
double perf = size * size * (size + size) / sec;
|
||||
println("Elapsed time: " + sec + " seconds");
|
||||
println("Performance: " + perf / 1e6 + " MFLOPS");
|
||||
|
||||
return sec;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class computes <code>A*A</code> for square matrix <code>A</code>.
|
||||
*/
|
||||
private static class SquareMatrix {
|
||||
volatile float value[][];
|
||||
boolean isConsistent = false;
|
||||
|
||||
/**
|
||||
* New square matrix with random elements.
|
||||
*/
|
||||
public SquareMatrix(int size) {
|
||||
value = new float[size][size];
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
value[line][column] = (float) (Math.random() * size);
|
||||
isConsistent = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update <code>value[][]</code> of <code>this</code> matrix.
|
||||
*
|
||||
* @param threads Split computation into the given number of threads.
|
||||
*/
|
||||
public void setSquareOf(SquareMatrix A, int threads) {
|
||||
if (this.value.length != A.value.length)
|
||||
throw new IllegalArgumentException(
|
||||
"this.value.length != A.value.length");
|
||||
|
||||
int size = value.length;
|
||||
if ((size % threads) != 0)
|
||||
throw new IllegalArgumentException("size%threads != 0");
|
||||
int bunch = size / threads;
|
||||
|
||||
Thread task[] = new Thread[threads];
|
||||
for (int t = 0; t < threads; t++) {
|
||||
int line0 = bunch * t;
|
||||
MatrixComputer computer =
|
||||
new MatrixComputer(value, A.value, line0, bunch);
|
||||
task[t] = computer;
|
||||
}
|
||||
|
||||
for (int t = 0; t < threads; t++)
|
||||
task[t].start();
|
||||
|
||||
isConsistent = true;
|
||||
for (int t = 0; t < threads; t++) {
|
||||
if (task[t].isAlive())
|
||||
try {
|
||||
task[t].join();
|
||||
} catch (InterruptedException exception) {
|
||||
throw new RuntimeException(exception.toString());
|
||||
}
|
||||
if (!((MatrixComputer) (task[t])).threadExecuted) {
|
||||
complain("Thread #" + t + " was not actually executed.");
|
||||
isConsistent = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread to compute a bunch of lines of matrix square.
|
||||
*/
|
||||
private static class MatrixComputer extends Thread {
|
||||
private float result[][];
|
||||
private float source[][];
|
||||
private int line0;
|
||||
private int bunch;
|
||||
|
||||
/**
|
||||
* Register a task for matrix multiplication.
|
||||
*/
|
||||
public MatrixComputer(
|
||||
float result[][], float source[][], int line0, int bunch) {
|
||||
|
||||
this.result = result; // reference to resulting matrix value
|
||||
this.source = source; // reference to matrix to be squared
|
||||
this.line0 = line0; // compute lines from line0 to ...
|
||||
this.bunch = bunch; // number of resulting lines to compute
|
||||
}
|
||||
|
||||
/**
|
||||
* Do execute the task just registered for <code>this</code> thread.
|
||||
*/
|
||||
public void run() {
|
||||
int line1 = line0 + bunch;
|
||||
int size = result.length;
|
||||
for (int line = line0; line < line1; line++)
|
||||
for (int column = 0; column < size; column++) {
|
||||
float sum = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
sum += source[line][i] * source[i][column];
|
||||
result[line][column] = sum;
|
||||
}
|
||||
threadExecuted = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method <code>run()</code> sets this flag on is actually
|
||||
* finishes to execute.
|
||||
*/
|
||||
boolean threadExecuted = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
369
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric003.java
Normal file
369
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric003.java
Normal file
@ -0,0 +1,369 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/numeric/numeric003.
|
||||
* VM testbase keywords: [stress, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test calculates the product A*A for a square matrix A of the type
|
||||
* long[][]. Elements of the matrix A are initiated with random numbers,
|
||||
* so that optimizing compiler could not eliminate any essential portion
|
||||
* of calculations.
|
||||
* That product A*A is calculated twice: in a single thread, and in N
|
||||
* separate threads, where NxN is the size of square matrix A. When executing
|
||||
* in N threads, each thread calculate distinct row of the resulting matrix.
|
||||
* The test checks if the resulting product A*A is the same when calculated
|
||||
* in single thread and in N threads.
|
||||
* By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if single-thread calculation is essentially
|
||||
* slower than N-threads calculation (surely, the number of CPUs installed
|
||||
* on the platform executing the test is taken into account for performance
|
||||
* testing). Note, that HotSpot may fail to adjust itself for better
|
||||
* performance in single-thread calculation.
|
||||
* COMMENTS
|
||||
* The bug was filed referencing to the same numeric algorithm,
|
||||
* which is used by this test:
|
||||
* 4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
*
|
||||
* @run main/othervm nsk.stress.numeric.numeric003.numeric003 300 300
|
||||
*/
|
||||
|
||||
package nsk.stress.numeric.numeric003;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* This test calculates the product <b>A</b><sup>.</sup><b>A</b> for
|
||||
* a square matrix <b>A</b> of the type <code>long[][]</code>.
|
||||
* Elements of the matrix <b>A</b> are initiated with random numbers,
|
||||
* so that optimizing compiler could not eliminate any essential portion
|
||||
* of calculations.
|
||||
* <p>
|
||||
* <p>That product <b>A</b><sup>.</sup><b>A</b> is calculated twice: in
|
||||
* a single thread, and in <i>N</i> separate threads, where <i>N</i>x<i>N</i>
|
||||
* is the size of square matrix <b>A</b>. When executing in <i>N</i> threads,
|
||||
* each thread calculate distinct row of the resulting matrix. The test checks
|
||||
* if the resulting product <b>A</b><sup>.</sup><b>A</b> is the same when
|
||||
* calculated in single thread and in <i>N</i> threads.
|
||||
* <p>
|
||||
* <p>By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if single-thread calculation is essentially
|
||||
* slower than <i>N</i>-threads calculation (surely, the number of CPUs
|
||||
* installed on the platform executing the test is taken into account for
|
||||
* performance testing). Note, that HotSpot may fail to adjust itself for
|
||||
* better performance in single-thread calculation.
|
||||
* <p>
|
||||
* <p>See the bug-report:
|
||||
* <br>
|
||||
* 4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
*/
|
||||
public class numeric003 {
|
||||
/**
|
||||
* When testing performance, single thread calculation is allowed to
|
||||
* be 10% slower than multi-threads calculation (<code>TOLERANCE</code>
|
||||
* is assigned to 10 now).
|
||||
*/
|
||||
public static final double TOLERANCE = 100; // 10;
|
||||
|
||||
/**
|
||||
* Re-assign this value to <code>true</code> for better
|
||||
* diagnostics.
|
||||
*/
|
||||
private static boolean verbose = false;
|
||||
|
||||
private static PrintStream out = null;
|
||||
|
||||
/**
|
||||
* Print error-message to the <code>out<code>.
|
||||
*/
|
||||
private static void complain(Object x) {
|
||||
out.println("# " + x);
|
||||
}
|
||||
|
||||
private static void print(Object x) {
|
||||
if (verbose)
|
||||
out.print(x);
|
||||
}
|
||||
|
||||
private static void println(Object x) {
|
||||
print(x + "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-invoke <code>run(args,out)</code> in order to simulate
|
||||
* JCK-like test interface.
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line parameters stored in <code>args[]</code> and run
|
||||
* the test.
|
||||
* <p>
|
||||
* <p>Command-line parameters are:
|
||||
* <br>
|
||||
* <code>java numeric003 [-verbose] [-performance] [-CPU:<i>number</i>]
|
||||
* <i>matrixSize</i> [<i>threads</i>]</code>
|
||||
* <p>
|
||||
* <p>Here:
|
||||
* <br> <code>-verbose</code> -
|
||||
* keyword, which alows to print execution trace
|
||||
* <br> <code>-performance</code> -
|
||||
* keyword, which alows performance testing
|
||||
* <br> <code><i>number</i></code> -
|
||||
* number of CPU installed on the computer just executing the test
|
||||
* <br> <code><i>matrixSize</i></code> -
|
||||
* number of rows (and columns) in square matrix to be tested
|
||||
* <br> <code><i>threads</i></code> -
|
||||
* for multi-thread calculation
|
||||
* (default: <code><i>matrixSize</i></code>)
|
||||
*
|
||||
* @param args strings array containing command-line parameters
|
||||
* @param out the test log, usually <code>System.out</code>
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
numeric003.out = out;
|
||||
|
||||
boolean testPerformance = false;
|
||||
int numberOfCPU = 1;
|
||||
|
||||
int argsShift = 0;
|
||||
for (; argsShift < args.length; argsShift++) {
|
||||
String argument = args[argsShift];
|
||||
|
||||
if (!argument.startsWith("-"))
|
||||
break;
|
||||
|
||||
if (argument.equals("-performance")) {
|
||||
testPerformance = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.equals("-verbose")) {
|
||||
verbose = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.startsWith("-CPU:")) {
|
||||
String value =
|
||||
argument.substring("-CPU:".length(), argument.length());
|
||||
numberOfCPU = Integer.parseInt(value);
|
||||
|
||||
if (numberOfCPU < 1) {
|
||||
complain("Illegal number of CPU: " + argument);
|
||||
return 2; // failure
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
complain("Cannot recognize argument: args[" + argsShift + "]: " + argument);
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
if ((args.length < argsShift + 1) || (args.length > argsShift + 2)) {
|
||||
complain("Illegal argument(s). Execute:");
|
||||
complain(
|
||||
" java numeric003 [-verbose] [-performance] [-CPU:number] " +
|
||||
"matrixSize [threads]");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int size = Integer.parseInt(args[argsShift]);
|
||||
if ((size < 100) || (size > 10000)) {
|
||||
complain("Matrix size should be 100 to 1000 lines & columns.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int threads = size;
|
||||
if (args.length >= argsShift + 2)
|
||||
threads = Integer.parseInt(args[argsShift + 1]);
|
||||
if ((threads < 1) || (threads > size)) {
|
||||
complain("Threads number should be 1 to matrix size.");
|
||||
return 2; // failure
|
||||
}
|
||||
if ((size % threads) != 0) {
|
||||
complain("Threads number should evenly divide matrix size.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
print("Preparing A[" + size + "," + size + "]:");
|
||||
SquareMatrix A = new SquareMatrix(size);
|
||||
SquareMatrix A1 = new SquareMatrix(size);
|
||||
SquareMatrix Am = new SquareMatrix(size);
|
||||
println(" done.");
|
||||
|
||||
double singleThread = elapsedTime(out, A, A1, size, 1);
|
||||
double multiThreads = elapsedTime(out, A, Am, size, threads);
|
||||
|
||||
print("Checking accuracy:");
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
if (A1.value[line][column] != Am.value[line][column]) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("Different results by single- and multi-threads:");
|
||||
complain(" line=" + line + ", column=" + column);
|
||||
complain("A1.value[line][column]=" + A1.value[line][column]);
|
||||
complain("Am.value[line][column]=" + Am.value[line][column]);
|
||||
return 2; // FAILED
|
||||
}
|
||||
println(" done.");
|
||||
|
||||
if (testPerformance) {
|
||||
print("Checking performance: ");
|
||||
double elapsed1 = singleThread;
|
||||
double elapsedM = multiThreads * numberOfCPU;
|
||||
if (elapsed1 > elapsedM * (1 + TOLERANCE / 100)) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("Single-thread calculation is essentially slower:");
|
||||
complain("Calculation time elapsed (seconds):");
|
||||
complain(" single thread: " + singleThread);
|
||||
complain(" multi-threads: " + multiThreads);
|
||||
complain(" number of CPU: " + numberOfCPU);
|
||||
complain(" tolerance: " + TOLERANCE + "%");
|
||||
return 2; // FAILED
|
||||
}
|
||||
println("done.");
|
||||
}
|
||||
|
||||
println("Test passed.");
|
||||
return 0; // PASSED
|
||||
}
|
||||
|
||||
private static double elapsedTime(PrintStream out,
|
||||
SquareMatrix A, SquareMatrix AA, int size, int threads) {
|
||||
|
||||
print("Computing A*A with " + threads + " thread(s):");
|
||||
long mark1 = System.currentTimeMillis();
|
||||
AA.setSquareOf(A, threads);
|
||||
long mark2 = System.currentTimeMillis();
|
||||
println(" done.");
|
||||
|
||||
double sec = (mark2 - mark1) / 1000.0;
|
||||
double perf = size * size * (size + size) / sec;
|
||||
println("Elapsed time: " + sec + " seconds");
|
||||
println("Performance: " + perf / 1e6 + " MFLOPS");
|
||||
|
||||
return sec;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class computes <code>A*A</code> for square matrix <code>A</code>.
|
||||
*/
|
||||
private static class SquareMatrix {
|
||||
volatile long value[][];
|
||||
|
||||
/**
|
||||
* New square matrix with random elements.
|
||||
*/
|
||||
public SquareMatrix(int size) {
|
||||
value = new long[size][size];
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
value[line][column] = Math.round(Math.random() * size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update <code>value[][]</code> of <code>this</code> matrix.
|
||||
*
|
||||
* @param threads Split computation into the given number of threads.
|
||||
*/
|
||||
public void setSquareOf(SquareMatrix A, int threads) {
|
||||
if (this.value.length != A.value.length)
|
||||
throw new IllegalArgumentException(
|
||||
"this.value.length != A.value.length");
|
||||
|
||||
int size = value.length;
|
||||
if ((size % threads) != 0)
|
||||
throw new IllegalArgumentException("size%threads != 0");
|
||||
int bunch = size / threads;
|
||||
|
||||
Thread task[] = new Thread[threads];
|
||||
for (int t = 0; t < threads; t++) {
|
||||
int line0 = bunch * t;
|
||||
MatrixComputer computer =
|
||||
new MatrixComputer(value, A.value, line0, bunch);
|
||||
task[t] = new Thread(computer);
|
||||
}
|
||||
|
||||
for (int t = 0; t < threads; t++)
|
||||
task[t].start();
|
||||
|
||||
for (int t = 0; t < threads; t++)
|
||||
if (task[t].isAlive())
|
||||
try {
|
||||
task[t].join();
|
||||
} catch (InterruptedException exception) {
|
||||
throw new RuntimeException(exception.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread to compute a bunch of lines of matrix square.
|
||||
*/
|
||||
private static class MatrixComputer implements Runnable {
|
||||
private long result[][];
|
||||
private long source[][];
|
||||
private int line0;
|
||||
private int bunch;
|
||||
|
||||
/**
|
||||
* Register a task for matrix multiplication.
|
||||
*/
|
||||
public MatrixComputer(
|
||||
long result[][], long source[][], int line0, int bunch) {
|
||||
|
||||
this.result = result; // reference to resulting matrix value
|
||||
this.source = source; // reference to matrix to be squared
|
||||
this.line0 = line0; // compute lines from line0 to ...
|
||||
this.bunch = bunch; // number of resulting lines to compute
|
||||
}
|
||||
|
||||
/**
|
||||
* Do execute the task just registered for <code>this</code> thread.
|
||||
*/
|
||||
public void run() {
|
||||
int line1 = line0 + bunch;
|
||||
int size = result.length;
|
||||
for (int line = line0; line < line1; line++)
|
||||
for (int column = 0; column < size; column++) {
|
||||
long sum = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
sum += source[line][i] * source[i][column];
|
||||
result[line][column] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
369
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric004.java
Normal file
369
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric004.java
Normal file
@ -0,0 +1,369 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/numeric/numeric004.
|
||||
* VM testbase keywords: [stress, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test calculates the product A*A for a square matrix A of the type
|
||||
* int[][]. Elements of the matrix A are initiated with random numbers,
|
||||
* so that optimizing compiler could not eliminate any essential portion
|
||||
* of calculations.
|
||||
* That product A*A is calculated twice: in a single thread, and in N
|
||||
* separate threads, where NxN is the size of square matrix A. When executing
|
||||
* in N threads, each thread calculate distinct row of the resulting matrix.
|
||||
* The test checks if the resulting product A*A is the same when calculated
|
||||
* in single thread and in N threads.
|
||||
* By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if single-thread calculation is essentially
|
||||
* slower than N-threads calculation (surely, the number of CPUs installed
|
||||
* on the platform executing the test is taken into account for performance
|
||||
* testing). Note, that HotSpot may fail to adjust itself for better
|
||||
* performance in single-thread calculation.
|
||||
* COMMENTS
|
||||
* The bug was filed referencing to the same numeric algorithm,
|
||||
* which is used by this test:
|
||||
* 4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
*
|
||||
* @run main/othervm nsk.stress.numeric.numeric004.numeric004 300 300
|
||||
*/
|
||||
|
||||
package nsk.stress.numeric.numeric004;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* This test calculates the product <b>A</b><sup>.</sup><b>A</b> for
|
||||
* a square matrix <b>A</b> of the type <code>int[][]</code>.
|
||||
* Elements of the matrix <b>A</b> are initiated with random numbers,
|
||||
* so that optimizing compiler could not eliminate any essential portion
|
||||
* of calculations.
|
||||
* <p>
|
||||
* <p>That product <b>A</b><sup>.</sup><b>A</b> is calculated twice: in
|
||||
* a single thread, and in <i>N</i> separate threads, where <i>N</i>x<i>N</i>
|
||||
* is the size of square matrix <b>A</b>. When executing in <i>N</i> threads,
|
||||
* each thread calculate distinct row of the resulting matrix. The test checks
|
||||
* if the resulting product <b>A</b><sup>.</sup><b>A</b> is the same when
|
||||
* calculated in single thread and in <i>N</i> threads.
|
||||
* <p>
|
||||
* <p>By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if single-thread calculation is essentially
|
||||
* slower than <i>N</i>-threads calculation (surely, the number of CPUs
|
||||
* installed on the platform executing the test is taken into account for
|
||||
* performance testing). Note, that HotSpot may fail to adjust itself for
|
||||
* better performance in single-thread calculation.
|
||||
* <p>
|
||||
* <p>See the bug-report:
|
||||
* <br>
|
||||
* 4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
*/
|
||||
public class numeric004 {
|
||||
/**
|
||||
* When testing performance, single thread calculation is allowed to
|
||||
* be 10% slower than multi-threads calculation (<code>TOLERANCE</code>
|
||||
* is assigned to 10 now).
|
||||
*/
|
||||
public static final double TOLERANCE = 100; // 10;
|
||||
|
||||
/**
|
||||
* Re-assign this value to <code>true</code> for better
|
||||
* diagnostics.
|
||||
*/
|
||||
private static boolean verbose = false;
|
||||
|
||||
private static PrintStream out = null;
|
||||
|
||||
/**
|
||||
* Print error-message to the <code>out<code>.
|
||||
*/
|
||||
private static void complain(Object x) {
|
||||
out.println("# " + x);
|
||||
}
|
||||
|
||||
private static void print(Object x) {
|
||||
if (verbose)
|
||||
out.print(x);
|
||||
}
|
||||
|
||||
private static void println(Object x) {
|
||||
print(x + "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-invoke <code>run(args,out)</code> in order to simulate
|
||||
* JCK-like test interface.
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line parameters stored in <code>args[]</code> and run
|
||||
* the test.
|
||||
* <p>
|
||||
* <p>Command-line parameters are:
|
||||
* <br>
|
||||
* <code>java numeric004 [-verbose] [-performance] [-CPU:<i>number</i>]
|
||||
* <i>matrixSize</i> [<i>threads</i>]</code>
|
||||
* <p>
|
||||
* <p>Here:
|
||||
* <br> <code>-verbose</code> -
|
||||
* keyword, which alows to print execution trace
|
||||
* <br> <code>-performance</code> -
|
||||
* keyword, which alows performance testing
|
||||
* <br> <code><i>number</i></code> -
|
||||
* number of CPU installed on the computer just executing the test
|
||||
* <br> <code><i>matrixSize</i></code> -
|
||||
* number of rows (and columns) in square matrix to be tested
|
||||
* <br> <code><i>threads</i></code> -
|
||||
* for multi-thread calculation
|
||||
* (default: <code><i>matrixSize</i></code>)
|
||||
*
|
||||
* @param args strings array containing command-line parameters
|
||||
* @param out the test log, usually <code>System.out</code>
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
numeric004.out = out;
|
||||
|
||||
boolean testPerformance = false;
|
||||
int numberOfCPU = 1;
|
||||
|
||||
int argsShift = 0;
|
||||
for (; argsShift < args.length; argsShift++) {
|
||||
String argument = args[argsShift];
|
||||
|
||||
if (!argument.startsWith("-"))
|
||||
break;
|
||||
|
||||
if (argument.equals("-performance")) {
|
||||
testPerformance = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.equals("-verbose")) {
|
||||
verbose = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.startsWith("-CPU:")) {
|
||||
String value =
|
||||
argument.substring("-CPU:".length(), argument.length());
|
||||
numberOfCPU = Integer.parseInt(value);
|
||||
|
||||
if (numberOfCPU < 1) {
|
||||
complain("Illegal number of CPU: " + argument);
|
||||
return 2; // failure
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
complain("Cannot recognize argument: args[" + argsShift + "]: " + argument);
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
if ((args.length < argsShift + 1) || (args.length > argsShift + 2)) {
|
||||
complain("Illegal argument(s). Execute:");
|
||||
complain(
|
||||
" java numeric004 [-verbose] [-performance] [-CPU:number] " +
|
||||
"matrixSize [threads]");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int size = Integer.parseInt(args[argsShift]);
|
||||
if ((size < 100) || (size > 10000)) {
|
||||
complain("Matrix size should be 100 to 1000 lines & columns.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int threads = size;
|
||||
if (args.length >= argsShift + 2)
|
||||
threads = Integer.parseInt(args[argsShift + 1]);
|
||||
if ((threads < 1) || (threads > size)) {
|
||||
complain("Threads number should be 1 to matrix size.");
|
||||
return 2; // failure
|
||||
}
|
||||
if ((size % threads) != 0) {
|
||||
complain("Threads number should evenly divide matrix size.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
print("Preparing A[" + size + "," + size + "]:");
|
||||
SquareMatrix A = new SquareMatrix(size);
|
||||
SquareMatrix A1 = new SquareMatrix(size);
|
||||
SquareMatrix Am = new SquareMatrix(size);
|
||||
println(" done.");
|
||||
|
||||
double singleThread = elapsedTime(out, A, A1, size, 1);
|
||||
double multiThreads = elapsedTime(out, A, Am, size, threads);
|
||||
|
||||
print("Checking accuracy:");
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
if (A1.value[line][column] != Am.value[line][column]) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("Different results by single- and multi-threads:");
|
||||
complain(" line=" + line + ", column=" + column);
|
||||
complain("A1.value[line][column]=" + A1.value[line][column]);
|
||||
complain("Am.value[line][column]=" + Am.value[line][column]);
|
||||
return 2; // FAILED
|
||||
}
|
||||
println(" done.");
|
||||
|
||||
if (testPerformance) {
|
||||
print("Checking performance: ");
|
||||
double elapsed1 = singleThread;
|
||||
double elapsedM = multiThreads * numberOfCPU;
|
||||
if (elapsed1 > elapsedM * (1 + TOLERANCE / 100)) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("Single-thread calculation is essentially slower:");
|
||||
complain("Calculation time elapsed (seconds):");
|
||||
complain(" single thread: " + singleThread);
|
||||
complain(" multi-threads: " + multiThreads);
|
||||
complain(" number of CPU: " + numberOfCPU);
|
||||
complain(" tolerance: " + TOLERANCE + "%");
|
||||
return 2; // FAILED
|
||||
}
|
||||
println("done.");
|
||||
}
|
||||
|
||||
println("Test passed.");
|
||||
return 0; // PASSED
|
||||
}
|
||||
|
||||
private static double elapsedTime(PrintStream out,
|
||||
SquareMatrix A, SquareMatrix AA, int size, int threads) {
|
||||
|
||||
print("Computing A*A with " + threads + " thread(s):");
|
||||
long mark1 = System.currentTimeMillis();
|
||||
AA.setSquareOf(A, threads);
|
||||
long mark2 = System.currentTimeMillis();
|
||||
println(" done.");
|
||||
|
||||
double sec = (mark2 - mark1) / 1000.0;
|
||||
double perf = size * size * (size + size) / sec;
|
||||
println("Elapsed time: " + sec + " seconds");
|
||||
println("Performance: " + perf / 1e6 + " MFLOPS");
|
||||
|
||||
return sec;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class computes <code>A*A</code> for square matrix <code>A</code>.
|
||||
*/
|
||||
private static class SquareMatrix {
|
||||
volatile int value[][];
|
||||
|
||||
/**
|
||||
* New square matrix with random elements.
|
||||
*/
|
||||
public SquareMatrix(int size) {
|
||||
value = new int[size][size];
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
value[line][column] = Math.round((float) (Math.random() * size));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update <code>value[][]</code> of <code>this</code> matrix.
|
||||
*
|
||||
* @param threads Split computation into the given number of threads.
|
||||
*/
|
||||
public void setSquareOf(SquareMatrix A, int threads) {
|
||||
if (this.value.length != A.value.length)
|
||||
throw new IllegalArgumentException(
|
||||
"this.value.length != A.value.length");
|
||||
|
||||
int size = value.length;
|
||||
if ((size % threads) != 0)
|
||||
throw new IllegalArgumentException("size%threads != 0");
|
||||
int bunch = size / threads;
|
||||
|
||||
Thread task[] = new Thread[threads];
|
||||
for (int t = 0; t < threads; t++) {
|
||||
int line0 = bunch * t;
|
||||
MatrixComputer computer =
|
||||
new MatrixComputer(value, A.value, line0, bunch);
|
||||
task[t] = new Thread(computer);
|
||||
}
|
||||
|
||||
for (int t = 0; t < threads; t++)
|
||||
task[t].start();
|
||||
|
||||
for (int t = 0; t < threads; t++)
|
||||
if (task[t].isAlive())
|
||||
try {
|
||||
task[t].join();
|
||||
} catch (InterruptedException exception) {
|
||||
throw new RuntimeException(exception.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread to compute a bunch of lines of matrix square.
|
||||
*/
|
||||
private static class MatrixComputer implements Runnable {
|
||||
private int result[][];
|
||||
private int source[][];
|
||||
private int line0;
|
||||
private int bunch;
|
||||
|
||||
/**
|
||||
* Register a task for matrix multiplication.
|
||||
*/
|
||||
public MatrixComputer(
|
||||
int result[][], int source[][], int line0, int bunch) {
|
||||
|
||||
this.result = result; // reference to resulting matrix value
|
||||
this.source = source; // reference to matrix to be squared
|
||||
this.line0 = line0; // compute lines from line0 to ...
|
||||
this.bunch = bunch; // number of resulting lines to compute
|
||||
}
|
||||
|
||||
/**
|
||||
* Do execute the task just registered for <code>this</code> thread.
|
||||
*/
|
||||
public void run() {
|
||||
int line1 = line0 + bunch;
|
||||
int size = result.length;
|
||||
for (int line = line0; line < line1; line++)
|
||||
for (int column = 0; column < size; column++) {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
sum += source[line][i] * source[i][column];
|
||||
result[line][column] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
382
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric005.java
Normal file
382
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric005.java
Normal file
@ -0,0 +1,382 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/numeric/numeric005.
|
||||
* VM testbase keywords: [stress, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test calculates the product A*A for a square matrix A of the type
|
||||
* double[][]. Elements of the matrix A are initiated with random numbers,
|
||||
* so that optimizing compiler could not eliminate any essential portion
|
||||
* of calculations.
|
||||
* Calculation of the product A*A is iterated three times, and result of
|
||||
* the 1st iteration is compared to result of the 3rd iteration. HotSpot
|
||||
* releases 1.0 and 1.3 seem to fail to adjust itself for better performance
|
||||
* in 1st iteration, while 3rd iteration usually runs much faster. So, the
|
||||
* 1st iteration is probably executed by HotSpot interpreter, and HotSpot
|
||||
* compiler is probably involved to execute the 3rd iteration. The test
|
||||
* just tries to check if HotSpot compiler produces the same results as the
|
||||
* HotSpot interpreter.
|
||||
* By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if 1st iteration is essentially slower than the
|
||||
* 3rd iteration. The calculations algorithm is encoded as compact 3-levels
|
||||
* cycle like:
|
||||
* for (int line=0; line<N; line++)
|
||||
* for (int column=0; column<N; column++) {
|
||||
* double sum = 0;
|
||||
* for (int k=0; k<N; k++)
|
||||
* sum += A[line][k] * A[k][column];
|
||||
* AA[line][column] = sum;
|
||||
* }
|
||||
* In this test, N=300, so that A is 300x300 matrix; and multiplication
|
||||
* A[line][k]*A[k][column] is executed 300**3=27 millions times in each
|
||||
* execution of this cycle. I believe, that this is HotSpot bug to do not
|
||||
* adjust itself for best performance during such a huge series of executions
|
||||
* of the same portion of program code.
|
||||
* COMMENTS
|
||||
* See the bug-report:
|
||||
* #4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
*
|
||||
* @run main/othervm nsk.stress.numeric.numeric005.numeric005 300 3
|
||||
*/
|
||||
|
||||
package nsk.stress.numeric.numeric005;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* This test calculates the product <code>A<sup>.</sup>A</code> for
|
||||
* a square matrix <code>A</code> of the type <code>double[][]</code>.
|
||||
* Elements of the matrix <code>A</code> are initiated with random numbers,
|
||||
* so that optimizing compiler could not eliminate any essential portion
|
||||
* of calculations.
|
||||
* <p>
|
||||
* <p>Calculation of the product <code>A<sup>.</sup>A</code> is iterated three
|
||||
* times, and result of the 1<sup>st</sup> iteration is compared to result of
|
||||
* the 3<sup>rd</sup> iteration. HotSpot 1.0 and 1.3 seem to fail to adjust
|
||||
* itself for better performance in 1<sup>st</sup> iteration, while 3<sup>rd</sup>
|
||||
* iteration usually runs much faster. So, 1<sup>st</sup> iteration is probably
|
||||
* executed by HotSpot interpreter, and HotSpot compiler is probably involved to
|
||||
* execute the 3<sup>rd</sup> iteration. The test just tries to check if HotSpot
|
||||
* compiler produces the same results as the HotSpot interpreter.
|
||||
* <p>
|
||||
* <p>By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if 1<sup>st</sup> iteration is essentially slower
|
||||
* than the 3<sup>rd</sup> iteration. The calculations algorithm is encoded
|
||||
* as compact ``canonical'' 3-levels cycle like:
|
||||
* <pre>
|
||||
* for (int line=0; line<N; line++)
|
||||
* for (int column=0; column<N; column++) {
|
||||
* double sum = 0;
|
||||
* for (int k=0; k<N; k++)
|
||||
* sum += A[line][k] * A[k][column];
|
||||
* AA[line][column] = sum;
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* In this test, <code>N</code>=300, so that <code>A</code> is 300x300 matrix;
|
||||
* and multiplication <code>A[line][k]*A[k][column]</code> is executed
|
||||
* 300<sup>3</sup>=27 millions times in each iteration of execution of this
|
||||
* cycle. I believe, that this is HotSpot bug to do not adjust itself for best
|
||||
* performance during such a huge series of executions of the same portion of
|
||||
* program code.
|
||||
* <p>
|
||||
* <p>See the bug-report:
|
||||
* <br>
|
||||
* #4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
*/
|
||||
public class numeric005 {
|
||||
/**
|
||||
* When testing performance, single thread calculation is allowed to
|
||||
* be 10% slower than multi-threads calculation (<code>TOLERANCE</code>
|
||||
* is assigned to 10 now).
|
||||
*/
|
||||
public static final double TOLERANCE = 100; // 10;
|
||||
|
||||
/**
|
||||
* Re-assign this value to <code>true</code> for better
|
||||
* diagnostics.
|
||||
*
|
||||
* @see #print(Object)
|
||||
* @see #println(Object)
|
||||
*/
|
||||
private static boolean verbose = false;
|
||||
|
||||
/**
|
||||
* Stream to print execution trace and/or error messages.
|
||||
* This stream usually equals to <code>System.out</code>
|
||||
*/
|
||||
private static PrintStream out = null;
|
||||
|
||||
/**
|
||||
* Print error-message.
|
||||
*
|
||||
* @see #out
|
||||
*/
|
||||
private static void complain(Object x) {
|
||||
out.println("# " + x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print to execution trace, if mode is <code>verbose</code>.
|
||||
*
|
||||
* @see #verbose
|
||||
* @see #out
|
||||
*/
|
||||
private static void print(Object x) {
|
||||
if (verbose)
|
||||
out.print(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print line to execution trace, if mode is <code>verbose</code>.
|
||||
*
|
||||
* @see #verbose
|
||||
* @see #out
|
||||
*/
|
||||
private static void println(Object x) {
|
||||
print(x + "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-invoke <code>run(args,out)</code> in order to simulate
|
||||
* JCK-like test interface.
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line parameters stored in <code>args[]</code> and run
|
||||
* the test.
|
||||
* <p>
|
||||
* <p>Command-line parameters are:
|
||||
* <br>
|
||||
* <code>java numeric005 [-verbose] [-performance] <i>matrixSize</i>
|
||||
* <i>iterations</i></code>
|
||||
* <p>
|
||||
* <p>Here:
|
||||
* <br> <code>-verbose</code> -
|
||||
* keyword, which alows to print execution trace
|
||||
* <br> <code>-performance</code> -
|
||||
* keyword, which alows performance testing
|
||||
* <br> <code><i>matrixSize</i></code> -
|
||||
* number of rows (and columns) in square matrix <code>A</code>
|
||||
* <br> <code><i>iterations</i></code> -
|
||||
* compute <code>A*A</code> several times
|
||||
*
|
||||
* @param args strings array containing command-line parameters
|
||||
* @param out the test log, usually <code>System.out</code>
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
numeric005.out = out;
|
||||
|
||||
boolean testPerformance = false;
|
||||
int numberOfCPU = 1;
|
||||
|
||||
// Parse parameters starting with "-" (like: "-verbose"):
|
||||
|
||||
int argsShift = 0;
|
||||
for (; argsShift < args.length; argsShift++) {
|
||||
String argument = args[argsShift];
|
||||
|
||||
if (!argument.startsWith("-"))
|
||||
break;
|
||||
|
||||
if (argument.equals("-performance")) {
|
||||
testPerformance = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.equals("-verbose")) {
|
||||
verbose = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
complain("Cannot recognize argument: args[" + argsShift + "]: " + argument);
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
if (args.length != argsShift + 2) {
|
||||
complain("Illegal arguments. Execute:");
|
||||
complain(
|
||||
" java numeric005 [-verbose] [-performance] [-CPU:number] " +
|
||||
"matrixSize iterations");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int size = Integer.parseInt(args[argsShift]);
|
||||
if ((size < 100) || (size > 10000)) {
|
||||
complain("Matrix size should be 100 to 1000 lines & columns.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int iterations = Integer.parseInt(args[argsShift + 1]);
|
||||
if ((iterations < 1) || (iterations > 100)) {
|
||||
complain("Iterations number should be 1 to 100.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
print("Preparing A[" + size + "," + size + "]:");
|
||||
double[][] A = newMatrix(size);
|
||||
double[][] A1 = new double[size][size];
|
||||
double[][] Ai = new double[size][size];
|
||||
println(" done.");
|
||||
|
||||
println("Should try " + iterations + " iteration(s):");
|
||||
println("==========================" +
|
||||
((iterations > 99) ? "==" : (iterations > 9) ? "=" : ""));
|
||||
println("");
|
||||
|
||||
double overallTime = 0;
|
||||
double firstTime = 0;
|
||||
double lastTime = 0;
|
||||
|
||||
for (int i = 1; i <= iterations; i++) {
|
||||
double seconds;
|
||||
|
||||
if (i == 1) {
|
||||
seconds = elapsedTime(i, A, A1);
|
||||
firstTime = seconds;
|
||||
} else {
|
||||
seconds = elapsedTime(i, A, Ai);
|
||||
lastTime = seconds;
|
||||
}
|
||||
|
||||
overallTime += seconds;
|
||||
}
|
||||
|
||||
double averageTime = overallTime / iterations;
|
||||
double averagePerformance = size * size * (size + size) / averageTime / 1e6;
|
||||
|
||||
println("");
|
||||
println("=======================" +
|
||||
((iterations > 99) ? "==" : (iterations > 9) ? "=" : ""));
|
||||
println("Overall iteration(s): " + iterations);
|
||||
println("Overall elapsed time: " + overallTime + " seconds.");
|
||||
println("Average elapsed time: " + averageTime + " seconds.");
|
||||
println("Average performance: " + averagePerformance + " MFLOPS");
|
||||
|
||||
println("========================");
|
||||
print("Checking accuracy:");
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
if (A1[line][column] != Ai[line][column]) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("Different results in 1st and last iterations:");
|
||||
complain(" line=" + line + ", column=" + column);
|
||||
return 2; // FAILED
|
||||
}
|
||||
println(" done.");
|
||||
|
||||
if (testPerformance) {
|
||||
print("Checking performance: ");
|
||||
if (firstTime > lastTime * (1 + TOLERANCE / 100)) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("1st iterartion is essentially slower:");
|
||||
complain("Calculation time elapsed (seconds):");
|
||||
complain(" 1-st iteration: " + firstTime);
|
||||
complain(" last iteration: " + lastTime);
|
||||
complain(" tolerance: " + TOLERANCE + "%");
|
||||
return 2; // FAILED
|
||||
}
|
||||
println("done.");
|
||||
}
|
||||
|
||||
println("Test passed.");
|
||||
return 0; // PASSED
|
||||
}
|
||||
|
||||
private static double elapsedTime(int i, double[][] A, double[][] AA) {
|
||||
int size = A.length;
|
||||
|
||||
if (i > 1)
|
||||
println("");
|
||||
println("Iteration #" + i + ":");
|
||||
|
||||
print("Computing A*A:");
|
||||
long mark1 = System.currentTimeMillis();
|
||||
setSquare(A, AA);
|
||||
long mark2 = System.currentTimeMillis();
|
||||
println(" done.");
|
||||
|
||||
double sec = (mark2 - mark1) / 1000.0;
|
||||
double perf = size * size * (size + size) / sec;
|
||||
println("Elapsed time: " + sec + " seconds");
|
||||
println("Performance: " + perf / 1e6 + " MFLOPS");
|
||||
|
||||
return sec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute <code>A*A</code> for the given square matrix <code>A</code>.
|
||||
*/
|
||||
private static void setSquare(double[][] A, double[][] AA) {
|
||||
if (A.length != A[0].length)
|
||||
throw new IllegalArgumentException(
|
||||
"the argument matrix A should be square matrix");
|
||||
if (AA.length != AA[0].length)
|
||||
throw new IllegalArgumentException(
|
||||
"the resulting matrix AA should be square matrix");
|
||||
if (A.length != AA.length)
|
||||
throw new IllegalArgumentException(
|
||||
"the matrices A and AA should have equal size");
|
||||
|
||||
int size = A.length;
|
||||
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++) {
|
||||
double sum = 0;
|
||||
for (int k = 0; k < size; k++)
|
||||
sum += A[line][k] * A[k][line];
|
||||
AA[line][column] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate new square matrix of the given <code>size</code>
|
||||
* and with elements initiated with random numbers.
|
||||
*/
|
||||
private static double[][] newMatrix(int size) {
|
||||
if ((size < 1) || (size > 1000))
|
||||
throw new IllegalArgumentException(
|
||||
"matrix size should be 1 to 1000");
|
||||
|
||||
double[][] A = new double[size][size];
|
||||
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
A[line][column] = (1 - 2 * Math.random()) * size;
|
||||
|
||||
return A;
|
||||
}
|
||||
|
||||
}
|
||||
381
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric006.java
Normal file
381
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric006.java
Normal file
@ -0,0 +1,381 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/numeric/numeric006.
|
||||
* VM testbase keywords: [stress, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test calculates the product A*A for a square matrix A of the type
|
||||
* float[][]. Elements of the matrix A are initiated with random numbers,
|
||||
* so that optimizing compiler could not eliminate any essential portion
|
||||
* of calculations.
|
||||
* Calculation of the product A*A is iterated three times, and result of
|
||||
* the 1st iteration is compared to result of the 3rd iteration. HotSpot
|
||||
* releases 1.0 and 1.3 seem to fail to adjust itself for better performance
|
||||
* in 1st iteration, while 3rd iteration usually runs much faster. So, the
|
||||
* 1st iteration is probably executed by HotSpot interpreter, and HotSpot
|
||||
* compiler is probably involved to execute the 3rd iteration. The test
|
||||
* just tries to check if HotSpot compiler produces the same results as the
|
||||
* HotSpot interpreter.
|
||||
* By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if 1st iteration is essentially slower than the
|
||||
* 3rd iteration. The calculations algorithm is encoded as compact 3-levels
|
||||
* cycle like:
|
||||
* for (int line=0; line<N; line++)
|
||||
* for (int column=0; column<N; column++) {
|
||||
* float sum = 0;
|
||||
* for (int k=0; k<N; k++)
|
||||
* sum += A[line][k] * A[k][column];
|
||||
* AA[line][column] = sum;
|
||||
* }
|
||||
* In this test, N=300, so that A is 300x300 matrix; and multiplication
|
||||
* A[line][k]*A[k][column] is executed 300**3=27 millions times in each
|
||||
* execution of this cycle. I believe, that this is HotSpot bug to do not
|
||||
* adjust itself for best performance during such a huge series of executions
|
||||
* of the same portion of program code.
|
||||
* COMMENTS
|
||||
* See the bug-report:
|
||||
* #4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
* @run main/othervm nsk.stress.numeric.numeric006.numeric006 300 3
|
||||
*/
|
||||
|
||||
package nsk.stress.numeric.numeric006;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* This test calculates the product <code>A<sup>.</sup>A</code> for
|
||||
* a square matrix <code>A</code> of the type <code>float[][]</code>.
|
||||
* Elements of the matrix <code>A</code> are initiated with random numbers,
|
||||
* so that optimizing compiler could not eliminate any essential portion
|
||||
* of calculations.
|
||||
* <p>
|
||||
* <p>Calculation of the product <code>A<sup>.</sup>A</code> is iterated three
|
||||
* times, and result of the 1<sup>st</sup> iteration is compared to result of
|
||||
* the 3<sup>rd</sup> iteration. HotSpot 1.0 and 1.3 seem to fail to adjust
|
||||
* itself for better performance in 1<sup>st</sup> iteration, while 3<sup>rd</sup>
|
||||
* iteration usually runs much faster. So, 1<sup>st</sup> iteration is probably
|
||||
* executed by HotSpot interpreter, and HotSpot compiler is probably involved to
|
||||
* execute the 3<sup>rd</sup> iteration. The test just tries to check if HotSpot
|
||||
* compiler produces the same results as the HotSpot interpreter.
|
||||
* <p>
|
||||
* <p>By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if 1<sup>st</sup> iteration is essentially slower
|
||||
* than the 3<sup>rd</sup> iteration. The calculations algorithm is encoded
|
||||
* as compact ``canonical'' 3-levels cycle like:
|
||||
* <pre>
|
||||
* for (int line=0; line<N; line++)
|
||||
* for (int column=0; column<N; column++) {
|
||||
* float sum = 0;
|
||||
* for (int k=0; k<N; k++)
|
||||
* sum += A[line][k] * A[k][column];
|
||||
* AA[line][column] = sum;
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* In this test, <code>N</code>=300, so that <code>A</code> is 300x300 matrix;
|
||||
* and multiplication <code>A[line][k]*A[k][column]</code> is executed
|
||||
* 300<sup>3</sup>=27 millions times in each iteration of execution of this
|
||||
* cycle. I believe, that this is HotSpot bug to do not adjust itself for best
|
||||
* performance during such a huge series of executions of the same portion of
|
||||
* program code.
|
||||
* <p>
|
||||
* <p>See the bug-report:
|
||||
* <br>
|
||||
* #4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
*/
|
||||
public class numeric006 {
|
||||
/**
|
||||
* When testing performance, single thread calculation is allowed to
|
||||
* be 10% slower than multi-threads calculation (<code>TOLERANCE</code>
|
||||
* is assigned to 10 now).
|
||||
*/
|
||||
public static final double TOLERANCE = 100; // 10;
|
||||
|
||||
/**
|
||||
* Re-assign this value to <code>true</code> for better
|
||||
* diagnostics.
|
||||
*
|
||||
* @see #print(Object)
|
||||
* @see #println(Object)
|
||||
*/
|
||||
private static boolean verbose = false;
|
||||
|
||||
/**
|
||||
* Stream to print execution trace and/or error messages.
|
||||
* This stream usually equals to <code>System.out</code>
|
||||
*/
|
||||
private static PrintStream out = null;
|
||||
|
||||
/**
|
||||
* Print error-message.
|
||||
*
|
||||
* @see #out
|
||||
*/
|
||||
private static void complain(Object x) {
|
||||
out.println("# " + x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print to execution trace, if mode is <code>verbose</code>.
|
||||
*
|
||||
* @see #verbose
|
||||
* @see #out
|
||||
*/
|
||||
private static void print(Object x) {
|
||||
if (verbose)
|
||||
out.print(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print line to execution trace, if mode is <code>verbose</code>.
|
||||
*
|
||||
* @see #verbose
|
||||
* @see #out
|
||||
*/
|
||||
private static void println(Object x) {
|
||||
print(x + "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-invoke <code>run(args,out)</code> in order to simulate
|
||||
* JCK-like test interface.
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line parameters stored in <code>args[]</code> and run
|
||||
* the test.
|
||||
* <p>
|
||||
* <p>Command-line parameters are:
|
||||
* <br>
|
||||
* <code>java numeric006 [-verbose] [-performance] <i>matrixSize</i>
|
||||
* <i>iterations</i></code>
|
||||
* <p>
|
||||
* <p>Here:
|
||||
* <br> <code>-verbose</code> -
|
||||
* keyword, which alows to print execution trace
|
||||
* <br> <code>-performance</code> -
|
||||
* keyword, which alows performance testing
|
||||
* <br> <code><i>matrixSize</i></code> -
|
||||
* number of rows (and columns) in square matrix <code>A</code>
|
||||
* <br> <code><i>iterations</i></code> -
|
||||
* compute <code>A*A</code> several times
|
||||
*
|
||||
* @param args strings array containing command-line parameters
|
||||
* @param out the test log, usually <code>System.out</code>
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
numeric006.out = out;
|
||||
|
||||
boolean testPerformance = false;
|
||||
int numberOfCPU = 1;
|
||||
|
||||
// Parse parameters starting with "-" (like: "-verbose"):
|
||||
|
||||
int argsShift = 0;
|
||||
for (; argsShift < args.length; argsShift++) {
|
||||
String argument = args[argsShift];
|
||||
|
||||
if (!argument.startsWith("-"))
|
||||
break;
|
||||
|
||||
if (argument.equals("-performance")) {
|
||||
testPerformance = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.equals("-verbose")) {
|
||||
verbose = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
complain("Cannot recognize argument: args[" + argsShift + "]: " + argument);
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
if (args.length != argsShift + 2) {
|
||||
complain("Illegal arguments. Execute:");
|
||||
complain(
|
||||
" java numeric006 [-verbose] [-performance] [-CPU:number] " +
|
||||
"matrixSize iterations");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int size = Integer.parseInt(args[argsShift]);
|
||||
if ((size < 100) || (size > 10000)) {
|
||||
complain("Matrix size should be 100 to 1000 lines & columns.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int iterations = Integer.parseInt(args[argsShift + 1]);
|
||||
if ((iterations < 1) || (iterations > 100)) {
|
||||
complain("Iterations number should be 1 to 100.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
print("Preparing A[" + size + "," + size + "]:");
|
||||
float[][] A = newMatrix(size);
|
||||
float[][] A1 = new float[size][size];
|
||||
float[][] Ai = new float[size][size];
|
||||
println(" done.");
|
||||
|
||||
println("Should try " + iterations + " iteration(s):");
|
||||
println("==========================" +
|
||||
((iterations > 99) ? "==" : (iterations > 9) ? "=" : ""));
|
||||
println("");
|
||||
|
||||
double overallTime = 0;
|
||||
double firstTime = 0;
|
||||
double lastTime = 0;
|
||||
|
||||
for (int i = 1; i <= iterations; i++) {
|
||||
double seconds;
|
||||
|
||||
if (i == 1) {
|
||||
seconds = elapsedTime(i, A, A1);
|
||||
firstTime = seconds;
|
||||
} else {
|
||||
seconds = elapsedTime(i, A, Ai);
|
||||
lastTime = seconds;
|
||||
}
|
||||
|
||||
overallTime += seconds;
|
||||
}
|
||||
|
||||
double averageTime = overallTime / iterations;
|
||||
double averagePerformance = size * size * (size + size) / averageTime / 1e6;
|
||||
|
||||
println("");
|
||||
println("=======================" +
|
||||
((iterations > 99) ? "==" : (iterations > 9) ? "=" : ""));
|
||||
println("Overall iteration(s): " + iterations);
|
||||
println("Overall elapsed time: " + overallTime + " seconds.");
|
||||
println("Average elapsed time: " + averageTime + " seconds.");
|
||||
println("Average performance: " + averagePerformance + " MFLOPS");
|
||||
|
||||
println("========================");
|
||||
print("Checking accuracy:");
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
if (A1[line][column] != Ai[line][column]) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("Different results in 1st and last iterations:");
|
||||
complain(" line=" + line + ", column=" + column);
|
||||
return 2; // FAILED
|
||||
}
|
||||
println(" done.");
|
||||
|
||||
if (testPerformance) {
|
||||
print("Checking performance: ");
|
||||
if (firstTime > lastTime * (1 + TOLERANCE / 100)) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("1st iterartion is essentially slower:");
|
||||
complain("Calculation time elapsed (seconds):");
|
||||
complain(" 1-st iteration: " + firstTime);
|
||||
complain(" last iteration: " + lastTime);
|
||||
complain(" tolerance: " + TOLERANCE + "%");
|
||||
return 2; // FAILED
|
||||
}
|
||||
println("done.");
|
||||
}
|
||||
|
||||
println("Test passed.");
|
||||
return 0; // PASSED
|
||||
}
|
||||
|
||||
private static double elapsedTime(int i, float[][] A, float[][] AA) {
|
||||
int size = A.length;
|
||||
|
||||
if (i > 1)
|
||||
println("");
|
||||
println("Iteration #" + i + ":");
|
||||
|
||||
print("Computing A*A:");
|
||||
long mark1 = System.currentTimeMillis();
|
||||
setSquare(A, AA);
|
||||
long mark2 = System.currentTimeMillis();
|
||||
println(" done.");
|
||||
|
||||
double sec = (mark2 - mark1) / 1000.0;
|
||||
double perf = size * size * (size + size) / sec;
|
||||
println("Elapsed time: " + sec + " seconds");
|
||||
println("Performance: " + perf / 1e6 + " MFLOPS");
|
||||
|
||||
return sec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute <code>A*A</code> for the given square matrix <code>A</code>.
|
||||
*/
|
||||
private static void setSquare(float[][] A, float[][] AA) {
|
||||
if (A.length != A[0].length)
|
||||
throw new IllegalArgumentException(
|
||||
"the argument matrix A should be square matrix");
|
||||
if (AA.length != AA[0].length)
|
||||
throw new IllegalArgumentException(
|
||||
"the resulting matrix AA should be square matrix");
|
||||
if (A.length != AA.length)
|
||||
throw new IllegalArgumentException(
|
||||
"the matrices A and AA should have equal size");
|
||||
|
||||
int size = A.length;
|
||||
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++) {
|
||||
float sum = 0;
|
||||
for (int k = 0; k < size; k++)
|
||||
sum += A[line][k] * A[k][line];
|
||||
AA[line][column] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate new square matrix of the given <code>size</code>
|
||||
* and with elements initiated with random numbers.
|
||||
*/
|
||||
private static float[][] newMatrix(int size) {
|
||||
if ((size < 1) || (size > 1000))
|
||||
throw new IllegalArgumentException(
|
||||
"matrix size should be 1 to 1000");
|
||||
|
||||
float[][] A = new float[size][size];
|
||||
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
A[line][column] = (float) ((1 - 2 * Math.random()) * size);
|
||||
|
||||
return A;
|
||||
}
|
||||
|
||||
}
|
||||
381
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric007.java
Normal file
381
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric007.java
Normal file
@ -0,0 +1,381 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/numeric/numeric007.
|
||||
* VM testbase keywords: [stress, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test calculates the product A*A for a square matrix A of the type
|
||||
* long[][]. Elements of the matrix A are initiated with random numbers,
|
||||
* so that optimizing compiler could not eliminate any essential portion
|
||||
* of calculations.
|
||||
* Calculation of the product A*A is iterated three times, and result of
|
||||
* the 1st iteration is compared to result of the 3rd iteration. HotSpot
|
||||
* releases 1.0 and 1.3 seem to fail to adjust itself for better performance
|
||||
* in 1st iteration, while 3rd iteration usually runs much faster. So, the
|
||||
* 1st iteration is probably executed by HotSpot interpreter, and HotSpot
|
||||
* compiler is probably involved to execute the 3rd iteration. The test
|
||||
* just tries to check if HotSpot compiler produces the same results as the
|
||||
* HotSpot interpreter.
|
||||
* By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if 1st iteration is essentially slower than the
|
||||
* 3rd iteration. The calculations algorithm is encoded as compact 3-levels
|
||||
* cycle like:
|
||||
* for (int line=0; line<N; line++)
|
||||
* for (int column=0; column<N; column++) {
|
||||
* long sum = 0;
|
||||
* for (int k=0; k<N; k++)
|
||||
* sum += A[line][k] * A[k][column];
|
||||
* AA[line][column] = sum;
|
||||
* }
|
||||
* In this test, N=300, so that A is 300x300 matrix; and multiplication
|
||||
* A[line][k]*A[k][column] is executed 300**3=27 millions times in each
|
||||
* execution of this cycle. I believe, that this is HotSpot bug to do not
|
||||
* adjust itself for best performance during such a huge series of executions
|
||||
* of the same portion of program code.
|
||||
* COMMENTS
|
||||
* See the bug-report:
|
||||
* #4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
* @run main/othervm nsk.stress.numeric.numeric007.numeric007 300 3
|
||||
*/
|
||||
|
||||
package nsk.stress.numeric.numeric007;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* This test calculates the product <code>A<sup>.</sup>A</code> for
|
||||
* a square matrix <code>A</code> of the type <code>long[][]</code>.
|
||||
* Elements of the matrix <code>A</code> are initiated with random numbers,
|
||||
* so that optimizing compiler could not eliminate any essential portion
|
||||
* of calculations.
|
||||
* <p>
|
||||
* <p>Calculation of the product <code>A<sup>.</sup>A</code> is iterated three
|
||||
* times, and result of the 1<sup>st</sup> iteration is compared to result of
|
||||
* the 3<sup>rd</sup> iteration. HotSpot 1.0 and 1.3 seem to fail to adjust
|
||||
* itself for better performance in 1<sup>st</sup> iteration, while 3<sup>rd</sup>
|
||||
* iteration usually runs much faster. So, 1<sup>st</sup> iteration is probably
|
||||
* executed by HotSpot interpreter, and HotSpot compiler is probably involved to
|
||||
* execute the 3<sup>rd</sup> iteration. The test just tries to check if HotSpot
|
||||
* compiler produces the same results as the HotSpot interpreter.
|
||||
* <p>
|
||||
* <p>By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if 1<sup>st</sup> iteration is essentially slower
|
||||
* than the 3<sup>rd</sup> iteration. The calculations algorithm is encoded
|
||||
* as compact ``canonical'' 3-levels cycle like:
|
||||
* <pre>
|
||||
* for (int line=0; line<N; line++)
|
||||
* for (int column=0; column<N; column++) {
|
||||
* long sum = 0;
|
||||
* for (int k=0; k<N; k++)
|
||||
* sum += A[line][k] * A[k][column];
|
||||
* AA[line][column] = sum;
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* In this test, <code>N</code>=300, so that <code>A</code> is 300x300 matrix;
|
||||
* and multiplication <code>A[line][k]*A[k][column]</code> is executed
|
||||
* 300<sup>3</sup>=27 millions times in each iteration of execution of this
|
||||
* cycle. I believe, that this is HotSpot bug to do not adjust itself for best
|
||||
* performance during such a huge series of executions of the same portion of
|
||||
* program code.
|
||||
* <p>
|
||||
* <p>See the bug-report:
|
||||
* <br>
|
||||
* #4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
*/
|
||||
public class numeric007 {
|
||||
/**
|
||||
* When testing performance, single thread calculation is allowed to
|
||||
* be 10% slower than multi-threads calculation (<code>TOLERANCE</code>
|
||||
* is assigned to 10 now).
|
||||
*/
|
||||
public static final double TOLERANCE = 100; // 10;
|
||||
|
||||
/**
|
||||
* Re-assign this value to <code>true</code> for better
|
||||
* diagnostics.
|
||||
*
|
||||
* @see #print(Object)
|
||||
* @see #println(Object)
|
||||
*/
|
||||
private static boolean verbose = false;
|
||||
|
||||
/**
|
||||
* Stream to print execution trace and/or error messages.
|
||||
* This stream usually equals to <code>System.out</code>
|
||||
*/
|
||||
private static PrintStream out = null;
|
||||
|
||||
/**
|
||||
* Print error-message.
|
||||
*
|
||||
* @see #out
|
||||
*/
|
||||
private static void complain(Object x) {
|
||||
out.println("# " + x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print to execution trace, if mode is <code>verbose</code>.
|
||||
*
|
||||
* @see #verbose
|
||||
* @see #out
|
||||
*/
|
||||
private static void print(Object x) {
|
||||
if (verbose)
|
||||
out.print(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print line to execution trace, if mode is <code>verbose</code>.
|
||||
*
|
||||
* @see #verbose
|
||||
* @see #out
|
||||
*/
|
||||
private static void println(Object x) {
|
||||
print(x + "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-invoke <code>run(args,out)</code> in order to simulate
|
||||
* JCK-like test interface.
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line parameters stored in <code>args[]</code> and run
|
||||
* the test.
|
||||
* <p>
|
||||
* <p>Command-line parameters are:
|
||||
* <br>
|
||||
* <code>java numeric007 [-verbose] [-performance] <i>matrixSize</i>
|
||||
* <i>iterations</i></code>
|
||||
* <p>
|
||||
* <p>Here:
|
||||
* <br> <code>-verbose</code> -
|
||||
* keyword, which alows to print execution trace
|
||||
* <br> <code>-performance</code> -
|
||||
* keyword, which alows performance testing
|
||||
* <br> <code><i>matrixSize</i></code> -
|
||||
* number of rows (and columns) in square matrix <code>A</code>
|
||||
* <br> <code><i>iterations</i></code> -
|
||||
* compute <code>A*A</code> several times
|
||||
*
|
||||
* @param args strings array containing command-line parameters
|
||||
* @param out the test log, usually <code>System.out</code>
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
numeric007.out = out;
|
||||
|
||||
boolean testPerformance = false;
|
||||
int numberOfCPU = 1;
|
||||
|
||||
// Parse parameters starting with "-" (like: "-verbose"):
|
||||
|
||||
int argsShift = 0;
|
||||
for (; argsShift < args.length; argsShift++) {
|
||||
String argument = args[argsShift];
|
||||
|
||||
if (!argument.startsWith("-"))
|
||||
break;
|
||||
|
||||
if (argument.equals("-performance")) {
|
||||
testPerformance = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.equals("-verbose")) {
|
||||
verbose = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
complain("Cannot recognize argument: args[" + argsShift + "]: " + argument);
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
if (args.length != argsShift + 2) {
|
||||
complain("Illegal arguments. Execute:");
|
||||
complain(
|
||||
" java numeric007 [-verbose] [-performance] [-CPU:number] " +
|
||||
"matrixSize iterations");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int size = Integer.parseInt(args[argsShift]);
|
||||
if ((size < 100) || (size > 10000)) {
|
||||
complain("Matrix size should be 100 to 1000 lines & columns.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int iterations = Integer.parseInt(args[argsShift + 1]);
|
||||
if ((iterations < 1) || (iterations > 100)) {
|
||||
complain("Iterations number should be 1 to 100.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
print("Preparing A[" + size + "," + size + "]:");
|
||||
long[][] A = newMatrix(size);
|
||||
long[][] A1 = new long[size][size];
|
||||
long[][] Ai = new long[size][size];
|
||||
println(" done.");
|
||||
|
||||
println("Should try " + iterations + " iteration(s):");
|
||||
println("==========================" +
|
||||
((iterations > 99) ? "==" : (iterations > 9) ? "=" : ""));
|
||||
println("");
|
||||
|
||||
double overallTime = 0;
|
||||
double firstTime = 0;
|
||||
double lastTime = 0;
|
||||
|
||||
for (int i = 1; i <= iterations; i++) {
|
||||
double seconds;
|
||||
|
||||
if (i == 1) {
|
||||
seconds = elapsedTime(i, A, A1);
|
||||
firstTime = seconds;
|
||||
} else {
|
||||
seconds = elapsedTime(i, A, Ai);
|
||||
lastTime = seconds;
|
||||
}
|
||||
|
||||
overallTime += seconds;
|
||||
}
|
||||
|
||||
double averageTime = overallTime / iterations;
|
||||
double averagePerformance = size * size * (size + size) / averageTime / 1e6;
|
||||
|
||||
println("");
|
||||
println("=======================" +
|
||||
((iterations > 99) ? "==" : (iterations > 9) ? "=" : ""));
|
||||
println("Overall iteration(s): " + iterations);
|
||||
println("Overall elapsed time: " + overallTime + " seconds.");
|
||||
println("Average elapsed time: " + averageTime + " seconds.");
|
||||
println("Average performance: " + averagePerformance + " MFLOPS");
|
||||
|
||||
println("========================");
|
||||
print("Checking accuracy:");
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
if (A1[line][column] != Ai[line][column]) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("Different results in 1st and last iterations:");
|
||||
complain(" line=" + line + ", column=" + column);
|
||||
return 2; // FAILED
|
||||
}
|
||||
println(" done.");
|
||||
|
||||
if (testPerformance) {
|
||||
print("Checking performance: ");
|
||||
if (firstTime > lastTime * (1 + TOLERANCE / 100)) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("1st iterartion is essentially slower:");
|
||||
complain("Calculation time elapsed (seconds):");
|
||||
complain(" 1-st iteration: " + firstTime);
|
||||
complain(" last iteration: " + lastTime);
|
||||
complain(" tolerance: " + TOLERANCE + "%");
|
||||
return 2; // FAILED
|
||||
}
|
||||
println("done.");
|
||||
}
|
||||
|
||||
println("Test passed.");
|
||||
return 0; // PASSED
|
||||
}
|
||||
|
||||
private static double elapsedTime(int i, long[][] A, long[][] AA) {
|
||||
int size = A.length;
|
||||
|
||||
if (i > 1)
|
||||
println("");
|
||||
println("Iteration #" + i + ":");
|
||||
|
||||
print("Computing A*A:");
|
||||
long mark1 = System.currentTimeMillis();
|
||||
setSquare(A, AA);
|
||||
long mark2 = System.currentTimeMillis();
|
||||
println(" done.");
|
||||
|
||||
double sec = (mark2 - mark1) / 1000.0;
|
||||
double perf = size * size * (size + size) / sec;
|
||||
println("Elapsed time: " + sec + " seconds");
|
||||
println("Performance: " + perf / 1e6 + " MFLOPS");
|
||||
|
||||
return sec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute <code>A*A</code> for the given square matrix <code>A</code>.
|
||||
*/
|
||||
private static void setSquare(long[][] A, long[][] AA) {
|
||||
if (A.length != A[0].length)
|
||||
throw new IllegalArgumentException(
|
||||
"the argument matrix A should be square matrix");
|
||||
if (AA.length != AA[0].length)
|
||||
throw new IllegalArgumentException(
|
||||
"the resulting matrix AA should be square matrix");
|
||||
if (A.length != AA.length)
|
||||
throw new IllegalArgumentException(
|
||||
"the matrices A and AA should have equal size");
|
||||
|
||||
int size = A.length;
|
||||
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++) {
|
||||
long sum = 0;
|
||||
for (int k = 0; k < size; k++)
|
||||
sum += A[line][k] * A[k][line];
|
||||
AA[line][column] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate new square matrix of the given <code>size</code>
|
||||
* and with elements initiated with random numbers.
|
||||
*/
|
||||
private static long[][] newMatrix(int size) {
|
||||
if ((size < 1) || (size > 1000))
|
||||
throw new IllegalArgumentException(
|
||||
"matrix size should be 1 to 1000");
|
||||
|
||||
long[][] A = new long[size][size];
|
||||
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
A[line][column] = Math.round((1 - 2 * Math.random()) * size);
|
||||
|
||||
return A;
|
||||
}
|
||||
|
||||
}
|
||||
381
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric008.java
Normal file
381
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric008.java
Normal file
@ -0,0 +1,381 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/numeric/numeric008.
|
||||
* VM testbase keywords: [stress, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test calculates the product A*A for a square matrix A of the type
|
||||
* int[][]. Elements of the matrix A are initiated with random numbers,
|
||||
* so that optimizing compiler could not eliminate any essential portion
|
||||
* of calculations.
|
||||
* Calculation of the product A*A is iterated three times, and result of
|
||||
* the 1st iteration is compared to result of the 3rd iteration. HotSpot
|
||||
* releases 1.0 and 1.3 seem to fail to adjust itself for better performance
|
||||
* in 1st iteration, while 3rd iteration usually runs much faster. So, the
|
||||
* 1st iteration is probably executed by HotSpot interpreter, and HotSpot
|
||||
* compiler is probably involved to execute the 3rd iteration. The test
|
||||
* just tries to check if HotSpot compiler produces the same results as the
|
||||
* HotSpot interpreter.
|
||||
* By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if 1st iteration is essentially slower than the
|
||||
* 3rd iteration. The calculations algorithm is encoded as compact 3-levels
|
||||
* cycle like:
|
||||
* for (int line=0; line<N; line++)
|
||||
* for (int column=0; column<N; column++) {
|
||||
* int sum = 0;
|
||||
* for (int k=0; k<N; k++)
|
||||
* sum += A[line][k] * A[k][column];
|
||||
* AA[line][column] = sum;
|
||||
* }
|
||||
* In this test, N=300, so that A is 300x300 matrix; and multiplication
|
||||
* A[line][k]*A[k][column] is executed 300**3=27 millions times in each
|
||||
* execution of this cycle. I believe, that this is HotSpot bug to do not
|
||||
* adjust itself for best performance during such a huge series of executions
|
||||
* of the same portion of program code.
|
||||
* COMMENTS
|
||||
* See the bug-report:
|
||||
* #4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
* @run main/othervm nsk.stress.numeric.numeric008.numeric008 300 3
|
||||
*/
|
||||
|
||||
package nsk.stress.numeric.numeric008;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* This test calculates the product <code>A<sup>.</sup>A</code> for
|
||||
* a square matrix <code>A</code> of the type <code>int[][]</code>.
|
||||
* Elements of the matrix <code>A</code> are initiated with random numbers,
|
||||
* so that optimizing compiler could not eliminate any essential portion
|
||||
* of calculations.
|
||||
* <p>
|
||||
* <p>Calculation of the product <code>A<sup>.</sup>A</code> is iterated three
|
||||
* times, and result of the 1<sup>st</sup> iteration is compared to result of
|
||||
* the 3<sup>rd</sup> iteration. HotSpot 1.0 and 1.3 seem to fail to adjust
|
||||
* itself for better performance in 1<sup>st</sup> iteration, while 3<sup>rd</sup>
|
||||
* iteration usually runs much faster. So, 1<sup>st</sup> iteration is probably
|
||||
* executed by HotSpot interpreter, and HotSpot compiler is probably involved to
|
||||
* execute the 3<sup>rd</sup> iteration. The test just tries to check if HotSpot
|
||||
* compiler produces the same results as the HotSpot interpreter.
|
||||
* <p>
|
||||
* <p>By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if 1<sup>st</sup> iteration is essentially slower
|
||||
* than the 3<sup>rd</sup> iteration. The calculations algorithm is encoded
|
||||
* as compact ``canonical'' 3-levels cycle like:
|
||||
* <pre>
|
||||
* for (int line=0; line<N; line++)
|
||||
* for (int column=0; column<N; column++) {
|
||||
* int sum = 0;
|
||||
* for (int k=0; k<N; k++)
|
||||
* sum += A[line][k] * A[k][column];
|
||||
* AA[line][column] = sum;
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* In this test, <code>N</code>=300, so that <code>A</code> is 300x300 matrix;
|
||||
* and multiplication <code>A[line][k]*A[k][column]</code> is executed
|
||||
* 300<sup>3</sup>=27 millions times in each iteration of execution of this
|
||||
* cycle. I believe, that this is HotSpot bug to do not adjust itself for best
|
||||
* performance during such a huge series of executions of the same portion of
|
||||
* program code.
|
||||
* <p>
|
||||
* <p>See the bug-report:
|
||||
* <br>
|
||||
* #4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
*/
|
||||
public class numeric008 {
|
||||
/**
|
||||
* When testing performance, single thread calculation is allowed to
|
||||
* be 10% slower than multi-threads calculation (<code>TOLERANCE</code>
|
||||
* is assigned to 10 now).
|
||||
*/
|
||||
public static final double TOLERANCE = 100; // 10;
|
||||
|
||||
/**
|
||||
* Re-assign this value to <code>true</code> for better
|
||||
* diagnostics.
|
||||
*
|
||||
* @see #print(Object)
|
||||
* @see #println(Object)
|
||||
*/
|
||||
private static boolean verbose = false;
|
||||
|
||||
/**
|
||||
* Stream to print execution trace and/or error messages.
|
||||
* This stream usually equals to <code>System.out</code>
|
||||
*/
|
||||
private static PrintStream out = null;
|
||||
|
||||
/**
|
||||
* Print error-message.
|
||||
*
|
||||
* @see #out
|
||||
*/
|
||||
private static void complain(Object x) {
|
||||
out.println("# " + x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print to execution trace, if mode is <code>verbose</code>.
|
||||
*
|
||||
* @see #verbose
|
||||
* @see #out
|
||||
*/
|
||||
private static void print(Object x) {
|
||||
if (verbose)
|
||||
out.print(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print line to execution trace, if mode is <code>verbose</code>.
|
||||
*
|
||||
* @see #verbose
|
||||
* @see #out
|
||||
*/
|
||||
private static void println(Object x) {
|
||||
print(x + "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-invoke <code>run(args,out)</code> in order to simulate
|
||||
* JCK-like test interface.
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line parameters stored in <code>args[]</code> and run
|
||||
* the test.
|
||||
* <p>
|
||||
* <p>Command-line parameters are:
|
||||
* <br>
|
||||
* <code>java numeric008 [-verbose] [-performance] <i>matrixSize</i>
|
||||
* <i>iterations</i></code>
|
||||
* <p>
|
||||
* <p>Here:
|
||||
* <br> <code>-verbose</code> -
|
||||
* keyword, which alows to print execution trace
|
||||
* <br> <code>-performance</code> -
|
||||
* keyword, which alows performance testing
|
||||
* <br> <code><i>matrixSize</i></code> -
|
||||
* number of rows (and columns) in square matrix <code>A</code>
|
||||
* <br> <code><i>iterations</i></code> -
|
||||
* compute <code>A*A</code> several times
|
||||
*
|
||||
* @param args strings array containing command-line parameters
|
||||
* @param out the test log, usually <code>System.out</code>
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
numeric008.out = out;
|
||||
|
||||
boolean testPerformance = false;
|
||||
int numberOfCPU = 1;
|
||||
|
||||
// Parse parameters starting with "-" (like: "-verbose"):
|
||||
|
||||
int argsShift = 0;
|
||||
for (; argsShift < args.length; argsShift++) {
|
||||
String argument = args[argsShift];
|
||||
|
||||
if (!argument.startsWith("-"))
|
||||
break;
|
||||
|
||||
if (argument.equals("-performance")) {
|
||||
testPerformance = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.equals("-verbose")) {
|
||||
verbose = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
complain("Cannot recognize argument: args[" + argsShift + "]: " + argument);
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
if (args.length != argsShift + 2) {
|
||||
complain("Illegal arguments. Execute:");
|
||||
complain(
|
||||
" java numeric008 [-verbose] [-performance] [-CPU:number] " +
|
||||
"matrixSize iterations");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int size = Integer.parseInt(args[argsShift]);
|
||||
if ((size < 100) || (size > 10000)) {
|
||||
complain("Matrix size should be 100 to 1000 lines & columns.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int iterations = Integer.parseInt(args[argsShift + 1]);
|
||||
if ((iterations < 1) || (iterations > 100)) {
|
||||
complain("Iterations number should be 1 to 100.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
print("Preparing A[" + size + "," + size + "]:");
|
||||
int[][] A = newMatrix(size);
|
||||
int[][] A1 = new int[size][size];
|
||||
int[][] Ai = new int[size][size];
|
||||
println(" done.");
|
||||
|
||||
println("Should try " + iterations + " iteration(s):");
|
||||
println("==========================" +
|
||||
((iterations > 99) ? "==" : (iterations > 9) ? "=" : ""));
|
||||
println("");
|
||||
|
||||
double overallTime = 0;
|
||||
double firstTime = 0;
|
||||
double lastTime = 0;
|
||||
|
||||
for (int i = 1; i <= iterations; i++) {
|
||||
double seconds;
|
||||
|
||||
if (i == 1) {
|
||||
seconds = elapsedTime(i, A, A1);
|
||||
firstTime = seconds;
|
||||
} else {
|
||||
seconds = elapsedTime(i, A, Ai);
|
||||
lastTime = seconds;
|
||||
}
|
||||
|
||||
overallTime += seconds;
|
||||
}
|
||||
|
||||
double averageTime = overallTime / iterations;
|
||||
double averagePerformance = size * size * (size + size) / averageTime / 1e6;
|
||||
|
||||
println("");
|
||||
println("=======================" +
|
||||
((iterations > 99) ? "==" : (iterations > 9) ? "=" : ""));
|
||||
println("Overall iteration(s): " + iterations);
|
||||
println("Overall elapsed time: " + overallTime + " seconds.");
|
||||
println("Average elapsed time: " + averageTime + " seconds.");
|
||||
println("Average performance: " + averagePerformance + " MFLOPS");
|
||||
|
||||
println("========================");
|
||||
print("Checking accuracy:");
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
if (A1[line][column] != Ai[line][column]) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("Different results in 1st and last iterations:");
|
||||
complain(" line=" + line + ", column=" + column);
|
||||
return 2; // FAILED
|
||||
}
|
||||
println(" done.");
|
||||
|
||||
if (testPerformance) {
|
||||
print("Checking performance: ");
|
||||
if (firstTime > lastTime * (1 + TOLERANCE / 100)) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("1st iterartion is essentially slower:");
|
||||
complain("Calculation time elapsed (seconds):");
|
||||
complain(" 1-st iteration: " + firstTime);
|
||||
complain(" last iteration: " + lastTime);
|
||||
complain(" tolerance: " + TOLERANCE + "%");
|
||||
return 2; // FAILED
|
||||
}
|
||||
println("done.");
|
||||
}
|
||||
|
||||
println("Test passed.");
|
||||
return 0; // PASSED
|
||||
}
|
||||
|
||||
private static double elapsedTime(int i, int[][] A, int[][] AA) {
|
||||
int size = A.length;
|
||||
|
||||
if (i > 1)
|
||||
println("");
|
||||
println("Iteration #" + i + ":");
|
||||
|
||||
print("Computing A*A:");
|
||||
long mark1 = System.currentTimeMillis();
|
||||
setSquare(A, AA);
|
||||
long mark2 = System.currentTimeMillis();
|
||||
println(" done.");
|
||||
|
||||
double sec = (mark2 - mark1) / 1000.0;
|
||||
double perf = size * size * (size + size) / sec;
|
||||
println("Elapsed time: " + sec + " seconds");
|
||||
println("Performance: " + perf / 1e6 + " MFLOPS");
|
||||
|
||||
return sec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute <code>A*A</code> for the given square matrix <code>A</code>.
|
||||
*/
|
||||
private static void setSquare(int[][] A, int[][] AA) {
|
||||
if (A.length != A[0].length)
|
||||
throw new IllegalArgumentException(
|
||||
"the argument matrix A should be square matrix");
|
||||
if (AA.length != AA[0].length)
|
||||
throw new IllegalArgumentException(
|
||||
"the resulting matrix AA should be square matrix");
|
||||
if (A.length != AA.length)
|
||||
throw new IllegalArgumentException(
|
||||
"the matrices A and AA should have equal size");
|
||||
|
||||
int size = A.length;
|
||||
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++) {
|
||||
int sum = 0;
|
||||
for (int k = 0; k < size; k++)
|
||||
sum += A[line][k] * A[k][line];
|
||||
AA[line][column] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate new square matrix of the given <code>size</code>
|
||||
* and with elements initiated with random numbers.
|
||||
*/
|
||||
private static int[][] newMatrix(int size) {
|
||||
if ((size < 1) || (size > 1000))
|
||||
throw new IllegalArgumentException(
|
||||
"matrix size should be 1 to 1000");
|
||||
|
||||
int[][] A = new int[size][size];
|
||||
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
A[line][column] = Math.round((float) ((1 - 2 * Math.random()) * size));
|
||||
|
||||
return A;
|
||||
}
|
||||
|
||||
}
|
||||
568
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric009.java
Normal file
568
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric009.java
Normal file
@ -0,0 +1,568 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/numeric/numeric009.
|
||||
* VM testbase keywords: [stress, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test calculates the product A*A for a square matrix A, and checks
|
||||
* if such product is calculated correctly. Elements of the matrix A are
|
||||
* initiated with integer numbers, so that A*A must be the same if calculated
|
||||
* with double, float, long, or int precision. The test just checks, if
|
||||
* double, float, long, and int variants of the product calculation result
|
||||
* in the same A*A matrix.
|
||||
* Calculation of the product A*A is iterated two times, because HotSpot
|
||||
* releases 1.0 and 1.3 seem to do not adjust JVM for better performance
|
||||
* in 1st iteration, while 2nd iteration usually runs much faster. I guess,
|
||||
* that the 1st iteration is probably executed by HotSpot interpreter, and
|
||||
* HotSpot compiler is probably involved to execute the 2nd iteration. So,
|
||||
* the test apparently checks accuracy of A*A calculation in both compilation
|
||||
* and interpretation modes.
|
||||
* By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if 1st iteration is essentially slower than the
|
||||
* 2nd iteration. The calculations algorithm is encoded as rather compact
|
||||
* 3-levels cycle like:
|
||||
* for (int line=0; line<N; line++)
|
||||
* for (int column=0; column<N; column++) {
|
||||
* float sum = 0;
|
||||
* for (int k=0; k<N; k++)
|
||||
* sum += A[line][k] * A[k][column];
|
||||
* AA[line][column] = sum;
|
||||
* }
|
||||
* In this test, N=200, so that A is 200x200 matrix; and multiplication
|
||||
* A[line][k]*A[k][column] is executed 200**3=8 millions times in each
|
||||
* iteration of execution of this cycle. I believe, that this is HotSpot
|
||||
* bug to do not adjust JVM for best performance during such a huge series
|
||||
* of executions of the rather compact portion of program code.
|
||||
* COMMENTS
|
||||
* See the bug-report:
|
||||
* #4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
*
|
||||
* @run main/othervm nsk.stress.numeric.numeric009.numeric009 200 2
|
||||
*/
|
||||
|
||||
package nsk.stress.numeric.numeric009;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* This test calculates the product <code>A<sup>.</sup>A</code> for a square
|
||||
* matrix <code>A</code>, and checks if such product is calculated correctly.
|
||||
* Elements of the matrix <code>A</code> are initiated with integer numbers,
|
||||
* so that <code>A<sup>.</sup>A</code> must be the same if calculated with
|
||||
* <code>double</code>, <code>float</code>, <code>long</code>, or
|
||||
* <code>int</code> precision. The test just checks, if <code>double</code>,
|
||||
* <code>float</code>, <code>long</code>, and <code>int</code> variants of
|
||||
* the product calculation result in the same <code>A<sup>.</sup>A</code>
|
||||
* matrix.
|
||||
* <p>
|
||||
* <p>Calculation of the product <code>A<sup>.</sup>A</code> is iterated two
|
||||
* times, because HotSpot releases 1.0 and 1.3 seem to do not adjust JVM for
|
||||
* better performance in 1<sup>st</sup> iteration, while 2<sup>nd</sup>
|
||||
* iteration usually runs much faster. I guess, that the 1<sup>st</sup> iteration
|
||||
* is probably executed by HotSpot interpreter, and HotSpot compiler is probably
|
||||
* involved to execute the 2<sup>nd</sup> iteration. So, the test apparently
|
||||
* checks accuracy of <code>A<sup>.</sup>A</code> calculation in both compilation
|
||||
* and interpretation modes.
|
||||
* <p>
|
||||
* <p>By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if 1<sup>st</sup> iteration is essentially slower
|
||||
* than the 2<sup>nd</sup> iteration. The calculations algorithm is encoded
|
||||
* as compact ``canonical'' 3-levels cycle like:
|
||||
* <pre>
|
||||
* for (int line=0; line<N; line++)
|
||||
* for (int column=0; column<N; column++) {
|
||||
* float sum = 0;
|
||||
* for (int k=0; k<N; k++)
|
||||
* sum += A[line][k] * A[k][column];
|
||||
* AA[line][column] = sum;
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* In this test, <code>N</code>=200, so that <code>A</code> is 200x200 matrix;
|
||||
* and multiplication <code>A[line][k]*A[k][column]</code> is executed
|
||||
* 200<sup>3</sup>=8 millions times in each iteration of execution of this
|
||||
* cycle. I believe, that this is HotSpot bug to do not adjust JVM for best
|
||||
* performance during such a huge series of executions of the rather compact
|
||||
* portion of program code.
|
||||
* <p>
|
||||
* <p>See the bug-report:
|
||||
* <br>
|
||||
* #4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
*/
|
||||
public class numeric009 {
|
||||
/**
|
||||
* When testing performance, 1st iteration is allowed to be 10% slower
|
||||
* than 2nd iteration (<code>tolerance</code> is assigned to 10 now).
|
||||
*/
|
||||
public static double tolerance = 100; // 10;
|
||||
|
||||
/**
|
||||
* Re-assign this value to <code>true</code> for better
|
||||
* diagnostics.
|
||||
*
|
||||
* @see #print(Object)
|
||||
* @see #println(Object)
|
||||
*/
|
||||
private static boolean verbose = false;
|
||||
|
||||
/**
|
||||
* Stream to print execution trace and/or error messages.
|
||||
* This stream usually equals to <code>System.out</code>
|
||||
*/
|
||||
private static PrintStream out = null;
|
||||
|
||||
/**
|
||||
* Print error-message.
|
||||
*
|
||||
* @see #out
|
||||
*/
|
||||
private static void complain(Object x) {
|
||||
out.println("# " + x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print to execution trace, if mode is <code>verbose</code>.
|
||||
*
|
||||
* @see #verbose
|
||||
* @see #out
|
||||
*/
|
||||
private static void print(Object x) {
|
||||
if (verbose)
|
||||
out.print(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print line to execution trace, if mode is <code>verbose</code>.
|
||||
*
|
||||
* @see #verbose
|
||||
* @see #out
|
||||
*/
|
||||
private static void println(Object x) {
|
||||
print(x + "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-invoke <code>run(args,out)</code> in order to simulate
|
||||
* JCK-like test interface.
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line parameters stored in <code>args[]</code> and run
|
||||
* the test.
|
||||
* <p>
|
||||
* <p>Command-line parameters are:
|
||||
* <br>
|
||||
* <code>java numeric009 [-verbose] [-performance]
|
||||
* [-tolerance:<i>percents</i>]
|
||||
* <i>matrixSize</i> <i>iterations</i></code>
|
||||
* <p>
|
||||
* <p>Here:
|
||||
* <br> <code>-verbose</code> -
|
||||
* keyword alowing to print execution trace
|
||||
* <br> <code>-performance</code> -
|
||||
* keyword turning on performance testing
|
||||
* <br> <code>-tolerance</code> -
|
||||
* setup tolerance of performance checking
|
||||
* <br> <code><i>percents</i></code> -
|
||||
* 1<sup>st</sup> iteration is allowed to be
|
||||
* <code><i>percents</i></code>% slower
|
||||
* <br> <code><i>matrixSize</i></code> -
|
||||
* number of rows (and columns) in square matrix <code>A</code>
|
||||
* <br> <code><i>iterations</i></code> -
|
||||
* how many times to execute the test for stronger checking
|
||||
*
|
||||
* @param args strings array containing command-line parameters
|
||||
* @param out the test log, usually <code>System.out</code>
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
numeric009.out = out;
|
||||
|
||||
boolean testPerformance = false;
|
||||
int numberOfCPU = 1;
|
||||
|
||||
// Parse parameters starting with "-" (like: "-verbose"):
|
||||
|
||||
int argsShift = 0;
|
||||
for (; argsShift < args.length; argsShift++) {
|
||||
String argument = args[argsShift];
|
||||
|
||||
if (!argument.startsWith("-"))
|
||||
break;
|
||||
|
||||
if (argument.equals("-performance")) {
|
||||
testPerformance = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.equals("-verbose")) {
|
||||
verbose = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.startsWith("-tolerance:")) {
|
||||
String percents =
|
||||
argument.substring("-tolerance:".length(), argument.length());
|
||||
tolerance = Integer.parseInt(percents);
|
||||
if ((tolerance < 0) || (tolerance > 100)) {
|
||||
complain("Tolerance should be 0 to 100%: " + argument);
|
||||
return 2; // failure
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
complain("Cannot recognize argument: args[" + argsShift + "]: " + argument);
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
if (args.length != argsShift + 2) {
|
||||
complain("Illegal arguments. Execute:");
|
||||
complain(
|
||||
" java numeric009 [-verbose] [-performance] " +
|
||||
"[-tolerance:percents] matrixSize iterations");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int size = Integer.parseInt(args[argsShift]);
|
||||
if ((size < 100) || (size > 10000)) {
|
||||
complain("Matrix size should be 100 to 1000 lines & columns.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int iterations = Integer.parseInt(args[argsShift + 1]);
|
||||
if ((iterations < 1) || (iterations > 100)) {
|
||||
complain("Iterations number should be 1 to 100.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
print("Preparing A[" + size + "," + size + "]:");
|
||||
int[][] intA = newIntegerMatrix(size);
|
||||
int[][] intAA = new int[size][size];
|
||||
long[][] longA = newLongMatrix(intA);
|
||||
long[][] longAA = new long[size][size];
|
||||
double[][] doubleA = newDoubleMatrix(intA);
|
||||
double[][] doubleAA = new double[size][size];
|
||||
float[][] floatA = newFloatMatrix(intA);
|
||||
float[][] floatAA = new float[size][size];
|
||||
println(" done.");
|
||||
|
||||
println("Should try " + iterations + " iteration(s):");
|
||||
println("==========================" +
|
||||
((iterations > 99) ? "==" : (iterations > 9) ? "=" : ""));
|
||||
println("");
|
||||
|
||||
double overallTime = 0;
|
||||
double firstTime = 0;
|
||||
double lastTime = 0;
|
||||
|
||||
for (int i = 1; i <= iterations; i++) {
|
||||
double seconds = elapsedTime(i,
|
||||
intA, intAA, longA, longAA, floatA, floatAA, doubleA, doubleAA);
|
||||
|
||||
if (i == 1)
|
||||
firstTime = seconds;
|
||||
else
|
||||
lastTime = seconds;
|
||||
overallTime += seconds;
|
||||
|
||||
print("Checking accuracy:");
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++) {
|
||||
if (intAA[line][column] != longAA[line][column]) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("Integer and Long results differ at:");
|
||||
complain(" line=" + line + ", column=" + column);
|
||||
return 2; // FAILED
|
||||
}
|
||||
if (intAA[line][column] != floatAA[line][column]) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("Integer and Float results differ at:");
|
||||
complain(" line=" + line + ", column=" + column);
|
||||
return 2; // FAILED
|
||||
}
|
||||
if (intAA[line][column] != doubleAA[line][column]) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("Integer and Double results differ at:");
|
||||
complain(" line=" + line + ", column=" + column);
|
||||
return 2; // FAILED
|
||||
}
|
||||
}
|
||||
println(" done.");
|
||||
}
|
||||
|
||||
double averageTime = overallTime / iterations / 4;
|
||||
double averagePerformance = size * size * (size + size) / averageTime / 1e6;
|
||||
|
||||
println("");
|
||||
println("=======================" +
|
||||
((iterations > 99) ? "==" : (iterations > 9) ? "=" : ""));
|
||||
println("Overall iteration(s): " + iterations);
|
||||
println("Overall elapsed time: " + overallTime + " seconds.");
|
||||
println("Average elapsed time: " + averageTime + " seconds.");
|
||||
println("Average performance: " + averagePerformance + " MFLOPS");
|
||||
|
||||
if (testPerformance) {
|
||||
print("Checking performance: ");
|
||||
if (firstTime > lastTime * (1 + tolerance / 100)) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("1st iterartion is essentially slower:");
|
||||
complain("Calculation time elapsed (seconds):");
|
||||
complain(" 1-st iteration: " + firstTime);
|
||||
complain(" last iteration: " + lastTime);
|
||||
complain(" tolerance: " + tolerance + "%");
|
||||
return 2; // FAILED
|
||||
}
|
||||
println("done.");
|
||||
}
|
||||
|
||||
println("Test passed.");
|
||||
return 0; // PASSED
|
||||
}
|
||||
|
||||
/**
|
||||
* Return time (in seconds) elapsed for calculation of matrix
|
||||
* product <code>A*A</code> with <code>int</code>, <code>long</code>,
|
||||
* <code>float</code>, and <code>double</code> representations.
|
||||
*/
|
||||
private static double elapsedTime(int i,
|
||||
int[][] intA, int[][] intAA,
|
||||
long[][] longA, long[][] longAA,
|
||||
float[][] floatA, float[][] floatAA,
|
||||
double[][] doubleA, double[][] doubleAA) {
|
||||
|
||||
int size = intA.length;
|
||||
|
||||
if (i > 1)
|
||||
println("");
|
||||
println("Iteration #" + i + ":");
|
||||
|
||||
print("Computing int, long, float, and double A*A:");
|
||||
long mark1 = System.currentTimeMillis();
|
||||
setSquare(intA, intAA);
|
||||
setSquare(longA, longAA);
|
||||
setSquare(floatA, floatAA);
|
||||
setSquare(doubleA, doubleAA);
|
||||
long mark2 = System.currentTimeMillis();
|
||||
println(" done.");
|
||||
|
||||
double sec = (mark2 - mark1) / 1000.0;
|
||||
double perf = size * size * (size + size) / (sec / 4);
|
||||
println("Elapsed time: " + sec + " seconds");
|
||||
println("Performance: " + perf / 1e6 + " MOPS");
|
||||
|
||||
return sec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute <code>A*A</code> for the given square matrix <code>A</code>.
|
||||
*/
|
||||
private static void setSquare(int[][] A, int[][] AA) {
|
||||
if (A.length != A[0].length)
|
||||
throw new IllegalArgumentException(
|
||||
"the argument matrix A should be square matrix");
|
||||
if (AA.length != AA[0].length)
|
||||
throw new IllegalArgumentException(
|
||||
"the resulting matrix AA should be square matrix");
|
||||
if (A.length != AA.length)
|
||||
throw new IllegalArgumentException(
|
||||
"the matrices A and AA should have equal size");
|
||||
|
||||
int size = A.length;
|
||||
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++) {
|
||||
int sum = 0;
|
||||
for (int k = 0; k < size; k++)
|
||||
sum += A[line][k] * A[k][line];
|
||||
AA[line][column] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute <code>A*A</code> for the given square matrix <code>A</code>.
|
||||
*/
|
||||
private static void setSquare(long[][] A, long[][] AA) {
|
||||
if (A.length != A[0].length)
|
||||
throw new IllegalArgumentException(
|
||||
"the argument matrix A should be square matrix");
|
||||
if (AA.length != AA[0].length)
|
||||
throw new IllegalArgumentException(
|
||||
"the resulting matrix AA should be square matrix");
|
||||
if (A.length != AA.length)
|
||||
throw new IllegalArgumentException(
|
||||
"the matrices A and AA should have equal size");
|
||||
|
||||
int size = A.length;
|
||||
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++) {
|
||||
long sum = 0;
|
||||
for (int k = 0; k < size; k++)
|
||||
sum += A[line][k] * A[k][line];
|
||||
AA[line][column] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute <code>A*A</code> for the given square matrix <code>A</code>.
|
||||
*/
|
||||
private static void setSquare(float[][] A, float[][] AA) {
|
||||
if (A.length != A[0].length)
|
||||
throw new IllegalArgumentException(
|
||||
"the argument matrix A should be square matrix");
|
||||
if (AA.length != AA[0].length)
|
||||
throw new IllegalArgumentException(
|
||||
"the resulting matrix AA should be square matrix");
|
||||
if (A.length != AA.length)
|
||||
throw new IllegalArgumentException(
|
||||
"the matrices A and AA should have equal size");
|
||||
|
||||
int size = A.length;
|
||||
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++) {
|
||||
float sum = 0;
|
||||
for (int k = 0; k < size; k++)
|
||||
sum += A[line][k] * A[k][line];
|
||||
AA[line][column] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute <code>A*A</code> for the given square matrix <code>A</code>.
|
||||
*/
|
||||
private static void setSquare(double[][] A, double[][] AA) {
|
||||
if (A.length != A[0].length)
|
||||
throw new IllegalArgumentException(
|
||||
"the argument matrix A should be square matrix");
|
||||
if (AA.length != AA[0].length)
|
||||
throw new IllegalArgumentException(
|
||||
"the resulting matrix AA should be square matrix");
|
||||
if (A.length != AA.length)
|
||||
throw new IllegalArgumentException(
|
||||
"the matrices A and AA should have equal size");
|
||||
|
||||
int size = A.length;
|
||||
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++) {
|
||||
double sum = 0;
|
||||
for (int k = 0; k < size; k++)
|
||||
sum += A[line][k] * A[k][line];
|
||||
AA[line][column] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate new square matrix of the given <code>size</code>
|
||||
* and with elements initiated with random numbers.
|
||||
*/
|
||||
private static int[][] newIntegerMatrix(int size) {
|
||||
if ((size < 1) || (size > 1000))
|
||||
throw new IllegalArgumentException(
|
||||
"matrix size should be 1 to 1000");
|
||||
|
||||
int[][] A = new int[size][size];
|
||||
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
A[line][column] =
|
||||
Math.round((float) ((1 - 2 * Math.random()) * size));
|
||||
|
||||
return A;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate new square matrix with <code>long</code> elements,
|
||||
* and initiate them with the same values as in the given matrix
|
||||
* <code>intA</code>.
|
||||
*/
|
||||
private static long[][] newLongMatrix(int[][] intA) {
|
||||
if (intA.length != intA[0].length)
|
||||
throw new IllegalArgumentException(
|
||||
"need square argument matrix");
|
||||
|
||||
int size = intA.length;
|
||||
long[][] longA = new long[size][size];
|
||||
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
longA[line][column] = intA[line][column];
|
||||
|
||||
return longA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate new square matrix with <code>double</code> elements,
|
||||
* and initiate them with the same values as in the given matrix
|
||||
* <code>intA</code>.
|
||||
*/
|
||||
private static double[][] newDoubleMatrix(int[][] intA) {
|
||||
if (intA.length != intA[0].length)
|
||||
throw new IllegalArgumentException(
|
||||
"need square argument matrix");
|
||||
|
||||
int size = intA.length;
|
||||
double[][] doubleA = new double[size][size];
|
||||
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
doubleA[line][column] = intA[line][column];
|
||||
|
||||
return doubleA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate new square matrix with <code>float</code> elements,
|
||||
* and initiate them with the same values as in the given matrix
|
||||
* <code>intA</code>.
|
||||
*/
|
||||
private static float[][] newFloatMatrix(int[][] intA) {
|
||||
if (intA.length != intA[0].length)
|
||||
throw new IllegalArgumentException(
|
||||
"need square argument matrix");
|
||||
|
||||
int size = intA.length;
|
||||
float[][] floatA = new float[size][size];
|
||||
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
floatA[line][column] = intA[line][column];
|
||||
|
||||
return floatA;
|
||||
}
|
||||
|
||||
}
|
||||
809
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric010.java
Normal file
809
test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric010.java
Normal file
@ -0,0 +1,809 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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/numeric/numeric010.
|
||||
* VM testbase keywords: [stress, slow, nonconcurrent, quick]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test calculates the product A*A for a square matrix A, and checks
|
||||
* if such product is calculated correctly. Elements of the matrix A are
|
||||
* initiated with integer numbers, so that A*A must be the same if calculated
|
||||
* with double, float, long, or int precision. The test just checks, if
|
||||
* double, float, long, and int variants of the product calculation result
|
||||
* in the same A*A matrix.
|
||||
* The product A*A is calculated twice: in a single thread, and in N separate
|
||||
* threads, where NxN is the size of square matrix A. When executing in N
|
||||
* threads, each thread calculate distinct row of the resulting matrix.
|
||||
* HotSpot releases 1.0 and 1.3 seem to do not adjust JVM for better
|
||||
* performance in single-thread calculation, while milti-threads calculation
|
||||
* usually runs much faster. I guess, that the 1-thread calculation is probably
|
||||
* executed by HotSpot interpreter, and HotSpot compiler is probably involved
|
||||
* to execute N-threads calculation. So, the test apparently checks accuracy
|
||||
* of A*A calculation in both compilation and interpretation modes.
|
||||
* By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if single-thread calculation is essentially
|
||||
* slower than N-threads calculation (surely, the number of CPUs installed
|
||||
* on the platform executing the test is taken into account for performance
|
||||
* testing). The calculation algorithm is encoded with 3-levels cycle like:
|
||||
* for (int line=0; line<N; line++)
|
||||
* for (int column=0; column<N; column++) {
|
||||
* float sum = 0;
|
||||
* for (int k=0; k<N; k++)
|
||||
* sum += A[line][k] A[k][column];
|
||||
* AA[line][column] = sum;
|
||||
* }
|
||||
* In this test, N=200, so that A is 200x200 matrix; and multiplication
|
||||
* A[line][k]*A[k][column] is executed 200**3=8 millions times in this
|
||||
* cycle. I believe, that this is HotSpot bug to do not adjust JVM for
|
||||
* best performance during such a huge series of executions of the rather
|
||||
* compact portion of program code.
|
||||
* COMMENTS
|
||||
* The bug was filed referencing to the same numeric algorithm,
|
||||
* which is used by this test:
|
||||
* 4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
* Note, that despite HotSpot works faster in milti-thread calculations,
|
||||
* it still remains essentially slower than classic VM with JIT on.
|
||||
*
|
||||
* @run main/othervm nsk.stress.numeric.numeric010.numeric010 200 200
|
||||
*/
|
||||
|
||||
package nsk.stress.numeric.numeric010;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* This test calculates the product <code>A<sup>.</sup>A</code> for a square
|
||||
* matrix <code>A</code>, and checks if such product is calculated correctly.
|
||||
* Elements of the matrix <code>A</code> are initiated with integer numbers,
|
||||
* so that <code>A<sup>.</sup>A</code> must be the same if calculated with
|
||||
* <code>double</code>, <code>float</code>, <code>long</code>, or
|
||||
* <code>int</code> precision. The test just checks, if <code>double</code>,
|
||||
* <code>float</code>, <code>long</code>, and <code>int</code> variants of
|
||||
* the product calculation result in the same <code>A<sup>.</sup>A</code>
|
||||
* matrix.
|
||||
* <p>
|
||||
* <p>The product <code>A<sup>.</sup>A</code> is calculated twice: in a single
|
||||
* thread, and in <code>N</code> separate threads, where <code>NxN</code> is
|
||||
* the size of square matrix <code>A</code>. When executing in <code>N</code>
|
||||
* threads, each thread calculate distinct row of the resulting matrix. HotSpot
|
||||
* releases 1.0 and 1.3 seem to do not adjust JVM for better performance in
|
||||
* single-thread calculation, while milti-threads calculation usually runs much
|
||||
* faster. I guess, that the 1-thread calculation is probably executed by HotSpot
|
||||
* interpreter, and HotSpot compiler is probably involved to execute
|
||||
* <code>N</code>-threads calculation. So, the test apparently checks accuracy
|
||||
* of <code>A<sup>.</sup>A</code> calculation in both compilation and
|
||||
* interpretation modes.
|
||||
* <p>
|
||||
* <p>By the way, the test checks JVM performance. The test is treated failed
|
||||
* due to poor performance, if single-thread calculation is essentially
|
||||
* slower than <code>N</code>-threads calculation (surely, the number of CPUs
|
||||
* installed on the platform executing the test is taken into account for
|
||||
* performance testing). The calculation algorithm is encoded with 3-levels
|
||||
* cycle like:
|
||||
* <pre>
|
||||
* for (int line=0; line<N; line++)
|
||||
* for (int column=0; column<N; column++) {
|
||||
* float sum = 0;
|
||||
* for (int k=0; k<N; k++)
|
||||
* sum += A[line][k] * A[k][column];
|
||||
* AA[line][column] = sum;
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* In this test, <code>N</code>=200, so that <code>A</code> is 200x200 matrix;
|
||||
* and multiplication <code>A[line][k]*A[k][column]</code> is executed
|
||||
* 200<sup>3</sup>=8 millions times in this cycle. I believe, that this is HotSpot
|
||||
* bug to do not adjust JVM for best performance during such a huge series of
|
||||
* executions of the rather compact portion of program code.
|
||||
* <p>
|
||||
* <p>See the bug-report:
|
||||
* <br>
|
||||
* 4242172 (P3/S5) 2.0: poor performance in matrix calculations
|
||||
*/
|
||||
public class numeric010 {
|
||||
/**
|
||||
* When testing performance, 1-thread calculation is allowed to be 10%
|
||||
* slower than multi-thread calculation (<code>tolerance</code> is
|
||||
* assigned to 10 now).
|
||||
*/
|
||||
public static double tolerance = 100; // 10;
|
||||
|
||||
/**
|
||||
* Re-assign this value to <code>true</code> for better diagnostics.
|
||||
*
|
||||
* @see #print(Object)
|
||||
* @see #println(Object)
|
||||
*/
|
||||
private static boolean verbose = false;
|
||||
|
||||
/**
|
||||
* Stream to print execution trace and/or error messages.
|
||||
* This stream usually equals to <code>System.out</code>
|
||||
*/
|
||||
private static PrintStream out = null;
|
||||
|
||||
/**
|
||||
* Print error-message.
|
||||
*
|
||||
* @see #out
|
||||
*/
|
||||
private static void complain(Object x) {
|
||||
out.println("# " + x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print to execution trace, if mode is <code>verbose</code>.
|
||||
*
|
||||
* @see #verbose
|
||||
* @see #out
|
||||
*/
|
||||
private static void print(Object x) {
|
||||
if (verbose)
|
||||
out.print(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print line to execution trace, if mode is <code>verbose</code>.
|
||||
*
|
||||
* @see #verbose
|
||||
* @see #out
|
||||
*/
|
||||
private static void println(Object x) {
|
||||
print(x + "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-invoke <code>run(args,out)</code> in order to simulate
|
||||
* JCK-like test interface.
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
// JCK-like exit status
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line parameters stored in <code>args[]</code> and run
|
||||
* the test.
|
||||
* <p>
|
||||
* <p>Command-line parameters are:
|
||||
* <br>
|
||||
* <code>java numeric010 [-verbose] [-performance]
|
||||
* [-tolerance:<i>percents</i>] [-CPU:<i>number</i>]
|
||||
* <i>matrixSize</i> [<i>threads</i>]</code>
|
||||
* <p>
|
||||
* <p>Here:
|
||||
* <br> <code>-verbose</code> -
|
||||
* keyword, which alows to print execution trace
|
||||
* <br> <code>-performance</code> -
|
||||
* keyword, which alows performance testing
|
||||
* <br> <code>-tolerance</code> -
|
||||
* setup tolerance of performance checking
|
||||
* <br> <code><i>percents</i></code> -
|
||||
* 1-thread calculation is allowed to be
|
||||
* <code><i>percents</i></code>% slower
|
||||
* <br> <code><i>number</i></code> -
|
||||
* number of CPU installed on the computer just executing the test
|
||||
* <br> <code><i>matrixSize</i></code> -
|
||||
* number of rows (and columns) in square matrix to be tested
|
||||
* <br> <code><i>threads</i></code> -
|
||||
* for multi-thread calculation
|
||||
* (default: <code><i>matrixSize</i></code>)
|
||||
*
|
||||
* @param args strings array containing command-line parameters
|
||||
* @param out the test log, usually <code>System.out</code>
|
||||
*/
|
||||
public static int run(String args[], PrintStream out) {
|
||||
numeric010.out = out;
|
||||
|
||||
boolean testPerformance = false;
|
||||
int numberOfCPU = 1;
|
||||
|
||||
int argsShift = 0;
|
||||
for (; argsShift < args.length; argsShift++) {
|
||||
String argument = args[argsShift];
|
||||
|
||||
if (!argument.startsWith("-"))
|
||||
break;
|
||||
|
||||
if (argument.equals("-performance")) {
|
||||
testPerformance = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.equals("-verbose")) {
|
||||
verbose = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.startsWith("-tolerance:")) {
|
||||
String percents =
|
||||
argument.substring("-tolerance:".length(), argument.length());
|
||||
tolerance = Integer.parseInt(percents);
|
||||
|
||||
if ((tolerance < 0) || (tolerance > 100)) {
|
||||
complain("Tolerance should be 0 to 100%: " + argument);
|
||||
return 2; // failure
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.startsWith("-CPU:")) {
|
||||
String value =
|
||||
argument.substring("-CPU:".length(), argument.length());
|
||||
numberOfCPU = Integer.parseInt(value);
|
||||
|
||||
if (numberOfCPU < 1) {
|
||||
complain("Illegal number of CPU: " + argument);
|
||||
return 2; // failure
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
complain("Cannot recognize argument: args[" + argsShift + "]: " + argument);
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
if ((args.length < argsShift + 1) || (args.length > argsShift + 2)) {
|
||||
complain("Illegal argument(s). Execute:");
|
||||
complain(
|
||||
" java numeric010 [-verbose] [-performance] " +
|
||||
"[-tolerance:percents] [-CPU:number] matrixSize [threads]");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int size = Integer.parseInt(args[argsShift]);
|
||||
if ((size < 100) || (size > 10000)) {
|
||||
complain("Matrix size should be 100 to 1000 lines & columns.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
int threads = size;
|
||||
if (args.length >= argsShift + 2)
|
||||
threads = Integer.parseInt(args[argsShift + 1]);
|
||||
if ((threads < 1) || (threads > size)) {
|
||||
complain("Threads number should be 1 to matrix size.");
|
||||
return 2; // failure
|
||||
}
|
||||
if ((size % threads) != 0) {
|
||||
complain("Threads number should evenly divide matrix size.");
|
||||
return 2; // failure
|
||||
}
|
||||
|
||||
print("Preparing A[" + size + "," + size + "]:");
|
||||
IntegerMatrix intA = new IntegerMatrix(size);
|
||||
IntegerMatrix intAA = new IntegerMatrix(size);
|
||||
LongMatrix longA = new LongMatrix(intA);
|
||||
LongMatrix longAA = new LongMatrix(intA);
|
||||
FloatMatrix floatA = new FloatMatrix(intA);
|
||||
FloatMatrix floatAA = new FloatMatrix(intA);
|
||||
DoubleMatrix doubleA = new DoubleMatrix(intA);
|
||||
DoubleMatrix doubleAA = new DoubleMatrix(intA);
|
||||
println(" done.");
|
||||
|
||||
double elapsed[] = {0, 0};
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
double seconds =
|
||||
elapsedTime((i == 0 ? 1 : threads),
|
||||
intA, intAA,
|
||||
longA, longAA,
|
||||
floatA, floatAA,
|
||||
doubleA, doubleAA);
|
||||
elapsed[i] = seconds;
|
||||
|
||||
print("Checking accuracy:");
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++) {
|
||||
if (intAA.value[line][column] != longAA.value[line][column]) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("Integer and Long results differ at:");
|
||||
complain(" line=" + line + ", column=" + column);
|
||||
complain(" intAA.value[line][column]=" + intAA.value[line][column]);
|
||||
complain("longAA.value[line][column]=" + longAA.value[line][column]);
|
||||
return 2; // FAILED
|
||||
}
|
||||
if (intAA.value[line][column] != floatAA.value[line][column]) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("Integer and Float results differ at:");
|
||||
complain(" line=" + line + ", column=" + column);
|
||||
complain(" intAA.value[line][column]=" + intAA.value[line][column]);
|
||||
complain("floatAA.value[line][column]=" + floatAA.value[line][column]);
|
||||
return 2; // FAILED
|
||||
}
|
||||
if (intAA.value[line][column] != doubleAA.value[line][column]) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("Integer and Double results differ at:");
|
||||
complain(" line=" + line + ", column=" + column);
|
||||
complain(" intAA.value[line][column]=" + intAA.value[line][column]);
|
||||
complain("doubleAA.value[line][column]=" + doubleAA.value[line][column]);
|
||||
return 2; // FAILED
|
||||
}
|
||||
}
|
||||
println(" done.");
|
||||
}
|
||||
|
||||
double overallTime = elapsed[0] + elapsed[1];
|
||||
double averageTime = overallTime / 2; // 2 excutions
|
||||
double averagePerformance = 4 * size * size * (size + size) / averageTime / 1e6;
|
||||
println("");
|
||||
println("Overall elapsed time: " + overallTime + " seconds.");
|
||||
println("Average elapsed time: " + averageTime + " seconds.");
|
||||
println("Average performance: " + averagePerformance + " MOPS");
|
||||
|
||||
if (testPerformance) {
|
||||
println("");
|
||||
print("Checking performance: ");
|
||||
double elapsed1 = elapsed[0];
|
||||
double elapsedM = elapsed[1] * numberOfCPU;
|
||||
if (elapsed1 > elapsedM * (1 + tolerance / 100)) {
|
||||
println("");
|
||||
complain("Test failed:");
|
||||
complain("Single-thread calculation is essentially slower:");
|
||||
complain("Calculation time elapsed (seconds):");
|
||||
complain(" single thread: " + elapsed[0]);
|
||||
complain(" multi-threads: " + elapsed[1]);
|
||||
complain(" number of CPU: " + numberOfCPU);
|
||||
complain(" tolerance: " + tolerance + "%");
|
||||
return 2; // FAILED
|
||||
}
|
||||
println("done.");
|
||||
}
|
||||
|
||||
println("Test passed.");
|
||||
return 0; // PASSED
|
||||
}
|
||||
|
||||
/**
|
||||
* Return time (in seconds) elapsed for calculation of matrix
|
||||
* product <code>A*A</code> with <code>int</code>, <code>long</code>,
|
||||
* <code>float</code>, and <code>double</code> representations.
|
||||
*/
|
||||
private static double elapsedTime(int threads,
|
||||
IntegerMatrix intA, IntegerMatrix intAA,
|
||||
LongMatrix longA, LongMatrix longAA,
|
||||
FloatMatrix floatA, FloatMatrix floatAA,
|
||||
DoubleMatrix doubleA, DoubleMatrix doubleAA) {
|
||||
|
||||
println("");
|
||||
print("Computing A*A with " + threads + " thread(s):");
|
||||
long mark1 = System.currentTimeMillis();
|
||||
intAA.setSquareOf(intA, threads);
|
||||
longAA.setSquareOf(longA, threads);
|
||||
floatAA.setSquareOf(floatA, threads);
|
||||
doubleAA.setSquareOf(doubleA, threads);
|
||||
long mark2 = System.currentTimeMillis();
|
||||
println(" done.");
|
||||
|
||||
int size = intA.size();
|
||||
double sec = (mark2 - mark1) / 1000.0;
|
||||
double perf = 4 * size * size * (size + size) / sec;
|
||||
println("Elapsed time: " + sec + " seconds");
|
||||
println("Performance: " + perf / 1e6 + " MOPS");
|
||||
|
||||
return sec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute <code>A*A</code> for <code>int</code> matrix <code>A</code>.
|
||||
*/
|
||||
private static class IntegerMatrix {
|
||||
volatile int value[][];
|
||||
|
||||
/**
|
||||
* Number of lines and columns in <code>this</code> square matrix.
|
||||
*/
|
||||
public int size() {
|
||||
return value.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* New square matrix with random elements.
|
||||
*/
|
||||
public IntegerMatrix(int size) {
|
||||
value = new int[size][size];
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
value[line][column] =
|
||||
Math.round((float) ((1 - 2 * Math.random()) * size));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign <code>this</code> matrix with <code>A*A</code>.
|
||||
*
|
||||
* @param threads Split computation into the given number of threads.
|
||||
*/
|
||||
public void setSquareOf(IntegerMatrix A, int threads) {
|
||||
if (this.size() != A.size())
|
||||
throw new IllegalArgumentException(
|
||||
"this.size() != A.size()");
|
||||
|
||||
if ((size() % threads) != 0)
|
||||
throw new IllegalArgumentException("size()%threads != 0");
|
||||
int bunch = size() / threads;
|
||||
|
||||
Thread task[] = new Thread[threads];
|
||||
for (int t = 0; t < threads; t++) {
|
||||
int line0 = bunch * t;
|
||||
MatrixComputer computer =
|
||||
new MatrixComputer(value, A.value, line0, bunch);
|
||||
task[t] = new Thread(computer);
|
||||
}
|
||||
|
||||
for (int t = 0; t < threads; t++)
|
||||
task[t].start();
|
||||
|
||||
for (int t = 0; t < threads; t++)
|
||||
if (task[t].isAlive())
|
||||
try {
|
||||
task[t].join();
|
||||
} catch (InterruptedException exception) {
|
||||
throw new RuntimeException(exception.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread to compute a bunch of lines of matrix square.
|
||||
*/
|
||||
private static class MatrixComputer implements Runnable {
|
||||
private int result[][];
|
||||
private int source[][];
|
||||
private int line0;
|
||||
private int bunch;
|
||||
|
||||
/**
|
||||
* Register a task for matrix multiplication.
|
||||
*/
|
||||
public MatrixComputer(
|
||||
int result[][], int source[][], int line0, int bunch) {
|
||||
|
||||
this.result = result; // reference to resulting matrix value
|
||||
this.source = source; // reference to matrix to be squared
|
||||
this.line0 = line0; // compute lines from line0 to ...
|
||||
this.bunch = bunch; // number of resulting lines to compute
|
||||
}
|
||||
|
||||
/**
|
||||
* Do execute the task just registered for <code>this</code> thread.
|
||||
*/
|
||||
public void run() {
|
||||
int line1 = line0 + bunch;
|
||||
int size = result.length;
|
||||
for (int line = line0; line < line1; line++)
|
||||
for (int column = 0; column < size; column++) {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
sum += source[line][i] * source[i][column];
|
||||
result[line][column] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute <code>A*A</code> for <code>long</code> matrix <code>A</code>.
|
||||
*/
|
||||
private static class LongMatrix {
|
||||
volatile long value[][];
|
||||
|
||||
/**
|
||||
* Number of lines and columns in <code>this</code> square matrix.
|
||||
*/
|
||||
public int size() {
|
||||
return value.length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* New square matrix with the given integer elements.
|
||||
*/
|
||||
public LongMatrix(IntegerMatrix A) {
|
||||
int size = A.size();
|
||||
value = new long[size][size];
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
value[line][column] = A.value[line][column];
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign <code>this</code> matrix with <code>A*A</code>.
|
||||
*
|
||||
* @param threads Split computation into the given number of threads.
|
||||
*/
|
||||
public void setSquareOf(LongMatrix A, int threads) {
|
||||
if (this.size() != A.size())
|
||||
throw new IllegalArgumentException(
|
||||
"this.size() != A.size()");
|
||||
|
||||
if ((size() % threads) != 0)
|
||||
throw new IllegalArgumentException("size()%threads != 0");
|
||||
int bunch = size() / threads;
|
||||
|
||||
Thread task[] = new Thread[threads];
|
||||
for (int t = 0; t < threads; t++) {
|
||||
int line0 = bunch * t;
|
||||
MatrixComputer computer =
|
||||
new MatrixComputer(value, A.value, line0, bunch);
|
||||
task[t] = new Thread(computer);
|
||||
}
|
||||
|
||||
for (int t = 0; t < threads; t++)
|
||||
task[t].start();
|
||||
|
||||
for (int t = 0; t < threads; t++)
|
||||
if (task[t].isAlive())
|
||||
try {
|
||||
task[t].join();
|
||||
} catch (InterruptedException exception) {
|
||||
throw new RuntimeException(exception.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread to compute a bunch of lines of matrix square.
|
||||
*/
|
||||
private static class MatrixComputer implements Runnable {
|
||||
private long result[][];
|
||||
private long source[][];
|
||||
private int line0;
|
||||
private int bunch;
|
||||
|
||||
/**
|
||||
* Register a task for matrix multiplication.
|
||||
*/
|
||||
public MatrixComputer(
|
||||
long result[][], long source[][], int line0, int bunch) {
|
||||
|
||||
this.result = result; // reference to resulting matrix value
|
||||
this.source = source; // reference to matrix to be squared
|
||||
this.line0 = line0; // compute lines from line0 to ...
|
||||
this.bunch = bunch; // number of resulting lines to compute
|
||||
}
|
||||
|
||||
/**
|
||||
* Do execute the task just registered for <code>this</code> thread.
|
||||
*/
|
||||
public void run() {
|
||||
int line1 = line0 + bunch;
|
||||
int size = result.length;
|
||||
for (int line = line0; line < line1; line++)
|
||||
for (int column = 0; column < size; column++) {
|
||||
long sum = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
sum += source[line][i] * source[i][column];
|
||||
result[line][column] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute <code>A*A</code> for <code>float</code> matrix <code>A</code>.
|
||||
*/
|
||||
private static class FloatMatrix {
|
||||
volatile float value[][];
|
||||
|
||||
/**
|
||||
* Number of lines and columns in <code>this</code> square matrix.
|
||||
*/
|
||||
public int size() {
|
||||
return value.length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* New square matrix with the given integer elements.
|
||||
*/
|
||||
public FloatMatrix(IntegerMatrix A) {
|
||||
int size = A.size();
|
||||
value = new float[size][size];
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
value[line][column] = A.value[line][column];
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign <code>this</code> matrix with <code>A*A</code>.
|
||||
*
|
||||
* @param threads Split computation into the given number of threads.
|
||||
*/
|
||||
public void setSquareOf(FloatMatrix A, int threads) {
|
||||
if (this.size() != A.size())
|
||||
throw new IllegalArgumentException(
|
||||
"this.size() != A.size()");
|
||||
|
||||
if ((size() % threads) != 0)
|
||||
throw new IllegalArgumentException("size()%threads != 0");
|
||||
int bunch = size() / threads;
|
||||
|
||||
Thread task[] = new Thread[threads];
|
||||
for (int t = 0; t < threads; t++) {
|
||||
int line0 = bunch * t;
|
||||
MatrixComputer computer =
|
||||
new MatrixComputer(value, A.value, line0, bunch);
|
||||
task[t] = new Thread(computer);
|
||||
}
|
||||
|
||||
for (int t = 0; t < threads; t++)
|
||||
task[t].start();
|
||||
|
||||
for (int t = 0; t < threads; t++)
|
||||
if (task[t].isAlive())
|
||||
try {
|
||||
task[t].join();
|
||||
} catch (InterruptedException exception) {
|
||||
throw new RuntimeException(exception.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread to compute a bunch of lines of matrix square.
|
||||
*/
|
||||
private static class MatrixComputer implements Runnable {
|
||||
private float result[][];
|
||||
private float source[][];
|
||||
private int line0;
|
||||
private int bunch;
|
||||
|
||||
/**
|
||||
* Register a task for matrix multiplication.
|
||||
*/
|
||||
public MatrixComputer(
|
||||
float result[][], float source[][], int line0, int bunch) {
|
||||
|
||||
this.result = result; // reference to resulting matrix value
|
||||
this.source = source; // reference to matrix to be squared
|
||||
this.line0 = line0; // compute lines from line0 to ...
|
||||
this.bunch = bunch; // number of resulting lines to compute
|
||||
}
|
||||
|
||||
/**
|
||||
* Do execute the task just registered for <code>this</code> thread.
|
||||
*/
|
||||
public void run() {
|
||||
int line1 = line0 + bunch;
|
||||
int size = result.length;
|
||||
for (int line = line0; line < line1; line++)
|
||||
for (int column = 0; column < size; column++) {
|
||||
float sum = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
sum += source[line][i] * source[i][column];
|
||||
result[line][column] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute <code>A*A</code> for <code>float</code> matrix <code>A</code>.
|
||||
*/
|
||||
private static class DoubleMatrix {
|
||||
volatile double value[][];
|
||||
|
||||
/**
|
||||
* Number of lines and columns in <code>this</code> square matrix.
|
||||
*/
|
||||
public int size() {
|
||||
return value.length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* New square matrix with the given integer elements.
|
||||
*/
|
||||
public DoubleMatrix(IntegerMatrix A) {
|
||||
int size = A.size();
|
||||
value = new double[size][size];
|
||||
for (int line = 0; line < size; line++)
|
||||
for (int column = 0; column < size; column++)
|
||||
value[line][column] = A.value[line][column];
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign <code>this</code> matrix with <code>A*A</code>.
|
||||
*
|
||||
* @param threads Split computation into the given number of threads.
|
||||
*/
|
||||
public void setSquareOf(DoubleMatrix A, int threads) {
|
||||
if (this.size() != A.size())
|
||||
throw new IllegalArgumentException(
|
||||
"this.size() != A.size()");
|
||||
|
||||
if ((size() % threads) != 0)
|
||||
throw new IllegalArgumentException("size()%threads != 0");
|
||||
int bunch = size() / threads;
|
||||
|
||||
Thread task[] = new Thread[threads];
|
||||
for (int t = 0; t < threads; t++) {
|
||||
int line0 = bunch * t;
|
||||
MatrixComputer computer =
|
||||
new MatrixComputer(value, A.value, line0, bunch);
|
||||
task[t] = new Thread(computer);
|
||||
}
|
||||
|
||||
for (int t = 0; t < threads; t++)
|
||||
task[t].start();
|
||||
|
||||
for (int t = 0; t < threads; t++)
|
||||
if (task[t].isAlive())
|
||||
try {
|
||||
task[t].join();
|
||||
} catch (InterruptedException exception) {
|
||||
throw new RuntimeException(exception.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread to compute a bunch of lines of matrix square.
|
||||
*/
|
||||
private static class MatrixComputer implements Runnable {
|
||||
private double result[][];
|
||||
private double source[][];
|
||||
private int line0;
|
||||
private int bunch;
|
||||
|
||||
/**
|
||||
* Register a task for matrix multiplication.
|
||||
*/
|
||||
public MatrixComputer(
|
||||
double result[][], double source[][], int line0, int bunch) {
|
||||
|
||||
this.result = result; // reference to resulting matrix value
|
||||
this.source = source; // reference to matrix to be squared
|
||||
this.line0 = line0; // compute lines from line0 to ...
|
||||
this.bunch = bunch; // number of resulting lines to compute
|
||||
}
|
||||
|
||||
/**
|
||||
* Do execute the task just registered for <code>this</code> thread.
|
||||
*/
|
||||
public void run() {
|
||||
int line1 = line0 + bunch;
|
||||
int size = result.length;
|
||||
for (int line = line0; line < line1; line++)
|
||||
for (int column = 0; column < size; column++) {
|
||||
double sum = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
sum += source[line][i] * source[i][column];
|
||||
result[line][column] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
#
|
||||
# Copyright (c) 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.
|
||||
#
|
||||
|
||||
exclusiveAccess.dirs=.
|
||||
90
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack001.java
Normal file
90
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack001.java
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/stack/stack001.
|
||||
* VM testbase keywords: [stress, quick, stack, nonconcurrent]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* Provoke StackOverflowError by infinite recursion in Java method,
|
||||
* intercept the exception try to make one more invocation.
|
||||
* COMMENTS
|
||||
* Kestrel for Solaris_JDK_1.3-b10 crashes while trying to execute
|
||||
* this test with Client HS VM.
|
||||
* See lots of bugs concerning similar failuires:
|
||||
* Evaluated:
|
||||
* 4217960 [native stack overflow bug] reflection test causes crash
|
||||
* Accepted:
|
||||
* 4285716 native stack overflow causes crash on Solaris
|
||||
* 4281578 Second stack overflow crashes HotSpot VM
|
||||
* Closed (duplicate):
|
||||
* 4027933 Native stack overflows not detected or handled correctly
|
||||
* 4134353 (hpi) sysThreadCheckStack is a no-op on win32
|
||||
* 4185411 Various crashes when using recursive reflection.
|
||||
* 4167055 infinite recursion in FindClass
|
||||
* 4222359 Infinite recursion crashes jvm
|
||||
* Closed (will not fix):
|
||||
* 4231968 StackOverflowError in a native method causes Segmentation Fault
|
||||
* 4254634 println() while catching StackOverflowError causes hotspot VM crash
|
||||
* 4302288 the second stack overflow causes Classic VM to exit on win32
|
||||
*
|
||||
* @run main/othervm nsk.stress.stack.stack001
|
||||
*/
|
||||
|
||||
package nsk.stress.stack;
|
||||
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class stack001 {
|
||||
public static void main(String[] args) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
stack001 test = new stack001();
|
||||
test.recurse(0);
|
||||
out.println("Maximal depth: " + test.maxdepth);
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int maxdepth;
|
||||
|
||||
private void recurse(int depth) {
|
||||
maxdepth = depth;
|
||||
try {
|
||||
recurse(depth + 1);
|
||||
} catch (Error error) {
|
||||
if (!(error instanceof StackOverflowError) &&
|
||||
!(error instanceof OutOfMemoryError))
|
||||
throw error;
|
||||
|
||||
if (maxdepth == depth)
|
||||
recurse(depth + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
152
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack002.java
Normal file
152
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack002.java
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/stack/stack002.
|
||||
* VM testbase keywords: [stress, quick, stack, nonconcurrent]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* Provoke StackOverflowError by infinite recursion in Java method,
|
||||
* intercept the exception and continue to invoke that method until
|
||||
* the test exceeds timeout, or until Java VM crashes.
|
||||
* COMMENTS
|
||||
* I believe that the test causes HS crashes due to the following bug:
|
||||
* 4330318 (P2/S2) NSK test fails as An irrecoverable stack overflow
|
||||
* See also bugs (lots of bugs!):
|
||||
* Evaluated:
|
||||
* 4217960 [native stack overflow bug] reflection test causes crash
|
||||
* Accepted:
|
||||
* 4285716 native stack overflow causes crash on Solaris
|
||||
* 4281578 Second stack overflow crashes HotSpot VM
|
||||
* Closed (duplicate):
|
||||
* 4027933 Native stack overflows not detected or handled correctly
|
||||
* 4134353 (hpi) sysThreadCheckStack is a no-op on win32
|
||||
* 4185411 Various crashes when using recursive reflection.
|
||||
* 4167055 infinite recursion in FindClass
|
||||
* 4222359 Infinite recursion crashes jvm
|
||||
* Closed (will not fix):
|
||||
* 4231968 StackOverflowError in a native method causes Segmentation Fault
|
||||
* 4254634 println() while catching StackOverflowError causes hotspot VM crash
|
||||
* 4302288 the second stack overflow causes Classic VM to exit on win32
|
||||
*
|
||||
* @run main/othervm nsk.stress.stack.stack002
|
||||
*/
|
||||
|
||||
package nsk.stress.stack;
|
||||
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class stack002 {
|
||||
static final long timeout = 10000; // 10 seconds
|
||||
|
||||
public static void main(String[] args) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
Tester tester = new Tester(out);
|
||||
Timer timer = new Timer(tester);
|
||||
timer.start();
|
||||
tester.start();
|
||||
while (timer.isAlive())
|
||||
try {
|
||||
timer.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace(out);
|
||||
return 2;
|
||||
}
|
||||
// if (tester.isAlive())
|
||||
// return 2;
|
||||
out.println("Maximal depth: " + tester.maxdepth);
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static class Tester extends Thread {
|
||||
int maxdepth;
|
||||
PrintStream out;
|
||||
|
||||
public Tester(PrintStream out) {
|
||||
this.out = out;
|
||||
maxdepth = 0;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
recurse(0);
|
||||
}
|
||||
|
||||
void recurse(int depth) {
|
||||
maxdepth = depth;
|
||||
try {
|
||||
recurse(depth + 1);
|
||||
// } catch (StackOverflowError e) {
|
||||
//
|
||||
// OutOfMemoryError is also eligible to indicate stack overflow:
|
||||
//
|
||||
} catch (Error error) {
|
||||
if (!(error instanceof StackOverflowError) &&
|
||||
!(error instanceof OutOfMemoryError))
|
||||
throw error;
|
||||
|
||||
/***
|
||||
*** Originally, I supposed that VM crashes because of unexpected
|
||||
*** native stack overflow (println() invokes native method).
|
||||
*** However, I found that HS 1.3 and HS 2.0 crash even on
|
||||
*** invocation of Java (not native) method.
|
||||
***
|
||||
out.println("StackOverflowError, depth=" + depth);
|
||||
***/
|
||||
recurse(depth + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class Timer extends Thread {
|
||||
private Tester tester;
|
||||
|
||||
public Timer(Tester tester) {
|
||||
this.tester = tester;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
long started;
|
||||
started = System.currentTimeMillis();
|
||||
while (System.currentTimeMillis() - started < timeout)
|
||||
; /***
|
||||
*** The test hangs on JDK 1.2.2 Classic VM if sleep() is invoked.
|
||||
***
|
||||
try {
|
||||
this.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace(tester.out);
|
||||
return;
|
||||
};
|
||||
***/
|
||||
tester.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
93
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack003.java
Normal file
93
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack003.java
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/stack/stack003.
|
||||
* VM testbase keywords: [stress, stack, nonconcurrent]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test provokes multiple stack overflows in the same thread
|
||||
* by invoking static recursive method for the given fixed depth
|
||||
* of recursion (though, for a large depth).
|
||||
* This test makes measures a number of recursive invocations
|
||||
* before 1st StackOverflowError, and then tries to reproduce
|
||||
* such StackOverflowError 100 times -- each time by trying to
|
||||
* invoke the same recursive method for the given fixed depth
|
||||
* of invocations (which is twice that depth just measured).
|
||||
* The test is deemed passed, if VM have not crashed.
|
||||
* COMMENTS
|
||||
* This test crashes all HS versions (2.0, 1.3, 1.4) on all
|
||||
* platforms (Win32, Solaris, Linux) in all execution modes
|
||||
* (-Xint, -Xmixed, -Xcomp) in 100% of executions in which
|
||||
* I had tryied it.
|
||||
* See the bug:
|
||||
* 4366625 (P4/S4) multiple stack overflow causes HS crash
|
||||
*
|
||||
* @run main/othervm nsk.stress.stack.stack003
|
||||
*/
|
||||
|
||||
package nsk.stress.stack;
|
||||
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class stack003 {
|
||||
final static int ITERATIONS = 100;
|
||||
final static int INCREMENT = 100;
|
||||
|
||||
public static void main(String[] args) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
int depth;
|
||||
for (depth = 1; ; depth += INCREMENT)
|
||||
try {
|
||||
recurse(depth);
|
||||
} catch (StackOverflowError soe) {
|
||||
break;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
break;
|
||||
}
|
||||
out.println("Max. depth: " + depth);
|
||||
for (int i = 0; i < ITERATIONS; i++)
|
||||
try {
|
||||
recurse(2 * depth);
|
||||
out.println("?");
|
||||
} catch (StackOverflowError soe) {
|
||||
// OK.
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Also OK.
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void recurse(int depth) {
|
||||
if (depth > 0)
|
||||
recurse(depth - 1);
|
||||
}
|
||||
}
|
||||
96
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack004.java
Normal file
96
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack004.java
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/stack/stack004.
|
||||
* VM testbase keywords: [stress, stack, nonconcurrent]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test provokes multiple stack overflows in the same thread
|
||||
* by invoking final static recursive method for the given fixed
|
||||
* depth of recursion (though, for a large depth).
|
||||
* This test makes measures a number of recursive invocations
|
||||
* before 1st StackOverflowError, and then tries to reproduce
|
||||
* such StackOverflowError 100 times -- each time by trying to
|
||||
* invoke the same recursive method for the given fixed depth
|
||||
* of invocations (which is twice that depth just measured).
|
||||
* The test is deemed passed, if VM have not crashed.
|
||||
* COMMENTS
|
||||
* This test crashes all HS versions (2.0, 1.3, 1.4) on all
|
||||
* platforms (Win32, Solaris, Linux) in all execution modes
|
||||
* (-Xint, -Xmixed, -Xcomp) in 100% of executions in which
|
||||
* I had tryied it.
|
||||
* See the bug:
|
||||
* 4366625 (P4/S4) multiple stack overflow causes HS crash
|
||||
*
|
||||
* @run main/othervm nsk.stress.stack.stack004
|
||||
*/
|
||||
|
||||
package nsk.stress.stack;
|
||||
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class stack004 {
|
||||
public static void main(String[] args) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
stack004 test = new stack004();
|
||||
int exitCode = test.doRun(args, out);
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
public int doRun(String args[], PrintStream out) {
|
||||
int depth;
|
||||
for (depth = 100; ; depth += 100)
|
||||
try {
|
||||
recurse(depth);
|
||||
} catch (StackOverflowError soe) {
|
||||
break;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
break;
|
||||
}
|
||||
out.println("Max. depth: " + depth);
|
||||
for (int i = 0; i < 100; i++)
|
||||
try {
|
||||
recurse(2 * depth);
|
||||
out.println("?");
|
||||
} catch (StackOverflowError soe) {
|
||||
// OK.
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Also OK.
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
final static void recurse(int depth) {
|
||||
if (depth > 0)
|
||||
recurse(depth - 1);
|
||||
}
|
||||
}
|
||||
91
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack005.java
Normal file
91
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack005.java
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/stack/stack005.
|
||||
* VM testbase keywords: [stress, quick, stack, nonconcurrent]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test provokes multiple stack overflows in the same thread
|
||||
* by invoking final recursive method for the given fixed depth of
|
||||
* recursion (though, for a large depth).
|
||||
* This test makes measures a number of recursive invocations
|
||||
* before 1st StackOverflowError, and then tries to reproduce
|
||||
* such StackOverflowError 100 times -- each time by trying to
|
||||
* invoke the same recursive method for the given fixed depth
|
||||
* of invocations (which is twice that depth just measured).
|
||||
* The test is deemed passed, if VM have not crashed.
|
||||
* COMMENTS
|
||||
* This test crashes all HS versions (2.0, 1.3, 1.4) on all
|
||||
* platforms (Win32, Solaris, Linux) in all execution modes
|
||||
* (-Xint, -Xmixed, -Xcomp) in 100% of executions in which
|
||||
* I had tryied it.
|
||||
* See the bug:
|
||||
* 4366625 (P4/S4) multiple stack overflow causes HS crash
|
||||
*
|
||||
* @run main/othervm nsk.stress.stack.stack005
|
||||
*/
|
||||
|
||||
package nsk.stress.stack;
|
||||
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class stack005 {
|
||||
public static void main(String[] args) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
stack005 test = new stack005();
|
||||
int depth;
|
||||
for (depth = 100; ; depth += 100)
|
||||
try {
|
||||
test.recurse(depth);
|
||||
} catch (StackOverflowError soe) {
|
||||
break;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
break;
|
||||
}
|
||||
out.println("Max. depth: " + depth);
|
||||
for (int i = 0; i < 100; i++)
|
||||
try {
|
||||
test.recurse(2 * depth);
|
||||
out.println("?");
|
||||
} catch (StackOverflowError soe) {
|
||||
// OK.
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Also OK.
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
final void recurse(int depth) {
|
||||
if (depth > 0)
|
||||
recurse(depth - 1);
|
||||
}
|
||||
}
|
||||
95
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack006.java
Normal file
95
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack006.java
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/stack/stack006.
|
||||
* VM testbase keywords: [stress, stack, nonconcurrent]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test provokes multiple stack overflows in the same thread
|
||||
* by invoking virtual recursive method for the given fixed depth
|
||||
* of recursion (though, for a large depth).
|
||||
* This test makes measures a number of recursive invocations
|
||||
* before 1st StackOverflowError, and then tries to reproduce
|
||||
* such StackOverflowError 100 times -- each time by trying to
|
||||
* invoke the same recursive method for the given fixed depth
|
||||
* of invocations (which is twice that depth just measured).
|
||||
* The test is deemed passed, if VM have not crashed.
|
||||
* COMMENTS
|
||||
* This test crashes all HS versions (2.0, 1.3, 1.4) on all
|
||||
* platforms (Win32, Solaris, Linux) in all execution modes
|
||||
* (-Xint, -Xmixed, -Xcomp) in 100% of executions in which
|
||||
* I had tryied it.
|
||||
* See the bug:
|
||||
* 4366625 (P4/S4) multiple stack overflow causes HS crash
|
||||
*
|
||||
* @run main/othervm nsk.stress.stack.stack006
|
||||
*/
|
||||
|
||||
package nsk.stress.stack;
|
||||
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class stack006 implements stack006i {
|
||||
public static void main(String[] args) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
stack006i test = new stack006();
|
||||
int depth;
|
||||
for (depth = 100; ; depth += 100)
|
||||
try {
|
||||
test.recurse(depth);
|
||||
} catch (StackOverflowError soe) {
|
||||
break;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
break;
|
||||
}
|
||||
out.println("Max. depth: " + depth);
|
||||
for (int i = 0; i < 100; i++)
|
||||
try {
|
||||
test.recurse(2 * depth);
|
||||
out.println("?");
|
||||
} catch (StackOverflowError soe) {
|
||||
// OK.
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Also OK.
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void recurse(int depth) {
|
||||
if (depth > 0)
|
||||
recurse(depth - 1);
|
||||
}
|
||||
}
|
||||
|
||||
interface stack006i {
|
||||
void recurse(int depth);
|
||||
}
|
||||
97
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack007.java
Normal file
97
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack007.java
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/stack/stack007.
|
||||
* VM testbase keywords: [stress, stack, nonconcurrent]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test provokes multiple stack overflows in the same thread
|
||||
* by invoking synchronized virtual recursive method for the given
|
||||
* fixed depth of recursion (though, for a large depth).
|
||||
* This test makes measures a number of recursive invocations
|
||||
* before 1st StackOverflowError, and then tries to reproduce
|
||||
* such StackOverflowError 10000 times -- each time by trying to
|
||||
* invoke the same recursive method for the given fixed depth
|
||||
* of invocations (which is 10 times that depth just measured).
|
||||
* The test is deemed passed, if VM have not crashed.
|
||||
* COMMENTS
|
||||
* This test crashes HS versions 1.3 and 1.4 on Win32, Solaris,
|
||||
* and Linux platforms in all execution modes. However, it passes
|
||||
* against HS 2.0 on Win32 platform.
|
||||
* See also the bug:
|
||||
* 4366625 (P4/S4) multiple stack overflow causes HS crash
|
||||
*
|
||||
* @run main/othervm nsk.stress.stack.stack007
|
||||
*/
|
||||
|
||||
package nsk.stress.stack;
|
||||
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class stack007 implements stack007i {
|
||||
final static int ITERATIONS = 1000;
|
||||
final static int INCREMENT = 100;
|
||||
|
||||
public static void main(String[] args) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
stack007i test = new stack007();
|
||||
int depth;
|
||||
for (depth = 100; ; depth += INCREMENT)
|
||||
try {
|
||||
test.recurse(depth);
|
||||
} catch (StackOverflowError soe) {
|
||||
break;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
break;
|
||||
}
|
||||
out.println("Max. depth: " + depth);
|
||||
for (int i = 0; i < ITERATIONS; i++)
|
||||
try {
|
||||
test.recurse(10 * depth);
|
||||
out.println("?");
|
||||
} catch (StackOverflowError soe) {
|
||||
// OK.
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Also OK.
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public synchronized void recurse(int depth) {
|
||||
if (depth > 0)
|
||||
recurse(depth - 1);
|
||||
}
|
||||
}
|
||||
|
||||
interface stack007i {
|
||||
void recurse(int depth);
|
||||
}
|
||||
148
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack008.java
Normal file
148
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack008.java
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/stack/stack008.
|
||||
* VM testbase keywords: [stress, stack, nonconcurrent, exclude]
|
||||
* VM testbase comments: 8139875
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test provokes multiple stack overflows in the same thread
|
||||
* by invocations via reflection. Recursive method is invoked for
|
||||
* the given fixed depth of recursion (though, for a large depth).
|
||||
* This test makes measures a number of recursive invocations
|
||||
* before 1st StackOverflowError, and then tries to reproduce
|
||||
* such StackOverflowError 100 times -- each time by trying to
|
||||
* invoke the same recursive method for the given fixed depth
|
||||
* of invocations (which is twice that depth just measured).
|
||||
* The test is deemed passed, if VM have not crashed.
|
||||
* COMMENTS
|
||||
* This test crashes all HS versions (2.0, 1.3, 1.4) on Solaris,
|
||||
* and crashes HS 2.0 on win32. However, it passes against HS 1.3
|
||||
* and 1.4 on Win32.
|
||||
* See the bug:
|
||||
* 4366625 (P4/S4) multiple stack overflow causes HS crash
|
||||
*
|
||||
* @ignore 8139875
|
||||
* @run main/othervm nsk.stress.stack.stack008
|
||||
*/
|
||||
|
||||
package nsk.stress.stack;
|
||||
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class stack008 {
|
||||
public static void main(String[] args) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
int depth;
|
||||
//
|
||||
// Measure maximal recursion depth until stack overflow:
|
||||
//
|
||||
for (depth = 100; ; depth += 100)
|
||||
try {
|
||||
invokeRecurse(depth);
|
||||
} catch (Throwable exception) {
|
||||
Throwable target = getTargetException(exception);
|
||||
if ((target instanceof StackOverflowError) ||
|
||||
(target instanceof OutOfMemoryError))
|
||||
break; // OK.
|
||||
target.printStackTrace(out);
|
||||
if (target instanceof ThreadDeath)
|
||||
throw (ThreadDeath) target;
|
||||
return 2;
|
||||
}
|
||||
out.println("Max. depth: " + depth);
|
||||
//
|
||||
// Provoke stack overflow multiple times:
|
||||
//
|
||||
for (int i = 0; i < 100; i++)
|
||||
try {
|
||||
invokeRecurse(2 * depth);
|
||||
// out.println("?");
|
||||
} catch (Throwable exception) {
|
||||
Throwable target = getTargetException(exception);
|
||||
if ((target instanceof StackOverflowError) ||
|
||||
(target instanceof OutOfMemoryError))
|
||||
continue; // OK.
|
||||
target.printStackTrace(out);
|
||||
if (target instanceof ThreadDeath)
|
||||
throw (ThreadDeath) target;
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static Throwable getTargetException(Throwable exception) {
|
||||
Throwable target;
|
||||
//
|
||||
// Unwrap deep chain of exceptions:
|
||||
//
|
||||
for (
|
||||
target = exception;
|
||||
target instanceof InvocationTargetException;
|
||||
target = ((InvocationTargetException) target).getTargetException()
|
||||
)
|
||||
;
|
||||
return target;
|
||||
}
|
||||
|
||||
static Method method = null;
|
||||
static stack008 instance = null;
|
||||
static Object params[] = null;
|
||||
|
||||
private static void invokeRecurse(int depth) throws Exception {
|
||||
if (method == null) {
|
||||
//
|
||||
// Optimization trick: allocate once, use everywhere.
|
||||
//
|
||||
instance = new stack008();
|
||||
method = stack008.class.getMethod("recurse");
|
||||
params = new Object[]{};
|
||||
}
|
||||
//
|
||||
// Note, that the same instance.depth is used in all invocations:
|
||||
//
|
||||
instance.depth = depth;
|
||||
method.invoke(instance, params);
|
||||
}
|
||||
|
||||
int depth = 0;
|
||||
|
||||
public void recurse() throws Exception {
|
||||
if (depth > 0)
|
||||
//
|
||||
// Self-invoke via reflection:
|
||||
//
|
||||
invokeRecurse(depth - 1);
|
||||
}
|
||||
}
|
||||
94
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack009.java
Normal file
94
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack009.java
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/stack/stack009.
|
||||
* VM testbase keywords: [stress, quick, stack, nonconcurrent]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* The test provokes second stack overflow from within the
|
||||
* stack overflow handler.
|
||||
* This test measures a number of recursive invocations until
|
||||
* StackOverflowError, and then tries to make an invocation
|
||||
* for the fixed invocations depth from within the "catch"
|
||||
* block just caught the 1st stack overflow. The depth of new
|
||||
* invocations is 10 times that depth seen at the 1st stack
|
||||
* overflow; so that another stack overflow occurs.
|
||||
* The test is deemed passed, if VM have not crashed, and
|
||||
* if there is no exception thrown other than due to stack
|
||||
* overflow.
|
||||
* COMMENTS
|
||||
* This test crashes HS versions 2.0, 1.3, and 1.4 on Win32
|
||||
* and Solaris platforms.
|
||||
* See the bug:
|
||||
* 4366625 (P4/S4) multiple stack overflow causes HS crash
|
||||
*
|
||||
* @run main/othervm nsk.stress.stack.stack009
|
||||
*/
|
||||
|
||||
package nsk.stress.stack;
|
||||
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class stack009 {
|
||||
public static void main(String[] args) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
for (int depth = 100; ; depth += 100)
|
||||
try {
|
||||
recurse(depth);
|
||||
} catch (Error error1) {
|
||||
if (!(error1 instanceof StackOverflowError) &&
|
||||
!(error1 instanceof OutOfMemoryError))
|
||||
throw error1;
|
||||
|
||||
out.println("Max. depth: " + depth);
|
||||
|
||||
try {
|
||||
recurse(10 * depth);
|
||||
out.println("?");
|
||||
} catch (Error error2) {
|
||||
if (!(error2 instanceof StackOverflowError) &&
|
||||
!(error2 instanceof OutOfMemoryError))
|
||||
throw error2;
|
||||
|
||||
// Stack overflow is OK here.
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void recurse(int depth) {
|
||||
if (depth > 0)
|
||||
recurse(depth - 1);
|
||||
}
|
||||
}
|
||||
144
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack010.java
Normal file
144
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack010.java
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/stack/stack010.
|
||||
* VM testbase keywords: [stress, stack, nonconcurrent]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test provokes multiple stack overflows in the multiple
|
||||
* threads -- by invoking static recursive method for the given
|
||||
* fixed depth of recursion (though, for a large depth).
|
||||
* This test measures a number of recursive invocations until
|
||||
* stack overflow, and then tries to provoke similar stack overflows
|
||||
* 10 times in each of 10 threads. Each provocation consists of
|
||||
* invoking that recursive method for the given fixed depth
|
||||
* of invocations which is 10 times that depth measured before.
|
||||
* The test is deemed passed, if VM have not crashed, and
|
||||
* if exception other than due to stack overflow was not
|
||||
* thrown.
|
||||
* COMMENTS
|
||||
* This test crashes HS versions 2.0, 1.3, 1.4 on Win32 and Solaris
|
||||
* platforms.
|
||||
* See the bug:
|
||||
* 4366625 (P4/S4) multiple stack overflow causes HS crash
|
||||
*
|
||||
* @run main/othervm nsk.stress.stack.stack010
|
||||
*/
|
||||
|
||||
package nsk.stress.stack;
|
||||
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class stack010 extends Thread {
|
||||
final static int THREADS = 10;
|
||||
final static int CYCLES = 10;
|
||||
|
||||
public static void main(String[] args) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
//
|
||||
// Measure maximal recursion depth until stack overflow:
|
||||
//
|
||||
int maxDepth = 0;
|
||||
for (int depth = 10; ; depth += 10)
|
||||
try {
|
||||
recurse(depth);
|
||||
maxDepth = depth;
|
||||
} catch (StackOverflowError soe) {
|
||||
break;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
break;
|
||||
}
|
||||
out.println("Max. depth: " + maxDepth);
|
||||
|
||||
//
|
||||
// Execute multiple threads repeatedly provoking stack overflows:
|
||||
//
|
||||
stack010 threads[] = new stack010[THREADS];
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
threads[i] = new stack010();
|
||||
threads[i].depthToTry = 10 * maxDepth;
|
||||
threads[i].start();
|
||||
}
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
if (threads[i].isAlive())
|
||||
try {
|
||||
threads[i].join();
|
||||
} catch (InterruptedException exception) {
|
||||
exception.printStackTrace(out);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if unexpected exceptions were not thrown:
|
||||
//
|
||||
int exitCode = 0;
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
if (threads[i].thrown != null) {
|
||||
threads[i].thrown.printStackTrace(out);
|
||||
exitCode = 2;
|
||||
}
|
||||
|
||||
if (exitCode != 0)
|
||||
out.println("# TEST FAILED");
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
int depthToTry = 0;
|
||||
Throwable thrown = null;
|
||||
|
||||
public void run() {
|
||||
for (int i = 0; i < CYCLES; i++)
|
||||
try {
|
||||
recurse(depthToTry);
|
||||
throw new Exception(
|
||||
"TEST_RFE: no stack overflow thrown" +
|
||||
", need to try deeper recursion?");
|
||||
|
||||
} catch (StackOverflowError soe) {
|
||||
// It's OK: stack overflow was expected.
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Also OK: out of memory may indacate stack overflow.
|
||||
|
||||
} catch (Throwable throwable) {
|
||||
if (throwable instanceof ThreadDeath)
|
||||
throw (ThreadDeath) throwable;
|
||||
// It isn't OK!
|
||||
thrown = throwable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void recurse(int depth) {
|
||||
if (depth > 0)
|
||||
recurse(depth - 1);
|
||||
}
|
||||
}
|
||||
144
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack011.java
Normal file
144
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack011.java
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/stack/stack011.
|
||||
* VM testbase keywords: [stress, stack, nonconcurrent]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test provokes multiple stack overflows in the multiple
|
||||
* threads -- by invoking final static recursive method for the
|
||||
* given fixed depth of recursion (though, for a large depth).
|
||||
* This test measures a number of recursive invocations until
|
||||
* stack overflow, and then tries to provoke similar stack overflows
|
||||
* 10 times in each of 10 threads. Each provocation consists of
|
||||
* invoking that recursive method for the given fixed depth
|
||||
* of invocations which is 10 times that depth measured before.
|
||||
* The test is deemed passed, if VM have not crashed, and
|
||||
* if exception other than due to stack overflow was not
|
||||
* thrown.
|
||||
* COMMENTS
|
||||
* This test crashes HS versions 2.0, 1.3, 1.4 on Win32 and Solaris
|
||||
* platforms.
|
||||
* See the bug:
|
||||
* 4366625 (P4/S4) multiple stack overflow causes HS crash
|
||||
*
|
||||
* @run main/othervm nsk.stress.stack.stack011
|
||||
*/
|
||||
|
||||
package nsk.stress.stack;
|
||||
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class stack011 extends Thread {
|
||||
final static int THREADS = 10;
|
||||
final static int CYCLES = 10;
|
||||
|
||||
public static void main(String[] args) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
//
|
||||
// Measure maximal recursion depth until stack overflow:
|
||||
//
|
||||
int maxDepth = 0;
|
||||
for (int depth = 10; ; depth += 10)
|
||||
try {
|
||||
recurse(depth);
|
||||
maxDepth = depth;
|
||||
} catch (StackOverflowError soe) {
|
||||
break;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
break;
|
||||
}
|
||||
out.println("Max. depth: " + maxDepth);
|
||||
|
||||
//
|
||||
// Execute multiple threads repeatedly provoking stack overflows:
|
||||
//
|
||||
stack011 threads[] = new stack011[THREADS];
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
threads[i] = new stack011();
|
||||
threads[i].depthToTry = 10 * maxDepth;
|
||||
threads[i].start();
|
||||
}
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
if (threads[i].isAlive())
|
||||
try {
|
||||
threads[i].join();
|
||||
} catch (InterruptedException exception) {
|
||||
exception.printStackTrace(out);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if unexpected exceptions were not thrown:
|
||||
//
|
||||
int exitCode = 0;
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
if (threads[i].thrown != null) {
|
||||
threads[i].thrown.printStackTrace(out);
|
||||
exitCode = 2;
|
||||
}
|
||||
|
||||
if (exitCode != 0)
|
||||
out.println("# TEST FAILED");
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
int depthToTry = 0;
|
||||
Throwable thrown = null;
|
||||
|
||||
public void run() {
|
||||
for (int i = 0; i < CYCLES; i++)
|
||||
try {
|
||||
recurse(depthToTry);
|
||||
throw new Exception(
|
||||
"TEST_RFE: no stack overflow thrown" +
|
||||
", need to try deeper recursion?");
|
||||
|
||||
} catch (StackOverflowError error) {
|
||||
// It's OK: stack overflow was expected.
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Also OK: recursion may result in memory lack.
|
||||
|
||||
} catch (Throwable throwable) {
|
||||
if (throwable instanceof ThreadDeath)
|
||||
throw (ThreadDeath) throwable;
|
||||
// It isn't OK!
|
||||
thrown = throwable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
final static void recurse(int depth) {
|
||||
if (depth > 0)
|
||||
recurse(depth - 1);
|
||||
}
|
||||
}
|
||||
146
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack012.java
Normal file
146
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack012.java
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/stack/stack012.
|
||||
* VM testbase keywords: [stress, stack, nonconcurrent]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test provokes multiple stack overflows in the multiple
|
||||
* threads -- by invoking final recursive method for the given
|
||||
* fixed depth of recursion (though, for a large depth).
|
||||
* This test measures a number of recursive invocations until
|
||||
* stack overflow, and then tries to provoke similar stack overflows
|
||||
* 10 times in each of 10 threads. Each provocation consists of
|
||||
* invoking that recursive method for the given fixed depth
|
||||
* of invocations which is 10 times that depth measured before.
|
||||
* The test is deemed passed, if VM have not crashed, and
|
||||
* if exception other than due to stack overflow was not
|
||||
* thrown.
|
||||
* COMMENTS
|
||||
* This test crashes HS versions 1.3, 1.4 on Win32, and HS versions
|
||||
* 2.0, 1.3, and 1.4 on Solaris. However, it passes against HS 2.0
|
||||
* on Win32.
|
||||
* See the bug:
|
||||
* 4366625 (P4/S4) multiple stack overflow causes HS crash
|
||||
*
|
||||
* @run main/othervm nsk.stress.stack.stack012
|
||||
*/
|
||||
|
||||
package nsk.stress.stack;
|
||||
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class stack012 extends Thread {
|
||||
final static int THREADS = 10;
|
||||
final static int CYCLES = 10;
|
||||
|
||||
public static void main(String[] args) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
stack012 test = new stack012();
|
||||
//
|
||||
// Measure maximal recursion depth until stack overflow:
|
||||
//
|
||||
int maxDepth = 0;
|
||||
for (int depth = 10; ; depth += 10)
|
||||
try {
|
||||
test.recurse(depth);
|
||||
maxDepth = depth;
|
||||
} catch (StackOverflowError soe) {
|
||||
break;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
break;
|
||||
}
|
||||
out.println("Max. depth: " + maxDepth);
|
||||
|
||||
//
|
||||
// Execute multiple threads repeatedly provoking stack overflows:
|
||||
//
|
||||
stack012 threads[] = new stack012[THREADS];
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
threads[i] = new stack012();
|
||||
threads[i].depthToTry = 10 * maxDepth;
|
||||
threads[i].start();
|
||||
}
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
if (threads[i].isAlive())
|
||||
try {
|
||||
threads[i].join();
|
||||
} catch (InterruptedException exception) {
|
||||
exception.printStackTrace(out);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if unexpected exceptions were not thrown:
|
||||
//
|
||||
int exitCode = 0;
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
if (threads[i].thrown != null) {
|
||||
threads[i].thrown.printStackTrace(out);
|
||||
exitCode = 2;
|
||||
}
|
||||
|
||||
if (exitCode != 0)
|
||||
out.println("# TEST FAILED");
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
int depthToTry = 0;
|
||||
Throwable thrown = null;
|
||||
|
||||
public void run() {
|
||||
for (int i = 0; i < CYCLES; i++)
|
||||
try {
|
||||
this.recurse(depthToTry);
|
||||
throw new Exception(
|
||||
"TEST_RFE: no stack overflow thrown" +
|
||||
", need to try deeper recursion?");
|
||||
|
||||
} catch (StackOverflowError error) {
|
||||
// It's OK: stack overflow was expected.
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Also OK: invocation may result in out of memory.
|
||||
|
||||
} catch (Throwable throwable) {
|
||||
if (throwable instanceof ThreadDeath)
|
||||
throw (ThreadDeath) throwable;
|
||||
// It isn't OK!
|
||||
thrown = throwable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
final void recurse(int depth) {
|
||||
if (depth > 0)
|
||||
recurse(depth - 1);
|
||||
}
|
||||
}
|
||||
157
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack013.java
Normal file
157
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack013.java
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/stack/stack013.
|
||||
* VM testbase keywords: [stress, stack, nonconcurrent]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test provokes multiple stack overflows in the multiple
|
||||
* threads -- by invoking virtual recursive method for the given
|
||||
* fixed depth of recursion (though, for a large depth).
|
||||
* This test measures a number of recursive invocations until
|
||||
* stack overflow, and then tries to provoke similar stack overflows
|
||||
* 10 times in each of 10 threads. Each provocation consists of
|
||||
* invoking that recursive method for the given fixed depth
|
||||
* of invocations which is 10 times that depth measured before.
|
||||
* The test is deemed passed, if VM have not crashed, and
|
||||
* if exception other than due to stack overflow was not
|
||||
* thrown.
|
||||
* COMMENTS
|
||||
* This test crashes HS versions 2.0, 1.3, and 1.4 on both Win32
|
||||
* and Solaris platforms.
|
||||
* See the bug:
|
||||
* 4366625 (P4/S4) multiple stack overflow causes HS crash
|
||||
*
|
||||
* @run main/othervm nsk.stress.stack.stack013
|
||||
*/
|
||||
|
||||
package nsk.stress.stack;
|
||||
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class stack013 extends stack013i {
|
||||
final static int THREADS = 10;
|
||||
final static int CYCLES = 10;
|
||||
|
||||
public static void main(String[] args) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
stack013i test = new stack013();
|
||||
//
|
||||
// Measure maximal recursion depth until stack overflow:
|
||||
//
|
||||
int maxDepth = 0;
|
||||
for (int depth = 10; ; depth += 10)
|
||||
try {
|
||||
test.recurse(depth);
|
||||
maxDepth = depth;
|
||||
} catch (StackOverflowError soe) {
|
||||
break;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
break;
|
||||
}
|
||||
out.println("Max. depth: " + maxDepth);
|
||||
|
||||
//
|
||||
// Execute multiple threads repeatedly provoking stack overflows:
|
||||
//
|
||||
stack013i threads[] = new stack013i[THREADS];
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
threads[i] = new stack013();
|
||||
threads[i].depthToTry = 10 * maxDepth;
|
||||
threads[i].cycles = CYCLES;
|
||||
threads[i].start();
|
||||
}
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
if (threads[i].isAlive())
|
||||
try {
|
||||
threads[i].join();
|
||||
} catch (InterruptedException exception) {
|
||||
exception.printStackTrace(out);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if unexpected exceptions were thrown:
|
||||
//
|
||||
int exitCode = 0;
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
if (threads[i].thrown != null) {
|
||||
threads[i].thrown.printStackTrace(out);
|
||||
exitCode = 2;
|
||||
}
|
||||
|
||||
if (exitCode != 0)
|
||||
out.println("# TEST FAILED");
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
void recurse(int depth) {
|
||||
if (depth > 0)
|
||||
recurse(depth - 1);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class stack013i extends Thread {
|
||||
//
|
||||
// Pure virtual method:
|
||||
//
|
||||
abstract void recurse(int depth);
|
||||
|
||||
Throwable thrown = null;
|
||||
int depthToTry;
|
||||
int cycles;
|
||||
|
||||
public void run() {
|
||||
//
|
||||
// Provoke multiple stack overflows:
|
||||
//
|
||||
for (int i = 0; i < cycles; i++)
|
||||
try {
|
||||
recurse(depthToTry);
|
||||
throw new Exception(
|
||||
"TEST_RFE: no stack overflow thrown" +
|
||||
", need to try deeper recursion?");
|
||||
|
||||
} catch (StackOverflowError error) {
|
||||
// It's OK: stack overflow was expected.
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Also OK: out of memory is eligible here.
|
||||
|
||||
} catch (Throwable throwable) {
|
||||
if (throwable instanceof ThreadDeath)
|
||||
throw (ThreadDeath) throwable;
|
||||
// It isn't OK!
|
||||
thrown = throwable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
160
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack014.java
Normal file
160
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack014.java
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/stack/stack014.
|
||||
* VM testbase keywords: [stress, stack, nonconcurrent]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test provokes multiple stack overflows in the multiple
|
||||
* threads -- by invoking synchronized virtual recursive method
|
||||
* for the given fixed depth of recursion (though, for a large
|
||||
* depth). Note however, that different threads are not actual
|
||||
* synchronized, because different instances having the recursive
|
||||
* method are used.
|
||||
* This test measures a number of recursive invocations until
|
||||
* stack overflow, and then tries to provoke similar stack overflows
|
||||
* 10 times in each of 10 threads. Each provocation consists of
|
||||
* invoking that recursive method for the given fixed depth
|
||||
* of invocations which is 10 times that depth measured before.
|
||||
* The test is deemed passed, if VM have not crashed, and
|
||||
* if exception other than due to stack overflow was not
|
||||
* thrown.
|
||||
* COMMENTS
|
||||
* This test crashes HS versions 2.0, 1.3, and 1.4 on Solaris.
|
||||
* However, it passes against all these HS versions on Win32.
|
||||
* See the bug:
|
||||
* 4366625 (P4/S4) multiple stack overflow causes HS crash
|
||||
*
|
||||
* @run main/othervm nsk.stress.stack.stack014
|
||||
*/
|
||||
|
||||
package nsk.stress.stack;
|
||||
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class stack014 extends stack014i {
|
||||
final static int THREADS = 10;
|
||||
final static int CYCLES = 10;
|
||||
|
||||
public static void main(String[] args) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
stack014i test = new stack014();
|
||||
//
|
||||
// Measure maximal recursion depth until stack overflow:
|
||||
//
|
||||
int maxDepth = 0;
|
||||
for (int depth = 10; ; depth += 10)
|
||||
try {
|
||||
test.recurse(depth);
|
||||
maxDepth = depth;
|
||||
} catch (StackOverflowError soe) {
|
||||
break;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
break;
|
||||
}
|
||||
out.println("Max. depth: " + maxDepth);
|
||||
|
||||
//
|
||||
// Execute multiple threads repeatedly provoking stack overflows:
|
||||
//
|
||||
stack014i threads[] = new stack014i[THREADS];
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
threads[i] = new stack014();
|
||||
threads[i].depthToTry = 10 * maxDepth;
|
||||
threads[i].cycles = CYCLES;
|
||||
threads[i].start();
|
||||
}
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
if (threads[i].isAlive())
|
||||
try {
|
||||
threads[i].join();
|
||||
} catch (InterruptedException exception) {
|
||||
exception.printStackTrace(out);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if unexpected exceptions were thrown:
|
||||
//
|
||||
int exitCode = 0;
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
if (threads[i].thrown != null) {
|
||||
threads[i].thrown.printStackTrace(out);
|
||||
exitCode = 2;
|
||||
}
|
||||
|
||||
if (exitCode != 0)
|
||||
out.println("# TEST FAILED");
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
synchronized void recurse(int depth) {
|
||||
if (depth > 0)
|
||||
recurse(depth - 1);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class stack014i extends Thread {
|
||||
//
|
||||
// Pure virtual method:
|
||||
//
|
||||
abstract void recurse(int depth);
|
||||
|
||||
Throwable thrown = null;
|
||||
int depthToTry;
|
||||
int cycles;
|
||||
|
||||
public void run() {
|
||||
//
|
||||
// Provoke multiple stack overflows:
|
||||
//
|
||||
for (int i = 0; i < cycles; i++)
|
||||
try {
|
||||
recurse(depthToTry);
|
||||
throw new Exception(
|
||||
"TEST_RFE: no stack overflow thrown" +
|
||||
", need to try deeper recursion?");
|
||||
|
||||
} catch (StackOverflowError error) {
|
||||
// It's OK: stack overflow was expected.
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Also OK: if there is no memory for stack expansion.
|
||||
|
||||
} catch (Throwable throwable) {
|
||||
if (throwable instanceof ThreadDeath)
|
||||
throw (ThreadDeath) throwable;
|
||||
// It isn't OK!
|
||||
thrown = throwable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
182
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack015.java
Normal file
182
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack015.java
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/stack/stack015.
|
||||
* VM testbase keywords: [stress, stack, nonconcurrent]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test provokes multiple stack overflows in the multiple
|
||||
* threads -- by invoking synchronized virtual recursive method
|
||||
* for the given fixed depth of recursion from within another
|
||||
* recursive method already deeply invoked.
|
||||
* This test measures a number of recursive invocations until
|
||||
* stack overflow, and then tries to provoke similar stack overflows
|
||||
* in 10 times in each of 10 threads. Each provocation consists of
|
||||
* invoking that recursive method for the given fixed depth
|
||||
* of invocations which is 10 times that depth measured before.
|
||||
* The test is deemed passed, if VM have not crashed, and
|
||||
* if exception other than due to stack overflow was not
|
||||
* thrown.
|
||||
* COMMENTS
|
||||
* This test crashes HS versions 2.0, 1.3, and 1.4 on Solaris.
|
||||
* However, it passes against all these HS versions on Win32.
|
||||
* See the bug:
|
||||
* 4366625 (P4/S4) multiple stack overflow causes HS crash
|
||||
*
|
||||
* @run main/othervm nsk.stress.stack.stack015
|
||||
*/
|
||||
|
||||
package nsk.stress.stack;
|
||||
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class stack015 extends stack015i {
|
||||
final static int THREADS = 10;
|
||||
final static int CYCLES = 10;
|
||||
final static int STEP = 10;
|
||||
final static int RESERVE = 10;
|
||||
|
||||
public static void main(String[] args) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
//
|
||||
// The test will invoke the particular stack015.recurse()
|
||||
// method via abstract test.recurse() invocations.
|
||||
//
|
||||
stack015i test = new stack015();
|
||||
stack015i.test = test;
|
||||
|
||||
//
|
||||
// Measure maximal recursion depth until stack overflow:
|
||||
//
|
||||
int maxDepth = 0;
|
||||
for (int depth = 0; ; depth += STEP)
|
||||
try {
|
||||
test.recurse(depth);
|
||||
maxDepth = depth;
|
||||
} catch (StackOverflowError soe) {
|
||||
break;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
break;
|
||||
}
|
||||
out.println("Max. depth: " + maxDepth);
|
||||
|
||||
//
|
||||
// Execute multiple threads repeatedly provoking stack overflows:
|
||||
//
|
||||
stack015i threads[] = new stack015i[THREADS];
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
threads[i] = new stack015();
|
||||
threads[i].depthToTry = RESERVE * maxDepth;
|
||||
threads[i].start();
|
||||
}
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
if (threads[i].isAlive())
|
||||
try {
|
||||
threads[i].join();
|
||||
} catch (InterruptedException exception) {
|
||||
exception.printStackTrace(out);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if unexpected exceptions were thrown:
|
||||
//
|
||||
int exitCode = 0;
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
if (threads[i].thrown != null) {
|
||||
threads[i].thrown.printStackTrace(out);
|
||||
exitCode = 2;
|
||||
}
|
||||
|
||||
if (exitCode != 0)
|
||||
out.println("# TEST FAILED");
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
synchronized void syncRecurse(int depth) {
|
||||
if (depth > 0)
|
||||
syncRecurse(depth - 1);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class stack015i extends Thread {
|
||||
//
|
||||
// Pure virtual method:
|
||||
//
|
||||
abstract void syncRecurse(int depth);
|
||||
|
||||
void recurse(int depth) {
|
||||
//
|
||||
// Stack overflow must occur here:
|
||||
//
|
||||
syncRecurse(stack015.STEP);
|
||||
//
|
||||
// If no stack overflow occured, try again with deeper stack:
|
||||
//
|
||||
if (depth > 0)
|
||||
recurse(depth - 1);
|
||||
}
|
||||
|
||||
Throwable thrown = null;
|
||||
int depthToTry;
|
||||
|
||||
static stack015i test;
|
||||
|
||||
public void run() {
|
||||
//
|
||||
// Provoke multiple stack overflows:
|
||||
//
|
||||
for (int i = 0; i < stack015.CYCLES; i++)
|
||||
try {
|
||||
//
|
||||
// All threads invoke the same synchronized method:
|
||||
//
|
||||
test.recurse(depthToTry);
|
||||
|
||||
throw new Exception(
|
||||
"TEST_RFE: no stack overflow thrown" +
|
||||
", need to try deeper recursion?");
|
||||
|
||||
} catch (StackOverflowError error) {
|
||||
// It's OK: stack overflow was expected.
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Also OK: there may be no memory for stack expansion.
|
||||
|
||||
} catch (Throwable throwable) {
|
||||
if (throwable instanceof ThreadDeath)
|
||||
throw (ThreadDeath) throwable;
|
||||
// It isn't OK!
|
||||
thrown = throwable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
201
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack016.java
Normal file
201
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack016.java
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/stack/stack016.
|
||||
* VM testbase keywords: [stress, diehard, stack, nonconcurrent, exclude]
|
||||
* VM testbase comments: 8139875
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* The test provokes second stack overflow from within the
|
||||
* stack overflow handler -- repeatedly multiple times, and
|
||||
* in multiple threads.
|
||||
* This test measures a number of recursive invocations until
|
||||
* stack overflow, and then tries to provoke similar stack overflows
|
||||
* in 10 times in each of 10 threads. Each provocation consists of
|
||||
* invoking that recursive method for the given fixed depth
|
||||
* of invocations which is 10 times that depth measured before,
|
||||
* and then trying to invoke that recursive method once again
|
||||
* from within the catch clause just caught StackOverflowError.
|
||||
* The test is deemed passed, if VM have not crashed, and
|
||||
* if exception other than due to stack overflow was not
|
||||
* thrown.
|
||||
* COMMENTS
|
||||
* This test crashes HS versions 2.0, 1.3, and 1.4 on both
|
||||
* Solaris and Win32 platforms.
|
||||
* See the bug:
|
||||
* 4366625 (P4/S4) multiple stack overflow causes HS crash
|
||||
*
|
||||
* @ignore 8139875
|
||||
* @run main/othervm nsk.stress.stack.stack016 -eager
|
||||
*/
|
||||
|
||||
package nsk.stress.stack;
|
||||
|
||||
|
||||
import nsk.share.Harakiri;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class stack016 extends Thread {
|
||||
private final static int THREADS = 10;
|
||||
private final static int CYCLES = 10;
|
||||
private final static int STEP = 10;
|
||||
private final static int RESERVE = 10;
|
||||
private final static int PROBES = STEP * RESERVE;
|
||||
|
||||
public static void main(String[] args) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
verbose = false;
|
||||
boolean eager = false;
|
||||
for (int i = 0; i < args.length; i++)
|
||||
if (args[i].toLowerCase().equals("-verbose"))
|
||||
verbose = true;
|
||||
else if (args[i].toLowerCase().equals("-eager"))
|
||||
eager = true;
|
||||
if (!eager)
|
||||
Harakiri.appoint(Harakiri.parseAppointment(args));
|
||||
stack016.out = out;
|
||||
stack016 test = new stack016();
|
||||
return test.doRun();
|
||||
}
|
||||
|
||||
private static boolean verbose;
|
||||
private static PrintStream out;
|
||||
|
||||
private void display(Object message) {
|
||||
if (!verbose)
|
||||
return;
|
||||
synchronized (out) {
|
||||
out.println(message.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private int doRun() {
|
||||
//
|
||||
// Measure recursive depth before stack overflow:
|
||||
//
|
||||
int maxDepth = 0;
|
||||
for (depthToTry = 0; ; depthToTry += STEP)
|
||||
try {
|
||||
trickyRecurse(depthToTry);
|
||||
maxDepth = depthToTry;
|
||||
} catch (Error error) {
|
||||
break;
|
||||
}
|
||||
out.println("Maximal recursion depth: " + maxDepth);
|
||||
|
||||
//
|
||||
// Run the tested threads:
|
||||
//
|
||||
stack016 threads[] = new stack016[THREADS];
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
threads[i] = new stack016();
|
||||
threads[i].setName("Thread: " + (i + 1) + "/" + THREADS);
|
||||
threads[i].depthToTry = RESERVE * maxDepth;
|
||||
threads[i].start();
|
||||
}
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
if (threads[i].isAlive())
|
||||
try {
|
||||
threads[i].join();
|
||||
} catch (InterruptedException exception) {
|
||||
exception.printStackTrace(out);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if unexpected exceptions were thrown:
|
||||
//
|
||||
int exitCode = 0;
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
if (threads[i].thrown != null) {
|
||||
threads[i].thrown.printStackTrace(out);
|
||||
exitCode = 2;
|
||||
}
|
||||
|
||||
if (exitCode != 0)
|
||||
out.println("# TEST FAILED");
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
private int stackTop = 0;
|
||||
private int depthToTry = 0;
|
||||
private Throwable thrown = null;
|
||||
|
||||
private void trickyRecurse(int depth) {
|
||||
stackTop = depthToTry - depth;
|
||||
if (depth > 0)
|
||||
try {
|
||||
trickyRecurse(depth - 1);
|
||||
} catch (Error error) {
|
||||
if (!(error instanceof StackOverflowError) &&
|
||||
!(error instanceof OutOfMemoryError))
|
||||
throw error;
|
||||
|
||||
//
|
||||
// Provoke more stack overflow,
|
||||
// if current stack is deep enough:
|
||||
//
|
||||
if (depthToTry - depth < stackTop - PROBES)
|
||||
throw error;
|
||||
recurse(depthToTry);
|
||||
|
||||
throw new Error("TEST_RFE: try deeper recursion!");
|
||||
}
|
||||
}
|
||||
|
||||
private static void recurse(int depth) {
|
||||
if (depth > 0)
|
||||
recurse(depth - 1);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
String threadName = Thread.currentThread().getName();
|
||||
for (int i = 1; i <= CYCLES; i++)
|
||||
try {
|
||||
display(threadName + ", iteration: " + i + "/" + CYCLES);
|
||||
trickyRecurse(depthToTry);
|
||||
throw new Error(
|
||||
"TEST_BUG: trickyRecursion() must throw an error anyway!");
|
||||
|
||||
} catch (StackOverflowError error) {
|
||||
// It's OK: stack overflow was expected.
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Also OK, if there is no memory for stack expansion.
|
||||
|
||||
} catch (Throwable throwable) {
|
||||
if (throwable instanceof ThreadDeath)
|
||||
throw (ThreadDeath) throwable;
|
||||
thrown = throwable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
189
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack017.java
Normal file
189
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack017.java
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/stack/stack017.
|
||||
* VM testbase keywords: [stress, diehard, stack, nonconcurrent, exclude]
|
||||
* VM testbase comments: 8139875
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* The test invokes infinitely recursive method from within stack
|
||||
* overflow handler -- repeatedly multiple times, and in multiple
|
||||
* threads.
|
||||
* The test is deemed passed, if VM have not crashed, and
|
||||
* if exception other than due to stack overflow was not
|
||||
* thrown.
|
||||
* COMMENTS
|
||||
* This test crashes HS versions 2.0, 1.3, and 1.4 on both
|
||||
* Solaris and Win32 platforms.
|
||||
* See the bug:
|
||||
* 4366625 (P4/S4) multiple stack overflow causes HS crash
|
||||
*
|
||||
* @ignore 8139875
|
||||
* @run main/othervm nsk.stress.stack.stack017 -eager
|
||||
*/
|
||||
|
||||
package nsk.stress.stack;
|
||||
|
||||
|
||||
import nsk.share.Harakiri;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class stack017 extends Thread {
|
||||
private final static int THREADS = 10;
|
||||
private final static int CYCLES = 10;
|
||||
private final static int PROBES = 100;
|
||||
|
||||
public static void main(String[] args) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
verbose = false;
|
||||
boolean eager = false;
|
||||
for (int i = 0; i < args.length; i++)
|
||||
if (args[i].toLowerCase().equals("-verbose"))
|
||||
verbose = true;
|
||||
else if (args[i].toLowerCase().equals("-eager"))
|
||||
eager = true;
|
||||
if (!eager)
|
||||
Harakiri.appoint(Harakiri.parseAppointment(args));
|
||||
stack017.out = out;
|
||||
stack017 test = new stack017();
|
||||
return test.doRun();
|
||||
}
|
||||
|
||||
private static boolean verbose;
|
||||
private static PrintStream out;
|
||||
|
||||
private void display(Object message) {
|
||||
if (!verbose)
|
||||
return;
|
||||
synchronized (out) {
|
||||
out.println(message.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static int depthToTry;
|
||||
|
||||
private int doRun() {
|
||||
//
|
||||
// Measure recursive depth before stack overflow:
|
||||
//
|
||||
try {
|
||||
recurse(0);
|
||||
} catch (StackOverflowError soe) {
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
out.println("Maximal recursion depth: " + maxDepth);
|
||||
depthToTry = maxDepth;
|
||||
|
||||
//
|
||||
// Run the tested threads:
|
||||
//
|
||||
stack017 threads[] = new stack017[THREADS];
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
threads[i] = new stack017();
|
||||
threads[i].setName("Thread: " + (i + 1) + "/" + THREADS);
|
||||
threads[i].start();
|
||||
}
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
if (threads[i].isAlive())
|
||||
try {
|
||||
threads[i].join();
|
||||
} catch (InterruptedException exception) {
|
||||
exception.printStackTrace(out);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if unexpected exceptions were thrown:
|
||||
//
|
||||
int exitCode = 0;
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
if (threads[i].thrown != null) {
|
||||
threads[i].thrown.printStackTrace(out);
|
||||
exitCode = 2;
|
||||
}
|
||||
|
||||
if (exitCode != 0)
|
||||
out.println("# TEST FAILED");
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
private int maxDepth = 0;
|
||||
|
||||
private void recurse(int depth) {
|
||||
maxDepth = depth;
|
||||
recurse(depth + 1);
|
||||
}
|
||||
|
||||
private void trickyRecurse(int depth) {
|
||||
try {
|
||||
maxDepth = depth;
|
||||
trickyRecurse(depth + 1);
|
||||
} catch (Error error) {
|
||||
if (!(error instanceof StackOverflowError) &&
|
||||
!(error instanceof OutOfMemoryError))
|
||||
throw error;
|
||||
|
||||
//
|
||||
// Stack problem caugth: provoke it again,
|
||||
// if current stack is enough deep:
|
||||
//
|
||||
if (depth < depthToTry - PROBES)
|
||||
throw error;
|
||||
recurse(depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
private Throwable thrown = null;
|
||||
|
||||
public void run() {
|
||||
String threadName = Thread.currentThread().getName();
|
||||
for (int i = 1; i <= CYCLES; i++)
|
||||
try {
|
||||
display(threadName + ", iteration: " + i + "/" + CYCLES);
|
||||
trickyRecurse(0);
|
||||
throw new Exception(
|
||||
"TEST_BUG: stack overflow was expected!");
|
||||
|
||||
} catch (StackOverflowError oome) {
|
||||
// It's OK: stack overflow was expected.
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// Also OK, if there is no memory for stack expansion.
|
||||
|
||||
} catch (Throwable throwable) {
|
||||
if (throwable instanceof ThreadDeath)
|
||||
throw (ThreadDeath) throwable;
|
||||
// It isn't OK!
|
||||
thrown = throwable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
217
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack018.java
Normal file
217
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack018.java
Normal file
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/stack/stack018.
|
||||
* VM testbase keywords: [stress, diehard, stack, nonconcurrent, exclude]
|
||||
* VM testbase comments: 8139875
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* This test provokes multiple stack overflows by invocations via
|
||||
* reflection -- repeatedly multiple times, and in multiple threads.
|
||||
* Recursive method is invoked for the given fixed depth of recursion
|
||||
* (though, for a large depth). The test measures a number of recursive
|
||||
* invocations until stack overflow, and then tries to reproduce similar
|
||||
* stack overflows 10 times in each of 10 threads -- each time by trying
|
||||
* to invoke the same recursive method for the given fixed depth
|
||||
* of invocations (which is 10 times that crucial depth just measured).
|
||||
* The test is deemed passed, if VM have not crashed, and
|
||||
* if exception other than due to stack overflow was not
|
||||
* thrown.
|
||||
* COMMENTS
|
||||
* This test crashes HS versions 2.0, 1.3, and 1.4 on both
|
||||
* Solaris and Win32 platforms.
|
||||
* See the bug:
|
||||
* 4366625 (P4/S4) multiple stack overflow causes HS crash
|
||||
*
|
||||
* @ignore 8139875
|
||||
* @run main/othervm nsk.stress.stack.stack018 -eager
|
||||
*/
|
||||
|
||||
package nsk.stress.stack;
|
||||
|
||||
|
||||
import nsk.share.Harakiri;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class stack018 extends Thread {
|
||||
private final static int THREADS = 10;
|
||||
private final static int CYCLES = 10;
|
||||
private final static int STEP = 100;
|
||||
private final static int RESERVE = 100;
|
||||
|
||||
public static void main(String[] args) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
verbose = false;
|
||||
boolean eager = false;
|
||||
for (int i = 0; i < args.length; i++)
|
||||
if (args[i].toLowerCase().equals("-verbose"))
|
||||
verbose = true;
|
||||
else if (args[i].toLowerCase().equals("-eager"))
|
||||
eager = true;
|
||||
if (!eager)
|
||||
Harakiri.appoint(Harakiri.parseAppointment(args));
|
||||
stack018.out = out;
|
||||
stack018 test = new stack018();
|
||||
return test.doRun();
|
||||
}
|
||||
|
||||
private static boolean verbose;
|
||||
private static PrintStream out;
|
||||
|
||||
private void display(Object message) {
|
||||
if (!verbose)
|
||||
return;
|
||||
synchronized (out) {
|
||||
out.println(message.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private int doRun() {
|
||||
//
|
||||
// Measure maximal recursion depth until stack overflow:
|
||||
//
|
||||
int maxDepth = 0;
|
||||
for (depthToTry = 0; ; depthToTry += STEP)
|
||||
try {
|
||||
invokeRecurse(depthToTry);
|
||||
maxDepth = depthToTry;
|
||||
} catch (Throwable exception) {
|
||||
Throwable target = getTargetException(exception);
|
||||
if ((target instanceof StackOverflowError) ||
|
||||
(target instanceof OutOfMemoryError))
|
||||
break; // OK.
|
||||
target.printStackTrace(out);
|
||||
if (target instanceof ThreadDeath)
|
||||
throw (ThreadDeath) target;
|
||||
return 2;
|
||||
}
|
||||
out.println("Maximal recursion depth: " + maxDepth);
|
||||
|
||||
//
|
||||
// Run the tested threads:
|
||||
//
|
||||
stack018 threads[] = new stack018[THREADS];
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
threads[i] = new stack018();
|
||||
threads[i].setName("Thread: " + (i + 1) + "/" + THREADS);
|
||||
threads[i].depthToTry = RESERVE * maxDepth;
|
||||
threads[i].start();
|
||||
}
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
if (threads[i].isAlive())
|
||||
try {
|
||||
threads[i].join();
|
||||
} catch (InterruptedException exception) {
|
||||
exception.printStackTrace(out);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if unexpected exceptions were thrown:
|
||||
//
|
||||
int exitCode = 0;
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
if (threads[i].thrown != null) {
|
||||
out.println("# " + threads[i].getName()
|
||||
+ ": " + threads[i].thrown);
|
||||
exitCode = 2;
|
||||
}
|
||||
|
||||
if (exitCode != 0)
|
||||
out.println("# TEST FAILED");
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
private int depthToTry = 0;
|
||||
private Throwable thrown = null;
|
||||
|
||||
public void run() {
|
||||
String threadName = Thread.currentThread().getName();
|
||||
for (int i = 1; i <= CYCLES; i++)
|
||||
try {
|
||||
display(threadName + ", iteration: " + i + "/" + CYCLES);
|
||||
invokeRecurse(depthToTry);
|
||||
throw new Error("TEST_RFE: try deeper invocations!");
|
||||
|
||||
} catch (Throwable exception) {
|
||||
Throwable target = getTargetException(exception);
|
||||
if ((target instanceof StackOverflowError) ||
|
||||
(target instanceof OutOfMemoryError))
|
||||
continue; // OK.
|
||||
if (target instanceof ThreadDeath)
|
||||
throw (ThreadDeath) target;
|
||||
thrown = target;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static Throwable getTargetException(Throwable exception) {
|
||||
Throwable target;
|
||||
//
|
||||
// Unwrap deep chain of exceptions to find StackOverflowError:
|
||||
//
|
||||
for (
|
||||
target = exception;
|
||||
target instanceof InvocationTargetException;
|
||||
target = ((InvocationTargetException) target).getTargetException()
|
||||
)
|
||||
;
|
||||
return target;
|
||||
}
|
||||
|
||||
private Method method = null;
|
||||
private Object params[] = null;
|
||||
|
||||
private void invokeRecurse(int depth) throws Exception {
|
||||
if (method == null) {
|
||||
//
|
||||
// Optimization trick: allocate once, use everywhere.
|
||||
//
|
||||
method = stack018.class.getMethod("recurse");
|
||||
params = new Object[]{};
|
||||
}
|
||||
this.depth = depth; // actual parameter
|
||||
method.invoke(this, params);
|
||||
}
|
||||
|
||||
private int depth = 0; // actual parameter for recurse()
|
||||
|
||||
public void recurse() throws Exception {
|
||||
if (depth > 0)
|
||||
//
|
||||
// Self-invoke via reflection:
|
||||
//
|
||||
invokeRecurse(depth - 1);
|
||||
}
|
||||
}
|
||||
133
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack019.java
Normal file
133
test/hotspot/jtreg/vmTestbase/nsk/stress/stack/stack019.java
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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/stack/stack019.
|
||||
* VM testbase keywords: [stress, diehard, stack, nonconcurrent, exclude]
|
||||
* VM testbase comments: 8139875
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* The test invokes infinitely recursive method from within stack
|
||||
* overflow handler -- repeatedly multiple times in a single thread.
|
||||
* The test is deemed passed, if VM have not crashed, and if exception
|
||||
* other than due to stack overflow was not thrown.
|
||||
* COMMENTS
|
||||
* This test crashes HS versions 2.0, 1.3, and 1.4 on both
|
||||
* Solaris and Win32 platforms.
|
||||
* See the bug:
|
||||
* 4366625 (P4/S4) multiple stack overflow causes HS crash
|
||||
*
|
||||
* @ignore 8139875
|
||||
* @run main/othervm nsk.stress.stack.stack019 -eager
|
||||
*/
|
||||
|
||||
package nsk.stress.stack;
|
||||
|
||||
|
||||
import nsk.share.Harakiri;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class stack019 {
|
||||
private final static int CYCLES = 100;
|
||||
private final static int PROBES = 100;
|
||||
|
||||
public static void main(String[] args) {
|
||||
int exitCode = run(args, System.out);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String args[], PrintStream out) {
|
||||
boolean verbose = false, eager = false;
|
||||
for (int i = 0; i < args.length; i++)
|
||||
if (args[i].toLowerCase().equals("-verbose"))
|
||||
verbose = true;
|
||||
else if (args[i].toLowerCase().equals("-eager"))
|
||||
eager = true;
|
||||
if (!eager)
|
||||
Harakiri.appoint(Harakiri.parseAppointment(args));
|
||||
//
|
||||
// Measure recursive depth before stack overflow:
|
||||
//
|
||||
try {
|
||||
recurse(0);
|
||||
} catch (StackOverflowError soe) {
|
||||
} catch (OutOfMemoryError oome) {
|
||||
}
|
||||
out.println("Maximal recursion depth: " + maxDepth);
|
||||
depthToTry = maxDepth;
|
||||
|
||||
//
|
||||
// Run the tested threads:
|
||||
//
|
||||
for (int i = 0; i < CYCLES; i++) {
|
||||
try {
|
||||
out.println("Iteration: " + i + "/" + CYCLES);
|
||||
trickyRecurse(0);
|
||||
out.println("# TEST_BUG: stack overflow was expected!");
|
||||
return 2;
|
||||
|
||||
} catch (StackOverflowError error) {
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// It's OK: stack overflow was expected.
|
||||
|
||||
} catch (Throwable throwable) {
|
||||
if (throwable instanceof ThreadDeath)
|
||||
throw (ThreadDeath) throwable;
|
||||
throwable.printStackTrace(out);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int maxDepth;
|
||||
private static int depthToTry;
|
||||
|
||||
private static void recurse(int depth) {
|
||||
maxDepth = depth;
|
||||
recurse(depth + 1);
|
||||
}
|
||||
|
||||
private static void trickyRecurse(int depth) {
|
||||
try {
|
||||
maxDepth = depth;
|
||||
trickyRecurse(depth + 1);
|
||||
} catch (Error error) {
|
||||
if (!(error instanceof StackOverflowError) &&
|
||||
!(error instanceof OutOfMemoryError))
|
||||
throw error;
|
||||
|
||||
//
|
||||
// Stack problem caugth: provoke it again,
|
||||
// if current stack is enough deep:
|
||||
//
|
||||
if (depth < depthToTry - PROBES)
|
||||
throw error;
|
||||
recurse(depth + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*/
|
||||
|
||||
#include "jni_tools.c"
|
||||
#include "nsk_tools.c"
|
||||
#include "strace003.c"
|
||||
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*/
|
||||
|
||||
#include "jni_tools.c"
|
||||
#include "nsk_tools.c"
|
||||
#include "strace004.c"
|
||||
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*/
|
||||
|
||||
#include "jni_tools.c"
|
||||
#include "nsk_tools.c"
|
||||
#include "strace005.c"
|
||||
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*/
|
||||
|
||||
#include "jni_tools.c"
|
||||
#include "nsk_tools.c"
|
||||
#include "strace006.c"
|
||||
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*/
|
||||
|
||||
#include "jni_tools.c"
|
||||
#include "nsk_tools.c"
|
||||
#include "strace008.c"
|
||||
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*/
|
||||
|
||||
#include "jni_tools.c"
|
||||
#include "nsk_tools.c"
|
||||
#include "strace009.c"
|
||||
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*/
|
||||
|
||||
#include "jni_tools.c"
|
||||
#include "nsk_tools.c"
|
||||
#include "strace011.c"
|
||||
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*/
|
||||
|
||||
#include "jni_tools.c"
|
||||
#include "nsk_tools.c"
|
||||
#include "strace012.c"
|
||||
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*/
|
||||
|
||||
#include "jni_tools.c"
|
||||
#include "nsk_tools.c"
|
||||
#include "strace014.c"
|
||||
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*/
|
||||
|
||||
#include "jni_tools.c"
|
||||
#include "nsk_tools.c"
|
||||
#include "strace015.c"
|
||||
140
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/nsk_strace.h
Normal file
140
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/nsk_strace.h
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "jni_tools.h"
|
||||
|
||||
#ifndef _IS_NSK_STRACE_DEFINED_
|
||||
#define _IS_NSK_STRACE_DEFINED_
|
||||
|
||||
#define JNI_VERSION JNI_VERSION_1_1
|
||||
|
||||
#define EXCEPTION_CLEAR (*env)->ExceptionClear(env)
|
||||
#define EXCEPTION_OCCURRED (*env)->ExceptionOccurred(env)
|
||||
|
||||
// Check for pending exception of the specified type
|
||||
// If it's present, then clear it
|
||||
#define EXCEPTION_CHECK(exceptionClass, recurDepth) \
|
||||
if (EXCEPTION_OCCURRED != NULL) { \
|
||||
jobject exception = EXCEPTION_OCCURRED; \
|
||||
if (NSK_CPP_STUB3(IsInstanceOf, env, exception, \
|
||||
exceptionClass) == JNI_TRUE) { \
|
||||
EXCEPTION_CLEAR; \
|
||||
NSK_DISPLAY1("StackOverflowError occurred at depth %d\n", recurDepth); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define FIND_CLASS(_class, _className)\
|
||||
if (!NSK_JNI_VERIFY(env, (_class = \
|
||||
NSK_CPP_STUB2(FindClass, env, _className)) != NULL))\
|
||||
exit(1)
|
||||
|
||||
#define GET_OBJECT_CLASS(_class, _obj)\
|
||||
if (!NSK_JNI_VERIFY(env, (_class = \
|
||||
NSK_CPP_STUB2(GetObjectClass, env, _obj)) != NULL))\
|
||||
exit(1)
|
||||
|
||||
#define GET_FIELD_ID(_fieldID, _class, _fieldName, _fieldSig)\
|
||||
if (!NSK_JNI_VERIFY(env, (_fieldID = \
|
||||
NSK_CPP_STUB4(GetFieldID, env, _class,\
|
||||
_fieldName, _fieldSig)) != NULL))\
|
||||
exit(1)
|
||||
|
||||
#define GET_STATIC_FIELD_ID(_fieldID, _class, _fieldName, _fieldSig)\
|
||||
if (!NSK_JNI_VERIFY(env, (_fieldID = \
|
||||
NSK_CPP_STUB4(GetStaticFieldID, env, _class,\
|
||||
_fieldName, _fieldSig)) != NULL))\
|
||||
exit(1)
|
||||
|
||||
#define GET_STATIC_BOOL_FIELD(_value, _class, _fieldName)\
|
||||
GET_STATIC_FIELD_ID(field, _class, _fieldName, "Z");\
|
||||
_value = NSK_CPP_STUB3(GetStaticBooleanField, env, _class, field)
|
||||
|
||||
#define GET_STATIC_INT_FIELD(_value, _class, _fieldName)\
|
||||
GET_STATIC_FIELD_ID(field, _class, _fieldName, "I");\
|
||||
_value = NSK_CPP_STUB3(GetStaticIntField, env, _class, field)
|
||||
|
||||
#define GET_STATIC_OBJ_FIELD(_value, _class, _fieldName, _fieldSig)\
|
||||
GET_STATIC_FIELD_ID(field, _class, _fieldName, _fieldSig);\
|
||||
_value = NSK_CPP_STUB3(GetStaticObjectField, env, _class, \
|
||||
field)
|
||||
|
||||
#define GET_INT_FIELD(_value, _obj, _class, _fieldName)\
|
||||
GET_FIELD_ID(field, _class, _fieldName, "I");\
|
||||
_value = NSK_CPP_STUB3(GetIntField, env, _obj, field)
|
||||
|
||||
#define SET_INT_FIELD(_obj, _class, _fieldName, _newValue)\
|
||||
GET_FIELD_ID(field, _class, _fieldName, "I");\
|
||||
NSK_CPP_STUB4(SetIntField, env, _obj, field, _newValue)
|
||||
|
||||
#define SET_STATIC_INT_FIELD(_class, _fieldName, _newValue)\
|
||||
GET_STATIC_FIELD_ID(field, _class, _fieldName, "I");\
|
||||
NSK_CPP_STUB4(SetStaticIntField, env, _class, field, _newValue)
|
||||
|
||||
#define GET_OBJ_FIELD(_value, _obj, _class, _fieldName, _fieldSig)\
|
||||
GET_FIELD_ID(field, _class, _fieldName, _fieldSig);\
|
||||
_value = NSK_CPP_STUB3(GetObjectField, env, _obj, field)
|
||||
|
||||
#define GET_STATIC_METHOD_ID(_methodID, _class, _methodName, _sig)\
|
||||
if (!NSK_JNI_VERIFY(env, (_methodID = \
|
||||
NSK_CPP_STUB4(GetStaticMethodID, env, _class,\
|
||||
_methodName, _sig)) != NULL))\
|
||||
exit(1)
|
||||
|
||||
#define GET_METHOD_ID(_methodID, _class, _methodName, _sig)\
|
||||
if (!NSK_JNI_VERIFY(env, (_methodID = \
|
||||
NSK_CPP_STUB4(GetMethodID, env, _class,\
|
||||
_methodName, _sig)) != NULL))\
|
||||
exit(1)
|
||||
|
||||
#define CALL_STATIC_VOID_NOPARAM(_class, _methodName)\
|
||||
GET_STATIC_METHOD_ID(method, _class, _methodName, "()V");\
|
||||
if (!NSK_JNI_VERIFY_VOID(env, NSK_CPP_STUB3(CallStaticVoidMethod, env,\
|
||||
_class, method)))\
|
||||
exit(1)
|
||||
|
||||
#define CALL_STATIC_VOID(_class, _methodName, _sig, _param)\
|
||||
GET_STATIC_METHOD_ID(method, _class, _methodName, _sig);\
|
||||
if (!NSK_JNI_VERIFY_VOID(env, NSK_CPP_STUB4(CallStaticVoidMethod, env,\
|
||||
_class, method, _param)))\
|
||||
exit(1)
|
||||
|
||||
#define CALL_VOID_NOPARAM(_obj, _class, _methodName)\
|
||||
GET_METHOD_ID(method, _class, _methodName, "()V");\
|
||||
if (!NSK_JNI_VERIFY_VOID(env, NSK_CPP_STUB3(CallVoidMethod, env, _obj,\
|
||||
method)))\
|
||||
exit(1)
|
||||
|
||||
#define CALL_VOID(_obj, _class, _methodName, _sig, _param)\
|
||||
GET_METHOD_ID(method, _class, _methodName, _sig);\
|
||||
if (!NSK_JNI_VERIFY_VOID(env, NSK_CPP_STUB4(CallVoidMethod, env, _obj,\
|
||||
method, _param)))\
|
||||
exit(1)
|
||||
|
||||
#define MONITOR_ENTER(x) \
|
||||
NSK_JNI_VERIFY(env, NSK_CPP_STUB2(MonitorEnter, env, x) == 0)
|
||||
|
||||
#define MONITOR_EXIT(x) \
|
||||
NSK_JNI_VERIFY(env, NSK_CPP_STUB2(MonitorExit, env, x) == 0)
|
||||
|
||||
#endif /* _IS_NSK_STRACE_DEFINED_ */
|
||||
304
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace001.java
Normal file
304
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace001.java
Normal file
@ -0,0 +1,304 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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/strace/strace001.
|
||||
* VM testbase keywords: [stress, quick, strace]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* The test checks up java.lang.Thread.getStackTrace() method for many threads,
|
||||
* that recursively invoke a pure java method in running mode ("alive" stack).
|
||||
* The test fails if:
|
||||
* - amount of stack trace elements is more than depth of recursion plus
|
||||
* four elements corresponding to invocations of Thread.run(), Thread.wait(),
|
||||
* Thread.exit(), Thread.yield() and ThreadGroup.remove() methods;
|
||||
* - there is at least one element corresponding to invocation of unexpected
|
||||
* method.
|
||||
*
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @run driver jdk.test.lib.FileInstaller . .
|
||||
* @run main/othervm nsk.stress.strace.strace001
|
||||
*/
|
||||
package nsk.stress.strace;
|
||||
|
||||
import nsk.share.ArgumentParser;
|
||||
import nsk.share.Failure;
|
||||
import nsk.share.Log;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* The test check up <code>java.lang.Thread.getStackTrace()</code> method for many threads,
|
||||
* that recursively invoke a pure java method in running mode ("alive" stack).
|
||||
* <p>
|
||||
* <p>The test creates <code>THRD_COUNT</code> instances of <code>strace001Thread</code>
|
||||
* class, tries to get their stack traces and checks up that returned array contains
|
||||
* correct stack frames. Each stack frame must be corresponded to one of the following
|
||||
* methods defined by the <code>EXPECTED_METHODS</code> array.</p>
|
||||
* <p>These checking are performed <code>REPEAT_COUNT</code> times.</p>
|
||||
*/
|
||||
public class strace001 {
|
||||
|
||||
static final int DEPTH = 200;
|
||||
static final int THRD_COUNT = 100;
|
||||
static final int REPEAT_COUNT = 10;
|
||||
static final String[] EXPECTED_METHODS = {
|
||||
"java.lang.System.arraycopy",
|
||||
"java.lang.Object.wait",
|
||||
"java.lang.Thread.exit",
|
||||
"java.lang.Thread.yield",
|
||||
"java.lang.ThreadGroup.remove",
|
||||
"java.lang.ThreadGroup.threadTerminated",
|
||||
"nsk.stress.strace.strace001Thread.run",
|
||||
"nsk.stress.strace.strace001Thread.recursiveMethod"
|
||||
};
|
||||
|
||||
|
||||
static volatile boolean isLocked = false;
|
||||
static PrintStream out;
|
||||
static long waitTime = 2;
|
||||
|
||||
static Object waitStart = new Object();
|
||||
|
||||
static strace001Thread[] threads;
|
||||
static StackTraceElement[][] snapshots = new StackTraceElement[THRD_COUNT][];
|
||||
static Log log;
|
||||
|
||||
public static void main(String[] args) {
|
||||
out = System.out;
|
||||
int exitCode = run(args);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
volatile int achivedCount = 0;
|
||||
|
||||
public static int run(String[] args) {
|
||||
|
||||
ArgumentParser argHandler = new ArgumentParser(args);
|
||||
log = new Log(out, argHandler);
|
||||
waitTime = argHandler.getWaitTime() * 60000;
|
||||
|
||||
strace001 test = new strace001();
|
||||
boolean res = true;
|
||||
|
||||
for (int j = 0; j < REPEAT_COUNT; j++) {
|
||||
test.startThreads();
|
||||
|
||||
if (!test.makeSnapshot(j + 1)) res = false;
|
||||
|
||||
display("waiting for threads finished\n");
|
||||
test.finishThreads();
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
complain("***>>>Test failed<<<***");
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void startThreads() {
|
||||
threads = new strace001Thread[THRD_COUNT];
|
||||
achivedCount = 0;
|
||||
|
||||
String tmp_name;
|
||||
for (int i = 0; i < THRD_COUNT; i++) {
|
||||
tmp_name = "strace001Thread" + Integer.toString(i);
|
||||
threads[i] = new strace001Thread(this, tmp_name);
|
||||
}
|
||||
|
||||
for (int i = 0; i < THRD_COUNT; i++) {
|
||||
threads[i].start();
|
||||
}
|
||||
|
||||
waitFor("all threads started ...");
|
||||
synchronized (waitStart) {
|
||||
isLocked = true;
|
||||
waitStart.notifyAll();
|
||||
}
|
||||
try {
|
||||
Thread.yield();
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
}
|
||||
|
||||
void waitFor(String msg) {
|
||||
if (msg.length() > 0)
|
||||
display("waiting for " + msg);
|
||||
|
||||
while (achivedCount < THRD_COUNT) {
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
}
|
||||
achivedCount = 0;
|
||||
}
|
||||
|
||||
boolean makeSnapshot(int repeat_number) {
|
||||
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
snapshots[i] = threads[i].getStackTrace();
|
||||
}
|
||||
|
||||
return checkTraces(repeat_number);
|
||||
}
|
||||
|
||||
boolean checkTraces(int repeat_number) {
|
||||
StackTraceElement[] elements;
|
||||
|
||||
boolean res = true;
|
||||
display(">>> snapshot " + repeat_number);
|
||||
int expectedCount = DEPTH + 1;
|
||||
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
elements = snapshots[i];
|
||||
|
||||
if (elements == null)
|
||||
continue;
|
||||
|
||||
if (elements.length == 0)
|
||||
continue;
|
||||
|
||||
if (elements.length > 3) {
|
||||
display("\tchecking " + threads[i].getName()
|
||||
+ "(trace elements: " + elements.length + ")");
|
||||
}
|
||||
|
||||
if (elements.length > expectedCount) {
|
||||
complain(threads[i].getName() + ">Contains more then " +
|
||||
+expectedCount + " elements");
|
||||
}
|
||||
|
||||
for (int j = 0; j < elements.length; j++) {
|
||||
if (!checkElement(elements[j])) {
|
||||
complain(threads[i].getName() + ">Unexpected method name: "
|
||||
+ elements[j].getMethodName());
|
||||
complain("\tat " + j + " position");
|
||||
if (elements[j].isNativeMethod()) {
|
||||
complain("\tline number: (native method)");
|
||||
complain("\tclass name: " + elements[j].getClassName());
|
||||
} else {
|
||||
complain("\tline number: " + elements[j].getLineNumber());
|
||||
complain("\tclass name: " + elements[j].getClassName());
|
||||
complain("\tfile name: " + elements[j].getFileName());
|
||||
}
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
boolean checkElement(StackTraceElement element) {
|
||||
String name = element.getClassName() + "." + element.getMethodName();
|
||||
for (int i = 0; i < EXPECTED_METHODS.length; i++) {
|
||||
if (EXPECTED_METHODS[i].compareTo(name) == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void finishThreads() {
|
||||
try {
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
if (threads[i].isAlive())
|
||||
threads[i].join(waitTime / THRD_COUNT);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
isLocked = false;
|
||||
}
|
||||
|
||||
static void display(String message) {
|
||||
log.display(message);
|
||||
}
|
||||
|
||||
static void complain(String message) {
|
||||
log.complain(message);
|
||||
}
|
||||
}
|
||||
|
||||
class strace001Thread extends Thread {
|
||||
|
||||
private int currentDepth = 0;
|
||||
|
||||
strace001 test;
|
||||
|
||||
strace001Thread(strace001 test, String name) {
|
||||
this.test = test;
|
||||
setName(name);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
recursiveMethod();
|
||||
} catch (Throwable throwable) {
|
||||
System.err.println("# ERROR: " + getName() + ": " + throwable);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void recursiveMethod() {
|
||||
|
||||
currentDepth++;
|
||||
|
||||
if (currentDepth == 1) {
|
||||
synchronized (test) {
|
||||
test.achivedCount++;
|
||||
}
|
||||
|
||||
int alltime = 0;
|
||||
while (!strace001.isLocked) {
|
||||
synchronized (test) {
|
||||
try {
|
||||
test.wait(1);
|
||||
alltime++;
|
||||
} catch (InterruptedException e) {
|
||||
strace001.complain("" + e);
|
||||
}
|
||||
if (alltime > strace001.waitTime) {
|
||||
throw new Failure("out of wait time");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strace001.DEPTH - currentDepth > 0) {
|
||||
yield();
|
||||
recursiveMethod();
|
||||
}
|
||||
|
||||
currentDepth--;
|
||||
}
|
||||
}
|
||||
313
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace002.java
Normal file
313
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace002.java
Normal file
@ -0,0 +1,313 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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/strace/strace002.
|
||||
* VM testbase keywords: [stress, quick, strace]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* The test checks up java.lang.Thread.getAllStackTraces() method for many
|
||||
* threads, that recursively invoke a pure java method in running mode
|
||||
* ("alive" stack).
|
||||
* The test fails if:
|
||||
* - amount of stack trace elements is more than depth of recursion plus
|
||||
* four elements corresponding to invocations of Thread.run(), Thread.wait(),
|
||||
* Thread.exit(), Thread.yield() and ThreadGroup.remove() methods;
|
||||
* - there is at least one element corresponding to invocation of unexpected
|
||||
* method.
|
||||
* This test is almost the same as nsk.stress.strace.strace001 except for
|
||||
* checking is performed for java.lang.Thread.getAllStackTraces() method.
|
||||
*
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @run driver jdk.test.lib.FileInstaller . .
|
||||
* @run main/othervm nsk.stress.strace.strace002
|
||||
*/
|
||||
|
||||
|
||||
package nsk.stress.strace;
|
||||
|
||||
import nsk.share.ArgumentParser;
|
||||
import nsk.share.Failure;
|
||||
import nsk.share.Log;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The test check up <code>java.lang.Thread.getAllStackTraces()</code> method for many
|
||||
* threads, that recursively invoke a pure java method in running mode ("alive" stack).
|
||||
* <p>
|
||||
* <p>The test creates <code>THRD_COUNT</code> instances of <code>strace002Thread</code>
|
||||
* class, tries to get their stack traces and checks up that returned array contains
|
||||
* correct stack frames. Each stack frame must be corresponded to one of the following
|
||||
* methods defined by the <code>EXPECTED_METHODS</code> array.</p>
|
||||
* <p>These checking are performed <code>REPEAT_COUNT</code> times.</p>
|
||||
*/
|
||||
public class strace002 {
|
||||
|
||||
static final int DEPTH = 200;
|
||||
static final int THRD_COUNT = 100;
|
||||
static final int REPEAT_COUNT = 10;
|
||||
static final String[] EXPECTED_METHODS = {
|
||||
"java.lang.System.arraycopy",
|
||||
"java.lang.Object.wait",
|
||||
"java.lang.Thread.exit",
|
||||
"java.lang.Thread.yield",
|
||||
"java.lang.ThreadGroup.remove",
|
||||
"java.lang.ThreadGroup.threadTerminated",
|
||||
"nsk.stress.strace.strace002Thread.run",
|
||||
"nsk.stress.strace.strace002Thread.recursiveMethod"
|
||||
};
|
||||
|
||||
|
||||
static volatile boolean isLocked = false;
|
||||
static PrintStream out;
|
||||
static long waitTime = 2;
|
||||
|
||||
static Object waitStart = new Object();
|
||||
|
||||
static strace002Thread[] threads;
|
||||
static StackTraceElement[][] snapshots = new StackTraceElement[THRD_COUNT][];
|
||||
static Log log;
|
||||
|
||||
public static void main(String[] args) {
|
||||
out = System.out;
|
||||
int exitCode = run(args);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
volatile int achivedCount = 0;
|
||||
|
||||
public static int run(String[] args) {
|
||||
|
||||
ArgumentParser argHandler = new ArgumentParser(args);
|
||||
log = new Log(out, argHandler);
|
||||
waitTime = argHandler.getWaitTime() * 60000;
|
||||
|
||||
strace002 test = new strace002();
|
||||
boolean res = true;
|
||||
|
||||
for (int j = 0; j < REPEAT_COUNT; j++) {
|
||||
test.startThreads();
|
||||
|
||||
if (!test.makeSnapshot(j + 1)) res = false;
|
||||
|
||||
display("waiting for threads finished\n");
|
||||
test.finishThreads();
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
complain("***>>>Test failed<<<***");
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void startThreads() {
|
||||
threads = new strace002Thread[THRD_COUNT];
|
||||
achivedCount = 0;
|
||||
|
||||
String tmp_name;
|
||||
for (int i = 0; i < THRD_COUNT; i++) {
|
||||
tmp_name = "strace002Thread" + Integer.toString(i);
|
||||
threads[i] = new strace002Thread(this, tmp_name);
|
||||
}
|
||||
|
||||
for (int i = 0; i < THRD_COUNT; i++) {
|
||||
threads[i].start();
|
||||
}
|
||||
|
||||
waitFor("all threads started ...");
|
||||
synchronized (waitStart) {
|
||||
isLocked = true;
|
||||
waitStart.notifyAll();
|
||||
}
|
||||
try {
|
||||
Thread.yield();
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
}
|
||||
|
||||
void waitFor(String msg) {
|
||||
if (msg.length() > 0)
|
||||
display("waiting for " + msg);
|
||||
|
||||
while (achivedCount < THRD_COUNT) {
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
}
|
||||
achivedCount = 0;
|
||||
}
|
||||
|
||||
boolean makeSnapshot(int repeat_number) {
|
||||
|
||||
Map traces = Thread.getAllStackTraces();
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
snapshots[i] = (StackTraceElement[]) traces.get(threads[i]);
|
||||
}
|
||||
|
||||
return checkTraces(repeat_number);
|
||||
}
|
||||
|
||||
boolean checkTraces(int repeat_number) {
|
||||
StackTraceElement[] elements;
|
||||
|
||||
boolean res = true;
|
||||
display(">>> snapshot " + repeat_number);
|
||||
int expectedCount = DEPTH + 1;
|
||||
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
elements = snapshots[i];
|
||||
|
||||
if (elements == null)
|
||||
continue;
|
||||
|
||||
if (elements.length == 0)
|
||||
continue;
|
||||
|
||||
if (elements.length > 3) {
|
||||
display("\tchecking " + threads[i].getName()
|
||||
+ "(trace elements: " + elements.length + ")");
|
||||
}
|
||||
|
||||
if (elements.length > expectedCount) {
|
||||
complain(threads[i].getName() + ">Contains more then " +
|
||||
+expectedCount + " elements");
|
||||
}
|
||||
|
||||
for (int j = 0; j < elements.length; j++) {
|
||||
if (!checkElement(elements[j])) {
|
||||
complain(threads[i].getName() + ">Unexpected method name: "
|
||||
+ elements[j].getMethodName());
|
||||
complain("\tat " + j + " position");
|
||||
if (elements[j].isNativeMethod()) {
|
||||
complain("\tline number: (native method)");
|
||||
complain("\tclass name: " + elements[j].getClassName());
|
||||
} else {
|
||||
complain("\tline number: " + elements[j].getLineNumber());
|
||||
complain("\tclass name: " + elements[j].getClassName());
|
||||
complain("\tfile name: " + elements[j].getFileName());
|
||||
}
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
boolean checkElement(StackTraceElement element) {
|
||||
String name = element.getClassName() + "." + element.getMethodName();
|
||||
for (int i = 0; i < EXPECTED_METHODS.length; i++) {
|
||||
if (EXPECTED_METHODS[i].compareTo(name) == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void finishThreads() {
|
||||
try {
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
if (threads[i].isAlive())
|
||||
threads[i].join(waitTime / THRD_COUNT);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
isLocked = false;
|
||||
}
|
||||
|
||||
static void display(String message) {
|
||||
log.display(message);
|
||||
}
|
||||
|
||||
static void complain(String message) {
|
||||
log.complain(message);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class strace002Thread extends Thread {
|
||||
|
||||
private int currentDepth = 0;
|
||||
|
||||
strace002 test;
|
||||
|
||||
strace002Thread(strace002 test, String name) {
|
||||
this.test = test;
|
||||
setName(name);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
recursiveMethod();
|
||||
} catch (Throwable throwable) {
|
||||
System.err.println("# ERROR: " + getName() + ": " + throwable);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void recursiveMethod() {
|
||||
|
||||
currentDepth++;
|
||||
|
||||
if (currentDepth == 1) {
|
||||
synchronized (test) {
|
||||
test.achivedCount++;
|
||||
}
|
||||
|
||||
int alltime = 0;
|
||||
while (!test.isLocked) {
|
||||
synchronized (test) {
|
||||
try {
|
||||
test.wait(1);
|
||||
alltime++;
|
||||
} catch (InterruptedException e) {
|
||||
strace002.complain("" + e);
|
||||
}
|
||||
if (alltime > strace002.waitTime) {
|
||||
throw new Failure("out of wait time");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strace002.DEPTH - currentDepth > 0) {
|
||||
yield();
|
||||
recursiveMethod();
|
||||
}
|
||||
|
||||
currentDepth--;
|
||||
}
|
||||
}
|
||||
94
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace003.c
Normal file
94
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace003.c
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "nsk_strace.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static const char *Stest_cn="nsk/stress/strace/strace003";
|
||||
static const char *Slongparam="(J)V";
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_nsk_stress_strace_strace003Thread_recursiveMethod(JNIEnv *env, jobject obj)
|
||||
{
|
||||
jfieldID field;
|
||||
jmethodID method;
|
||||
jint currDepth;
|
||||
jclass testClass, threadClass, objClass;
|
||||
jint maxDepth;
|
||||
jboolean isLocked;
|
||||
jint achivedCount;
|
||||
jobject testField, waitStart;
|
||||
|
||||
FIND_CLASS(testClass, Stest_cn);
|
||||
FIND_CLASS(objClass, "java/lang/Object");
|
||||
GET_OBJECT_CLASS(threadClass, obj);
|
||||
|
||||
/* currDepth++ */
|
||||
GET_INT_FIELD(currDepth, obj, threadClass, "currentDepth");
|
||||
currDepth++;
|
||||
SET_INT_FIELD(obj, threadClass, "currentDepth", currDepth);
|
||||
|
||||
if (currDepth == 1)
|
||||
{
|
||||
GET_OBJ_FIELD(testField, obj, threadClass, "test",
|
||||
"Lnsk/stress/strace/strace003;");
|
||||
|
||||
GET_STATIC_OBJ_FIELD(waitStart, testClass, "waitStart",
|
||||
"Ljava/lang/Object;");
|
||||
|
||||
MONITOR_ENTER(testField);
|
||||
GET_INT_FIELD(achivedCount, testField, testClass, "achivedCount");
|
||||
achivedCount++;
|
||||
SET_INT_FIELD(testField, testClass, "achivedCount", achivedCount);
|
||||
MONITOR_EXIT(testField);
|
||||
|
||||
GET_STATIC_BOOL_FIELD(isLocked, testClass, "isLocked");
|
||||
while (isLocked != JNI_TRUE)
|
||||
{
|
||||
MONITOR_ENTER(waitStart);
|
||||
CALL_VOID(waitStart, objClass, "wait", Slongparam, 1LL);
|
||||
MONITOR_EXIT(waitStart);
|
||||
GET_STATIC_BOOL_FIELD(isLocked, testClass, "isLocked");
|
||||
}
|
||||
}
|
||||
|
||||
GET_STATIC_INT_FIELD(maxDepth, testClass, "DEPTH");
|
||||
|
||||
if (maxDepth - currDepth > 0)
|
||||
{
|
||||
CALL_STATIC_VOID_NOPARAM(threadClass, "yield");
|
||||
CALL_VOID_NOPARAM(obj, threadClass, "recursiveMethod");
|
||||
}
|
||||
|
||||
currDepth--;
|
||||
GET_OBJECT_CLASS(threadClass, obj);
|
||||
SET_INT_FIELD(obj, threadClass, "currentDepth", currDepth);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
327
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace003.java
Normal file
327
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace003.java
Normal file
@ -0,0 +1,327 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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/strace/strace003.
|
||||
* VM testbase keywords: [stress, strace]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* The test checks up java.lang.Thread.getStackTrace() method for many threads,
|
||||
* that recursively invoke a native method in running mode ("alive" stack).
|
||||
* The test fails if:
|
||||
* - amount of stack trace elements is more than depth of recursion plus
|
||||
* four elements corresponding to invocations of Thread.run(), Thread.wait(),
|
||||
* Thread.exit(), Thread.yield() and ThreadGroup.remove() methods;
|
||||
* - there is at least one element corresponding to invocation of unexpected
|
||||
* method.
|
||||
* This test is almost the same as nsk.stress.strace.strace001 except for
|
||||
* the recursive method is a native one.
|
||||
* COMMENTS
|
||||
* Below assertion is revealed on engineer's build. It is needed to check
|
||||
* on a promoted build.
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Started at: Fri Apr 25 15:47:13 NSK 2003
|
||||
* waiting for all threads started ...
|
||||
* >>> snapshot 1
|
||||
* checking strace003Thread0(trace elements: 2)
|
||||
* checking strace003Thread1(trace elements: 2)
|
||||
* checking strace003Thread2(trace elements: 3)
|
||||
* checking strace003Thread3(trace elements: 2)
|
||||
* checking strace003Thread4(trace elements: 2)
|
||||
* checking strace003Thread5(trace elements: 2)
|
||||
* checking strace003Thread6(trace elements: 3)
|
||||
* checking strace003Thread7(trace elements: 2)
|
||||
* # To suppress the following error report, specify this argument
|
||||
* # after -XX: or in .hotspotrc: SuppressErrorAt=/jniHandles.hpp:157
|
||||
* #
|
||||
* # HotSpot Virtual Machine Error, assertion failure
|
||||
* # Please report this error at
|
||||
* # http://java.sun.com/cgi-bin/bugreport.cgi
|
||||
* #
|
||||
* # Java VM: Java HotSpot(TM) Client VM (1.4.1-internal-debug mixed mode)
|
||||
* #
|
||||
* # assert(result != ((oop)::badJNIHandleVal), "Pointing to zapped jni handle area")
|
||||
* #
|
||||
* # Error ID: src/share/vm/runtime/jniHandles.hpp, 157 [ Patched ]
|
||||
* #
|
||||
* # Problematic Thread: prio=5 tid=0x001b99e8 nid=0xbf runnable
|
||||
* #
|
||||
* Heap at VM Abort:
|
||||
* Heap
|
||||
* def new generation total 2112K, used 300K [0xf1800000, 0xf1a20000, 0xf1f10000)
|
||||
* eden space 2048K, 14% used [0xf1800000, 0xf184b358, 0xf1a00000)
|
||||
* from space 64K, 0% used [0xf1a00000, 0xf1a00000, 0xf1a10000)
|
||||
* to space 64K, 0% used [0xf1a10000, 0xf1a10000, 0xf1a20000)
|
||||
* tenured generation total 1408K, used 0K [0xf1f10000, 0xf2070000, 0xf5800000)
|
||||
* the space 1408K, 0% used [0xf1f10000, 0xf1f10000, 0xf1f10200, 0xf2070000)
|
||||
* compacting perm gen total 4096K, used 1024K [0xf5800000, 0xf5c00000, 0xf9800000)
|
||||
* the space 4096K, 25% used [0xf5800000, 0xf5900240, 0xf5900400, 0xf5c00000)
|
||||
* Dumping core....
|
||||
* Abort
|
||||
* Finished at: Fri Apr 25 15:48:10 NSK 2003
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @run driver jdk.test.lib.FileInstaller . .
|
||||
* @run main/othervm/native nsk.stress.strace.strace003
|
||||
*/
|
||||
|
||||
package nsk.stress.strace;
|
||||
|
||||
import nsk.share.ArgumentParser;
|
||||
import nsk.share.Log;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* The test check up <code>java.lang.Thread.getStackTrace()</code> method for many threads,
|
||||
* that recursively invoke a native method in running mode ("alive" stack).
|
||||
* <p>
|
||||
* <p>The test creates <code>THRD_COUNT</code> instances of <code>strace003Thread</code>
|
||||
* class, tries to get their stack traces and checks up that returned array contains
|
||||
* correct stack frames. Each stack frame must be corresponded to one of the following
|
||||
* methods defined by the <code>EXPECTED_METHODS</code> array.</p>
|
||||
* <p>These checking are performed <code>REPEAT_COUNT</code> times.</p>
|
||||
*/
|
||||
public class strace003 {
|
||||
|
||||
static final int DEPTH = 100;
|
||||
static final int THRD_COUNT = 100;
|
||||
static final int REPEAT_COUNT = 10;
|
||||
static final String[] EXPECTED_METHODS = {
|
||||
"java.lang.System.arraycopy",
|
||||
"java.lang.Object.wait",
|
||||
"java.lang.Thread.exit",
|
||||
"java.lang.Thread.yield",
|
||||
"java.lang.ThreadGroup.remove",
|
||||
"java.lang.ThreadGroup.threadTerminated",
|
||||
"nsk.stress.strace.strace003Thread.run",
|
||||
"nsk.stress.strace.strace003Thread.recursiveMethod"
|
||||
};
|
||||
|
||||
|
||||
static volatile boolean isLocked = false;
|
||||
static PrintStream out;
|
||||
static long waitTime = 2;
|
||||
|
||||
static Object waitStart = new Object();
|
||||
|
||||
static strace003Thread[] threads;
|
||||
static StackTraceElement[][] snapshots = new StackTraceElement[THRD_COUNT][];
|
||||
static Log log;
|
||||
|
||||
volatile int achivedCount = 0;
|
||||
|
||||
public static void main(String[] args) {
|
||||
out = System.out;
|
||||
int exitCode = run(args);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String[] args) {
|
||||
ArgumentParser argHandler = new ArgumentParser(args);
|
||||
log = new Log(out, argHandler);
|
||||
waitTime = argHandler.getWaitTime() * 60000;
|
||||
|
||||
strace003 test = new strace003();
|
||||
boolean res = true;
|
||||
|
||||
for (int j = 0; j < REPEAT_COUNT; j++) {
|
||||
test.startThreads();
|
||||
|
||||
if (!test.makeSnapshot(j + 1)) res = false;
|
||||
|
||||
display("waiting for threads finished\n");
|
||||
test.finishThreads();
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
complain("***>>>Test failed<<<***");
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void startThreads() {
|
||||
threads = new strace003Thread[THRD_COUNT];
|
||||
achivedCount = 0;
|
||||
|
||||
String tmp_name;
|
||||
for (int i = 0; i < THRD_COUNT; i++) {
|
||||
tmp_name = "strace003Thread" + Integer.toString(i);
|
||||
threads[i] = new strace003Thread(this, tmp_name);
|
||||
}
|
||||
|
||||
for (int i = 0; i < THRD_COUNT; i++) {
|
||||
threads[i].start();
|
||||
}
|
||||
|
||||
waitFor("all threads started ...");
|
||||
synchronized (waitStart) {
|
||||
isLocked = true;
|
||||
waitStart.notifyAll();
|
||||
}
|
||||
try {
|
||||
Thread.yield();
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
}
|
||||
|
||||
void waitFor(String msg) {
|
||||
if (msg.length() > 0)
|
||||
display("waiting for " + msg);
|
||||
|
||||
while (achivedCount < THRD_COUNT) {
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
}
|
||||
achivedCount = 0;
|
||||
}
|
||||
|
||||
boolean makeSnapshot(int repeat_number) {
|
||||
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
snapshots[i] = threads[i].getStackTrace();
|
||||
}
|
||||
|
||||
return checkTraces(repeat_number);
|
||||
}
|
||||
|
||||
boolean checkTraces(int repeat_number) {
|
||||
StackTraceElement[] elements;
|
||||
|
||||
boolean res = true;
|
||||
display(">>> snapshot " + repeat_number);
|
||||
int expectedCount = DEPTH + 1;
|
||||
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
elements = snapshots[i];
|
||||
|
||||
if (elements == null)
|
||||
continue;
|
||||
|
||||
if (elements.length == 0)
|
||||
continue;
|
||||
|
||||
if (elements.length > 0) {
|
||||
display("\tchecking " + threads[i].getName()
|
||||
+ "(trace elements: " + elements.length + ")");
|
||||
}
|
||||
|
||||
if (elements.length > expectedCount) {
|
||||
complain(threads[i].getName() + ">Contains more then " +
|
||||
+expectedCount + " elements");
|
||||
}
|
||||
|
||||
for (int j = 0; j < elements.length; j++) {
|
||||
if (!checkElement(elements[j])) {
|
||||
complain(threads[i].getName() + ">Unexpected method name: "
|
||||
+ elements[j].getMethodName());
|
||||
complain("\tat " + j + " position");
|
||||
if (elements[j].isNativeMethod()) {
|
||||
complain("\tline number: (native method)");
|
||||
complain("\tclass name: " + elements[j].getClassName());
|
||||
} else {
|
||||
complain("\tline number: " + elements[j].getLineNumber());
|
||||
complain("\tclass name: " + elements[j].getClassName());
|
||||
complain("\tfile name: " + elements[j].getFileName());
|
||||
}
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
boolean checkElement(StackTraceElement element) {
|
||||
String name = element.getClassName() + "." + element.getMethodName();
|
||||
for (int i = 0; i < EXPECTED_METHODS.length; i++) {
|
||||
if (EXPECTED_METHODS[i].compareTo(name) == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void finishThreads() {
|
||||
try {
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
if (threads[i].isAlive())
|
||||
threads[i].join(waitTime / THRD_COUNT);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
isLocked = false;
|
||||
}
|
||||
|
||||
static void display(String message) {
|
||||
log.display(message);
|
||||
}
|
||||
|
||||
static void complain(String message) {
|
||||
log.complain(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class strace003Thread extends Thread {
|
||||
|
||||
private int currentDepth = 0;
|
||||
|
||||
strace003 test;
|
||||
|
||||
static {
|
||||
try {
|
||||
System.loadLibrary("strace003");
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
System.err.println("Could not load strace003 library");
|
||||
System.err.println("java.library.path:"
|
||||
+ System.getProperty("java.library.path"));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
strace003Thread(strace003 test, String name) {
|
||||
this.test = test;
|
||||
setName(name);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
|
||||
recursiveMethod();
|
||||
|
||||
}
|
||||
|
||||
native void recursiveMethod();
|
||||
}
|
||||
94
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace004.c
Normal file
94
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace004.c
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "nsk_strace.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static const char *Stest_cn="nsk/stress/strace/strace004";
|
||||
static const char *Slongparam="(J)V";
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_nsk_stress_strace_strace004Thread_recursiveMethod(JNIEnv *env, jobject obj)
|
||||
{
|
||||
jfieldID field;
|
||||
jmethodID method;
|
||||
jint currDepth;
|
||||
jclass testClass, threadClass, objClass;
|
||||
jint maxDepth;
|
||||
jboolean isLocked;
|
||||
jint achivedCount;
|
||||
jobject testField, waitStart;
|
||||
|
||||
FIND_CLASS(testClass, Stest_cn);
|
||||
FIND_CLASS(objClass, "java/lang/Object");
|
||||
GET_OBJECT_CLASS(threadClass, obj);
|
||||
|
||||
/* currDepth++ */
|
||||
GET_INT_FIELD(currDepth, obj, threadClass, "currentDepth");
|
||||
currDepth++;
|
||||
SET_INT_FIELD(obj, threadClass, "currentDepth", currDepth);
|
||||
|
||||
if (currDepth == 1)
|
||||
{
|
||||
GET_OBJ_FIELD(testField, obj, threadClass, "test",
|
||||
"Lnsk/stress/strace/strace004;");
|
||||
|
||||
GET_STATIC_OBJ_FIELD(waitStart, testClass, "waitStart",
|
||||
"Ljava/lang/Object;");
|
||||
|
||||
MONITOR_ENTER(testField);
|
||||
GET_INT_FIELD(achivedCount, testField, testClass, "achivedCount");
|
||||
achivedCount++;
|
||||
SET_INT_FIELD(testField, testClass, "achivedCount", achivedCount);
|
||||
MONITOR_EXIT(testField);
|
||||
|
||||
GET_STATIC_BOOL_FIELD(isLocked, testClass, "isLocked");
|
||||
while (isLocked != JNI_TRUE)
|
||||
{
|
||||
MONITOR_ENTER(waitStart);
|
||||
CALL_VOID(waitStart, objClass, "wait", Slongparam, 1LL);
|
||||
MONITOR_EXIT(waitStart);
|
||||
GET_STATIC_BOOL_FIELD(isLocked, testClass, "isLocked");
|
||||
}
|
||||
}
|
||||
|
||||
GET_STATIC_INT_FIELD(maxDepth, testClass, "DEPTH");
|
||||
|
||||
if (maxDepth - currDepth > 0)
|
||||
{
|
||||
CALL_STATIC_VOID_NOPARAM(threadClass, "yield");
|
||||
CALL_VOID_NOPARAM(obj, threadClass, "recursiveMethod");
|
||||
}
|
||||
|
||||
currDepth--;
|
||||
GET_OBJECT_CLASS(threadClass, obj);
|
||||
SET_INT_FIELD(obj, threadClass, "currentDepth", currDepth);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
321
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace004.java
Normal file
321
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace004.java
Normal file
@ -0,0 +1,321 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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/strace/strace004.
|
||||
* VM testbase keywords: [stress, strace]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* The test checks up java.lang.Thread.getAllStackTraces() method for many
|
||||
* threads, that recursively invoke a native method in running mode
|
||||
* ("alive" stack).
|
||||
* The test fails if:
|
||||
* - amount of stack trace elements is more than depth of recursion plus
|
||||
* four elements corresponding to invocations of Thread.run(), Thread.wait(),
|
||||
* Thread.exit(), Thread.yield() and ThreadGroup.remove() methods;
|
||||
* - there is at least one element corresponding to invocation of unexpected
|
||||
* method.
|
||||
* This test is almost the same as nsk.stress.strace.strace003 except for
|
||||
* checking is performed for java.lang.Thread.getAllStackTraces() method.
|
||||
* COMMENTS
|
||||
* java.lang.Thread.getAllStackTraces() is too slow method. So it is not successed
|
||||
* to catch an alive thread during execution of this method for the first snapshot
|
||||
* and it is needed to check on a promoted build due to the below assertion.
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* waiting for all threads started ...
|
||||
* >>> snapshot 1
|
||||
* waiting for threads finished
|
||||
* # To suppress the following error report, specify this argument
|
||||
* # after -XX: or in .hotspotrc: SuppressErrorAt=/jniHandles.hpp:157
|
||||
* #
|
||||
* # HotSpot Virtual Machine Error, assertion failure
|
||||
* # Please report this error at
|
||||
* # http://java.sun.com/cgi-bin/bugreport.cgi
|
||||
* #
|
||||
* # Java VM: Java HotSpot(TM) Client VM (1.4.1-internal-debug mixed mode)
|
||||
* #
|
||||
* # assert(result != ((oop)::badJNIHandleVal), "Pointing to zapped jni handle area")
|
||||
* #
|
||||
* # Error ID: src/share/vm/runtime/jniHandles.hpp, 157 [ Patched ]
|
||||
* #
|
||||
* # Problematic Thread: prio=5 tid=0x001976e0 nid=0x96 runnable
|
||||
* #
|
||||
* Heap at VM Abort:
|
||||
* Heap
|
||||
* def new generation total 2112K, used 455K [0xf1800000, 0xf1a20000, 0xf1f10000)
|
||||
* eden space 2048K, 22% used [0xf1800000, 0xf1871f60, 0xf1a00000)
|
||||
* from space 64K, 0% used [0xf1a00000, 0xf1a00000, 0xf1a10000)
|
||||
* to space 64K, 0% used [0xf1a10000, 0xf1a10000, 0xf1a20000)
|
||||
* tenured generation total 1408K, used 0K [0xf1f10000, 0xf2070000, 0xf5800000)
|
||||
* the space 1408K, 0% used [0xf1f10000, 0xf1f10000, 0xf1f10200, 0xf2070000)
|
||||
* compacting perm gen total 4096K, used 1025K [0xf5800000, 0xf5c00000, 0xf9800000)
|
||||
* the space 4096K, 25% used [0xf5800000, 0xf5900660, 0xf5900800, 0xf5c00000)
|
||||
* Dumping core....
|
||||
* Abort
|
||||
* Finished at: Fri Apr 25 18:01:37 NSK 2003
|
||||
*
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @run driver jdk.test.lib.FileInstaller . .
|
||||
* @run main/othervm/native nsk.stress.strace.strace004
|
||||
*/
|
||||
|
||||
package nsk.stress.strace;
|
||||
|
||||
import nsk.share.ArgumentParser;
|
||||
import nsk.share.Log;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The test check up <code>java.lang.Thread.getAllStackTraces()</code> method for many
|
||||
* threads, that recursively invoke a native method in running mode ("alive" stack).
|
||||
* <p>
|
||||
* <p>The test creates <code>THRD_COUNT</code> instances of <code>strace004Thread</code>
|
||||
* class, tries to get their stack traces and checks up that returned array contains
|
||||
* correct stack frames. Each stack frame must be corresponded to one of the following
|
||||
* methods defined by the <code>EXPECTED_METHODS</code> array.</p>
|
||||
* <p>These checking are performed <code>REPEAT_COUNT</code> times.</p>
|
||||
*/
|
||||
public class strace004 {
|
||||
|
||||
static final int DEPTH = 100;
|
||||
static final int THRD_COUNT = 100;
|
||||
static final int REPEAT_COUNT = 10;
|
||||
static final String[] EXPECTED_METHODS = {
|
||||
"java.lang.System.arraycopy",
|
||||
"java.lang.Object.wait",
|
||||
"java.lang.Thread.exit",
|
||||
"java.lang.Thread.yield",
|
||||
"java.lang.ThreadGroup.remove",
|
||||
"java.lang.ThreadGroup.threadTerminated",
|
||||
"nsk.stress.strace.strace004Thread.run",
|
||||
"nsk.stress.strace.strace004Thread.recursiveMethod"
|
||||
};
|
||||
|
||||
|
||||
static volatile boolean isLocked = false;
|
||||
static PrintStream out;
|
||||
static long waitTime = 2;
|
||||
|
||||
static Object waitStart = new Object();
|
||||
|
||||
static strace004Thread[] threads;
|
||||
static StackTraceElement[][] snapshots = new StackTraceElement[THRD_COUNT][];
|
||||
static Log log;
|
||||
|
||||
volatile int achivedCount = 0;
|
||||
|
||||
public static void main(String[] args) {
|
||||
out = System.out;
|
||||
int exitCode = run(args);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String[] args) {
|
||||
ArgumentParser argHandler = new ArgumentParser(args);
|
||||
log = new Log(out, argHandler);
|
||||
waitTime = argHandler.getWaitTime() * 60000;
|
||||
|
||||
strace004 test = new strace004();
|
||||
boolean res = true;
|
||||
|
||||
for (int j = 0; j < REPEAT_COUNT; j++) {
|
||||
test.startThreads();
|
||||
|
||||
if (!test.makeSnapshot(j + 1)) res = false;
|
||||
|
||||
display("waiting for threads finished\n");
|
||||
test.finishThreads();
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
complain("***>>>Test failed<<<***");
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void startThreads() {
|
||||
threads = new strace004Thread[THRD_COUNT];
|
||||
achivedCount = 0;
|
||||
|
||||
String tmp_name;
|
||||
for (int i = 0; i < THRD_COUNT; i++) {
|
||||
tmp_name = "strace004Thread" + Integer.toString(i);
|
||||
threads[i] = new strace004Thread(this, tmp_name);
|
||||
}
|
||||
|
||||
for (int i = 0; i < THRD_COUNT; i++) {
|
||||
threads[i].start();
|
||||
}
|
||||
|
||||
waitFor("all threads started ...");
|
||||
synchronized (waitStart) {
|
||||
isLocked = true;
|
||||
waitStart.notifyAll();
|
||||
}
|
||||
try {
|
||||
Thread.yield();
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
}
|
||||
|
||||
void waitFor(String msg) {
|
||||
if (msg.length() > 0)
|
||||
display("waiting for " + msg);
|
||||
|
||||
while (achivedCount < THRD_COUNT) {
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
}
|
||||
achivedCount = 0;
|
||||
}
|
||||
|
||||
boolean makeSnapshot(int repeat_number) {
|
||||
|
||||
Map traces = Thread.getAllStackTraces();
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
snapshots[i] = (StackTraceElement[]) traces.get(threads[i]);
|
||||
}
|
||||
|
||||
return checkTraces(repeat_number);
|
||||
}
|
||||
|
||||
boolean checkTraces(int repeat_number) {
|
||||
StackTraceElement[] elements;
|
||||
|
||||
boolean res = true;
|
||||
display(">>> snapshot " + repeat_number);
|
||||
int expectedCount = DEPTH + 1;
|
||||
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
elements = snapshots[i];
|
||||
|
||||
if (elements == null)
|
||||
continue;
|
||||
|
||||
if (elements.length == 0)
|
||||
continue;
|
||||
|
||||
if (elements.length > 3) {
|
||||
display("\tchecking " + threads[i].getName()
|
||||
+ "(trace elements: " + elements.length + ")");
|
||||
}
|
||||
|
||||
if (elements.length > expectedCount) {
|
||||
complain(threads[i].getName() + ">Contains more then " +
|
||||
+expectedCount + " elements");
|
||||
}
|
||||
|
||||
for (int j = 0; j < elements.length; j++) {
|
||||
if (!checkElement(elements[j])) {
|
||||
complain(threads[i].getName() + ">Unexpected method name: "
|
||||
+ elements[j].getMethodName());
|
||||
complain("\tat " + j + " position");
|
||||
if (elements[j].isNativeMethod()) {
|
||||
complain("\tline number: (native method)");
|
||||
complain("\tclass name: " + elements[j].getClassName());
|
||||
} else {
|
||||
complain("\tline number: " + elements[j].getLineNumber());
|
||||
complain("\tclass name: " + elements[j].getClassName());
|
||||
complain("\tfile name: " + elements[j].getFileName());
|
||||
}
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
boolean checkElement(StackTraceElement element) {
|
||||
String name = element.getClassName() + "." + element.getMethodName();
|
||||
for (int i = 0; i < EXPECTED_METHODS.length; i++) {
|
||||
if (EXPECTED_METHODS[i].compareTo(name) == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void finishThreads() {
|
||||
try {
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
if (threads[i].isAlive())
|
||||
threads[i].join(waitTime / THRD_COUNT);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
isLocked = false;
|
||||
}
|
||||
|
||||
static void display(String message) {
|
||||
log.display(message);
|
||||
}
|
||||
|
||||
static void complain(String message) {
|
||||
log.complain(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class strace004Thread extends Thread {
|
||||
|
||||
private int currentDepth = 0;
|
||||
|
||||
strace004 test;
|
||||
|
||||
static {
|
||||
try {
|
||||
System.loadLibrary("strace004");
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
System.err.println("Could not load strace004 library");
|
||||
System.err.println("java.library.path:"
|
||||
+ System.getProperty("java.library.path"));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
strace004Thread(strace004 test, String name) {
|
||||
this.test = test;
|
||||
setName(name);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
|
||||
recursiveMethod();
|
||||
|
||||
}
|
||||
|
||||
native void recursiveMethod();
|
||||
}
|
||||
107
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace005.c
Normal file
107
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace005.c
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "nsk_strace.h"
|
||||
#include "nsk_tools.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static const char *Stest_cn="nsk/stress/strace/strace005";
|
||||
static jclass stackOverflowErrorClass;
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
JNI_OnLoad(JavaVM *vm, void *reserved)
|
||||
{
|
||||
JNIEnv *env;
|
||||
|
||||
if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION) != JNI_OK) {
|
||||
printf("%s:%d: Failed to call GetEnv\n", __FILE__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FIND_CLASS(stackOverflowErrorClass, "java/lang/StackOverflowError");
|
||||
if ((stackOverflowErrorClass = (*env)->NewGlobalRef(env, stackOverflowErrorClass)) == NULL) {
|
||||
printf("Can't create global ref for stack overflow class\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return JNI_VERSION;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNI_OnUnload(JavaVM *vm, void *reserved)
|
||||
{
|
||||
JNIEnv *env;
|
||||
|
||||
if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION) != JNI_OK) {
|
||||
if (stackOverflowErrorClass != NULL) {
|
||||
(*env)->DeleteGlobalRef(env, stackOverflowErrorClass);
|
||||
}
|
||||
} else {
|
||||
printf("%s:%d: Failed to call GetEnv\n", __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_nsk_stress_strace_strace005Thread_recursiveMethod2(JNIEnv *env, jobject obj)
|
||||
{
|
||||
jfieldID field;
|
||||
jmethodID method;
|
||||
jint currDepth;
|
||||
jclass testClass, threadClass;
|
||||
jint maxDepth;
|
||||
|
||||
FIND_CLASS(testClass, Stest_cn);
|
||||
GET_OBJECT_CLASS(threadClass, obj);
|
||||
|
||||
GET_STATIC_INT_FIELD(maxDepth, testClass, "DEPTH");
|
||||
|
||||
/* currDepth++ */
|
||||
GET_INT_FIELD(currDepth, obj, threadClass, "currentDepth");
|
||||
currDepth++;
|
||||
SET_INT_FIELD(obj, threadClass, "currentDepth", currDepth);
|
||||
|
||||
|
||||
if (maxDepth - currDepth > 0)
|
||||
{
|
||||
GET_STATIC_METHOD_ID(method, threadClass, "yield", "()V");
|
||||
NSK_CPP_STUB3(CallStaticVoidMethod, env, threadClass, method);
|
||||
EXCEPTION_CHECK(stackOverflowErrorClass, currDepth);
|
||||
|
||||
GET_METHOD_ID(method, threadClass, "recursiveMethod1", "()V");
|
||||
NSK_CPP_STUB3(CallVoidMethod, env, obj, method);
|
||||
EXCEPTION_CHECK(stackOverflowErrorClass, currDepth);
|
||||
}
|
||||
|
||||
currDepth--;
|
||||
GET_OBJECT_CLASS(threadClass, obj);
|
||||
SET_INT_FIELD(obj, threadClass, "currentDepth", currDepth);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
401
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace005.java
Normal file
401
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace005.java
Normal file
@ -0,0 +1,401 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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/strace/strace005.
|
||||
* VM testbase keywords: [stress, strace]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* The test checks up java.lang.Thread.getStackTrace() method for many threads,
|
||||
* that recursively invoke pure java and native methods by turns in running
|
||||
* mode ("alive" stack).
|
||||
* The test fails if:
|
||||
* - amount of stack trace elements is more than depth of recursion plus
|
||||
* four elements corresponding to invocations of Thread.run(), Thread.wait(),
|
||||
* Thread.exit(), Thread.yield() and ThreadGroup.remove() methods;
|
||||
* - there is at least one element corresponding to invocation of unexpected
|
||||
* method.
|
||||
* This test is almost the same as nsk.stress.strace.strace001 and
|
||||
* nsk.stress.strace.strace003 except for the recursive methods are
|
||||
* pure java and native one.
|
||||
* COMMENTS
|
||||
* Below assertion is revealed on engineer's build. It is needed to check
|
||||
* on a promoted build.
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* waiting for all threads started ...
|
||||
* Unexpected Signal : 11 occurred at PC=0xFDBB7820
|
||||
* Function=[Unknown. Nearest: SUNWprivate_1.1+0x3B7820]
|
||||
* Library=java/vitp/jdk/4593133/solaris-sparc/jre/lib/sparc/client/libjvm.so
|
||||
* Current Java thread:
|
||||
* at nsk.stress.strace.strace005Thread.recursiveMethod2(Native Method)
|
||||
* at nsk.stress.strace.strace005Thread.recursiveMethod1(strace005.java:285)
|
||||
* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
* at nsk.stress.strace.strace005Thread.recursiveMethod2(Native Method)
|
||||
* at nsk.stress.strace.strace005Thread.recursiveMethod1(strace005.java:285)
|
||||
* at nsk.stress.strace.strace005Thread.recursiveMethod2(Native Method)
|
||||
* Dynamic libraries:
|
||||
* 0x10000 jdk/4593133/solaris-sparc/bin/java
|
||||
* 0xff350000 /usr/lib/libthread.so.1
|
||||
* 0xff390000 /usr/lib/libdl.so.1
|
||||
* 0xff200000 /usr/lib/libc.so.1
|
||||
* 0xff330000 /usr/platform/SUNW,Ultra-60/lib/libc_psr.so.1
|
||||
* 0xfd800000 java/vitp/jdk/4593133/solaris-sparc/jre/lib/sparc/client/libjvm.so
|
||||
* 0xff2d0000 /usr/lib/libCrun.so.1
|
||||
* 0xff1d0000 /usr/lib/libsocket.so.1
|
||||
* 0xff100000 /usr/lib/libnsl.so.1
|
||||
* 0xff0d0000 /usr/lib/libm.so.1
|
||||
* 0xff0b0000 /usr/lib/libsched.so.1
|
||||
* 0xff300000 /usr/lib/libw.so.1
|
||||
* 0xff090000 /usr/lib/libmp.so.2
|
||||
* 0xff050000 java/vitp/jdk/4593133/solaris-sparc/jre/lib/sparc/native_threads/libhpi.so
|
||||
* 0xfd7d0000 java/vitp/jdk/4593133/solaris-sparc/jre/lib/sparc/libverify.so
|
||||
* 0xfd790000 java/vitp/jdk/4593133/solaris-sparc/jre/lib/sparc/libjava.so
|
||||
* 0xfe7e0000 java/vitp/jdk/4593133/solaris-sparc/jre/lib/sparc/libzip.so
|
||||
* 0xfc6e0000 java/vitp/tests/4593133/src/libstrace005.so
|
||||
* Heap at VM Abort:
|
||||
* Heap
|
||||
* def new generation total 2112K, used 336K [0xf1800000, 0xf1a20000, 0xf1f10000)
|
||||
* eden space 2048K, 16% used [0xf1800000, 0xf1854300, 0xf1a00000)
|
||||
* from space 64K, 0% used [0xf1a00000, 0xf1a00000, 0xf1a10000)
|
||||
* to space 64K, 0% used [0xf1a10000, 0xf1a10000, 0xf1a20000)
|
||||
* tenured generation total 1408K, used 0K [0xf1f10000, 0xf2070000, 0xf5800000)
|
||||
* the space 1408K, 0% used [0xf1f10000, 0xf1f10000, 0xf1f10200, 0xf2070000)
|
||||
* compacting perm gen total 4096K, used 1020K [0xf5800000, 0xf5c00000, 0xf9800000)
|
||||
* the space 4096K, 24% used [0xf5800000, 0xf58ff028, 0xf58ff200, 0xf5c00000)
|
||||
* Local Time = Fri Apr 25 18:09:16 2003
|
||||
* Elapsed Time = 13
|
||||
* #
|
||||
* # HotSpot Virtual Machine Error : 11
|
||||
* # Error ID : src/share/vm/runtime/os.cpp, 753 [ Patched ]
|
||||
* # Please report this error at
|
||||
* # http://java.sun.com/cgi-bin/bugreport.cgi
|
||||
* #
|
||||
* # Java VM: Java HotSpot(TM) Client VM (1.4.1-internal-debug mixed mode)
|
||||
* #
|
||||
* # An error report file has been saved as hs_err_pid16847.log.
|
||||
* # Please refer to the file for further information.
|
||||
* #
|
||||
* Dumping core....
|
||||
* Abort
|
||||
* Finished at: Fri Apr 25 18:09:17 NSK 2003
|
||||
*
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @run driver jdk.test.lib.FileInstaller . .
|
||||
* @run main/othervm/native nsk.stress.strace.strace005
|
||||
*/
|
||||
|
||||
package nsk.stress.strace;
|
||||
|
||||
import nsk.share.ArgumentParser;
|
||||
import nsk.share.Failure;
|
||||
import nsk.share.Log;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* The test checks up <code>java.lang.Thread.getStackTrace()</code> method for many threads,
|
||||
* that recursively invoke pure java and native methods by turns in running mode
|
||||
* ("alive" stack).
|
||||
* <p>
|
||||
* <p>The test creates <code>THRD_COUNT</code> instances of <code>strace005Thread</code>
|
||||
* class, tries to get their stack traces and checks up that returned array contains
|
||||
* correct stack frames. Each stack frame must be corresponded to one of the following
|
||||
* methods defined by the <code>EXPECTED_METHODS</code> array.</p>
|
||||
* <p>These checking are performed <code>REPEAT_COUNT</code> times.</p>
|
||||
*/
|
||||
public class strace005 {
|
||||
|
||||
static final int DEPTH = 500;
|
||||
static final int THRD_COUNT = 100;
|
||||
static final int REPEAT_COUNT = 10;
|
||||
static final String[] EXPECTED_METHODS = {
|
||||
"java.lang.System.arraycopy",
|
||||
"java.lang.Object.wait",
|
||||
"java.lang.Thread.exit",
|
||||
"java.lang.Thread.yield",
|
||||
"java.lang.ThreadGroup.remove",
|
||||
"java.lang.ThreadGroup.threadTerminated",
|
||||
"nsk.stress.strace.strace005Thread.run",
|
||||
"nsk.stress.strace.strace005Thread.recursiveMethod1",
|
||||
"nsk.stress.strace.strace005Thread.recursiveMethod2"
|
||||
};
|
||||
|
||||
|
||||
static volatile boolean isLocked = false;
|
||||
static PrintStream out;
|
||||
static long waitTime = 2;
|
||||
|
||||
static Object waitStart = new Object();
|
||||
|
||||
static strace005Thread[] threads;
|
||||
static StackTraceElement[][] snapshots = new StackTraceElement[THRD_COUNT][];
|
||||
static Log log;
|
||||
|
||||
volatile int achivedCount = 0;
|
||||
|
||||
public static void main(String[] args) {
|
||||
out = System.out;
|
||||
int exitCode = run(args);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String[] args) {
|
||||
ArgumentParser argHandler = new ArgumentParser(args);
|
||||
log = new Log(out, argHandler);
|
||||
waitTime = argHandler.getWaitTime() * 60000;
|
||||
|
||||
strace005 test = new strace005();
|
||||
boolean res = true;
|
||||
|
||||
for (int j = 0; j < REPEAT_COUNT; j++) {
|
||||
test.startThreads();
|
||||
|
||||
if (!test.makeSnapshot(j + 1)) res = false;
|
||||
|
||||
display("waiting for threads finished\n");
|
||||
test.finishThreads();
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
complain("***>>>Test failed<<<***");
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void startThreads() {
|
||||
threads = new strace005Thread[THRD_COUNT];
|
||||
achivedCount = 0;
|
||||
|
||||
String tmp_name;
|
||||
for (int i = 0; i < THRD_COUNT; i++) {
|
||||
tmp_name = "strace005Thread" + Integer.toString(i);
|
||||
threads[i] = new strace005Thread(this, tmp_name);
|
||||
// threads[i].setPriority(Thread.MIN_PRIORITY);
|
||||
}
|
||||
|
||||
for (int i = 0; i < THRD_COUNT; i++) {
|
||||
threads[i].start();
|
||||
}
|
||||
|
||||
waitFor("all threads started ...");
|
||||
synchronized (waitStart) {
|
||||
isLocked = true;
|
||||
waitStart.notifyAll();
|
||||
}
|
||||
try {
|
||||
Thread.yield();
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
}
|
||||
|
||||
void waitFor(String msg) {
|
||||
if (msg.length() > 0)
|
||||
display("waiting for " + msg);
|
||||
|
||||
while (achivedCount < THRD_COUNT) {
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
}
|
||||
achivedCount = 0;
|
||||
}
|
||||
|
||||
boolean makeSnapshot(int repeat_number) {
|
||||
// wait for native resolution completed (all threads have finished recursiveMethod2)
|
||||
boolean isNativeResolved = false;
|
||||
while (!isNativeResolved) {
|
||||
try {
|
||||
isNativeResolved = true;
|
||||
for (int i = 0; i < threads.length; ++i)
|
||||
if (!threads[i].isNativeResolved)
|
||||
isNativeResolved = false;
|
||||
Thread.sleep(20);
|
||||
} catch (InterruptedException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
snapshots[i] = threads[i].getStackTrace();
|
||||
}
|
||||
|
||||
return checkTraces(repeat_number);
|
||||
}
|
||||
|
||||
boolean checkTraces(int repeat_number) {
|
||||
StackTraceElement[] elements;
|
||||
|
||||
boolean res = true;
|
||||
display(">>> snapshot " + repeat_number);
|
||||
int expectedCount = DEPTH + 1;
|
||||
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
elements = snapshots[i];
|
||||
|
||||
if (elements == null || elements.length == 0)
|
||||
continue;
|
||||
|
||||
if (elements.length > 0) {
|
||||
display("\tchecking " + threads[i].getName()
|
||||
+ "(trace elements: " + elements.length + ")");
|
||||
}
|
||||
|
||||
if (elements.length > expectedCount) {
|
||||
complain(threads[i].getName() + ">Contains more then " +
|
||||
+expectedCount + " elements");
|
||||
}
|
||||
|
||||
for (int j = 0; j < elements.length; j++) {
|
||||
if (!checkElement(elements[j])) {
|
||||
complain(threads[i].getName() + ">Unexpected method name: "
|
||||
+ elements[j].getMethodName());
|
||||
complain("\tat " + j + " position");
|
||||
if (elements[j].isNativeMethod()) {
|
||||
complain("\tline number: (native method)");
|
||||
complain("\tclass name: " + elements[j].getClassName());
|
||||
} else {
|
||||
complain("\tline number: " + elements[j].getLineNumber());
|
||||
complain("\tclass name: " + elements[j].getClassName());
|
||||
complain("\tfile name: " + elements[j].getFileName());
|
||||
}
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
boolean checkElement(StackTraceElement element) {
|
||||
String name = element.getClassName() + "." + element.getMethodName();
|
||||
for (int i = 0; i < EXPECTED_METHODS.length; i++) {
|
||||
if (EXPECTED_METHODS[i].compareTo(name) == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void finishThreads() {
|
||||
try {
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
if (threads[i].isAlive())
|
||||
threads[i].join(waitTime / THRD_COUNT);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
isLocked = false;
|
||||
}
|
||||
|
||||
static void display(String message) {
|
||||
log.display(message);
|
||||
}
|
||||
|
||||
static void complain(String message) {
|
||||
log.complain(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The test creates many instances of <code>strace005Thread</code> class and tries
|
||||
* to get their stack traces.
|
||||
*/
|
||||
class strace005Thread extends Thread {
|
||||
|
||||
private int currentDepth = 0;
|
||||
public boolean isNativeResolved = false;
|
||||
|
||||
strace005 test;
|
||||
|
||||
static {
|
||||
try {
|
||||
System.loadLibrary("strace005");
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
System.err.println("Could not load strace005 library");
|
||||
System.err.println("java.library.path:"
|
||||
+ System.getProperty("java.library.path"));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
strace005Thread(strace005 test, String name) {
|
||||
this.test = test;
|
||||
setName(name);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
|
||||
recursiveMethod1();
|
||||
|
||||
}
|
||||
|
||||
void recursiveMethod1() {
|
||||
|
||||
currentDepth++;
|
||||
|
||||
if (currentDepth == 1) {
|
||||
synchronized (test) {
|
||||
test.achivedCount++;
|
||||
}
|
||||
|
||||
int alltime = 0;
|
||||
while (!strace005.isLocked) {
|
||||
synchronized (test) {
|
||||
try {
|
||||
test.wait(1);
|
||||
alltime++;
|
||||
} catch (InterruptedException e) {
|
||||
strace005.complain("" + e);
|
||||
}
|
||||
if (alltime > strace005.waitTime) {
|
||||
throw new Failure("out of wait time");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (currentDepth > 1 && !isNativeResolved)
|
||||
isNativeResolved = true;
|
||||
|
||||
if (strace005.DEPTH - currentDepth > 0) {
|
||||
try {
|
||||
yield();
|
||||
recursiveMethod2();
|
||||
} catch (StackOverflowError e) {
|
||||
// ignore this exception
|
||||
}
|
||||
}
|
||||
|
||||
currentDepth--;
|
||||
}
|
||||
|
||||
native void recursiveMethod2();
|
||||
}
|
||||
108
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace006.c
Normal file
108
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace006.c
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "nsk_strace.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static const char *Stest_cn="nsk/stress/strace/strace006";
|
||||
|
||||
static jclass testClass, threadClass;
|
||||
static jint DEPTH;
|
||||
static jclass stackOverflowErrorClass;
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
JNI_OnLoad(JavaVM *vm, void *reserved)
|
||||
{
|
||||
JNIEnv *env;
|
||||
|
||||
if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION) != JNI_OK) {
|
||||
printf("%s:%d: Failed to call GetEnv\n", __FILE__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FIND_CLASS(stackOverflowErrorClass, "java/lang/StackOverflowError");
|
||||
if ((stackOverflowErrorClass = (*env)->NewGlobalRef(env, stackOverflowErrorClass)) == NULL) {
|
||||
printf("Can't create global ref for stack overflow class\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return JNI_VERSION;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JNI_OnUnload(JavaVM *vm, void *reserved)
|
||||
{
|
||||
JNIEnv *env;
|
||||
|
||||
if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION) != JNI_OK) {
|
||||
if (stackOverflowErrorClass != NULL) {
|
||||
(*env)->DeleteGlobalRef(env, stackOverflowErrorClass);
|
||||
}
|
||||
} else {
|
||||
printf("%s:%d: Failed to call GetEnv\n", __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_nsk_stress_strace_strace006Thread_recursiveMethod2(JNIEnv *env, jobject obj)
|
||||
{
|
||||
jfieldID field;
|
||||
jmethodID method;
|
||||
jint currDepth;
|
||||
jclass testClass, threadClass;
|
||||
jint maxDepth;
|
||||
|
||||
FIND_CLASS(testClass, Stest_cn);
|
||||
GET_OBJECT_CLASS(threadClass, obj);
|
||||
|
||||
GET_STATIC_INT_FIELD(maxDepth, testClass, "DEPTH");
|
||||
|
||||
/* currDepth++ */
|
||||
GET_INT_FIELD(currDepth, obj, threadClass, "currentDepth");
|
||||
currDepth++;
|
||||
SET_INT_FIELD(obj, threadClass, "currentDepth", currDepth);
|
||||
|
||||
if (maxDepth - currDepth > 0)
|
||||
{
|
||||
GET_STATIC_METHOD_ID(method, threadClass, "yield", "()V");
|
||||
NSK_CPP_STUB3(CallStaticVoidMethod, env, threadClass, method);
|
||||
EXCEPTION_CHECK(stackOverflowErrorClass, currDepth);
|
||||
|
||||
GET_METHOD_ID(method, threadClass, "recursiveMethod1", "()V");
|
||||
NSK_CPP_STUB3(CallVoidMethod, env, obj, method);
|
||||
EXCEPTION_CHECK(stackOverflowErrorClass, currDepth);
|
||||
}
|
||||
|
||||
currDepth--;
|
||||
GET_OBJECT_CLASS(threadClass, obj);
|
||||
SET_INT_FIELD(obj, threadClass, "currentDepth", currDepth);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
345
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace006.java
Normal file
345
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace006.java
Normal file
@ -0,0 +1,345 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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/strace/strace006.
|
||||
* VM testbase keywords: [stress, strace]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* The test checks up java.lang.Thread.getAllStackTraces() method for many
|
||||
* threads, that recursively invoke pure java and native methods by turns
|
||||
* in running mode ("alive" stack).
|
||||
* The test fails if:
|
||||
* - amount of stack trace elements is more than depth of recursion plus
|
||||
* four elements corresponding to invocations of Thread.run(), Thread.wait(),
|
||||
* Thread.exit(), Thread.yield() and ThreadGroup.remove() methods;
|
||||
* - there is at least one element corresponding to invocation of unexpected
|
||||
* method.
|
||||
* This test is almost the same as nsk.stress.strace.strace005 except for
|
||||
* checking is performed for java.lang.Thread.getAllStackTraces() method.
|
||||
* COMMENTS
|
||||
* Similar assertion is thrown (see strace005.README).
|
||||
*
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @run driver jdk.test.lib.FileInstaller . .
|
||||
* @run main/othervm/native nsk.stress.strace.strace006
|
||||
*/
|
||||
|
||||
package nsk.stress.strace;
|
||||
|
||||
import nsk.share.ArgumentParser;
|
||||
import nsk.share.Failure;
|
||||
import nsk.share.Log;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The test check up <code>java.lang.Thread.getStackTrace()</code> method for the pure
|
||||
* java recursion.
|
||||
* <p>The test creates <code>THRD_COUNT</code> instances of <code>strace006Thread</code>
|
||||
* class, tries to get their stack traces and checks up that returned array contains
|
||||
* correct stack frames. Each stack frame must be corresponded to one of the following
|
||||
* methods defined by the <code>expectedMethod</code> array.</p>
|
||||
* <p>These checking are performed <code>REPEAT_COUNT</code> times.</p>
|
||||
*/
|
||||
public class strace006 {
|
||||
|
||||
static final int DEPTH = 500;
|
||||
static final int THRD_COUNT = 100;
|
||||
static final int REPEAT_COUNT = 10;
|
||||
static final String[] EXPECTED_METHODS = {
|
||||
"java.lang.System.arraycopy",
|
||||
"java.lang.Object.wait",
|
||||
"java.lang.Thread.exit",
|
||||
"java.lang.Thread.yield",
|
||||
"java.lang.ThreadGroup.remove",
|
||||
"java.lang.ThreadGroup.threadTerminated",
|
||||
"nsk.stress.strace.strace006Thread.run",
|
||||
"nsk.stress.strace.strace006Thread.recursiveMethod1",
|
||||
"nsk.stress.strace.strace006Thread.recursiveMethod2"
|
||||
};
|
||||
|
||||
|
||||
static volatile boolean isLocked = false;
|
||||
static PrintStream out;
|
||||
static long waitTime = 2;
|
||||
|
||||
static Object waitStart = new Object();
|
||||
|
||||
static strace006Thread[] threads;
|
||||
static StackTraceElement[][] snapshots = new StackTraceElement[THRD_COUNT][];
|
||||
static Log log;
|
||||
|
||||
volatile int achivedCount = 0;
|
||||
|
||||
public static void main(String[] args) {
|
||||
out = System.out;
|
||||
int exitCode = run(args);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String[] args) {
|
||||
ArgumentParser argHandler = new ArgumentParser(args);
|
||||
log = new Log(out, argHandler);
|
||||
waitTime = argHandler.getWaitTime() * 60000;
|
||||
|
||||
strace006 test = new strace006();
|
||||
boolean res = true;
|
||||
|
||||
for (int j = 0; j < REPEAT_COUNT; j++) {
|
||||
test.startThreads();
|
||||
|
||||
if (!test.makeSnapshot(j + 1)) res = false;
|
||||
|
||||
display("waiting for threads finished\n");
|
||||
test.finishThreads();
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
complain("***>>>Test failed<<<***");
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void startThreads() {
|
||||
threads = new strace006Thread[THRD_COUNT];
|
||||
achivedCount = 0;
|
||||
|
||||
String tmp_name;
|
||||
for (int i = 0; i < THRD_COUNT; i++) {
|
||||
tmp_name = "strace006Thread" + Integer.toString(i);
|
||||
threads[i] = new strace006Thread(this, tmp_name);
|
||||
// threads[i].setPriority(Thread.MIN_PRIORITY);
|
||||
}
|
||||
|
||||
for (int i = 0; i < THRD_COUNT; i++) {
|
||||
threads[i].start();
|
||||
}
|
||||
|
||||
waitFor("all threads started ...");
|
||||
synchronized (waitStart) {
|
||||
isLocked = true;
|
||||
waitStart.notifyAll();
|
||||
}
|
||||
try {
|
||||
Thread.yield();
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
}
|
||||
|
||||
void waitFor(String msg) {
|
||||
if (msg.length() > 0)
|
||||
display("waiting for " + msg);
|
||||
|
||||
while (achivedCount < THRD_COUNT) {
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
}
|
||||
achivedCount = 0;
|
||||
}
|
||||
|
||||
boolean makeSnapshot(int repeat_number) {
|
||||
|
||||
// wait for native resolution completed (all threads have finished recursiveMethod2)
|
||||
boolean isNativeResolved = false;
|
||||
while (!isNativeResolved) {
|
||||
try {
|
||||
isNativeResolved = true;
|
||||
for (int i = 0; i < threads.length; ++i)
|
||||
if (!threads[i].isNativeResolved)
|
||||
isNativeResolved = false;
|
||||
Thread.sleep(20);
|
||||
} catch (InterruptedException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
Map traces = Thread.getAllStackTraces();
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
snapshots[i] = (StackTraceElement[]) traces.get(threads[i]);
|
||||
}
|
||||
|
||||
return checkTraces(repeat_number);
|
||||
}
|
||||
|
||||
boolean checkTraces(int repeat_number) {
|
||||
StackTraceElement[] elements;
|
||||
|
||||
boolean res = true;
|
||||
display(">>> snapshot " + repeat_number);
|
||||
int expectedCount = DEPTH + 1;
|
||||
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
elements = snapshots[i];
|
||||
|
||||
if (elements == null || elements.length == 0)
|
||||
continue;
|
||||
|
||||
if (elements.length > 0) {
|
||||
display("\tchecking " + threads[i].getName()
|
||||
+ "(trace elements: " + elements.length + ")");
|
||||
}
|
||||
|
||||
if (elements.length > expectedCount) {
|
||||
complain(threads[i].getName() + ">Contains more then "
|
||||
+ expectedCount + " elements");
|
||||
}
|
||||
|
||||
for (int j = 0; j < elements.length; j++) {
|
||||
if (!checkElement(elements[j])) {
|
||||
complain(threads[i].getName() + ">Unexpected method name: "
|
||||
+ elements[j].getMethodName());
|
||||
complain("\tat " + j + " position");
|
||||
if (elements[j].isNativeMethod()) {
|
||||
complain("\tline number: (native method)");
|
||||
complain("\tclass name: " + elements[j].getClassName());
|
||||
} else {
|
||||
complain("\tline number: " + elements[j].getLineNumber());
|
||||
complain("\tclass name: " + elements[j].getClassName());
|
||||
complain("\tfile name: " + elements[j].getFileName());
|
||||
}
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
boolean checkElement(StackTraceElement element) {
|
||||
if (element.getClassName().equals("java.lang.ClassLoader"))
|
||||
return true;
|
||||
String name = element.getClassName() + "." + element.getMethodName();
|
||||
for (int i = 0; i < EXPECTED_METHODS.length; i++) {
|
||||
if (EXPECTED_METHODS[i].compareTo(name) == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void finishThreads() {
|
||||
try {
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
if (threads[i].isAlive())
|
||||
threads[i].join(waitTime / THRD_COUNT);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
isLocked = false;
|
||||
}
|
||||
|
||||
static void display(String message) {
|
||||
log.display(message);
|
||||
}
|
||||
|
||||
static void complain(String message) {
|
||||
log.complain(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The test creates many instances of <code>strace006Thread</code> class and tries
|
||||
* to get their stack traces.
|
||||
*/
|
||||
class strace006Thread extends Thread {
|
||||
|
||||
private int currentDepth = 0;
|
||||
public boolean isNativeResolved = false;
|
||||
|
||||
strace006 test;
|
||||
|
||||
static {
|
||||
try {
|
||||
System.loadLibrary("strace006");
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
System.err.println("Could not load strace006 library");
|
||||
System.err.println("java.library.path:"
|
||||
+ System.getProperty("java.library.path"));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
strace006Thread(strace006 test, String name) {
|
||||
this.test = test;
|
||||
setName(name);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
|
||||
recursiveMethod1();
|
||||
|
||||
}
|
||||
|
||||
void recursiveMethod1() {
|
||||
|
||||
currentDepth++;
|
||||
|
||||
if (currentDepth == 1) {
|
||||
synchronized (test) {
|
||||
test.achivedCount++;
|
||||
}
|
||||
|
||||
int alltime = 0;
|
||||
while (!strace006.isLocked) {
|
||||
synchronized (test) {
|
||||
try {
|
||||
test.wait(1);
|
||||
alltime++;
|
||||
} catch (InterruptedException e) {
|
||||
strace006.complain("" + e);
|
||||
}
|
||||
if (alltime > strace006.waitTime) {
|
||||
throw new Failure("out of wait time");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (currentDepth > 1 && !isNativeResolved)
|
||||
isNativeResolved = true;
|
||||
|
||||
if (strace006.DEPTH - currentDepth > 0) {
|
||||
try {
|
||||
yield();
|
||||
recursiveMethod2();
|
||||
} catch (StackOverflowError e) {
|
||||
// ignore this exception
|
||||
}
|
||||
}
|
||||
|
||||
currentDepth--;
|
||||
}
|
||||
|
||||
native void recursiveMethod2();
|
||||
}
|
||||
283
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace007.java
Normal file
283
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace007.java
Normal file
@ -0,0 +1,283 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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/strace/strace007.
|
||||
* VM testbase keywords: [stress, quick, strace]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* The test runs many threads, that recursively invoke a pure java method.
|
||||
* After arriving at defined depth of recursion, the test calls
|
||||
* java.lang.Thread.getStackTrace() and java.lang.Thread.getAllStackTraces()
|
||||
* methods and checks their results. All threads are running in a loop
|
||||
* as long as these methods are executed.
|
||||
* The test fails if:
|
||||
* - amount of stack trace elements and stack trace elements themselves are
|
||||
* the same for both methods;
|
||||
* - there is at least one element corresponding to invocation of unexpected
|
||||
* method. Expected methods are Thread.sleep(), Thread.run() and the
|
||||
* recursive method.
|
||||
*
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @run driver jdk.test.lib.FileInstaller . .
|
||||
* @run main/othervm nsk.stress.strace.strace007
|
||||
*/
|
||||
|
||||
package nsk.stress.strace;
|
||||
|
||||
import nsk.share.ArgumentParser;
|
||||
import nsk.share.Log;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The test runs <code>THRD_COUNT</code> instances of <code>strace007Thread</code>,
|
||||
* that recursively invoke a pure java method. After arriving at defined depth
|
||||
* <code>DEPTH</code> of recursion, the test calls
|
||||
* <code>java.lang.Thread.getStackTrace()</code> and
|
||||
* <code>java.lang.Thread.getAllStackTraces()</code> methods and checks their results.
|
||||
* <p>
|
||||
* <p>It is expected that these methods return the same stack traces. Each stack frame
|
||||
* for both stack traces must be corresponded to invocation of one of the methods
|
||||
* defined by the <code>EXPECTED_METHODS</code> array.</p>
|
||||
*/
|
||||
public class strace007 {
|
||||
|
||||
static final int DEPTH = 500;
|
||||
static final int THRD_COUNT = 100;
|
||||
static final int SLEEP_TIME = 50;
|
||||
static final String[] EXPECTED_METHODS = {
|
||||
"java.lang.Thread.sleep",
|
||||
"nsk.stress.strace.strace007Thread.run",
|
||||
"nsk.stress.strace.strace007Thread.recursiveMethod"
|
||||
};
|
||||
|
||||
|
||||
static PrintStream out;
|
||||
static long waitTime = 2;
|
||||
|
||||
static Object doSnapshot = new Object();
|
||||
static volatile boolean isSnapshotDone = false;
|
||||
static volatile int achivedCount = 0;
|
||||
static Log log;
|
||||
|
||||
static strace007Thread[] threads;
|
||||
|
||||
public static void main(String[] args) {
|
||||
out = System.out;
|
||||
int exitCode = run(args);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String[] args) {
|
||||
ArgumentParser argHandler = new ArgumentParser(args);
|
||||
log = new Log(out, argHandler);
|
||||
waitTime = argHandler.getWaitTime() * 60000;
|
||||
|
||||
boolean res = true;
|
||||
|
||||
startThreads();
|
||||
|
||||
res = makeSnapshot();
|
||||
|
||||
finishThreads();
|
||||
|
||||
if (!res) {
|
||||
complain("***>>>Test failed<<<***");
|
||||
return 2;
|
||||
}
|
||||
|
||||
display(">>>Test passed<<<");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void startThreads() {
|
||||
threads = new strace007Thread[THRD_COUNT];
|
||||
achivedCount = 0;
|
||||
|
||||
String tmp_name;
|
||||
display("starting threads...");
|
||||
for (int i = 0; i < THRD_COUNT; i++) {
|
||||
tmp_name = "strace007Thread" + Integer.toString(i);
|
||||
threads[i] = new strace007Thread(tmp_name);
|
||||
threads[i].start();
|
||||
}
|
||||
|
||||
display("waiting for the defined recursion depth ...");
|
||||
while (achivedCount < THRD_COUNT) {
|
||||
synchronized (doSnapshot) {
|
||||
try {
|
||||
doSnapshot.wait(1);
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static boolean makeSnapshot() {
|
||||
|
||||
display("making all threads snapshots...");
|
||||
Map traces = Thread.getAllStackTraces();
|
||||
int count = ((StackTraceElement[]) traces.get(threads[0])).length;
|
||||
|
||||
display("making snapshots of each thread...");
|
||||
StackTraceElement[][] elements = new StackTraceElement[THRD_COUNT][];
|
||||
for (int i = 0; i < THRD_COUNT; i++) {
|
||||
elements[i] = threads[i].getStackTrace();
|
||||
}
|
||||
|
||||
display("checking lengths of stack traces...");
|
||||
StackTraceElement[] all;
|
||||
for (int i = 1; i < THRD_COUNT; i++) {
|
||||
all = (StackTraceElement[]) traces.get(threads[i]);
|
||||
int k = all.length;
|
||||
if (count - k > 2) {
|
||||
complain("wrong lengths of stack traces:\n\t"
|
||||
+ threads[0].getName() + ": " + count
|
||||
+ "\t"
|
||||
+ threads[i].getName() + ": " + k);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
display("checking stack traces...");
|
||||
boolean res = true;
|
||||
for (int i = 0; i < THRD_COUNT; i++) {
|
||||
all = (StackTraceElement[]) traces.get(threads[i]);
|
||||
if (!checkTraces(threads[i].getName(), elements[i], all)) {
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static boolean checkTraces(String threadName, StackTraceElement[] threadSnap,
|
||||
StackTraceElement[] allSnap) {
|
||||
|
||||
int checkedLength = threadSnap.length < allSnap.length ?
|
||||
threadSnap.length : allSnap.length;
|
||||
boolean res = true;
|
||||
|
||||
for (int j = 0; j < checkedLength; j++) {
|
||||
if (!checkElement(threadSnap[j])) {
|
||||
complain("Unexpected " + j + "-element:");
|
||||
complain("\tmethod name: " + threadSnap[j].getMethodName());
|
||||
complain("\tclass name: " + threadSnap[j].getClassName());
|
||||
if (threadSnap[j].isNativeMethod()) {
|
||||
complain("\tline number: (native method)");
|
||||
} else {
|
||||
complain("\tline number: " + threadSnap[j].getLineNumber());
|
||||
complain("\tfile name: " + threadSnap[j].getFileName());
|
||||
}
|
||||
complain("");
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static boolean checkElement(StackTraceElement element) {
|
||||
String name = element.getClassName() + "." + element.getMethodName();
|
||||
for (int i = 0; i < EXPECTED_METHODS.length; i++) {
|
||||
if (EXPECTED_METHODS[i].compareTo(name) == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void finishThreads() {
|
||||
isSnapshotDone = true;
|
||||
try {
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
if (threads[i].isAlive()) {
|
||||
display("waiting for finish " + threads[i].getName());
|
||||
threads[i].join(waitTime);
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
isSnapshotDone = false;
|
||||
}
|
||||
|
||||
static void display(String message) {
|
||||
log.display(message);
|
||||
}
|
||||
|
||||
static void complain(String message) {
|
||||
log.complain(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class strace007Thread extends Thread {
|
||||
|
||||
private int currentDepth = 0;
|
||||
|
||||
static int[] arr = new int[1000];
|
||||
|
||||
strace007Thread(String name) {
|
||||
setName(name);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
recursiveMethod(arr);
|
||||
} catch (Throwable throwable) {
|
||||
System.err.println("# ERROR: " + getName() + ": " + throwable);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void recursiveMethod(int[] arr) {
|
||||
currentDepth++;
|
||||
|
||||
if (strace007.DEPTH - currentDepth > 0) {
|
||||
recursiveMethod(arr);
|
||||
}
|
||||
|
||||
if (strace007.DEPTH == currentDepth) {
|
||||
|
||||
synchronized (strace007.doSnapshot) {
|
||||
strace007.achivedCount++;
|
||||
strace007.doSnapshot.notify();
|
||||
}
|
||||
|
||||
while (!strace007.isSnapshotDone) {
|
||||
try {
|
||||
sleep(strace007.SLEEP_TIME);
|
||||
} catch (InterruptedException e) {
|
||||
strace007.complain(getName() + "> " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentDepth--;
|
||||
}
|
||||
}
|
||||
92
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace008.c
Normal file
92
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace008.c
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "nsk_strace.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static const char *Stest_cn="nsk/stress/strace/strace008";
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_nsk_stress_strace_strace008Thread_recursiveMethod(JNIEnv *env, jobject obj)
|
||||
{
|
||||
jfieldID field;
|
||||
jmethodID method;
|
||||
jint currDepth;
|
||||
jclass testClass, threadClass;
|
||||
jint maxDepth;
|
||||
jboolean isDone;
|
||||
jint achivedCount;
|
||||
jobject doSnapshot;
|
||||
jint sleepTime;
|
||||
|
||||
FIND_CLASS(testClass, Stest_cn);
|
||||
GET_OBJECT_CLASS(threadClass, obj);
|
||||
|
||||
/* currDepth++ */
|
||||
GET_INT_FIELD(currDepth, obj, threadClass, "currentDepth");
|
||||
currDepth++;
|
||||
SET_INT_FIELD(obj, threadClass, "currentDepth", currDepth);
|
||||
|
||||
GET_STATIC_INT_FIELD(maxDepth, testClass, "DEPTH");
|
||||
GET_STATIC_INT_FIELD(sleepTime, testClass, "SLEEP_TIME");
|
||||
|
||||
if (maxDepth - currDepth > 0)
|
||||
{
|
||||
CALL_VOID_NOPARAM(obj, threadClass, "recursiveMethod");
|
||||
}
|
||||
|
||||
|
||||
if (maxDepth == currDepth)
|
||||
{
|
||||
GET_STATIC_OBJ_FIELD(doSnapshot, testClass, "doSnapshot",
|
||||
"Ljava/lang/Object;");
|
||||
|
||||
MONITOR_ENTER(doSnapshot);
|
||||
|
||||
GET_STATIC_INT_FIELD(achivedCount, testClass, "achivedCount");
|
||||
achivedCount++;
|
||||
SET_STATIC_INT_FIELD(testClass, "achivedCount", achivedCount);
|
||||
|
||||
CALL_VOID_NOPARAM(doSnapshot, testClass, "notify");
|
||||
MONITOR_EXIT(doSnapshot);
|
||||
}
|
||||
|
||||
GET_STATIC_BOOL_FIELD(isDone, testClass, "isSnapshotDone");
|
||||
|
||||
while (!isDone)
|
||||
{
|
||||
CALL_STATIC_VOID(threadClass, "sleep", "(J)V", (jlong)sleepTime);
|
||||
GET_STATIC_BOOL_FIELD(isDone, testClass, "isSnapshotDone");
|
||||
}
|
||||
|
||||
currDepth--;
|
||||
SET_INT_FIELD(obj, threadClass, "currentDepth", currDepth);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
270
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace008.java
Normal file
270
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace008.java
Normal file
@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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/strace/strace008.
|
||||
* VM testbase keywords: [stress, quick, strace]
|
||||
* VM testbase readme:
|
||||
* DESCRIPTION
|
||||
* The test runs many threads, that recursively invoke a native method.
|
||||
* After arriving at defined depth of recursion, the test calls
|
||||
* java.lang.Thread.getStackTrace() and java.lang.Thread.getAllStackTraces()
|
||||
* methods and checks their results. All threads are running in a loop
|
||||
* as long as these methods are executed.
|
||||
* The test fails if:
|
||||
* - amount of stack trace elements and stack trace elements themselves are
|
||||
* the same for both methods;
|
||||
* - there is at least one element corresponding to invocation of unexpected
|
||||
* method. Expected methods are Thread.sleep(), Thread.run() and the
|
||||
* recursive method.
|
||||
* This test is almost the same as nsk.stress.strace.strace007 except for
|
||||
* the recursive method is a native one.
|
||||
*
|
||||
* @library /vmTestbase
|
||||
* /test/lib
|
||||
* @run driver jdk.test.lib.FileInstaller . .
|
||||
* @run main/othervm/native nsk.stress.strace.strace008
|
||||
*/
|
||||
|
||||
package nsk.stress.strace;
|
||||
|
||||
import nsk.share.ArgumentParser;
|
||||
import nsk.share.Log;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The test runs <code>THRD_COUNT</code> instances of <code>strace008Thread</code>,
|
||||
* that recursively invoke a native method. After arriving at defined depth
|
||||
* <code>DEPTH</code> of recursion, the test calls
|
||||
* <code>java.lang.Thread.getStackTrace()</code> and
|
||||
* <code>java.lang.Thread.getAllStackTraces()</code> methods and checks their results.
|
||||
* <p>
|
||||
* It is expected that these methods return the same stack traces. Each stack frame
|
||||
* for both stack traces must be corresponded to invocation of one of the methods
|
||||
* defined by the <code>EXPECTED_METHODS</code> array.</p>
|
||||
*/
|
||||
public class strace008 {
|
||||
|
||||
static final int DEPTH = 100;
|
||||
static final int THRD_COUNT = 50;
|
||||
static final int SLEEP_TIME = 50;
|
||||
static final String NATIVE_LIB = "strace008";
|
||||
static final String[] EXPECTED_METHODS = {
|
||||
"java.lang.Thread.sleep",
|
||||
"nsk.stress.strace.strace008Thread.run",
|
||||
"nsk.stress.strace.strace008Thread.recursiveMethod"
|
||||
};
|
||||
|
||||
|
||||
static long waitTime = 2;
|
||||
|
||||
static Object doSnapshot = new Object();
|
||||
static volatile boolean isSnapshotDone = false;
|
||||
static volatile int achivedCount = 0;
|
||||
static PrintStream out;
|
||||
static Log log;
|
||||
|
||||
static strace008Thread[] threads;
|
||||
|
||||
public static void main(String[] args) {
|
||||
out = System.out;
|
||||
int exitCode = run(args);
|
||||
System.exit(exitCode + 95);
|
||||
}
|
||||
|
||||
public static int run(String[] args) {
|
||||
ArgumentParser argHandler = new ArgumentParser(args);
|
||||
log = new Log(out, argHandler);
|
||||
waitTime = argHandler.getWaitTime() * 60000;
|
||||
|
||||
boolean res = true;
|
||||
|
||||
startThreads();
|
||||
|
||||
res = makeSnapshot();
|
||||
|
||||
finishThreads();
|
||||
|
||||
if (!res) {
|
||||
complain("***>>>Test failed<<<***");
|
||||
return 2;
|
||||
}
|
||||
|
||||
display(">>>Test passed<<<");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void startThreads() {
|
||||
threads = new strace008Thread[THRD_COUNT];
|
||||
achivedCount = 0;
|
||||
|
||||
String tmp_name;
|
||||
display("starting threads...");
|
||||
for (int i = 0; i < THRD_COUNT; i++) {
|
||||
tmp_name = "strace008Thread" + Integer.toString(i);
|
||||
threads[i] = new strace008Thread(tmp_name);
|
||||
threads[i].start();
|
||||
}
|
||||
|
||||
display("waiting for the defined recursion depth ...");
|
||||
while (achivedCount < THRD_COUNT) {
|
||||
synchronized (doSnapshot) {
|
||||
try {
|
||||
doSnapshot.wait(1);
|
||||
} catch (InterruptedException e) {
|
||||
complain("" + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static boolean makeSnapshot() {
|
||||
|
||||
display("making all threads snapshots...");
|
||||
Map traces = Thread.getAllStackTraces();
|
||||
int count = ((StackTraceElement[]) traces.get(threads[0])).length;
|
||||
|
||||
display("making snapshots of each thread...");
|
||||
StackTraceElement[][] elements = new StackTraceElement[THRD_COUNT][];
|
||||
for (int i = 0; i < THRD_COUNT; i++) {
|
||||
elements[i] = threads[i].getStackTrace();
|
||||
}
|
||||
|
||||
display("checking lengths of stack traces...");
|
||||
StackTraceElement[] all;
|
||||
for (int i = 1; i < THRD_COUNT; i++) {
|
||||
all = (StackTraceElement[]) traces.get(threads[i]);
|
||||
int k = all.length;
|
||||
if (count - k > 2) {
|
||||
complain("wrong lengths of stack traces:\n\t"
|
||||
+ threads[0].getName() + ": " + count
|
||||
+ "\t"
|
||||
+ threads[i].getName() + ": " + k);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
display("checking stack traces...");
|
||||
boolean res = true;
|
||||
for (int i = 0; i < THRD_COUNT; i++) {
|
||||
all = (StackTraceElement[]) traces.get(threads[i]);
|
||||
if (!checkTraces(threads[i].getName(), elements[i], all)) {
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static boolean checkTraces(String threadName, StackTraceElement[] threadSnap,
|
||||
StackTraceElement[] allSnap) {
|
||||
|
||||
int checkedLength = threadSnap.length < allSnap.length ?
|
||||
threadSnap.length : allSnap.length;
|
||||
boolean res = true;
|
||||
|
||||
for (int j = checkedLength; j < 0; j--) {
|
||||
if (!checkElement(threadSnap[j])) {
|
||||
complain("Unexpected " + j + "-element:");
|
||||
complain("\tmethod name: " + threadSnap[j].getMethodName());
|
||||
complain("\tclass name: " + threadSnap[j].getClassName());
|
||||
if (threadSnap[j].isNativeMethod()) {
|
||||
complain("\tline number: (native method)");
|
||||
} else {
|
||||
complain("\tline number: " + threadSnap[j].getLineNumber());
|
||||
complain("\tfile name: " + threadSnap[j].getFileName());
|
||||
}
|
||||
complain("");
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static boolean checkElement(StackTraceElement element) {
|
||||
String name = element.getClassName() + "." + element.getMethodName();
|
||||
for (int i = 0; i < EXPECTED_METHODS.length; i++) {
|
||||
if (EXPECTED_METHODS[i].compareTo(name) == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void finishThreads() {
|
||||
isSnapshotDone = true;
|
||||
/* try {
|
||||
for (int i=0; i<threads.length; i++) {
|
||||
if (threads[i].isAlive()) {
|
||||
display("waiting for finish " + threads[i].getName());
|
||||
threads[i].join(waitTime);
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
display(e);
|
||||
}
|
||||
*/
|
||||
isSnapshotDone = false;
|
||||
}
|
||||
|
||||
static void display(String message) {
|
||||
log.display(message);
|
||||
}
|
||||
|
||||
static void complain(String message) {
|
||||
log.complain(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class strace008Thread extends Thread {
|
||||
|
||||
private int currentDepth = 0;
|
||||
|
||||
static {
|
||||
try {
|
||||
System.loadLibrary(strace008.NATIVE_LIB);
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
System.err.println("Could not load strace008 library");
|
||||
System.err.println("java.library.path:"
|
||||
+ System.getProperty("java.library.path"));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
strace008Thread(String name) {
|
||||
setName(name);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
|
||||
recursiveMethod();
|
||||
|
||||
}
|
||||
|
||||
native void recursiveMethod();
|
||||
}
|
||||
64
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace009.c
Normal file
64
test/hotspot/jtreg/vmTestbase/nsk/stress/strace/strace009.c
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "nsk_strace.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static const char *Stest_cn="nsk/stress/strace/strace009";
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_nsk_stress_strace_strace009Thread_recursiveMethod2(JNIEnv *env, jobject obj)
|
||||
{
|
||||
jclass testClass, threadClass;
|
||||
|
||||
jint currDepth, maxDepth;
|
||||
jmethodID method;
|
||||
jfieldID field;
|
||||
|
||||
FIND_CLASS(testClass, Stest_cn);
|
||||
GET_OBJECT_CLASS(threadClass, obj);
|
||||
|
||||
/* currDepth++ */
|
||||
GET_INT_FIELD(currDepth, obj, threadClass, "currentDepth");
|
||||
currDepth++;
|
||||
SET_INT_FIELD(obj, threadClass, "currentDepth", currDepth);
|
||||
|
||||
GET_STATIC_INT_FIELD(maxDepth, testClass, "DEPTH");
|
||||
|
||||
if (maxDepth - currDepth > 0)
|
||||
{
|
||||
CALL_VOID_NOPARAM(obj, threadClass, "recursiveMethod1");
|
||||
}
|
||||
|
||||
currDepth--;
|
||||
GET_OBJECT_CLASS(threadClass, obj);
|
||||
SET_INT_FIELD(obj, threadClass, "currentDepth", currDepth);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user