8199643: [TESTBUG] Open source common VM testbase code
Reviewed-by: vlivanov, erikj, mseledtsov, gthornbr
This commit is contained in:
parent
1298458a1d
commit
08855df46a
@ -48,6 +48,21 @@ BUILD_HOTSPOT_JTREG_OUTPUT_DIR := $(OUTPUTDIR)/support/test/hotspot/jtreg/native
|
|||||||
|
|
||||||
BUILD_HOTSPOT_JTREG_IMAGE_DIR := $(TEST_IMAGE_DIR)/hotspot/jtreg
|
BUILD_HOTSPOT_JTREG_IMAGE_DIR := $(TEST_IMAGE_DIR)/hotspot/jtreg
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Former VM TestBase tests.
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
VM_TESTBASE_DIR := $(TOPDIR)/test/hotspot/jtreg/vmTestbase
|
||||||
|
|
||||||
|
VM_SHARE_INCLUDES := \
|
||||||
|
-I$(VM_TESTBASE_DIR)/vm/share \
|
||||||
|
-I$(VM_TESTBASE_DIR)/nsk/share/native \
|
||||||
|
-I$(VM_TESTBASE_DIR)/nsk/share/jni
|
||||||
|
|
||||||
|
BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libProcessUtils := $(VM_SHARE_INCLUDES)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
# Platform specific setup
|
# Platform specific setup
|
||||||
ifneq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc)
|
ifneq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc)
|
||||||
BUILD_HOTSPOT_JTREG_EXCLUDE += liboverflow.c exeThreadSignalMask.c
|
BUILD_HOTSPOT_JTREG_EXCLUDE += liboverflow.c exeThreadSignalMask.c
|
||||||
|
170
test/hotspot/jtreg/vmTestbase/ExecDriver.java
Normal file
170
test/hotspot/jtreg/vmTestbase/ExecDriver.java
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import jdk.test.lib.Platform;
|
||||||
|
import jdk.test.lib.Utils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a new process to execute a command.
|
||||||
|
* <p>Usage: --java|--cmd|--launcher <arg>+
|
||||||
|
* <p>If {@code --cmd} flag is specified, the arguments are treated as
|
||||||
|
* a program to run and its arguments. Non-zero exit code of the created process
|
||||||
|
* will be reported as an {@link AssertionError}.
|
||||||
|
* <p>If {@code --java} flag is specified, the arguments are passed to {@code java}
|
||||||
|
* from JDK under test. If exit code doesn't equal to 0 or 95, {@link AssertionError}
|
||||||
|
* will be thrown.
|
||||||
|
* <p>If {@code --launcher} flag is specified, the arguments treated similar as
|
||||||
|
* for {@code --cmd}, but the started process will have the directory which
|
||||||
|
* contains {@code jvm.so} in dynamic library path, and {@code test.class.path}
|
||||||
|
* as CLASSPATH environment variable. Exit codes are checked as in
|
||||||
|
* {@code --java}, i.e. 0 or 95 means pass.
|
||||||
|
*/
|
||||||
|
public class ExecDriver {
|
||||||
|
public static void main(String[] args) throws IOException, InterruptedException {
|
||||||
|
boolean java = false;
|
||||||
|
boolean launcher = false;
|
||||||
|
|
||||||
|
String type = args[0];
|
||||||
|
switch (type) {
|
||||||
|
case "--java":
|
||||||
|
String[] oldArgs = args;
|
||||||
|
int count;
|
||||||
|
String libraryPath = System.getProperty("test.nativepath");
|
||||||
|
if (libraryPath != null && !libraryPath.isEmpty()) {
|
||||||
|
count = 4;
|
||||||
|
args = new String[args.length + 3];
|
||||||
|
args[3] = "-Djava.library.path=" + libraryPath;
|
||||||
|
} else {
|
||||||
|
count = 3;
|
||||||
|
args = new String[args.length + 2];
|
||||||
|
}
|
||||||
|
args[0] = javaBin();
|
||||||
|
args[1] = "-cp";
|
||||||
|
args[2] = Utils.TEST_CLASS_PATH;
|
||||||
|
System.arraycopy(oldArgs, 1, args, count, oldArgs.length - 1);
|
||||||
|
java = true;
|
||||||
|
break;
|
||||||
|
case "--launcher":
|
||||||
|
java = true;
|
||||||
|
launcher = true;
|
||||||
|
case "--cmd":
|
||||||
|
args = Arrays.copyOfRange(args, 1, args.length);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error("unknown type: " + type);
|
||||||
|
}
|
||||||
|
// adding 'test.vm.opts' and 'test.java.opts'
|
||||||
|
if (java) {
|
||||||
|
String[] oldArgs = args;
|
||||||
|
String[] testJavaOpts = Utils.getTestJavaOpts();
|
||||||
|
if (testJavaOpts.length > 0) {
|
||||||
|
args = new String[args.length + testJavaOpts.length];
|
||||||
|
// bin/java goes before options
|
||||||
|
args[0] = oldArgs[0];
|
||||||
|
// then external java options
|
||||||
|
System.arraycopy(testJavaOpts, 0, args, 1, testJavaOpts.length);
|
||||||
|
// and then options and args from a test
|
||||||
|
System.arraycopy(oldArgs, 1, args, 1 + testJavaOpts.length, oldArgs.length - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String command = Arrays.toString(args);
|
||||||
|
System.out.println("exec " + command);
|
||||||
|
|
||||||
|
ProcessBuilder pb = new ProcessBuilder(args);
|
||||||
|
// adding jvm.so to library path
|
||||||
|
if (launcher) {
|
||||||
|
Path dir = Paths.get(Utils.TEST_JDK);
|
||||||
|
String name;
|
||||||
|
if (Platform.isWindows()) {
|
||||||
|
dir = dir.resolve("bin")
|
||||||
|
.resolve(variant())
|
||||||
|
.toAbsolutePath();
|
||||||
|
name = "PATH";
|
||||||
|
} else {
|
||||||
|
dir = dir.resolve("lib")
|
||||||
|
.resolve(variant())
|
||||||
|
.toAbsolutePath();
|
||||||
|
name = Platform.isOSX() ? "DYLD_LIBRARY_PATH" : "LD_LIBRARY_PATH";
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(" with " + name + " = " +
|
||||||
|
pb.environment()
|
||||||
|
.merge(name, dir.toString(), (x, y) -> y + File.pathSeparator + x));
|
||||||
|
System.out.println(" with CLASSPATH = " +
|
||||||
|
pb.environment()
|
||||||
|
.put("CLASSPATH", Utils.TEST_CLASS_PATH));
|
||||||
|
}
|
||||||
|
Process p = pb.start();
|
||||||
|
// inheritIO does not work as expected for @run driver
|
||||||
|
new Thread(() -> copy(p.getInputStream(), System.out)).start();
|
||||||
|
new Thread(() -> copy(p.getErrorStream(), System.out)).start();
|
||||||
|
int exitCode = p.waitFor();
|
||||||
|
|
||||||
|
if (exitCode != 0 && (!java || exitCode != 95)) {
|
||||||
|
throw new AssertionError(command + " exit code is " + exitCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String variant() {
|
||||||
|
if (Platform.isServer()) {
|
||||||
|
return "server";
|
||||||
|
} else if (Platform.isClient()) {
|
||||||
|
return "client";
|
||||||
|
} else if (Platform.isMinimal()) {
|
||||||
|
return "minimal";
|
||||||
|
} else {
|
||||||
|
throw new Error("TESTBUG: unsuppported vm variant");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void copy(InputStream is, OutputStream os) {
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
int n;
|
||||||
|
try (InputStream close = is) {
|
||||||
|
while ((n = is.read(buffer)) != -1) {
|
||||||
|
os.write(buffer, 0, n);
|
||||||
|
}
|
||||||
|
os.flush();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String javaBin() {
|
||||||
|
return Paths.get(Utils.TEST_JDK)
|
||||||
|
.resolve("bin")
|
||||||
|
.resolve("java")
|
||||||
|
.toAbsolutePath()
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
138
test/hotspot/jtreg/vmTestbase/PropertyResolvingWrapper.java
Normal file
138
test/hotspot/jtreg/vmTestbase/PropertyResolvingWrapper.java
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces all {@code ${<X>}} with value of corresponding property({@code X}),
|
||||||
|
* resulting string is handled similarly to {@code @run main} in jtreg.
|
||||||
|
* In other words, {@code main} of first token will be executed with the rest
|
||||||
|
* tokens as arguments.
|
||||||
|
*
|
||||||
|
* If one of properties can't be resolved, {@link Error} will be thrown.
|
||||||
|
*/
|
||||||
|
public class PropertyResolvingWrapper {
|
||||||
|
private static final Properties properties;
|
||||||
|
static {
|
||||||
|
Properties p = System.getProperties();
|
||||||
|
String name = p.getProperty("os.name");
|
||||||
|
String arch = p.getProperty("os.arch");
|
||||||
|
String family;
|
||||||
|
String simple_arch;
|
||||||
|
|
||||||
|
// copy from jtreg/src/share/classes/com/sun/javatest/regtest/config/OS.java
|
||||||
|
if (name.startsWith("AIX"))
|
||||||
|
family = "aix";
|
||||||
|
else if (name.startsWith("Linux"))
|
||||||
|
family = "linux";
|
||||||
|
else if (name.startsWith("Mac") || name.startsWith("Darwin"))
|
||||||
|
family = "mac";
|
||||||
|
else if (name.startsWith("OS400") || name.startsWith("OS/400") )
|
||||||
|
family = "os400";
|
||||||
|
else if (name.startsWith("SunOS") || name.startsWith("Solaris"))
|
||||||
|
family = "solaris";
|
||||||
|
else if (name.startsWith("Windows"))
|
||||||
|
family = "windows";
|
||||||
|
else
|
||||||
|
family = name.replaceFirst("^([^ ]+).*", "$1"); // use first word of name
|
||||||
|
|
||||||
|
if (arch.contains("64")
|
||||||
|
&& !arch.equals("ia64")
|
||||||
|
&& !arch.equals("ppc64")
|
||||||
|
&& !arch.equals("ppc64le")
|
||||||
|
&& !arch.equals("zArch_64")
|
||||||
|
&& !arch.equals("aarch64"))
|
||||||
|
simple_arch = "x64";
|
||||||
|
else if (arch.contains("86"))
|
||||||
|
simple_arch = "i586";
|
||||||
|
else if (arch.equals("ppc") || arch.equals("powerpc"))
|
||||||
|
simple_arch = "ppc";
|
||||||
|
else if (arch.equals("s390x") || arch.equals("zArch_64"))
|
||||||
|
simple_arch = "s390x";
|
||||||
|
else
|
||||||
|
simple_arch = arch;
|
||||||
|
|
||||||
|
p.setProperty("os.family", family);
|
||||||
|
p.setProperty("os.simpleArch", simple_arch);
|
||||||
|
properties = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Throwable {
|
||||||
|
List<String> command = new ArrayList<>(args.length);
|
||||||
|
for (int i = 0; i < args.length; ++i) {
|
||||||
|
StringBuilder arg = new StringBuilder(args[i]);
|
||||||
|
while (i < args.length - 1
|
||||||
|
&& (arg.chars()
|
||||||
|
.filter(c -> c == '"')
|
||||||
|
.count() % 2) != 0) {
|
||||||
|
arg.append(" ")
|
||||||
|
.append(args[++i]);
|
||||||
|
}
|
||||||
|
command.add(eval(arg.toString()));
|
||||||
|
}
|
||||||
|
System.out.println("run " + command);
|
||||||
|
try {
|
||||||
|
Class.forName(command.remove(0))
|
||||||
|
.getMethod("main", String[].class)
|
||||||
|
.invoke(null, new Object[]{command.toArray(new String[0])});
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
Throwable t = e.getCause();
|
||||||
|
t = t != null ? t : e;
|
||||||
|
throw t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String eval(String string) {
|
||||||
|
int index;
|
||||||
|
int current = 0;
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
while (current < string.length() && (index = string.indexOf("${", current)) >= 0) {
|
||||||
|
result.append(string.substring(current, index));
|
||||||
|
int endName = string.indexOf('}', index);
|
||||||
|
current = endName + 1;
|
||||||
|
String name = string.substring(index + 2, endName);
|
||||||
|
String value = properties.getProperty(name);
|
||||||
|
if (value == null) {
|
||||||
|
throw new Error("can't find property " + name);
|
||||||
|
}
|
||||||
|
result.append(value);
|
||||||
|
}
|
||||||
|
if (current < string.length()) {
|
||||||
|
result.append(string.substring(current));
|
||||||
|
}
|
||||||
|
int length = result.length();
|
||||||
|
|
||||||
|
if (length > 1 && result.charAt(0) == '"' && result.charAt(length - 1) == '"') {
|
||||||
|
result.deleteCharAt(length - 1);
|
||||||
|
result.deleteCharAt(0);
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
}
|
10
test/hotspot/jtreg/vmTestbase/README.md
Normal file
10
test/hotspot/jtreg/vmTestbase/README.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# VM Testbase landing
|
||||||
|
|
||||||
|
This directory serves as a _temporary_ landing place for tests converted from so-called VM testbase.
|
||||||
|
Most of these tests have been written a long time ago, don't meet modern coding
|
||||||
|
standards, guidelines and are in need of reworking.
|
||||||
|
Eventually, all the tests located here should be reworked and moved accordingly to
|
||||||
|
regular JTReg test suite directory layout convention, i.e. following the same
|
||||||
|
layout as product code as close as possible.
|
||||||
|
|
||||||
|
New tests must **not** be added into this directory.
|
164
test/hotspot/jtreg/vmTestbase/nsk/share/AbstractGoldChecker.java
Normal file
164
test/hotspot/jtreg/vmTestbase/nsk/share/AbstractGoldChecker.java
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2008, 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.share;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
|
public abstract class AbstractGoldChecker {
|
||||||
|
|
||||||
|
private final StringBuffer sb = new StringBuffer();
|
||||||
|
|
||||||
|
protected abstract String getGoldenString();
|
||||||
|
|
||||||
|
public void print(boolean b) {
|
||||||
|
sb.append(String.valueOf(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(byte b) {
|
||||||
|
sb.append(String.valueOf(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(char c) {
|
||||||
|
sb.append(String.valueOf(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(int i) {
|
||||||
|
sb.append(String.valueOf(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(long l) {
|
||||||
|
sb.append(String.valueOf(l));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(float f) {
|
||||||
|
sb.append(String.valueOf(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(double d) {
|
||||||
|
sb.append(String.valueOf(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(String s) {
|
||||||
|
sb.append(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println() {
|
||||||
|
sb.append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println(boolean b) {
|
||||||
|
sb.append(String.valueOf(b));
|
||||||
|
sb.append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println(byte b) {
|
||||||
|
sb.append(String.valueOf(b));
|
||||||
|
sb.append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println(char c) {
|
||||||
|
sb.append(String.valueOf(c));
|
||||||
|
sb.append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println(int i) {
|
||||||
|
sb.append(String.valueOf(i));
|
||||||
|
sb.append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println(long l) {
|
||||||
|
sb.append(String.valueOf(l));
|
||||||
|
sb.append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println(float f) {
|
||||||
|
sb.append(String.valueOf(f));
|
||||||
|
sb.append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println(double d) {
|
||||||
|
sb.append(String.valueOf(d));
|
||||||
|
sb.append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
public void println(String s) {
|
||||||
|
sb.append(s);
|
||||||
|
sb.append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
public void check() {
|
||||||
|
String testOutput;
|
||||||
|
try {
|
||||||
|
testOutput = new String(sb.toString().getBytes("US-ASCII"), "US-ASCII");
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new TestFailure(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
String goldOutput = getGoldenString();
|
||||||
|
if (!compare(testOutput, goldOutput)) {
|
||||||
|
throw new TestFailure(
|
||||||
|
"Gold comparison failed\n" +
|
||||||
|
"\n" +
|
||||||
|
"Test output:\n" +
|
||||||
|
"============\n" +
|
||||||
|
"\n" +
|
||||||
|
testOutput +
|
||||||
|
"\n" +
|
||||||
|
"------------\n" +
|
||||||
|
"\n" +
|
||||||
|
"Gold output:\n" +
|
||||||
|
"============\n" +
|
||||||
|
"\n" +
|
||||||
|
goldOutput +
|
||||||
|
"\n" +
|
||||||
|
"------------\n" +
|
||||||
|
"\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean compare(String src, String dst) {
|
||||||
|
int i1 = 0;
|
||||||
|
int i2 = 0;
|
||||||
|
|
||||||
|
int src_len = src.length();
|
||||||
|
int dst_len = dst.length();
|
||||||
|
|
||||||
|
while ((i1 < src_len) && (i2 < dst_len)) {
|
||||||
|
|
||||||
|
char c1 = src.charAt(i1++);
|
||||||
|
if ((c1 == '\r') && (i1 < src_len)) {
|
||||||
|
c1 = src.charAt(i1++);
|
||||||
|
}
|
||||||
|
|
||||||
|
char c2 = dst.charAt(i2++);
|
||||||
|
if ((c2 == '\r') && (i2 < dst_len)) {
|
||||||
|
c2 = dst.charAt(i2++);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c1 != c2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (i1 == src_len) && (i2 == dst_len);
|
||||||
|
}
|
||||||
|
}
|
507
test/hotspot/jtreg/vmTestbase/nsk/share/ArgumentParser.java
Normal file
507
test/hotspot/jtreg/vmTestbase/nsk/share/ArgumentParser.java
Normal file
@ -0,0 +1,507 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2001, 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.share;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import nsk.share.test.StressOptions;
|
||||||
|
import nsk.share.test.Stresser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser for JDI test's command-line arguments.
|
||||||
|
* <p>
|
||||||
|
* Test's command line may contain two kind of arguments, namely:
|
||||||
|
* <ul>
|
||||||
|
* <li> options for ArgumentParser
|
||||||
|
* <li> other arguments for the test itself
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* We call <i>raw arguments</i> the <code>args[]</code> array
|
||||||
|
* passed to the test's method <code>main(String args[])</code>.
|
||||||
|
* ArgumentParser instance initialized with raw arguments serves to parse
|
||||||
|
* these two kinds of arguments. Use <code>ArgumentParser(args[])</code>
|
||||||
|
* constructor, or <code>setRawArguments(args[])</code> method
|
||||||
|
* to initialize a ArgumentParser instance with particular raw arguments.
|
||||||
|
* <p>
|
||||||
|
* Arguments, started with ``<code>-</code>'' symbol are called <i>options</i>.
|
||||||
|
* They are recognized by ArgumentParser and are used by support classes
|
||||||
|
* (such as Log, Binder, etc.).
|
||||||
|
* These options should be specified in the following general form:
|
||||||
|
* <ul>
|
||||||
|
* <li> <code>-option=<i>value</i></code>
|
||||||
|
* </ul>
|
||||||
|
* or
|
||||||
|
* <ul>
|
||||||
|
* <li> <code>-option <i>value</i></code>
|
||||||
|
* </ul>
|
||||||
|
* List of the recognized options with their values may be obtained by
|
||||||
|
* invoking method <code>getOptions()</code> that returnes
|
||||||
|
* a <code>Properties</code> object with options values.
|
||||||
|
* It is not recommended to get options value directly. An appropriate methods
|
||||||
|
* such as <code>verbose()</code>, <code>getArch()</code>, etc. should be used
|
||||||
|
* instead.
|
||||||
|
* Options may appear in the test command line in any order.
|
||||||
|
* <p>
|
||||||
|
* All the other arguments of command line are called <i>test arguments</i>
|
||||||
|
* (or simply <i>arguments</i>). These arguments should be handled by test itself.
|
||||||
|
* Full list of the test arguments in the same order as they appears in the command line
|
||||||
|
* may be obtained by invoking method <code>getArguments()</code>.
|
||||||
|
* <p>
|
||||||
|
* Following is the list of basic options accepted by AgrumentParser:
|
||||||
|
* <ul>
|
||||||
|
* <li> <code>-arch=</code><<i>${ARCH}</i>> -
|
||||||
|
* architecture name
|
||||||
|
* <li> <code>-waittime=</code><<i>minutes</i>> -
|
||||||
|
* timeout in minutes for waiting events or so
|
||||||
|
* <li> <code>-verbose</code> -
|
||||||
|
* verbose Log mode (default is quiet)
|
||||||
|
* <li> <code>-trace.time</code> -
|
||||||
|
* prefix log messages with timestamps (default is no)
|
||||||
|
* </ul>
|
||||||
|
* Also AgrumentParser supports following stress options (see nsk.share.test.StressOptions for details):
|
||||||
|
* <ul>
|
||||||
|
* <li> <code>-stressTime</code>
|
||||||
|
* <li> <code>-stressIterationsFactor</code>
|
||||||
|
* <li> <code>-stressThreadsFactor</code>
|
||||||
|
* <li> <code>-stressDebug</code>
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* Note, that the tests from the particular subsuites have its own argument handlers
|
||||||
|
* wich accepts additional options. See <code>jpda.DebugeeArgumentHandler</code>,
|
||||||
|
* <code>jdi.ArgumentHandler</code>, <code>jdwp.ArgumentHandler</code>.
|
||||||
|
*
|
||||||
|
* @see #setRawArguments(String[])
|
||||||
|
* @see #getRawArguments()
|
||||||
|
* @see #getArguments()
|
||||||
|
* @see #getOptions()
|
||||||
|
*
|
||||||
|
* @see nsk.share.jpda.DebugeeArgumentHandler
|
||||||
|
* @see nsk.share.jdwp.ArgumentHandler
|
||||||
|
* @see nsk.share.jdi.ArgumentHandler
|
||||||
|
* @see nsk.share.jvmti.ArgumentHandler
|
||||||
|
* @see nsk.share.monitoring.ArgumentHandler
|
||||||
|
*/
|
||||||
|
public class ArgumentParser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raw array of command-line arguments.
|
||||||
|
*
|
||||||
|
* @see #setRawArguments(String[])
|
||||||
|
* @see #getRawArguments()
|
||||||
|
*/
|
||||||
|
protected String rawArguments[] = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refined arguments -- raw arguments but options.
|
||||||
|
*
|
||||||
|
* @see #options
|
||||||
|
* @see #getArguments()
|
||||||
|
*/
|
||||||
|
protected String arguments[] = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recognized options for ArgumentParser class.
|
||||||
|
*
|
||||||
|
* @see #arguments
|
||||||
|
* @see #getOptions()
|
||||||
|
*/
|
||||||
|
protected Properties options = new Properties();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make new ArgumentParser object with default values of otions.
|
||||||
|
* This constructor is used only to obtain default values of options.
|
||||||
|
*
|
||||||
|
* @see #setRawArguments(String[])
|
||||||
|
*/
|
||||||
|
protected ArgumentParser() {
|
||||||
|
String[] args = new String[0];
|
||||||
|
setRawArguments(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep a copy of raw command-line arguments and parse them;
|
||||||
|
* but throw an exception on parsing error.
|
||||||
|
*
|
||||||
|
* @param args Array of the raw command-line arguments.
|
||||||
|
*
|
||||||
|
* @throws BadOption If option values are invalid.
|
||||||
|
*
|
||||||
|
* @see #setRawArguments(String[])
|
||||||
|
* @see BadOption
|
||||||
|
*/
|
||||||
|
public ArgumentParser(String args[]) {
|
||||||
|
setRawArguments(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a copy of the raw command-line arguments kept by
|
||||||
|
* this ArgumentParser instance.
|
||||||
|
*
|
||||||
|
* @throws NullPointerException If raw arguments were not
|
||||||
|
* set for this instance.
|
||||||
|
*
|
||||||
|
* @see #setRawArguments(String[])
|
||||||
|
*/
|
||||||
|
public String[] getRawArguments() {
|
||||||
|
return (String[]) rawArguments.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return given raw command-line argument.
|
||||||
|
*
|
||||||
|
* @param index index of argument
|
||||||
|
* @return value of raw argument
|
||||||
|
*/
|
||||||
|
public String getRawArgument(int index) {
|
||||||
|
return rawArguments[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return refined array of test arguments (only those of the raw
|
||||||
|
* arguments which are not recognized as options for ArgumentParser).
|
||||||
|
*
|
||||||
|
* <p>Note, that sintax of test arguments was not checked;
|
||||||
|
* while syntax of arguments describing ArgumentParser's options
|
||||||
|
* was checked while raw arguments were set to this ArgumentParser
|
||||||
|
* instance.
|
||||||
|
*
|
||||||
|
* @throws NullPointerException If raw arguments were not
|
||||||
|
* set for this instance.
|
||||||
|
*
|
||||||
|
* @see #setRawArguments(String[])
|
||||||
|
* @see #getOptions()
|
||||||
|
*/
|
||||||
|
public String[] getArguments() {
|
||||||
|
return (String[]) arguments.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return list of recognized otions with their values in the form of
|
||||||
|
* <code>Properties</code> object.
|
||||||
|
* If no options has been recognized, this list will be empty.
|
||||||
|
*
|
||||||
|
* @see #setRawArguments(String[])
|
||||||
|
* @see #getArguments()
|
||||||
|
*/
|
||||||
|
public Properties getOptions() {
|
||||||
|
return (Properties) options.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Join specified arguments into one line using given quoting
|
||||||
|
* and separator symbols.
|
||||||
|
*
|
||||||
|
* @param args Array of the command-line arguments
|
||||||
|
* @param quote Symbol used to quote each argument
|
||||||
|
* @param separator Symbol used as separator between argumnets
|
||||||
|
* @return Single line with arguments
|
||||||
|
*/
|
||||||
|
static public String joinArguments(String args[], String quote, String separator) {
|
||||||
|
if (args.length <= 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
String line = quote + args[0] + quote;
|
||||||
|
for (int i = 1; i < args.length; i++) {
|
||||||
|
line += separator + quote + args[i] + quote;
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Join specified arguments into one line using given quoting symbol
|
||||||
|
* and space as a separator symbol.
|
||||||
|
*
|
||||||
|
* @param args Array of the command-line arguments
|
||||||
|
* @param quote Symbol used to quote each argument
|
||||||
|
* @return Single line with arguments
|
||||||
|
*/
|
||||||
|
static public String joinArguments(String args[], String quote) {
|
||||||
|
return joinArguments(args, quote, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep a copy of command-line arguments and parse them;
|
||||||
|
* but throw an exception on parsing error.
|
||||||
|
*
|
||||||
|
* @param args Array of the raw command-line arguments.
|
||||||
|
*
|
||||||
|
* @throws BadOption If an option has invalid value.
|
||||||
|
*
|
||||||
|
* @see #getRawArguments()
|
||||||
|
* @see #getArguments()
|
||||||
|
*/
|
||||||
|
public void setRawArguments(String args[]) {
|
||||||
|
this.rawArguments = (String[]) args.clone();
|
||||||
|
parseArguments();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add or replace given option value in options list and in raw arguments list.
|
||||||
|
* Use specified <code>rawPrefix</code> while adding to raw arguments list.
|
||||||
|
*
|
||||||
|
* @see #getRawArguments()
|
||||||
|
* @see #getOptions()
|
||||||
|
*/
|
||||||
|
public void setOption(String rawPrefix, String name, String value) {
|
||||||
|
String prefix = rawPrefix + name + "=";
|
||||||
|
String arg = prefix + value;
|
||||||
|
|
||||||
|
options.setProperty(name, value);
|
||||||
|
|
||||||
|
int length = rawArguments.length;
|
||||||
|
boolean found = false;
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
if (rawArguments[i].startsWith(prefix)) {
|
||||||
|
found = true;
|
||||||
|
rawArguments[i] = arg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
String[] newRawArguments = new String[length + 1];
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
newRawArguments[i] = rawArguments[i];
|
||||||
|
}
|
||||||
|
newRawArguments[length] = arg;
|
||||||
|
rawArguments = newRawArguments;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return current architecture name from ArgumentParser's
|
||||||
|
* options.
|
||||||
|
*
|
||||||
|
* <p>Note that null string is returning if test argument
|
||||||
|
* <code>-arch</code> has not been set.
|
||||||
|
*
|
||||||
|
* @see #setRawArguments(String[])
|
||||||
|
*/
|
||||||
|
public String getArch() {
|
||||||
|
return options.getProperty("arch");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timeout (in minutes) for test's critical section like:
|
||||||
|
* (a) awaiting for an event, or conversly (b) making sure
|
||||||
|
* that there is no unexpected event.
|
||||||
|
*
|
||||||
|
* <p>By default, <i>2</i> minutes is returned if option
|
||||||
|
* <code>-waittime</code> is not set with command line.
|
||||||
|
*
|
||||||
|
* @see TimeoutHandler
|
||||||
|
*/
|
||||||
|
public int getWaitTime() {
|
||||||
|
String val = options.getProperty("waittime", "2");
|
||||||
|
int minutes;
|
||||||
|
try {
|
||||||
|
minutes = Integer.parseInt(val);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new TestBug("Not integer value of \"waittime\" argument: " + val);
|
||||||
|
}
|
||||||
|
return minutes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return boolean value of current Log mode:
|
||||||
|
* <ul>
|
||||||
|
* <li><i>true</i> if Log mode is verbose.
|
||||||
|
* <li><i>false</i> otherwise.
|
||||||
|
*
|
||||||
|
* <p>Note that default Log mode is quiet if test argument
|
||||||
|
* <code>-verbose</code> has not been set.
|
||||||
|
*
|
||||||
|
* @see #setRawArguments(String[])
|
||||||
|
*/
|
||||||
|
public boolean verbose() {
|
||||||
|
return options.getProperty("verbose") != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return boolean value of setting of timestamp for log messages:
|
||||||
|
* <ul>
|
||||||
|
* <li><i>true</i> if Log messages are timestamp'ed.
|
||||||
|
* <li><i>false</i> otherwise.
|
||||||
|
*
|
||||||
|
* <p>Note that by default Log messages won't be timestamp'ed until
|
||||||
|
* <code>-trace.time</code> has not been set.
|
||||||
|
*
|
||||||
|
* @see #setRawArguments(String[])
|
||||||
|
*/
|
||||||
|
public boolean isTimestamp() {
|
||||||
|
return options.getProperty("trace.time") != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return level of printing tracing mesages for debugging purpose.
|
||||||
|
* Level <i>0</i> means no tracing messages at all.
|
||||||
|
*
|
||||||
|
* <p>Note that by default no tracing messages will be printed out
|
||||||
|
* until <code>-trace.level</code> has not been set.
|
||||||
|
*
|
||||||
|
* @see #setRawArguments(String[])
|
||||||
|
*/
|
||||||
|
public int getTraceLevel() {
|
||||||
|
String value = options.getProperty("trace.level", Integer.toString(Log.TraceLevel.DEFAULT));
|
||||||
|
try {
|
||||||
|
int level = Integer.parseInt(value);
|
||||||
|
return level;
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new Failure("Not integer value of -trace.level option: " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse arguments from rawArgumnets, extact recognized options,
|
||||||
|
* check legality of options values options and store non-option
|
||||||
|
* arguments.
|
||||||
|
*
|
||||||
|
* @throws NullPointerException If raw arguments were not set
|
||||||
|
* for this ArgumentParser instance.
|
||||||
|
* @throws BadOption If Option name is not accepted or
|
||||||
|
* option has illegal value.
|
||||||
|
*
|
||||||
|
* @see #setRawArguments(String[])
|
||||||
|
* @see #checkOption(String, String)
|
||||||
|
* @see #checkOptions()
|
||||||
|
*/
|
||||||
|
protected void parseArguments() {
|
||||||
|
String selected[] = new String [rawArguments.length];
|
||||||
|
Properties properties = new Properties();
|
||||||
|
int count = 0;
|
||||||
|
for (int i=0; i<rawArguments.length; i++) {
|
||||||
|
String argument = rawArguments[i];
|
||||||
|
if (argument.startsWith("-")) {
|
||||||
|
int pos = argument.indexOf("=", 1);
|
||||||
|
String option, value;
|
||||||
|
if (pos < 0) {
|
||||||
|
option = argument.substring(1);
|
||||||
|
if (i + 1 < rawArguments.length && !rawArguments[i + 1].startsWith("-")) {
|
||||||
|
value = rawArguments[i + 1];
|
||||||
|
++i;
|
||||||
|
} else
|
||||||
|
value = "";
|
||||||
|
} else {
|
||||||
|
option = argument.substring(1, pos);
|
||||||
|
value = argument.substring(pos + 1);
|
||||||
|
}
|
||||||
|
if (!checkOption(option, value)) {
|
||||||
|
throw new BadOption("Unrecognized command line option: " + argument);
|
||||||
|
}
|
||||||
|
properties.setProperty(option, value);
|
||||||
|
} else {
|
||||||
|
selected[count++] = rawArguments[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Strip away the dummy tail of the selected[] array:
|
||||||
|
arguments = new String [count];
|
||||||
|
System.arraycopy(selected,0,arguments,0,count);
|
||||||
|
options = properties;
|
||||||
|
checkOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
public StressOptions getStressOptions() {
|
||||||
|
return new StressOptions(rawArguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the specified option is allowed and has legal value.
|
||||||
|
* <p>
|
||||||
|
* Derived classes for hadling test arguments in particular sub-suites
|
||||||
|
* override this method to allow to accept sub-suite specific options.
|
||||||
|
* However, they should invoke this method of the base class to enshure
|
||||||
|
* that the basic options will be accepted too.
|
||||||
|
*
|
||||||
|
* @return <i>true</i> if option is allowed and has legel value
|
||||||
|
* <i>false</I> if option is unknown
|
||||||
|
*
|
||||||
|
* @throws BadOption If value of the allowed option is illegal.
|
||||||
|
*
|
||||||
|
* @see #setRawArguments(String[])
|
||||||
|
* @see #parseArguments()
|
||||||
|
*/
|
||||||
|
protected boolean checkOption(String option, String value) {
|
||||||
|
|
||||||
|
// accept arguments of nsk.share.test.StressOptions
|
||||||
|
if (StressOptions.isValidStressOption(option))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// options with any string value
|
||||||
|
if (option.equals("arch")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// options with positive integer value
|
||||||
|
if (option.equals("waittime")
|
||||||
|
|| option.equals("trace.level")) {
|
||||||
|
try {
|
||||||
|
int number = Integer.parseInt(value);
|
||||||
|
if (number < 0) {
|
||||||
|
throw new BadOption(option + ": value must be a positive integer");
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new BadOption(option + ": value must be an integer");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// options without any value
|
||||||
|
if (option.equals("verbose")
|
||||||
|
|| option.equals("vbs")
|
||||||
|
|| option.equals("trace.time")) {
|
||||||
|
if (!(value == null || value.length() <= 0)) {
|
||||||
|
throw new BadOption(option + ": no value must be specified");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that the value of all options are not inconsistent.
|
||||||
|
* This method is invoked by <code>parseArguments()</code>
|
||||||
|
*
|
||||||
|
* @throws BadOption If value of the options are inconsistent
|
||||||
|
*
|
||||||
|
* @see #parseArguments()
|
||||||
|
*/
|
||||||
|
protected void checkOptions() {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown if invalid option or option value is found.
|
||||||
|
*/
|
||||||
|
public static class BadOption extends IllegalArgumentException {
|
||||||
|
/**
|
||||||
|
* Explain the reason.
|
||||||
|
*
|
||||||
|
* @param message Printing message.
|
||||||
|
*/
|
||||||
|
public BadOption(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
52
test/hotspot/jtreg/vmTestbase/nsk/share/ClassFileFinder.java
Normal file
52
test/hotspot/jtreg/vmTestbase/nsk/share/ClassFileFinder.java
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* 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.share;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class ClassFileFinder {
|
||||||
|
private ClassFileFinder() { }
|
||||||
|
/**
|
||||||
|
* Searches for a classfile for the specified class in the specified
|
||||||
|
* classpath.
|
||||||
|
*
|
||||||
|
* @param name a classname
|
||||||
|
* @param classPath @{link File.pathSeparator} separated directories
|
||||||
|
* @return an absolute path to the found classfile, or null if it cannot be
|
||||||
|
* found
|
||||||
|
*/
|
||||||
|
public static Path findClassFile(String name, String classPath) {
|
||||||
|
return Arrays.stream(classPath.split(File.pathSeparator))
|
||||||
|
.map(java.nio.file.Paths::get)
|
||||||
|
.map(p -> p.resolve(name.replace('.', File.separatorChar) + ".class"))
|
||||||
|
.filter(p -> java.nio.file.Files.exists(p))
|
||||||
|
.map(Path::toAbsolutePath)
|
||||||
|
.findAny()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
352
test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java
Normal file
352
test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java
Normal file
@ -0,0 +1,352 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2001, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Warning! Using this component need VM option -XX:-UseGCOverheadLimit
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import nsk.share.gc.gp.*;
|
||||||
|
import nsk.share.test.ExecutionController;
|
||||||
|
import nsk.share.test.Stresser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The <code>ClassUnloader</code> class allows to force VM to unload class(es)
|
||||||
|
* using memory stressing technique.
|
||||||
|
*
|
||||||
|
* <p>The method <code>unloadClass()</code> is provided which eats memory
|
||||||
|
* to enforce GC to cleanup the heap. So, if all references to a class
|
||||||
|
* and its loader are canceled, this may result in unloading the class.
|
||||||
|
*
|
||||||
|
* <p>ClassUnloader mainly intends to unload a class which was loaded
|
||||||
|
* with especial <code>ClassUnloader.loadClass()</code> method.
|
||||||
|
* A class is considered unloaded if its class loader is finalized.
|
||||||
|
* If there no finalization of class loader detected for some timeout,
|
||||||
|
* class is considered still loaded and method returns <i>false</i>.
|
||||||
|
*
|
||||||
|
* <p>Such finalization control applies only to a class loaded by
|
||||||
|
* ClassUnloader's <code>loadClass()</code> method. Otherwise, if there
|
||||||
|
* was no such class loaded, <code>unloadClass()</code> doesn't wait
|
||||||
|
* for a timeout and always returns <i>false</i>.
|
||||||
|
*
|
||||||
|
* <p>By default internal class loader of <code>CustomClassLoader</code> class
|
||||||
|
* is used for loading classes. This class loader can load class from .class file
|
||||||
|
* located in the specified directory.
|
||||||
|
* Application may define its own class loader, which may load classes using
|
||||||
|
* any other technique. Such class loader should be derived from base
|
||||||
|
* <code>CustomClassLoader</code> class, and set by <code>setClassLoader()</code>
|
||||||
|
* method.
|
||||||
|
*
|
||||||
|
* @see #setClassLoader(CustomClassLoader)
|
||||||
|
* @see #loadClass(String)
|
||||||
|
* @see #loadClass(String, String)
|
||||||
|
* @see #unloadClass()
|
||||||
|
*/
|
||||||
|
public class ClassUnloader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class name of default class loader.
|
||||||
|
*/
|
||||||
|
public static final String INTERNAL_CLASS_LOADER_NAME = "nsk.share.CustomClassLoader";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whole amount of time in milliseconds to wait for class loader finalization.
|
||||||
|
*/
|
||||||
|
private static final int WAIT_TIMEOUT = 15000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Piece of time in milliseconds to wait in a loop for class loader finalization.
|
||||||
|
*/
|
||||||
|
private static final int WAIT_DELTA = 1000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has class loader been finalized or not.
|
||||||
|
*/
|
||||||
|
volatile boolean finalized = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current class loader used for loading classes.
|
||||||
|
*/
|
||||||
|
private CustomClassLoader customClassLoader = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of classes loaded with current class loader.
|
||||||
|
*/
|
||||||
|
private Vector<Class<?>> classObjects = new Vector<Class<?>>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class object of the first class been loaded with current class loader.
|
||||||
|
* To get the rest loaded classes use <code>getLoadedClass(int)</code>.
|
||||||
|
* The call <code>getLoadedClass()</code> is effectively equivalent to the call
|
||||||
|
* <code>getLoadedClass(0)</code>
|
||||||
|
*
|
||||||
|
* @return class object of the first loaded class.
|
||||||
|
*
|
||||||
|
* @see #getLoadedClass(int)
|
||||||
|
*/
|
||||||
|
public Class<?> getLoadedClass() {
|
||||||
|
return classObjects.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns class objects at the specified index in the list of classes loaded
|
||||||
|
* with current class loader.
|
||||||
|
*
|
||||||
|
* @return class objects at the specified index.
|
||||||
|
*/
|
||||||
|
public Class<?> getLoadedClass(int index) {
|
||||||
|
return classObjects.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new instance of <code>CustomClassLoader</code> class as the current
|
||||||
|
* class loader and clears the list of loaded classes.
|
||||||
|
*
|
||||||
|
* @return created instance of <code>CustomClassLoader</code> class.
|
||||||
|
*
|
||||||
|
* @see #getClassLoader()
|
||||||
|
* @see #setClassLoader(CustomClassLoader)
|
||||||
|
*/
|
||||||
|
public CustomClassLoader createClassLoader() {
|
||||||
|
customClassLoader = new CustomClassLoader(this);
|
||||||
|
classObjects.removeAllElements();
|
||||||
|
|
||||||
|
return customClassLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets new current class loader and clears the list of loaded classes.
|
||||||
|
*
|
||||||
|
* @see #getClassLoader()
|
||||||
|
* @see #createClassLoader()
|
||||||
|
*/
|
||||||
|
public void setClassLoader(CustomClassLoader customClassLoader) {
|
||||||
|
this.customClassLoader = customClassLoader;
|
||||||
|
classObjects.removeAllElements();
|
||||||
|
customClassLoader.setClassUnloader(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns current class loader or <i>null</i> if not yet created or set.
|
||||||
|
*
|
||||||
|
* @return class loader object or null.
|
||||||
|
*
|
||||||
|
* @see #createClassLoader()
|
||||||
|
* @see #setClassLoader(CustomClassLoader)
|
||||||
|
*/
|
||||||
|
public CustomClassLoader getClassLoader() {
|
||||||
|
return customClassLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads class for specified class name using current class loader.
|
||||||
|
*
|
||||||
|
* <p>Current class loader should be set and capable to load class using only
|
||||||
|
* given class name. No other information such a location of .class files
|
||||||
|
* is passed to class loader.
|
||||||
|
*
|
||||||
|
* @param className name of class to load
|
||||||
|
*
|
||||||
|
* @throws ClassNotFoundException if no bytecode found for specified class name
|
||||||
|
* @throws Failure if current class loader is not specified;
|
||||||
|
* or if class was actually loaded with different class loader
|
||||||
|
*
|
||||||
|
* @see #loadClass(String, String)
|
||||||
|
*/
|
||||||
|
public void loadClass(String className) throws ClassNotFoundException {
|
||||||
|
|
||||||
|
if (customClassLoader == null) {
|
||||||
|
throw new Failure("No current class loader defined");
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<?> cls = Class.forName(className, true, customClassLoader);
|
||||||
|
|
||||||
|
// ensure that class was loaded by current class loader
|
||||||
|
if (cls.getClassLoader() != customClassLoader) {
|
||||||
|
throw new Failure("Class was loaded by unexpected class loader: " + cls.getClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
classObjects.add(cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads class from .class file located into specified directory using
|
||||||
|
* current class loader.
|
||||||
|
*
|
||||||
|
* <p>If there is no current class loader, then default class loader
|
||||||
|
* is created using <code>createClassLoader()</code>. Parameter <i>classDir</i>
|
||||||
|
* is passed to class loader using <code>CustomClassLoader.setClassPath()</code>
|
||||||
|
* method before loading class.
|
||||||
|
*
|
||||||
|
* @param className name of class to load
|
||||||
|
* @param classDir path to .class file location
|
||||||
|
*
|
||||||
|
* @throws ClassNotFoundException if no .class file found
|
||||||
|
* for specified class name
|
||||||
|
* @throws Failure if class was actually loaded with different class loader
|
||||||
|
*
|
||||||
|
* @see #loadClass(String)
|
||||||
|
* @see CustomClassLoader#setClassPath(String)
|
||||||
|
*/
|
||||||
|
public void loadClass(String className, String classDir) throws ClassNotFoundException {
|
||||||
|
|
||||||
|
if (customClassLoader == null) {
|
||||||
|
createClassLoader();
|
||||||
|
}
|
||||||
|
|
||||||
|
customClassLoader.setClassPath(classDir);
|
||||||
|
loadClass(className);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forces GC to unload previously loaded classes by cleaning all references
|
||||||
|
* to class loader with its loaded classes and eating memory.
|
||||||
|
*
|
||||||
|
* @return <i>true</i> if classes unloading has been detected
|
||||||
|
or <i>false</i> otherwise
|
||||||
|
*
|
||||||
|
* @throws Failure if exception other than OutOfMemoryError
|
||||||
|
* is thrown while eating memory
|
||||||
|
*
|
||||||
|
* @see #eatMemory()
|
||||||
|
*/
|
||||||
|
public boolean unloadClass(ExecutionController stresser) {
|
||||||
|
|
||||||
|
finalized = false;
|
||||||
|
|
||||||
|
// free references to class and class loader to be able for collecting by GC
|
||||||
|
long waitTimeout = (customClassLoader == null) ? 0 : WAIT_TIMEOUT;
|
||||||
|
classObjects.removeAllElements();
|
||||||
|
customClassLoader = null;
|
||||||
|
|
||||||
|
// force class unloading by eating memory pool
|
||||||
|
eatMemory(stresser);
|
||||||
|
|
||||||
|
// give GC chance to run and wait for finalization
|
||||||
|
long timeToFinish = System.currentTimeMillis() + waitTimeout;
|
||||||
|
while (!finalized && System.currentTimeMillis() < timeToFinish) {
|
||||||
|
if (!stresser.continueExecution()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// suspend thread for a while
|
||||||
|
Thread.sleep(WAIT_DELTA);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new Failure("Unexpected InterruptedException while class unloading: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// force GC to unload marked class loader and its classes
|
||||||
|
if (finalized) {
|
||||||
|
Runtime.getRuntime().gc();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// class loader has not been finalized
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean unloadClass() {
|
||||||
|
Stresser stresser = new Stresser() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean continueExecution() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
return unloadClass(stresser);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stresses memory by allocating arrays of bytes.
|
||||||
|
*
|
||||||
|
* Note that this method can throw Failure if any exception
|
||||||
|
* is thrown while eating memory. To avoid OOM while allocating
|
||||||
|
* exception we preallocate it before the lunch starts. It means
|
||||||
|
* that exception stack trace does not correspond to the place
|
||||||
|
* where exception is thrown, but points at start of the method.
|
||||||
|
*
|
||||||
|
* @throws Failure if exception other than OutOfMemoryError
|
||||||
|
* is thrown while eating memory
|
||||||
|
*/
|
||||||
|
public static void eatMemory(ExecutionController stresser) {
|
||||||
|
GarbageUtils.eatMemory(stresser, 50, 1024, 2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* System.runFinalization() may potentially fail with OOM. This is why
|
||||||
|
* System.runFinalization() is repeated several times.
|
||||||
|
*/
|
||||||
|
for (int i = 0; i < 10; ++i) {
|
||||||
|
try {
|
||||||
|
if(!stresser.continueExecution()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
System.runFinalization();
|
||||||
|
break;
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stresses memory by allocating arrays of bytes.
|
||||||
|
*
|
||||||
|
* Note that this method can throw Failure if any exception
|
||||||
|
* is thrown while eating memory. To avoid OOM while allocating
|
||||||
|
* exception we preallocate it before the lunch starts. It means
|
||||||
|
* that exception stack trace does not correspond to the place
|
||||||
|
* where exception is thrown, but points at start of the method.
|
||||||
|
*
|
||||||
|
* @throws Failure if exception other than OutOfMemoryError
|
||||||
|
* is thrown while eating memory
|
||||||
|
*/
|
||||||
|
public static void eatMemory() {
|
||||||
|
Stresser stresser = new Stresser() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean continueExecution() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
GarbageUtils.eatMemory(stresser, 50, 1024, 2);
|
||||||
|
/*
|
||||||
|
* System.runFinalization() may potentially fail with OOM. This is why
|
||||||
|
* System.runFinalization() is repeated several times.
|
||||||
|
*/
|
||||||
|
for (int i = 0; i < 10; ++i) {
|
||||||
|
try {
|
||||||
|
if(!stresser.continueExecution()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
System.runFinalization();
|
||||||
|
break;
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
47
test/hotspot/jtreg/vmTestbase/nsk/share/Consts.java
Normal file
47
test/hotspot/jtreg/vmTestbase/nsk/share/Consts.java
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2002, 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.share;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class defines constants
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Consts {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exit code when test passed
|
||||||
|
*/
|
||||||
|
public final static int TEST_PASSED = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exit code when test failed
|
||||||
|
*/
|
||||||
|
public final static int TEST_FAILED = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shift of exit code
|
||||||
|
*/
|
||||||
|
public final static int JCK_STATUS_BASE = 95;
|
||||||
|
|
||||||
|
}
|
150
test/hotspot/jtreg/vmTestbase/nsk/share/CustomClassLoader.java
Normal file
150
test/hotspot/jtreg/vmTestbase/nsk/share/CustomClassLoader.java
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The <code>CustomClassLoader</code> class is used in <code>ClassUnloader</code>.
|
||||||
|
*
|
||||||
|
* <p>This class loader can load classes and notify <code>ClassUnloader</code>
|
||||||
|
* about own finalization to make sure that all loaded classes have been unloaded.
|
||||||
|
*
|
||||||
|
* <p>By default this class loader loads class from .class file located in directory
|
||||||
|
* specified with <code>setClassPath()</code> method. To use any other technique
|
||||||
|
* of class loading one should implement derived class, which would override
|
||||||
|
* <code>findClass</code> method.
|
||||||
|
*
|
||||||
|
* @see nsk.share.ClassUnloader
|
||||||
|
*
|
||||||
|
* @see #setClassPath(String)
|
||||||
|
* @see #findClass(String)
|
||||||
|
*/
|
||||||
|
public class CustomClassLoader extends ClassLoader {
|
||||||
|
|
||||||
|
private ClassUnloader classUnloader;
|
||||||
|
protected String classPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a newly created <code>CustomClassloader</code> object
|
||||||
|
* not yet linked with any <code>ClassUnloader</code> object.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public CustomClassLoader() {
|
||||||
|
super(CustomClassLoader.class.getClassLoader());
|
||||||
|
this.classUnloader = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a newly created <code>CustomClassloader</code> object
|
||||||
|
* linked with specified <code>ClassUnloader</code> object.
|
||||||
|
*
|
||||||
|
* @param classUnloader an instance of <code>ClassUnloader</code>
|
||||||
|
*/
|
||||||
|
public CustomClassLoader(ClassUnloader classUnloader) {
|
||||||
|
super(CustomClassLoader.class.getClassLoader());
|
||||||
|
this.classUnloader = classUnloader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Links this class loader with specified <code>ClassUnloader</code> object.
|
||||||
|
*
|
||||||
|
* @param classUnloader an instance of <code>ClassUnloader</code>
|
||||||
|
*/
|
||||||
|
public void setClassUnloader(ClassUnloader classUnloader) {
|
||||||
|
this.classUnloader = classUnloader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies path to .class file location.
|
||||||
|
*
|
||||||
|
* @param classPath a path to .class file location
|
||||||
|
*/
|
||||||
|
public void setClassPath(String classPath) {
|
||||||
|
this.classPath = classPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds and loads class for specified class name.
|
||||||
|
* This method loads class from .class file located in a directory
|
||||||
|
* previously specified by <code>setClassPath()</code>.
|
||||||
|
*
|
||||||
|
* @param name The name of the class.
|
||||||
|
*
|
||||||
|
* @throws ClassNotFoundException if no .class file found
|
||||||
|
* for specified class name
|
||||||
|
*
|
||||||
|
* @see #setClassPath(String)
|
||||||
|
*/
|
||||||
|
protected synchronized Class findClass(String name) throws ClassNotFoundException {
|
||||||
|
java.nio.file.Path path = ClassFileFinder.findClassFile(name, classPath);
|
||||||
|
if (path == null) {
|
||||||
|
throw new ClassNotFoundException(name);
|
||||||
|
}
|
||||||
|
String classFileName = path.toString();
|
||||||
|
|
||||||
|
FileInputStream in;
|
||||||
|
try {
|
||||||
|
in = new FileInputStream(classFileName);
|
||||||
|
if (in == null) {
|
||||||
|
throw new ClassNotFoundException(classFileName);
|
||||||
|
}
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
throw new ClassNotFoundException(classFileName, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
int len;
|
||||||
|
byte data[];
|
||||||
|
try {
|
||||||
|
len = in.available();
|
||||||
|
data = new byte[len];
|
||||||
|
for (int total = 0; total < data.length; ) {
|
||||||
|
total += in.read(data, total, data.length - total);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ClassNotFoundException(classFileName, e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
in.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ClassNotFoundException(classFileName, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return defineClass(name, data, 0, data.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies <code>ClassUnloader</code> about finalization.
|
||||||
|
*/
|
||||||
|
protected void finalize() throws Throwable {
|
||||||
|
|
||||||
|
// notify ClassUnloader about finalization
|
||||||
|
if (classUnloader != null) {
|
||||||
|
classUnloader.finalized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.finalize();
|
||||||
|
}
|
||||||
|
}
|
45
test/hotspot/jtreg/vmTestbase/nsk/share/Debug.java
Normal file
45
test/hotspot/jtreg/vmTestbase/nsk/share/Debug.java
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share;
|
||||||
|
|
||||||
|
public class Debug
|
||||||
|
{
|
||||||
|
// tests assertion to be valid, otherwise FAIL test with message
|
||||||
|
static public void Assert(boolean condition, String message)
|
||||||
|
{
|
||||||
|
if (!condition)
|
||||||
|
Debug.Fail(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// print message and FAIL test
|
||||||
|
static public void Fail(String message)
|
||||||
|
{
|
||||||
|
System.out.println(message);
|
||||||
|
System.exit(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public void Fail(Throwable e)
|
||||||
|
{
|
||||||
|
Fail(e.toString());
|
||||||
|
}
|
||||||
|
}
|
139
test/hotspot/jtreg/vmTestbase/nsk/share/Denotation.java
Normal file
139
test/hotspot/jtreg/vmTestbase/nsk/share/Denotation.java
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2002, 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.share;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Denotation implies a pair of algorithms for naming and
|
||||||
|
* indexing of some objects.
|
||||||
|
*
|
||||||
|
* <p>No matter what kind of objects, just make sure that:
|
||||||
|
* <ul>
|
||||||
|
* <li><tt>indexFor(nameFor(index))</tt> equals to <tt>index</tt>
|
||||||
|
* </li>
|
||||||
|
* <li><tt>nameFor(indexFor(name))</tt> is equivalent to <tt>name</tt>
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>The notions of indeces equality and names equivalence
|
||||||
|
* are formalized by the methods <tt>equality()</tt> and
|
||||||
|
* <tt>equivalence()</tt> correspondingly.
|
||||||
|
*
|
||||||
|
* <p>For better understanding of Denotation, you may want to
|
||||||
|
* see the TreeNodesDenotation class as an implementation example.
|
||||||
|
*
|
||||||
|
* @see #equality(int[],int[])
|
||||||
|
* @see #equivalence(String,String)
|
||||||
|
* @see TreeNodesDenotation
|
||||||
|
*/
|
||||||
|
abstract public class Denotation {
|
||||||
|
/**
|
||||||
|
* Check if the <tt>name</tt> is legal, and return the
|
||||||
|
* numeric index for that object denoted by the given
|
||||||
|
* <tt>name</tt>.
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException If the <tt>name</tt>
|
||||||
|
* is illegal.
|
||||||
|
*/
|
||||||
|
abstract public int[] indexFor(String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the <tt>index[]</tt> is legal, and return
|
||||||
|
* a symbolic name for the object denoted by the given
|
||||||
|
* <tt>index[]</tt>.
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException If the <tt>index[]</tt>
|
||||||
|
* is illegal.
|
||||||
|
*/
|
||||||
|
abstract public String nameFor(int[] index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-call to <tt>nameFor(int[])</tt> with the 1-element
|
||||||
|
* array <tt>{i}</tt> as the <tt>index</tt> argument.
|
||||||
|
*
|
||||||
|
* @see #nameFor(int[])
|
||||||
|
*/
|
||||||
|
public String nameFor(int i) {
|
||||||
|
return nameFor(new int[] { i });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-call to <tt>nameFor(int[])</tt> with the 2-elements
|
||||||
|
* array <tt>{i0,i1}</tt> as the <tt>index</tt> argument.
|
||||||
|
*
|
||||||
|
* @see #nameFor(int[])
|
||||||
|
*/
|
||||||
|
public String nameFor(int i0, int i1) {
|
||||||
|
return nameFor(new int[] {i0, i1});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-call to <tt>nameFor(int[])</tt> with the 3-elements
|
||||||
|
* array <tt>{i0,i1,i2}</tt> as the <tt>index</tt> argument.
|
||||||
|
*
|
||||||
|
* @see #nameFor(int[])
|
||||||
|
*/
|
||||||
|
public String nameFor(int i0, int i1, int i2) {
|
||||||
|
return nameFor(new int[] {i0, i1, i2});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indeces equality means equality of objects they denote.
|
||||||
|
*
|
||||||
|
* <p>Indeces <tt>index1[]</tt> and <tt>index2[]</tt> are
|
||||||
|
* equal, if they are equal as <tt>int[]</tt> arrays. But,
|
||||||
|
* there is no index equal to <tt>null</tt>; particularly,
|
||||||
|
* <tt>null</tt> is not equal to itself.
|
||||||
|
*
|
||||||
|
* @see Arrays#equals(int[],int[])
|
||||||
|
*/
|
||||||
|
public boolean equality(int[] index1, int[] index2) {
|
||||||
|
if (index1 == null || index2 == null)
|
||||||
|
return false;
|
||||||
|
return Arrays.equals(index1,index2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Names equivalence means equality of objects they denote.
|
||||||
|
*
|
||||||
|
* <p>Strings <tt>name1</tt> and <tt>name2</tt> are equivalent,
|
||||||
|
* if correspondent indeces are equal. There is no <tt>name</tt>
|
||||||
|
* equivalent to <tt>null</tt>; particularly, <tt>null</tt> is
|
||||||
|
* not equivalent to itself.
|
||||||
|
*
|
||||||
|
* @see #equality(int[],int[])
|
||||||
|
*/
|
||||||
|
public boolean equivalence(String name1, String name2) {
|
||||||
|
if (name1 == null || name2 == null)
|
||||||
|
return false;
|
||||||
|
return equality(indexFor(name1),indexFor(name2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dummy constructor.
|
||||||
|
*/
|
||||||
|
protected Denotation() {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2002, 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.share;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This loader's <tt>findClass()</tt> method is dummy.
|
||||||
|
*/
|
||||||
|
public class DummyClassLoader extends ClassLoader {
|
||||||
|
/**
|
||||||
|
* Cannot instantiate w/o a parent loader.
|
||||||
|
*/
|
||||||
|
protected DummyClassLoader() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delegate everything to the <tt>parent</tt> loader.
|
||||||
|
*/
|
||||||
|
public DummyClassLoader(ClassLoader parent) {
|
||||||
|
super(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do nothing: parent loader must load everything.
|
||||||
|
*
|
||||||
|
* @throws ClassNotFoundException In any case.
|
||||||
|
*/
|
||||||
|
public Class findClass(String name) throws ClassNotFoundException {
|
||||||
|
throw new ClassNotFoundException(name);
|
||||||
|
}
|
||||||
|
}
|
46
test/hotspot/jtreg/vmTestbase/nsk/share/Failure.java
Normal file
46
test/hotspot/jtreg/vmTestbase/nsk/share/Failure.java
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2001, 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.share;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown to indicate failure caused by some occasional reason,
|
||||||
|
* which does not indicate a problem in the JVM being tested.
|
||||||
|
*/
|
||||||
|
public class Failure extends RuntimeException {
|
||||||
|
/** Enwrap another throwable. */
|
||||||
|
public Failure(Throwable throwable) {
|
||||||
|
super(throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Explain particular failure. */
|
||||||
|
public Failure(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Failure(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
71
test/hotspot/jtreg/vmTestbase/nsk/share/FileUtils.java
Normal file
71
test/hotspot/jtreg/vmTestbase/nsk/share/FileUtils.java
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
|
||||||
|
public class FileUtils {
|
||||||
|
private FileUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read whole file.
|
||||||
|
*
|
||||||
|
* @param file file
|
||||||
|
* @return contents of file as byte array
|
||||||
|
*/
|
||||||
|
public static byte[] readFile(File file) throws IOException {
|
||||||
|
InputStream in = new FileInputStream(file);
|
||||||
|
long countl = file.length();
|
||||||
|
if (countl > Integer.MAX_VALUE)
|
||||||
|
throw new IOException("File is too huge");
|
||||||
|
int count = (int) countl;
|
||||||
|
byte[] buffer = new byte[count];
|
||||||
|
int n = 0;
|
||||||
|
try {
|
||||||
|
while (n < count) {
|
||||||
|
int k = in.read(buffer, n, count - n);
|
||||||
|
if (k < 0)
|
||||||
|
throw new IOException("Unexpected EOF");
|
||||||
|
n += k;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read whole file.
|
||||||
|
*
|
||||||
|
* @param name file name
|
||||||
|
* @return contents of file as byte array
|
||||||
|
*/
|
||||||
|
public static byte[] readFile(String name) throws IOException {
|
||||||
|
return readFile(new File(name));
|
||||||
|
}
|
||||||
|
}
|
43
test/hotspot/jtreg/vmTestbase/nsk/share/Finalizable.java
Normal file
43
test/hotspot/jtreg/vmTestbase/nsk/share/Finalizable.java
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2001, 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.share;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalizable interface allows <tt>Finalizer</tt> to perform finalization of an object.
|
||||||
|
* Each object that requires finalization at VM shutdown time should implement this
|
||||||
|
* interface and activate a <tt>Finalizer</tt> hook.
|
||||||
|
*
|
||||||
|
* @see Finalizer
|
||||||
|
*/
|
||||||
|
public interface Finalizable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will be invoked by <tt>Finalizer</tt> when virtual mashine
|
||||||
|
* shuts down.
|
||||||
|
*
|
||||||
|
* @throws Throwable if any throwable exception thrown during finalization
|
||||||
|
*/
|
||||||
|
public void finalizeAtExit() throws Throwable;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2001, 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.share;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is an simple exalmple of finalizable object, that implements interface
|
||||||
|
* <code>Finalizable</code> and invokes standard <code>finalize()</code> method
|
||||||
|
* as finalization.
|
||||||
|
*
|
||||||
|
* @see Finalizable
|
||||||
|
* @see Finalizer
|
||||||
|
*/
|
||||||
|
public class FinalizableObject implements Finalizable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will be invoked by <tt>Finalizer</tt> when virtual mashine
|
||||||
|
* shuts down.
|
||||||
|
* For <code>FinalizableObject</code> this method just invoke
|
||||||
|
* <code>finalize()</code>.
|
||||||
|
*
|
||||||
|
* @throws Throwable if any throwable exception thrown during finalization
|
||||||
|
*
|
||||||
|
* @see Object#finalize()
|
||||||
|
* @see Finalizer
|
||||||
|
*/
|
||||||
|
public void finalizeAtExit() throws Throwable {
|
||||||
|
finalize();
|
||||||
|
}
|
||||||
|
}
|
133
test/hotspot/jtreg/vmTestbase/nsk/share/Finalizer.java
Normal file
133
test/hotspot/jtreg/vmTestbase/nsk/share/Finalizer.java
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2001, 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.share;
|
||||||
|
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalizer performs object finalization when virtual mashine shuts down.
|
||||||
|
* Finalizer is a thread that acts as a VM shutdown hook.
|
||||||
|
* This thread will be activated as VM shuts down because of
|
||||||
|
* invocation of <code>exit()</code> or termination. After activation
|
||||||
|
* Finalizer just calls <code>finalizeAtExit()</code> method of the specified object.
|
||||||
|
* The finalizable object should implement interface <code>Finalizable</code>.
|
||||||
|
*
|
||||||
|
* @see Finalizable
|
||||||
|
*/
|
||||||
|
public class Finalizer {
|
||||||
|
|
||||||
|
/** Finalizer thread to register as a VM shutdown hook. */
|
||||||
|
private static FinalizerThread finalizerThread = null;
|
||||||
|
|
||||||
|
/** An object to finalize. */
|
||||||
|
private Finalizable object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create finalizer for the specified object.
|
||||||
|
*/
|
||||||
|
public Finalizer(Finalizable object) {
|
||||||
|
this.object = object;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register finalizer for finalization at VM shutdown.
|
||||||
|
*/
|
||||||
|
public void activate() {
|
||||||
|
if (finalizerThread == null) {
|
||||||
|
finalizerThread = new FinalizerThread("FinalizerThread for Finalizable objects");
|
||||||
|
finalizerThread.activate();
|
||||||
|
}
|
||||||
|
finalizerThread.add(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister finalizer for finalization at VM shutdown.
|
||||||
|
*/
|
||||||
|
public void deactivate() {
|
||||||
|
if (finalizerThread == null)
|
||||||
|
return;
|
||||||
|
finalizerThread.remove(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static inner thread that is registered as a VM shutdown hook
|
||||||
|
* and performs finalization of all registered finalizable objects.
|
||||||
|
*/
|
||||||
|
private static class FinalizerThread extends Thread {
|
||||||
|
|
||||||
|
/** Stack of objects registered for finalization. */
|
||||||
|
private Stack<Object> objects = new Stack<Object>();
|
||||||
|
|
||||||
|
/** Make new instance of FinalizerThread with given thread name. */
|
||||||
|
public FinalizerThread(String threadName) {
|
||||||
|
super(threadName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Push an object to the stack of registered objects.
|
||||||
|
*/
|
||||||
|
public void add(Finalizable object) {
|
||||||
|
objects.push(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove an object from the stack of registered objects.
|
||||||
|
*/
|
||||||
|
public void remove(Finalizable object) {
|
||||||
|
objects.remove(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register finalizer thread as a VM shutdown hook.
|
||||||
|
*/
|
||||||
|
public void activate() {
|
||||||
|
Runtime.getRuntime().addShutdownHook( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister finalizer thread as a VM shutdown hook.
|
||||||
|
*/
|
||||||
|
public void deactivate() {
|
||||||
|
Runtime.getRuntime().removeShutdownHook( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pop all registered objects from the stack and finalize them.
|
||||||
|
*/
|
||||||
|
public void run() {
|
||||||
|
while (!objects.empty()) {
|
||||||
|
Finalizable object = (Finalizable)objects.pop();
|
||||||
|
try {
|
||||||
|
object.finalizeAtExit();
|
||||||
|
} catch (ThreadDeath e) {
|
||||||
|
throw e;
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of FinalizerThread
|
||||||
|
|
||||||
|
} // end of Finalizer
|
71
test/hotspot/jtreg/vmTestbase/nsk/share/GoldChecker.java
Normal file
71
test/hotspot/jtreg/vmTestbase/nsk/share/GoldChecker.java
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2008, 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.share;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class GoldChecker extends AbstractGoldChecker
|
||||||
|
{
|
||||||
|
private final String goldOutput;
|
||||||
|
|
||||||
|
public GoldChecker(String main_class_name) {
|
||||||
|
goldOutput = readGoldStr(main_class_name + ".gold");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getGoldenString() {
|
||||||
|
return goldOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String readGoldStr(String gold_file_name) {
|
||||||
|
RandomAccessFile f;
|
||||||
|
|
||||||
|
try {
|
||||||
|
f = new RandomAccessFile(gold_file_name, "r");
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
throw new TestBug("Unable to open golden file '" + gold_file_name + "' for reading");
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] data;
|
||||||
|
|
||||||
|
try {
|
||||||
|
int len = (int)f.length();
|
||||||
|
data = new byte[len];
|
||||||
|
f.read(data);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new TestBug("Error reading from golden file'" + gold_file_name + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
f.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new String(data, "US-ASCII");
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new TestFailure( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
103
test/hotspot/jtreg/vmTestbase/nsk/share/Grep.java
Normal file
103
test/hotspot/jtreg/vmTestbase/nsk/share/Grep.java
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2002, 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.share;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.regex.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emulator of perl's grep function.
|
||||||
|
* This class uses java.util.regexp classes which appear in
|
||||||
|
* JDK1.4 API. This implies the restriction for this class
|
||||||
|
* to not be used with the tests against JDKs prior to 1.4.
|
||||||
|
*
|
||||||
|
* @see java.util.regex.Pattern
|
||||||
|
* @see java.util.regex.Matcher
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Grep {
|
||||||
|
|
||||||
|
String[] stringArray;
|
||||||
|
/**
|
||||||
|
* Takes String array as character sequence for matching the pattern.
|
||||||
|
*/
|
||||||
|
public Grep (String[] stringArray) {
|
||||||
|
this.stringArray = stringArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns number of non-interleaved occurences of groups which match the pattern.
|
||||||
|
*/
|
||||||
|
public int find (String regExpPattern) {
|
||||||
|
if (regExpPattern.length() == 0) {
|
||||||
|
throw new Failure("Empty string as input parameter for Grep.find(regExpPattern) method");
|
||||||
|
}
|
||||||
|
Pattern pattern = Pattern.compile(regExpPattern);
|
||||||
|
int counter = 0;
|
||||||
|
for (int i = 0; i < stringArray.length; i++) {
|
||||||
|
|
||||||
|
String string = stringArray[i];
|
||||||
|
if (string != null) {
|
||||||
|
// Create matcher for this string
|
||||||
|
Matcher matcher = pattern.matcher(string);
|
||||||
|
|
||||||
|
// Find all non-interleaved occurences of pattern in this string
|
||||||
|
for (int ind = 0; ind < string.length(); ) {
|
||||||
|
if (matcher.find(ind)) {
|
||||||
|
counter++;
|
||||||
|
ind = matcher.end();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns first string of stringArray with group which matches
|
||||||
|
* the pattern or empty string othrewise.
|
||||||
|
*/
|
||||||
|
public String findFirst (String regExpPattern) {
|
||||||
|
if (regExpPattern.length() == 0) {
|
||||||
|
throw new Failure("Empty string as input parameter for Grep.findFirst(regExpPattern) method");
|
||||||
|
}
|
||||||
|
Pattern pattern = Pattern.compile(regExpPattern);
|
||||||
|
String result = "";
|
||||||
|
for (int i = 0; i < stringArray.length; i++) {
|
||||||
|
|
||||||
|
String string = stringArray[i];
|
||||||
|
if (string != null) {
|
||||||
|
// Create matcher for this string
|
||||||
|
Matcher matcher = pattern.matcher(string);
|
||||||
|
if (matcher.find()) {
|
||||||
|
result = string;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
175
test/hotspot/jtreg/vmTestbase/nsk/share/Harakiri.java
Normal file
175
test/hotspot/jtreg/vmTestbase/nsk/share/Harakiri.java
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2001, 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.share;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Harakiri is used to terminate a stress test with PASS exit status
|
||||||
|
* before the test is terminated as timed out (and so failed).
|
||||||
|
*
|
||||||
|
* <p>Harakiri class holds a thread which sleeps for the given amount
|
||||||
|
* of time, and then wakes up and executes <tt>System.exit()</tt>
|
||||||
|
* with the given exit status. That thread is daemon, so it doesn't
|
||||||
|
* prevent application from exiting once all its threads finish
|
||||||
|
* before it's time for harakiri. Appointing harakiri in zero
|
||||||
|
* delay implies immediate <tt>exit()</tt>.
|
||||||
|
*
|
||||||
|
* <p>There is a limitation: you may appoint no more than one harakiri
|
||||||
|
* per application.
|
||||||
|
*/
|
||||||
|
public class Harakiri {
|
||||||
|
/**
|
||||||
|
* Use specific <tt>appoint()</tt> method to appoint harakiri.
|
||||||
|
*
|
||||||
|
* @see #appoint(int)
|
||||||
|
* @see #appoint(int,int)
|
||||||
|
*/
|
||||||
|
protected Harakiri() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One harakiri per application, or <tt>null</tt> (by default).
|
||||||
|
*/
|
||||||
|
private static Thread harakiri = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Return timeout (or waittime) value munus the margin
|
||||||
|
* value (which is assumed 1 minute by default).
|
||||||
|
*
|
||||||
|
* <p>Treat <tt>args[0]</tt> as <tt>$TIMEOUT</tt> value, or seek for
|
||||||
|
* <tt>-waittime=$WAITTIME</tt> value. If both parameters
|
||||||
|
* (or either none of them) are assigned, throw an exception to
|
||||||
|
* report parameters inconsistency.
|
||||||
|
*
|
||||||
|
* <p>Also, seek for <tt>-margin=...</tt> assignment, or assume margin
|
||||||
|
* is 1 minute.
|
||||||
|
*
|
||||||
|
* @param args Is usually obtained via the application's command-line.
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException If <tt>args[]</tt> is inconsistent.
|
||||||
|
*
|
||||||
|
* @see #appoint(int)
|
||||||
|
* @see #appoint(int,int)
|
||||||
|
*/
|
||||||
|
public static int parseAppointment(String args[]) {
|
||||||
|
int timeout=-1, margin=1;
|
||||||
|
int timeouts=0, waittimes=0, margins=0;
|
||||||
|
for (int i=0; i<args.length; i++) {
|
||||||
|
if (args[i].startsWith("-")) {
|
||||||
|
if (args[i].startsWith("-waittime=")) {
|
||||||
|
timeout = Integer.parseInt(args[i].substring(10));
|
||||||
|
waittimes++;
|
||||||
|
}
|
||||||
|
if (args[i].startsWith("-margin=")) {
|
||||||
|
margin = Integer.parseInt(args[i].substring(8));
|
||||||
|
margins++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (i == 0) {
|
||||||
|
timeout = Integer.parseInt(args[i]);
|
||||||
|
timeouts++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (timeouts==0 && waittimes==0)
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"no $TIMEOUT, nor -waittime=$WAITTIME is set");
|
||||||
|
if (waittimes > 1)
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"more than one -waittime=... is set");
|
||||||
|
if (margins > 1)
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"more than one -margin=... is set");
|
||||||
|
|
||||||
|
int result = timeout - margin;
|
||||||
|
if (result <= 0)
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"delay appointment must be greater than "+margin+" minutes");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appoint harakiri after the given amount of <tt>minutes</tt>,
|
||||||
|
* so that exit status would be 95 (to simulate JCK-like PASS
|
||||||
|
* status).
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException If harakiri is already appointed.
|
||||||
|
*
|
||||||
|
* @see #appoint(int,int)
|
||||||
|
* @see #parseAppointment(String[])
|
||||||
|
*/
|
||||||
|
public static void appoint(int minutes) {
|
||||||
|
appoint(minutes,95); // JCK-like PASS status
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appoint Harakiri for the given amount of <tt>minutes</tt>,
|
||||||
|
* so that the given <tt>status</tt> would be exited when time
|
||||||
|
* is over.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException If harakiri is already appointed.
|
||||||
|
*
|
||||||
|
* @see #appoint(int)
|
||||||
|
* @see #parseAppointment(String[])
|
||||||
|
*/
|
||||||
|
public static void appoint(int minutes, int status) {
|
||||||
|
if (harakiri != null)
|
||||||
|
throw new IllegalStateException("Harakiri is already appointed.");
|
||||||
|
|
||||||
|
final long timeToExit = System.currentTimeMillis() + 60*1000L*minutes;
|
||||||
|
final int exitStatus = status;
|
||||||
|
|
||||||
|
harakiri = new Thread(Harakiri.class.getName()) {
|
||||||
|
public void run() {
|
||||||
|
long timeToSleep = timeToExit - System.currentTimeMillis();
|
||||||
|
if (timeToSleep > 0)
|
||||||
|
try {
|
||||||
|
//
|
||||||
|
// Use wait() instead of sleep(), because Java 2
|
||||||
|
// specification doesn't guarantee the method
|
||||||
|
// sleep() to yield to other threads.
|
||||||
|
//
|
||||||
|
Object someDummyObject = new Object();
|
||||||
|
synchronized (someDummyObject) {
|
||||||
|
someDummyObject.wait(timeToSleep);
|
||||||
|
}
|
||||||
|
} catch (InterruptedException exception) {
|
||||||
|
exception.printStackTrace(System.err);
|
||||||
|
//
|
||||||
|
// OOPS, the dagger for harakiri looks broken:
|
||||||
|
//
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
//
|
||||||
|
// OK, lets do it now:
|
||||||
|
//
|
||||||
|
System.err.println(
|
||||||
|
"#\n# Harakiri: prescheduled program termination.\n#");
|
||||||
|
System.exit(exitStatus); // harakiri to all threads
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
harakiri.setPriority(Thread.MAX_PRIORITY);
|
||||||
|
harakiri.setDaemon(true);
|
||||||
|
harakiri.start();
|
||||||
|
}
|
||||||
|
}
|
142
test/hotspot/jtreg/vmTestbase/nsk/share/IORedirector.java
Normal file
142
test/hotspot/jtreg/vmTestbase/nsk/share/IORedirector.java
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2001, 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.share;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class implements a thread transfering bytes from
|
||||||
|
* a given InputStream to a given OutputStream.
|
||||||
|
*/
|
||||||
|
public class IORedirector extends Thread {
|
||||||
|
private BufferedReader bin = null;
|
||||||
|
private PrintStream pout = null;
|
||||||
|
private Log log = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Few symbols to precede every text line being redirected.
|
||||||
|
*/
|
||||||
|
private String prefix = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input and output streams must be specified.
|
||||||
|
*/
|
||||||
|
private IORedirector() {
|
||||||
|
super("IORedirector");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirect <code>in</code> to <code>out</code>.
|
||||||
|
*
|
||||||
|
* @deprecated Use newer constructor.
|
||||||
|
*
|
||||||
|
* @see #IORedirector(BufferedReader,Log,String)
|
||||||
|
*/
|
||||||
|
public IORedirector(InputStream in, OutputStream out) {
|
||||||
|
this();
|
||||||
|
bin = new BufferedReader(new InputStreamReader(in));
|
||||||
|
pout = new PrintStream(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirect <code>in</code> to <code>log</code>; and assign
|
||||||
|
* few <code>prefix</code> symbols to precede each text line
|
||||||
|
* being redirected.
|
||||||
|
*/
|
||||||
|
public IORedirector(BufferedReader in, Log log, String prefix) {
|
||||||
|
this();
|
||||||
|
this.prefix = prefix;
|
||||||
|
this.bin = in;
|
||||||
|
this.log = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the prefix for redirected messages;
|
||||||
|
*/
|
||||||
|
public void setPrefix(String prefix) {
|
||||||
|
this.prefix = prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cancelled = false;
|
||||||
|
private boolean stopped = false;
|
||||||
|
private boolean started = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal to <code>run()</code> method that it should terminate,
|
||||||
|
* and wait until it is finished.
|
||||||
|
*/
|
||||||
|
public void cancel () {
|
||||||
|
cancelled = true;
|
||||||
|
while (this.isAlive())
|
||||||
|
try {
|
||||||
|
this.join();
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
throw new Failure(ie);
|
||||||
|
};
|
||||||
|
// stopped==true here.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pass data bytes from <code>in</code> to <code>out</code> stream
|
||||||
|
* until EOF is read, or this IORedirector is cancelled.
|
||||||
|
*/
|
||||||
|
public void run () {
|
||||||
|
started = true;
|
||||||
|
String logPrefix = "IORedirector-" + prefix;
|
||||||
|
if (bin == null || (pout == null && log == null))
|
||||||
|
return;
|
||||||
|
try {
|
||||||
|
while (!cancelled) {
|
||||||
|
String line = bin.readLine();
|
||||||
|
if (line == null)
|
||||||
|
break; //EOF
|
||||||
|
String message = prefix + line;
|
||||||
|
if (log != null) {
|
||||||
|
// It's synchronized and auto-flushed:
|
||||||
|
log.println(message);
|
||||||
|
} else if (pout != null) {
|
||||||
|
synchronized (pout) {
|
||||||
|
pout.println(message);
|
||||||
|
pout.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
// e.printStackTrace(log.getOutStream());
|
||||||
|
String msg = "# WARNING: Caught IOException while redirecting output stream:\n\t" + e;
|
||||||
|
if (log != null) {
|
||||||
|
log.println(msg);
|
||||||
|
} else if (pout != null) {
|
||||||
|
synchronized (pout) {
|
||||||
|
pout.println(msg);
|
||||||
|
pout.flush();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.err.println(msg);
|
||||||
|
System.err.flush();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
stopped = true;
|
||||||
|
}
|
||||||
|
}
|
173
test/hotspot/jtreg/vmTestbase/nsk/share/JVMDITools.c
Normal file
173
test/hotspot/jtreg/vmTestbase/nsk/share/JVMDITools.c
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2001, 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 "jvmdi.h"
|
||||||
|
#include "JVMDITools.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char const *TranslateEvent(jint kind) {
|
||||||
|
switch (kind) {
|
||||||
|
case JVMDI_EVENT_SINGLE_STEP:
|
||||||
|
return ("JVMDI_EVENT_SINGLE_STEP");
|
||||||
|
case JVMDI_EVENT_BREAKPOINT:
|
||||||
|
return ("JVMDI_EVENT_BREAKPOINT");
|
||||||
|
case JVMDI_EVENT_FRAME_POP:
|
||||||
|
return ("JVMDI_EVENT_FRAME_POP");
|
||||||
|
case JVMDI_EVENT_EXCEPTION:
|
||||||
|
return ("JVMDI_EVENT_EXCEPTION");
|
||||||
|
case JVMDI_EVENT_USER_DEFINED:
|
||||||
|
return ("JVMDI_EVENT_USER_DEFINED");
|
||||||
|
case JVMDI_EVENT_THREAD_START:
|
||||||
|
return ("JVMDI_EVENT_THREAD_START");
|
||||||
|
case JVMDI_EVENT_THREAD_END:
|
||||||
|
return ("JVMDI_EVENT_THREAD_END");
|
||||||
|
case JVMDI_EVENT_CLASS_PREPARE:
|
||||||
|
return ("JVMDI_EVENT_CLASS_PREPARE");
|
||||||
|
case JVMDI_EVENT_CLASS_UNLOAD:
|
||||||
|
return ("JVMDI_EVENT_CLASS_UNLOAD");
|
||||||
|
case JVMDI_EVENT_CLASS_LOAD:
|
||||||
|
return ("JVMDI_EVENT_CLASS_LOAD");
|
||||||
|
case JVMDI_EVENT_FIELD_ACCESS:
|
||||||
|
return ("JVMDI_EVENT_FIELD_ACCESS");
|
||||||
|
case JVMDI_EVENT_FIELD_MODIFICATION:
|
||||||
|
return ("JVMDI_EVENT_FIELD_MODIFICATION");
|
||||||
|
case JVMDI_EVENT_EXCEPTION_CATCH:
|
||||||
|
return ("JVMDI_EVENT_EXCEPTION_CATCH");
|
||||||
|
case JVMDI_EVENT_METHOD_ENTRY:
|
||||||
|
return ("JVMDI_EVENT_METHOD_ENTRY");
|
||||||
|
case JVMDI_EVENT_METHOD_EXIT:
|
||||||
|
return ("JVMDI_EVENT_METHOD_EXIT");
|
||||||
|
case JVMDI_EVENT_VM_INIT:
|
||||||
|
return ("JVMDI_EVENT_VM_INIT");
|
||||||
|
case JVMDI_EVENT_VM_DEATH:
|
||||||
|
return ("JVMDI_EVENT_VM_DEATH");
|
||||||
|
default:
|
||||||
|
return ("<Unknown Event>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char const *TranslateError(jvmdiError err) {
|
||||||
|
switch (err) {
|
||||||
|
case JVMDI_ERROR_NONE:
|
||||||
|
return ("JVMDI_ERROR_NONE");
|
||||||
|
case JVMDI_ERROR_OUT_OF_MEMORY:
|
||||||
|
return ("JVMDI_ERROR_OUT_OF_MEMORY");
|
||||||
|
case JVMDI_ERROR_ACCESS_DENIED:
|
||||||
|
return ("JVMDI_ERROR_ACCESS_DENIED");
|
||||||
|
case JVMDI_ERROR_UNATTACHED_THREAD:
|
||||||
|
return ("JVMDI_ERROR_UNATTACHED_THREAD");
|
||||||
|
case JVMDI_ERROR_VM_DEAD:
|
||||||
|
return ("JVMDI_ERROR_VM_DEAD");
|
||||||
|
case JVMDI_ERROR_INTERNAL:
|
||||||
|
return ("JVMDI_ERROR_INTERNAL");
|
||||||
|
case JVMDI_ERROR_INVALID_THREAD:
|
||||||
|
return ("JVMDI_ERROR_INVALID_THREAD");
|
||||||
|
case JVMDI_ERROR_INVALID_FIELDID:
|
||||||
|
return ("JVMDI_ERROR_INVALID_FIELDID");
|
||||||
|
case JVMDI_ERROR_INVALID_METHODID:
|
||||||
|
return ("JVMDI_ERROR_INVALID_METHODID");
|
||||||
|
case JVMDI_ERROR_INVALID_LOCATION:
|
||||||
|
return ("JVMDI_ERROR_INVALID_LOCATION");
|
||||||
|
case JVMDI_ERROR_INVALID_FRAMEID:
|
||||||
|
return ("JVMDI_ERROR_INVALID_FRAMEID");
|
||||||
|
case JVMDI_ERROR_NO_MORE_FRAMES:
|
||||||
|
return ("JVMDI_ERROR_NO_MORE_FRAMES");
|
||||||
|
case JVMDI_ERROR_OPAQUE_FRAME:
|
||||||
|
return ("JVMDI_ERROR_OPAQUE_FRAME");
|
||||||
|
case JVMDI_ERROR_NOT_CURRENT_FRAME:
|
||||||
|
return ("JVMDI_ERROR_NOT_CURRENT_FRAME");
|
||||||
|
case JVMDI_ERROR_TYPE_MISMATCH:
|
||||||
|
return ("JVMDI_ERROR_TYPE_MISMATCH");
|
||||||
|
case JVMDI_ERROR_INVALID_SLOT:
|
||||||
|
return ("JVMDI_ERROR_INVALID_SLOT");
|
||||||
|
case JVMDI_ERROR_DUPLICATE:
|
||||||
|
return ("JVMDI_ERROR_DUPLICATE");
|
||||||
|
case JVMDI_ERROR_THREAD_NOT_SUSPENDED:
|
||||||
|
return ("JVMDI_ERROR_THREAD_NOT_SUSPENDED");
|
||||||
|
case JVMDI_ERROR_THREAD_SUSPENDED:
|
||||||
|
return ("JVMDI_ERROR_THREAD_SUSPENDED");
|
||||||
|
case JVMDI_ERROR_INVALID_OBJECT:
|
||||||
|
return ("JVMDI_ERROR_INVALID_OBJECT");
|
||||||
|
case JVMDI_ERROR_INVALID_CLASS:
|
||||||
|
return ("JVMDI_ERROR_INVALID_CLASS");
|
||||||
|
case JVMDI_ERROR_CLASS_NOT_PREPARED:
|
||||||
|
return ("JVMDI_ERROR_CLASS_NOT_PREPARED");
|
||||||
|
case JVMDI_ERROR_NULL_POINTER:
|
||||||
|
return ("JVMDI_ERROR_NULL_POINTER");
|
||||||
|
case JVMDI_ERROR_ABSENT_INFORMATION:
|
||||||
|
return ("JVMDI_ERROR_ABSENT_INFORMATION");
|
||||||
|
case JVMDI_ERROR_INVALID_EVENT_TYPE:
|
||||||
|
return ("JVMDI_ERROR_INVALID_EVENT_TYPE");
|
||||||
|
case JVMDI_ERROR_NOT_IMPLEMENTED:
|
||||||
|
return ("JVMDI_ERROR_NOT_IMPLEMENTED");
|
||||||
|
case JVMDI_ERROR_INVALID_THREAD_GROUP:
|
||||||
|
return ("JVMDI_ERROR_INVALID_THREAD_GROUP");
|
||||||
|
case JVMDI_ERROR_INVALID_PRIORITY:
|
||||||
|
return ("JVMDI_ERROR_INVALID_PRIORITY");
|
||||||
|
case JVMDI_ERROR_NOT_FOUND:
|
||||||
|
return ("JVMDI_ERROR_NOT_FOUND");
|
||||||
|
case JVMDI_ERROR_INVALID_MONITOR:
|
||||||
|
return ("JVMDI_ERROR_INVALID_MONITOR");
|
||||||
|
case JVMDI_ERROR_ILLEGAL_ARGUMENT:
|
||||||
|
return ("JVMDI_ERROR_ILLEGAL_ARGUMENT");
|
||||||
|
case JVMDI_ERROR_NOT_MONITOR_OWNER:
|
||||||
|
return ("JVMDI_ERROR_NOT_MONITOR_OWNER");
|
||||||
|
case JVMDI_ERROR_INTERRUPT:
|
||||||
|
return ("JVMDI_ERROR_INTERRUPT");
|
||||||
|
case JVMDI_ERROR_INVALID_TYPESTATE:
|
||||||
|
return ("JVMDI_ERROR_INVALID_TYPESTATE");
|
||||||
|
case JVMDI_ERROR_INVALID_CLASS_FORMAT:
|
||||||
|
return ("JVMDI_ERROR_INVALID_CLASS_FORMAT");
|
||||||
|
case JVMDI_ERROR_CIRCULAR_CLASS_DEFINITION:
|
||||||
|
return ("JVMDI_ERROR_CIRCULAR_CLASS_DEFINITION");
|
||||||
|
case JVMDI_ERROR_ADD_METHOD_NOT_IMPLEMENTED:
|
||||||
|
return ("JVMDI_ERROR_ADD_METHOD_NOT_IMPLEMENTED");
|
||||||
|
case JVMDI_ERROR_SCHEMA_CHANGE_NOT_IMPLEMENTED:
|
||||||
|
return ("JVMDI_ERROR_SCHEMA_CHANGE_NOT_IMPLEMENTED");
|
||||||
|
case JVMDI_ERROR_FAILS_VERIFICATION:
|
||||||
|
return ("JVMDI_ERROR_FAILS_VERIFICATION");
|
||||||
|
#ifdef JVMDI_VERSION_1_2
|
||||||
|
case JVMDI_ERROR_UNSUPPORTED_VERSION:
|
||||||
|
return ("JVMDI_ERROR_UNSUPPORTED_VERSION");
|
||||||
|
case JVMDI_ERROR_HIERARCHY_CHANGE_NOT_IMPLEMENTED:
|
||||||
|
return ("JVMDI_ERROR_HIERARCHY_CHANGE_NOT_IMPLEMENTED");
|
||||||
|
case JVMDI_ERROR_DELETE_METHOD_NOT_IMPLEMENTED:
|
||||||
|
return ("JVMDI_ERROR_DELETE_METHOD_NOT_IMPLEMENTED");
|
||||||
|
case JVMDI_ERROR_NAMES_DONT_MATCH:
|
||||||
|
return ("JVMDI_ERROR_NAMES_DONT_MATCH");
|
||||||
|
case JVMDI_ERROR_CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED:
|
||||||
|
return ("JVMDI_ERROR_CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED");
|
||||||
|
case JVMDI_ERROR_METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED:
|
||||||
|
return ("JVMDI_ERROR_METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED");
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return ("<Unknown Error>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
33
test/hotspot/jtreg/vmTestbase/nsk/share/JVMDITools.h
Normal file
33
test/hotspot/jtreg/vmTestbase/nsk/share/JVMDITools.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2001, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char const *TranslateEvent(jint kind);
|
||||||
|
char const *TranslateError(jvmdiError err);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
1276
test/hotspot/jtreg/vmTestbase/nsk/share/JVMTIagent.c
Normal file
1276
test/hotspot/jtreg/vmTestbase/nsk/share/JVMTIagent.c
Normal file
File diff suppressed because it is too large
Load Diff
177
test/hotspot/jtreg/vmTestbase/nsk/share/LocalProcess.java
Normal file
177
test/hotspot/jtreg/vmTestbase/nsk/share/LocalProcess.java
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2002, 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.share;
|
||||||
|
|
||||||
|
import nsk.share.*;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for local process.
|
||||||
|
* <p>
|
||||||
|
* This class provides abilities to launch such process,
|
||||||
|
* redirect standard output streams, wait for process terminates
|
||||||
|
* or kill the process, and so on.
|
||||||
|
* <p>
|
||||||
|
* This object is finalized with <code>nsk.share.Finalizer</code>.
|
||||||
|
*
|
||||||
|
* @see nsk.share.FinalizableObject
|
||||||
|
* @see nsk.share.Finalizer
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class LocalProcess extends FinalizableObject {
|
||||||
|
|
||||||
|
public final static int PROCESS_IS_ALIVE = 222;
|
||||||
|
|
||||||
|
private Process process;
|
||||||
|
|
||||||
|
protected Process getProcess() {
|
||||||
|
return process;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void launch (String[] args) throws IOException {
|
||||||
|
System.out.println("Launching process by array of args: ");
|
||||||
|
for (int mm=0; mm < args.length; mm++) {
|
||||||
|
System.out.println(" args[" + Integer.toString(mm) + "]: >" +
|
||||||
|
args[mm] + "<");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
process = Runtime.getRuntime().exec(args);
|
||||||
|
|
||||||
|
Finalizer finalizer = new Finalizer(this);
|
||||||
|
finalizer.activate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void launch (String cmdLine) throws IOException {
|
||||||
|
System.out.println("Launching process by command line: " + cmdLine);
|
||||||
|
|
||||||
|
process = Runtime.getRuntime().exec(cmdLine);
|
||||||
|
|
||||||
|
Finalizer finalizer = new Finalizer(this);
|
||||||
|
finalizer.activate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return exit status. */
|
||||||
|
public int getStatus () {
|
||||||
|
return process.exitValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check whether the process has been terminated. */
|
||||||
|
public boolean terminated() {
|
||||||
|
try {
|
||||||
|
int value = process.exitValue();
|
||||||
|
return true;
|
||||||
|
} catch (IllegalThreadStateException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Wait until the process shutdown or crash. */
|
||||||
|
public int waitFor () throws InterruptedException {
|
||||||
|
return process.waitFor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait until the process shutdown or crash for given timeout in milliseconds.
|
||||||
|
* Returns <code>LocalProcess.PROCESS_IS_ALIVE</code> if process is not terminated
|
||||||
|
* after timeout.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public int waitFor (long timeMillisec) throws InterruptedException {
|
||||||
|
final Object waitObject = new Object();
|
||||||
|
|
||||||
|
class Watcher extends Thread {
|
||||||
|
int exitCode = LocalProcess.PROCESS_IS_ALIVE;
|
||||||
|
Process process;
|
||||||
|
|
||||||
|
Watcher (Process process) {
|
||||||
|
this.process = process;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run () {
|
||||||
|
try {
|
||||||
|
synchronized (this) {
|
||||||
|
exitCode = process.waitFor();
|
||||||
|
}
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
}
|
||||||
|
synchronized (waitObject) {
|
||||||
|
waitObject.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized public int getExitCode() {
|
||||||
|
return exitCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Watcher watcher;
|
||||||
|
// yield control to watcher for timeMillisec time.
|
||||||
|
synchronized (waitObject) {
|
||||||
|
watcher = new Watcher(process);
|
||||||
|
watcher.start();
|
||||||
|
|
||||||
|
waitObject.wait(timeMillisec);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (watcher.isAlive()) {
|
||||||
|
watcher.interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
return watcher.getExitCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------- //
|
||||||
|
|
||||||
|
/** Get a pipe to write to the process' stdin stream. */
|
||||||
|
public OutputStream getStdin () {
|
||||||
|
return process.getOutputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get a pipe to read the process' stdout stream. */
|
||||||
|
public InputStream getStdout () {
|
||||||
|
return process.getInputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get a pipe to read the process stderr stream. */
|
||||||
|
public InputStream getStderr () {
|
||||||
|
return process.getErrorStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Kill the process. */
|
||||||
|
protected void kill() {
|
||||||
|
process.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize mirror by invoking <code>close()</code>.
|
||||||
|
*
|
||||||
|
* @throws Throwable if any throwable exception is thrown during finalization
|
||||||
|
*/
|
||||||
|
protected void finalize() throws Throwable {
|
||||||
|
kill();
|
||||||
|
super.finalize();
|
||||||
|
}
|
||||||
|
}
|
736
test/hotspot/jtreg/vmTestbase/nsk/share/Log.java
Normal file
736
test/hotspot/jtreg/vmTestbase/nsk/share/Log.java
Normal file
@ -0,0 +1,736 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2001, 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.share;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import nsk.share.test.LazyFormatString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class helps to print test-execution trace messages
|
||||||
|
* and filter them when execution mode is not verbose.
|
||||||
|
* <p>
|
||||||
|
* Verbose mode if defined by providing <i>-verbose</i> command line
|
||||||
|
* option, handled by <code>ArgumentParser</code>. Use <code>verbose()</code>
|
||||||
|
* method to determine which mode is used.
|
||||||
|
* <p>
|
||||||
|
* <code>Log</code> provides with two main methods to print messages:
|
||||||
|
* <ul>
|
||||||
|
* <li> <code>complain(String)</code> - to print error message
|
||||||
|
* <li> <code>display(String)</code> - to print additional log message
|
||||||
|
* </ul>
|
||||||
|
* No other way to print messages to the log stream should be used.
|
||||||
|
* <p>
|
||||||
|
* Error messages appeares in log stream in all modes. Additional log massages,
|
||||||
|
* printed with <code>display()</code> method will be filtered out, if log mode
|
||||||
|
* is not verbose. In verbose log made messages of both types are printed.
|
||||||
|
* Additionally, in verbose mode a summary of all occured errors will be printed
|
||||||
|
* at the program exit, by automatically invoking method
|
||||||
|
* <code>printErrorsSummary()</code>.
|
||||||
|
* <p>
|
||||||
|
* To provide printing messages from different sources into one log
|
||||||
|
* with distinct prefixes use internal <code>Log.Logger</code> class.
|
||||||
|
*
|
||||||
|
* @see #verbose()
|
||||||
|
* @see #complain(String)
|
||||||
|
* @see #display(String)
|
||||||
|
* @see ArgumentParser
|
||||||
|
* @see Log.Logger
|
||||||
|
*/
|
||||||
|
public class Log extends FinalizableObject {
|
||||||
|
/**
|
||||||
|
* Report step-by-step activity to this stream.
|
||||||
|
*
|
||||||
|
* @deprecated Tests should not use this field directly.
|
||||||
|
*/
|
||||||
|
protected PrintStream out = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is log-mode verbose?
|
||||||
|
* Default value is <code>false</code>.
|
||||||
|
*/
|
||||||
|
private boolean verbose = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should log messages prefixed with timestamps?
|
||||||
|
* Default value is <code>false</code>.
|
||||||
|
*/
|
||||||
|
private boolean timestamp = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Names for trace levels
|
||||||
|
*/
|
||||||
|
public static final class TraceLevel {
|
||||||
|
public static final int TRACE_NONE = 0;
|
||||||
|
public static final int TRACE_IMPORTANT = 1;
|
||||||
|
public static final int TRACE_NORMAL = 2;
|
||||||
|
public static final int TRACE_VERBOSE = 3;
|
||||||
|
public static final int TRACE_DEBUG = 4;
|
||||||
|
|
||||||
|
public static final int DEFAULT = TRACE_IMPORTANT;
|
||||||
|
|
||||||
|
public static final Map<String, Integer> NAME_TO_LEVEL_MAP = new HashMap<String, Integer>();
|
||||||
|
static {
|
||||||
|
NAME_TO_LEVEL_MAP.put("none", TRACE_NONE);
|
||||||
|
NAME_TO_LEVEL_MAP.put("important", TRACE_IMPORTANT);
|
||||||
|
NAME_TO_LEVEL_MAP.put("info", TRACE_NORMAL);
|
||||||
|
NAME_TO_LEVEL_MAP.put("verbose", TRACE_VERBOSE);
|
||||||
|
NAME_TO_LEVEL_MAP.put("debug", TRACE_DEBUG);
|
||||||
|
NAME_TO_LEVEL_MAP.put("default", DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int nameToLevel(String value) throws IllegalArgumentException {
|
||||||
|
Integer level = NAME_TO_LEVEL_MAP.get(value.toLowerCase());
|
||||||
|
if ( level == null )
|
||||||
|
throw new IllegalArgumentException("Wrong trace level: " + value);
|
||||||
|
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getLevelsString() {
|
||||||
|
StringBuffer result = new StringBuffer();
|
||||||
|
for ( String s : NAME_TO_LEVEL_MAP.keySet() ) {
|
||||||
|
result.append(s).append(", ");
|
||||||
|
}
|
||||||
|
return result.substring(0, result.length() - 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Threshold value for printing trace messages for debugging purpose.
|
||||||
|
* Default value is <code>0</code> a.k.a. <code>TraceLevel.INFO</code>;
|
||||||
|
*/
|
||||||
|
private int traceLevel = TraceLevel.DEFAULT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is printing errors summary enabled? Default value is <code>true</code>;
|
||||||
|
*/
|
||||||
|
private boolean errorsSummaryEnabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is printing saved verbose messages on error enabled? Default value is <code>true</code>;
|
||||||
|
*/
|
||||||
|
private boolean verboseOnErrorEnabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This <code>errosBuffer</code> will keep all messages printed via
|
||||||
|
* <code>complain()</code> method for final summary output.
|
||||||
|
* Ensure that buffer has enough room for messages to keep,
|
||||||
|
* to minimize probability or OutOfMemory error while keeping
|
||||||
|
* an error message in stress tests.
|
||||||
|
*/
|
||||||
|
private Vector<String> errorsBuffer = new Vector<String>(1000);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Most tests in nsk do not log exceptions, they only log an error message.
|
||||||
|
* This makes failure analysis harder.
|
||||||
|
* To solve this we will automatically generate Exceptions for error logs.
|
||||||
|
* To not log too many Exceptions, we try to log each unique error only once.
|
||||||
|
* <code>loggedExceptions</code> contains all messages that have already been logged.
|
||||||
|
*/
|
||||||
|
private Set<String> loggedExceptions = new HashSet<String>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This <code>logBuffer</code> will keep all messages printed via
|
||||||
|
* <code>display()</code> method in non-verbose mode until
|
||||||
|
* swithching verbose mode on or invoking <code>complain()</code>.
|
||||||
|
* Ensure that buffer has enough room for messages to keep,
|
||||||
|
* to minimize probability or OutOfMemory error while keeping
|
||||||
|
* an error message in stress tests.
|
||||||
|
*/
|
||||||
|
private Vector<String> logBuffer = new Vector<String>(1000);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Did I already warned if output stream is not assigned?
|
||||||
|
*/
|
||||||
|
private boolean noOutWarned = false;
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new Log's only with <code>Log(out)</code> or with
|
||||||
|
* <code>Log(out,argsHandler)</code> constructors.
|
||||||
|
*
|
||||||
|
* @deprecated Extending test class with Log is obsolete.
|
||||||
|
*/
|
||||||
|
protected Log() {
|
||||||
|
// install finalizer to print errors summary at exit
|
||||||
|
Finalizer finalizer = new Finalizer(this);
|
||||||
|
finalizer.activate();
|
||||||
|
|
||||||
|
// Don't log exceptions from this method. It would just add unnecessary logs.
|
||||||
|
loggedExceptions.add("nsk.share.jdi.SerialExecutionDebugger.executeTests");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Incarnate new Log for the given <code>stream</code> and
|
||||||
|
* for non-verbose mode.
|
||||||
|
*/
|
||||||
|
public Log(PrintStream stream) {
|
||||||
|
this();
|
||||||
|
out = stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Incarnate new Log for the given <code>stream</code>; and
|
||||||
|
* either for verbose or for non-verbose mode accordingly to
|
||||||
|
* the given <code>verbose</code> key.
|
||||||
|
*/
|
||||||
|
public Log(PrintStream stream, boolean verbose) {
|
||||||
|
this(stream);
|
||||||
|
this.verbose = verbose;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Incarnate new Log for the given <code>stream</code>; and
|
||||||
|
* either for verbose or for non-verbose mode accordingly to
|
||||||
|
* the given <code>argsHandler</code>.
|
||||||
|
*/
|
||||||
|
public Log(PrintStream stream, ArgumentParser argsParser) {
|
||||||
|
this(stream, argsParser.verbose());
|
||||||
|
traceLevel = argsParser.getTraceLevel();
|
||||||
|
timestamp = argsParser.isTimestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return <i>true</i> if log mode is verbose.
|
||||||
|
*/
|
||||||
|
public boolean verbose() {
|
||||||
|
return verbose;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return <i>true</i> if printing errors summary at exit is enabled.
|
||||||
|
*/
|
||||||
|
public boolean isErrorsSummaryEnabled() {
|
||||||
|
return errorsSummaryEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable or disable printing errors summary at exit.
|
||||||
|
*/
|
||||||
|
public void enableErrorsSummary(boolean enable) {
|
||||||
|
errorsSummaryEnabled = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return <i>true</i> if printing saved verbose messages on error is enabled.
|
||||||
|
*/
|
||||||
|
public boolean isVerboseOnErrorEnabled() {
|
||||||
|
return errorsSummaryEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable or disable printing saved verbose messages on error.
|
||||||
|
*/
|
||||||
|
public void enableVerboseOnError(boolean enable) {
|
||||||
|
verboseOnErrorEnabled = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable or disable verbose mode for printing messages.
|
||||||
|
*/
|
||||||
|
public void enableVerbose(boolean enable) {
|
||||||
|
if (!verbose) {
|
||||||
|
flushLogBuffer();
|
||||||
|
}
|
||||||
|
verbose = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTraceLevel() {
|
||||||
|
return traceLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set threshold for printing trace messages.
|
||||||
|
* Warning: trace level changes may NOT be observed by other threads immediately.
|
||||||
|
*/
|
||||||
|
public void setTraceLevel(int level) {
|
||||||
|
traceLevel = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return output stream of this <code>Log</code> object.
|
||||||
|
*/
|
||||||
|
public PrintStream getOutStream() {
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string that contains prefix concatenated
|
||||||
|
* with Throwable.printStackTrace() output.
|
||||||
|
*/
|
||||||
|
public static String printExceptionToString(Object prefix, Throwable exception) {
|
||||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
PrintWriter pw = new PrintWriter(bos);
|
||||||
|
pw.println(prefix);
|
||||||
|
exception.printStackTrace(pw);
|
||||||
|
pw.close();
|
||||||
|
return bos.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print <code>message</code> to the assigned output stream.
|
||||||
|
*
|
||||||
|
* @deprecated Test ought to be quiet if log mode is non-verbose
|
||||||
|
* and there is no errors found by the test. Methods
|
||||||
|
* <code>display()</code> and <code>complain()</code>
|
||||||
|
* are enough for testing purposes.
|
||||||
|
*/
|
||||||
|
public synchronized void println(String message) {
|
||||||
|
doPrint(message);
|
||||||
|
if (!verbose() && isVerboseOnErrorEnabled()) {
|
||||||
|
keepLog(composeLine(message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print <code>message</code> to the assigned output stream,
|
||||||
|
* if log mode is <i>non</i>-verbose.
|
||||||
|
*
|
||||||
|
* @deprecated Test ought to be quiet if log mode is non-verbose
|
||||||
|
* and there is no errors found by the test. Methods
|
||||||
|
* <code>display()</code> and <code>complain()</code>
|
||||||
|
* are enough for testing purposes.
|
||||||
|
*/
|
||||||
|
public synchronized void comment(String message) {
|
||||||
|
if (!verbose()) {
|
||||||
|
doPrint(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print trace <code>message</code> to the assigned output stream,
|
||||||
|
* only if specified <code>level</code> is less or equal for the
|
||||||
|
* trace level specified in command line by <code>-trace.level</code>
|
||||||
|
* option.
|
||||||
|
*/
|
||||||
|
public void trace(int level, Object message) {
|
||||||
|
if (level <= traceLevel) {
|
||||||
|
synchronized ( this ) {
|
||||||
|
doPrint("### TRACE " + level + ": " + message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Print trace <code>message</code> and <code>exception</code> to
|
||||||
|
* the assigned output stream,
|
||||||
|
* only if specified <code>level</code> is less or equal for the
|
||||||
|
* trace level specified in command line by <code>-trace.level</code>
|
||||||
|
* option.
|
||||||
|
*/
|
||||||
|
public void trace(int level, Object message, Throwable exception) {
|
||||||
|
if (level <= traceLevel) {
|
||||||
|
trace(level, printExceptionToString(message, exception));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print <code>message</code> to the assigned output stream,
|
||||||
|
* if log mode is verbose. The <code>message</code> will be lost,
|
||||||
|
* if execution mode is non-verbose, and there is no error messages
|
||||||
|
* printed.
|
||||||
|
*/
|
||||||
|
public synchronized void display(Object message) {
|
||||||
|
if (verbose()) {
|
||||||
|
doPrint(message.toString());
|
||||||
|
} else if (isVerboseOnErrorEnabled()) {
|
||||||
|
keepLog(composeLine(message.toString()));
|
||||||
|
} else {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print error <code>message</code> to the assigned output stream
|
||||||
|
* (or to stderr if output is not specified) and keep the message
|
||||||
|
* into <code>errorsBuffer</code>.
|
||||||
|
*/
|
||||||
|
public synchronized void complain(Object message) {
|
||||||
|
if (!verbose() && isVerboseOnErrorEnabled()) {
|
||||||
|
PrintStream stream = findOutStream();
|
||||||
|
stream.println("#> ");
|
||||||
|
stream.println("#> WARNING: switching log to verbose mode,");
|
||||||
|
stream.println("#> because error is complained");
|
||||||
|
stream.println("#> ");
|
||||||
|
stream.flush();
|
||||||
|
enableVerbose(true);
|
||||||
|
}
|
||||||
|
String msgStr = message.toString();
|
||||||
|
printError(msgStr);
|
||||||
|
if (isErrorsSummaryEnabled()) {
|
||||||
|
keepError(msgStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
logExceptionForFailureAnalysis(msgStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print error <code>message</code> and <code>exception</code>
|
||||||
|
* to the assigned output stream
|
||||||
|
* (or to stderr if output is not specified) and keep the message
|
||||||
|
* into <code>errorsBuffer</code>.
|
||||||
|
*/
|
||||||
|
public void complain(Object message, Throwable exception) {
|
||||||
|
if ( exception != null )
|
||||||
|
complain(printExceptionToString(message, exception));
|
||||||
|
else
|
||||||
|
complain(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an Exception and print the stack trace for an error msg.
|
||||||
|
* This makes it possible to detect a failure reason for this error.
|
||||||
|
*/
|
||||||
|
private void logExceptionForFailureAnalysis(String msg) {
|
||||||
|
// Some error messages are formatted in multiple lines and with tabs.
|
||||||
|
// We clean the messages to help parse the stack traces for failure analysis.
|
||||||
|
// We keep at most 2 lines, otherwise the error message may be too long.
|
||||||
|
String[] lines = msg.split("[\r\n]+");
|
||||||
|
msg = lines.length >= 2 ? lines[0] + " " + lines[1] : lines[0];
|
||||||
|
msg = msg.replaceAll("\t", " ");
|
||||||
|
|
||||||
|
// Create a dummy exception just so we can print the stack trace.
|
||||||
|
TestFailure e = new TestFailure(msg);
|
||||||
|
StackTraceElement[] elements = e.getStackTrace();
|
||||||
|
|
||||||
|
final int callerIndex = 2; // 0=this function, 1=complain(), 2=caller
|
||||||
|
if (elements.length <= callerIndex) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only log the first complain message from each function.
|
||||||
|
// The reason is that some functions splits an error message
|
||||||
|
// into multiple lines and call complain() many times.
|
||||||
|
// We do not want a RULE for each of those calls.
|
||||||
|
// This means that we may miss some rules, but that
|
||||||
|
// is better than to create far too many rules.
|
||||||
|
String callerClass = elements[callerIndex].getClassName();
|
||||||
|
String callerMethod = elements[callerIndex].getMethodName();
|
||||||
|
String callerKey = callerClass + "." + callerMethod;
|
||||||
|
boolean isAlreadyLogged = loggedExceptions.contains(msg) || loggedExceptions.contains(callerKey);
|
||||||
|
|
||||||
|
if (!isAlreadyLogged) {
|
||||||
|
PrintStream stream = findOutStream();
|
||||||
|
stream.println("The following stacktrace is for failure analysis.");
|
||||||
|
e.printStackTrace(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
loggedExceptions.add(callerKey);
|
||||||
|
loggedExceptions.add(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirect log to the given <code>stream</code>, and switch
|
||||||
|
* log mode to verbose.
|
||||||
|
* Prints errors summary to current stream, cancel current stream
|
||||||
|
* and switches to new stream. Turns on verbose mode for new stream.
|
||||||
|
*
|
||||||
|
* @deprecated This method is obsolete.
|
||||||
|
*/
|
||||||
|
protected synchronized void logTo(PrintStream stream) {
|
||||||
|
finalize(); // flush older log stream
|
||||||
|
out = stream;
|
||||||
|
verbose = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print all messages from log buffer which were hidden because
|
||||||
|
* of non-verbose mode,
|
||||||
|
*/
|
||||||
|
private synchronized void flushLogBuffer() {
|
||||||
|
if (!logBuffer.isEmpty()) {
|
||||||
|
PrintStream stream = findOutStream();
|
||||||
|
for (int i = 0; i < logBuffer.size(); i++) {
|
||||||
|
stream.println(logBuffer.elementAt(i));
|
||||||
|
}
|
||||||
|
stream.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return <code>out</code> stream if defined or <code>Sytem.err<code> otherwise;
|
||||||
|
* print a warning message when <code>System.err</code> is used first time.
|
||||||
|
*/
|
||||||
|
private synchronized PrintStream findOutStream() {
|
||||||
|
PrintStream stream = out;
|
||||||
|
if (stream == null) {
|
||||||
|
stream = System.err;
|
||||||
|
if (!noOutWarned) {
|
||||||
|
noOutWarned = true;
|
||||||
|
stream.println("#> ");
|
||||||
|
stream.println("#> WARNING: switching log stream to stderr,");
|
||||||
|
stream.println("#> because no output stream is assigned");
|
||||||
|
stream.println("#> ");
|
||||||
|
};
|
||||||
|
};
|
||||||
|
stream.flush();
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compose line to print possible prefixing it with timestamp.
|
||||||
|
*/
|
||||||
|
private String composeLine(String message) {
|
||||||
|
if (timestamp) {
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
long ms = time % 1000;
|
||||||
|
time /= 1000;
|
||||||
|
long secs = time % 60;
|
||||||
|
time /= 60;
|
||||||
|
long mins = time % 60;
|
||||||
|
time /= 60;
|
||||||
|
long hours = time % 24;
|
||||||
|
return "[" + hours + ":" + mins + ":" + secs + "." + ms + "] " + message;
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print the given <code>message</code> either to <code>out</code>
|
||||||
|
* stream, or to <code>System.err</code> if <code>out</code>
|
||||||
|
* stream is not specified.
|
||||||
|
*/
|
||||||
|
private synchronized void doPrint(String message) {
|
||||||
|
PrintStream stream = findOutStream();
|
||||||
|
stream.println(composeLine(message));
|
||||||
|
stream.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print the given error <code>message</code> either to <code>out</code>
|
||||||
|
* stream, or to <code>System.err</code> if <code>out</code>
|
||||||
|
* stream is not specified.
|
||||||
|
*/
|
||||||
|
private synchronized void printError(String message) {
|
||||||
|
// Print each line with the ERROR prefix:
|
||||||
|
BufferedReader br = new BufferedReader(new StringReader(message));
|
||||||
|
for (String line; ; ) {
|
||||||
|
try {
|
||||||
|
line = br.readLine();
|
||||||
|
if (line == null)
|
||||||
|
break;
|
||||||
|
doPrint("# ERROR: " + line);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new TestBug("Exception in Log.printError(): " + e);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep the given log <code>message</code> into <code>logBuffer</code>.
|
||||||
|
*/
|
||||||
|
private synchronized void keepLog(String message) {
|
||||||
|
logBuffer.addElement(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep the given error <code>message</code> into <code>errorsBuffer</code>.
|
||||||
|
*/
|
||||||
|
private synchronized void keepError(String message) {
|
||||||
|
errorsBuffer.addElement(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print errors messages summary from errors buffer if any;
|
||||||
|
* print a warning message first.
|
||||||
|
*/
|
||||||
|
private synchronized void printErrorsSummary() {
|
||||||
|
if (errorsBuffer.size() <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PrintStream stream = findOutStream();
|
||||||
|
stream.println();
|
||||||
|
stream.println();
|
||||||
|
stream.println("#> ");
|
||||||
|
stream.println("#> SUMMARY: Following errors occured");
|
||||||
|
stream.println("#> during test execution:");
|
||||||
|
stream.println("#> ");
|
||||||
|
stream.flush();
|
||||||
|
|
||||||
|
for (Enumeration e = errorsBuffer.elements(); e.hasMoreElements(); ) {
|
||||||
|
printError((String) e.nextElement());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print errors summary if mode is verbose, flush and cancel output stream.
|
||||||
|
*/
|
||||||
|
protected void finalize() {
|
||||||
|
if (verbose() && isErrorsSummaryEnabled()) {
|
||||||
|
printErrorsSummary();
|
||||||
|
}
|
||||||
|
if (out != null)
|
||||||
|
out.flush();
|
||||||
|
out = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform finalization at the exit.
|
||||||
|
*/
|
||||||
|
public void finalizeAtExit() {
|
||||||
|
finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class can be used as a base for each class that use <code>Log</code>
|
||||||
|
* for print messages and errors.
|
||||||
|
* <code>Logger</code> provides with ability to print such messages with
|
||||||
|
* specified prefix to make it possible to distinct messages printed from
|
||||||
|
* different sources.
|
||||||
|
*
|
||||||
|
* @see Log
|
||||||
|
*/
|
||||||
|
public static class Logger {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default prefix for messages.
|
||||||
|
*/
|
||||||
|
public static final String LOG_PREFIX = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log to print messages to.
|
||||||
|
*/
|
||||||
|
protected Log log = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefix for messages.
|
||||||
|
*/
|
||||||
|
protected String logPrefix = LOG_PREFIX;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make <code>Logger</code> object with empty <code>Log</code> and
|
||||||
|
* default prefix.
|
||||||
|
* This method may be used only in derived class, that should specify
|
||||||
|
* the used <code>Log</code> object further and assign it to <code>log</code>.
|
||||||
|
*
|
||||||
|
* @see #log
|
||||||
|
* @see #setLogPrefix
|
||||||
|
*/
|
||||||
|
protected Logger() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make <code>Logger</code> object for specified <code>Log</code>
|
||||||
|
* with default prefix.
|
||||||
|
*
|
||||||
|
* @see #setLogPrefix
|
||||||
|
*/
|
||||||
|
public Logger(Log log) {
|
||||||
|
this.log = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make <code>Logger</code> object for specified <code>Log</code> with
|
||||||
|
* given messages prefix.
|
||||||
|
*/
|
||||||
|
public Logger(Log log, String prefix) {
|
||||||
|
this.log = log;
|
||||||
|
this.logPrefix = prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return <code>Log</code> object.
|
||||||
|
*/
|
||||||
|
public Log getLog() {
|
||||||
|
return log;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return output stream of this <code>Log</code> object.
|
||||||
|
*/
|
||||||
|
public PrintStream getOutStream() {
|
||||||
|
return log.getOutStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set prefix for printed messages.
|
||||||
|
*/
|
||||||
|
public void setLogPrefix(String prefix) {
|
||||||
|
logPrefix = prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make printable message by adding <code>logPrefix<code> to it.
|
||||||
|
*/
|
||||||
|
public String makeLogMessage(String message) {
|
||||||
|
return logPrefix + message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print trace message by invoking <code>Log.trace()</code>.
|
||||||
|
*
|
||||||
|
* @see Log#trace
|
||||||
|
*/
|
||||||
|
public void trace(int level, String message) {
|
||||||
|
log.trace(level, makeLogMessage(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print message by invoking <code>Log.println()</code>.
|
||||||
|
*
|
||||||
|
* @see Log#println
|
||||||
|
*/
|
||||||
|
public void println(String message) {
|
||||||
|
log.println(makeLogMessage(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print message by invoking <code>Log.display()</code>.
|
||||||
|
*
|
||||||
|
* @see Log#display
|
||||||
|
*/
|
||||||
|
public void display(String message) {
|
||||||
|
log.display(makeLogMessage(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Complain about an error by invoking <code>Log.complain()</code> method.
|
||||||
|
*
|
||||||
|
* @see Log#complain
|
||||||
|
*/
|
||||||
|
public void complain(String message) {
|
||||||
|
log.complain(makeLogMessage(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
31
test/hotspot/jtreg/vmTestbase/nsk/share/NativeUtils.java
Normal file
31
test/hotspot/jtreg/vmTestbase/nsk/share/NativeUtils.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006, 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.share;
|
||||||
|
|
||||||
|
public class NativeUtils {
|
||||||
|
static {
|
||||||
|
System.loadLibrary("native_utils");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static native long getCurrentPID();
|
||||||
|
}
|
@ -0,0 +1,232 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006, 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.share;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class create/delete instances with given reference type and given referrers number
|
||||||
|
*/
|
||||||
|
public class ObjectInstancesManager
|
||||||
|
{
|
||||||
|
public static String STRONG_REFERENCE = "STRONG";
|
||||||
|
public static String WEAK_REFERENCE = "WEAK";
|
||||||
|
public static String SOFT_REFERENCE = "SOFT";
|
||||||
|
public static String PHANTOM_REFERENCE = "PHANTOM";
|
||||||
|
public static String JNI_GLOBAL_REFERENCE = "JNI_GLOBAL";
|
||||||
|
public static String JNI_LOCAL_REFERENCE = "JNI_LOCAL";
|
||||||
|
public static String JNI_WEAK_REFERENCE = "JNI_WEAK";
|
||||||
|
|
||||||
|
// used to create references of all types
|
||||||
|
private static String USE_ALL_REFERENCE_TYPES = "ALL_REFERENCE_TYPES";
|
||||||
|
|
||||||
|
private Map<String, Collection<ReferringObjectSet>> instances = new TreeMap<String, Collection<ReferringObjectSet>>();
|
||||||
|
|
||||||
|
public static Set<String> primitiveArrayClassNames = new HashSet<String>();
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
primitiveArrayClassNames.add("boolean[]");
|
||||||
|
primitiveArrayClassNames.add("byte[]");
|
||||||
|
primitiveArrayClassNames.add("char[]");
|
||||||
|
primitiveArrayClassNames.add("int[]");
|
||||||
|
primitiveArrayClassNames.add("long[]");
|
||||||
|
primitiveArrayClassNames.add("float[]");
|
||||||
|
primitiveArrayClassNames.add("double[]");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Set<String> allReferenceTypes = new HashSet<String>();
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
allReferenceTypes.add(ObjectInstancesManager.STRONG_REFERENCE);
|
||||||
|
allReferenceTypes.add(ObjectInstancesManager.WEAK_REFERENCE);
|
||||||
|
allReferenceTypes.add(ObjectInstancesManager.SOFT_REFERENCE);
|
||||||
|
allReferenceTypes.add(ObjectInstancesManager.PHANTOM_REFERENCE);
|
||||||
|
allReferenceTypes.add(ObjectInstancesManager.JNI_GLOBAL_REFERENCE);
|
||||||
|
allReferenceTypes.add(ObjectInstancesManager.JNI_LOCAL_REFERENCE);
|
||||||
|
allReferenceTypes.add(ObjectInstancesManager.JNI_WEAK_REFERENCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isWeak(String type) {
|
||||||
|
return !(type.equals(ObjectInstancesManager.JNI_GLOBAL_REFERENCE)
|
||||||
|
|| type.equals(ObjectInstancesManager.JNI_LOCAL_REFERENCE)
|
||||||
|
|| type.equals(ObjectInstancesManager.STRONG_REFERENCE));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Log log;
|
||||||
|
|
||||||
|
public ObjectInstancesManager(Log log)
|
||||||
|
{
|
||||||
|
ObjectInstancesManager.log = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete a given number of referrers
|
||||||
|
public void deleteReferrers(String className, int referrersCount, Set<String> referrerTypes)
|
||||||
|
{
|
||||||
|
Collection<ReferringObjectSet> objectInstances;
|
||||||
|
|
||||||
|
objectInstances = instances.get(className);
|
||||||
|
|
||||||
|
if(objectInstances == null)
|
||||||
|
{
|
||||||
|
log.display("Error command 'deleteObjectInstances' is requsted: instances of class " + className + " was not created");
|
||||||
|
System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<ReferringObjectSet> iterator = objectInstances.iterator();
|
||||||
|
|
||||||
|
while(iterator.hasNext())
|
||||||
|
{
|
||||||
|
ReferringObjectSet debugeeObjectReference = iterator.next();
|
||||||
|
if (referrerTypes.isEmpty() || referrerTypes.contains(debugeeObjectReference.getReferenceType())) {
|
||||||
|
debugeeObjectReference.delete(referrersCount);
|
||||||
|
|
||||||
|
if(debugeeObjectReference.getReferrerCount() == 0)
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete all object referrers, it is equal to make object unreacheable
|
||||||
|
public void deleteAllReferrers(int count, String className)
|
||||||
|
{
|
||||||
|
Collection<ReferringObjectSet> objectInstances;
|
||||||
|
|
||||||
|
objectInstances = instances.get(className);
|
||||||
|
|
||||||
|
if(objectInstances == null)
|
||||||
|
{
|
||||||
|
throw new TestBug("Command 'deleteObjectInstances' is requsted: instances of class " + className + " was not created");
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<ReferringObjectSet> iterator = objectInstances.iterator();
|
||||||
|
|
||||||
|
if(count == 0)
|
||||||
|
count = objectInstances.size();
|
||||||
|
|
||||||
|
for(int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
ReferringObjectSet debugeeObjectReference = iterator.next();
|
||||||
|
debugeeObjectReference.deleteAll();
|
||||||
|
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create object instance with referrers of all possible types
|
||||||
|
public void createAllTypeReferences(String className, int count)
|
||||||
|
{
|
||||||
|
createReferences(count, className, 1, allReferenceTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a given number of object instances with given number of referrers
|
||||||
|
public void createReferences(int count, String className, int referrerCount, Set<String> referrerTypes)
|
||||||
|
{
|
||||||
|
Collection<ReferringObjectSet> objectInstances;
|
||||||
|
|
||||||
|
Class klass = null;
|
||||||
|
|
||||||
|
if(!primitiveArrayClassNames.contains(className))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
klass = Class.forName(className);
|
||||||
|
}
|
||||||
|
catch(ClassNotFoundException e)
|
||||||
|
{
|
||||||
|
log.display("Can't find class: " + className);
|
||||||
|
System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
objectInstances = instances.get(className);
|
||||||
|
|
||||||
|
if(objectInstances == null)
|
||||||
|
{
|
||||||
|
objectInstances = new ArrayList<ReferringObjectSet>();
|
||||||
|
instances.put(className, objectInstances);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Object instance;
|
||||||
|
|
||||||
|
if(!primitiveArrayClassNames.contains(className))
|
||||||
|
{
|
||||||
|
instance = klass.newInstance();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
instance = createPrimitiveTypeArray(className);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(String type : referrerTypes) {
|
||||||
|
objectInstances.add(new ReferringObjectSet(instance, referrerCount, type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
log.display("Unexpected exception: " + e);
|
||||||
|
System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object createPrimitiveTypeArray(String typeName)
|
||||||
|
{
|
||||||
|
int arraySize = 1;
|
||||||
|
|
||||||
|
if(typeName.equals("boolean[]"))
|
||||||
|
return new boolean[arraySize];
|
||||||
|
else
|
||||||
|
if(typeName.equals("byte[]"))
|
||||||
|
return new byte[arraySize];
|
||||||
|
else
|
||||||
|
if(typeName.equals("char[]"))
|
||||||
|
return new char[arraySize];
|
||||||
|
else
|
||||||
|
if(typeName.equals("int[]"))
|
||||||
|
return new int[arraySize];
|
||||||
|
else
|
||||||
|
if(typeName.equals("long[]"))
|
||||||
|
return new long[arraySize];
|
||||||
|
else
|
||||||
|
if(typeName.equals("float[]"))
|
||||||
|
return new float[arraySize];
|
||||||
|
else
|
||||||
|
if(typeName.equals("double[]"))
|
||||||
|
return new double[arraySize];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new TestBug("Invalid primitive type array type name: " + typeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
36
test/hotspot/jtreg/vmTestbase/nsk/share/Oddity.java
Normal file
36
test/hotspot/jtreg/vmTestbase/nsk/share/Oddity.java
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2001, 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.share;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Oddity exception is used to simulate C/C++ style <code>assert()</code>
|
||||||
|
* facility. It is thrown when an internal contradiction is revealed, which
|
||||||
|
* may do not indicate a bug in the JDI implementation or in the test.
|
||||||
|
*/
|
||||||
|
public class Oddity extends Failure {
|
||||||
|
/** Explain particular oddity. */
|
||||||
|
public Oddity (String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
42
test/hotspot/jtreg/vmTestbase/nsk/share/Pair.java
Normal file
42
test/hotspot/jtreg/vmTestbase/nsk/share/Pair.java
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011, 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.share;
|
||||||
|
|
||||||
|
public class Pair<A, B> {
|
||||||
|
final public A first;
|
||||||
|
final public B second;
|
||||||
|
|
||||||
|
private Pair(A first, B second) {
|
||||||
|
this.first = first;
|
||||||
|
this.second = second;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <A, B> Pair<A, B> of(A first, B second) {
|
||||||
|
return new Pair<A, B>(first, second);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "(" + first + ", " + second + ")";
|
||||||
|
}
|
||||||
|
}
|
176
test/hotspot/jtreg/vmTestbase/nsk/share/Paragrep.java
Normal file
176
test/hotspot/jtreg/vmTestbase/nsk/share/Paragrep.java
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2002, 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.share;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.regex.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Weak emulator of perl's grep function with very small functionality.
|
||||||
|
* This class does not use java.util.regexp classes which appear in
|
||||||
|
* JDK1.4 API.
|
||||||
|
*
|
||||||
|
* @see Grep
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Paragrep {
|
||||||
|
|
||||||
|
String[] stringArray;
|
||||||
|
/**
|
||||||
|
* Takes String array as character sequence for matching the pattern.
|
||||||
|
*/
|
||||||
|
public Paragrep (String[] stringArray) {
|
||||||
|
this.stringArray = stringArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns number of non-interleaved occurences of the pattern string.
|
||||||
|
*/
|
||||||
|
public int find (String pattern) {
|
||||||
|
if (pattern.length() == 0) {
|
||||||
|
throw new Failure("Empty string as input parameter for Grep.find(pattern) method");
|
||||||
|
}
|
||||||
|
int counter = 0;
|
||||||
|
for (int i = 0; i < stringArray.length; i++) {
|
||||||
|
|
||||||
|
String string = stringArray[i];
|
||||||
|
if (string != null) {
|
||||||
|
// Find all non-interleaved occurences of pattern in this string
|
||||||
|
for (int ind = 0; ind < string.length(); ) {
|
||||||
|
int k = 0;
|
||||||
|
if ((k = string.indexOf(pattern, ind)) >= 0) {
|
||||||
|
counter++;
|
||||||
|
ind = k + pattern.length();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all string in <code>stringArray</code> which have
|
||||||
|
* occurences of the pattern string.
|
||||||
|
*/
|
||||||
|
public String[] findStrings (String pattern) {
|
||||||
|
if (pattern.length() == 0) {
|
||||||
|
throw new Failure("Empty string as input parameter for Grep.find(pattern) method");
|
||||||
|
}
|
||||||
|
Vector<String> v = new Vector<String>();
|
||||||
|
for (int i = 0; i < stringArray.length; i++) {
|
||||||
|
String string = stringArray[i];
|
||||||
|
if (string != null && string.indexOf(pattern) >= 0) {
|
||||||
|
v.add(string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String[] result = new String[v.size()];
|
||||||
|
v.toArray(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns first string of stringArray which contains
|
||||||
|
* the pattern string or empty string othrewise.
|
||||||
|
*/
|
||||||
|
public String findFirst (String pattern) {
|
||||||
|
if (pattern.length() == 0) {
|
||||||
|
throw new Failure("Empty string as input parameter for Paragrep.findFirst(pattern) method");
|
||||||
|
}
|
||||||
|
String result = "";
|
||||||
|
for (int i = 0; i < stringArray.length; i++) {
|
||||||
|
String string = stringArray[i];
|
||||||
|
if (string != null) {
|
||||||
|
if (string.indexOf(pattern) >= 0) {
|
||||||
|
result = string;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns first string of stringArray which contains
|
||||||
|
* all of the pattern strings or empty string otherwise.
|
||||||
|
*/
|
||||||
|
public String findFirst (Vector<String> patternVector) {
|
||||||
|
if (patternVector.isEmpty()) {
|
||||||
|
throw new Failure("Empty vector as input parameter for Paragrep.findFirst(patternVector) method");
|
||||||
|
}
|
||||||
|
String[] patterns = new String[patternVector.size()];
|
||||||
|
patternVector.toArray(patterns);
|
||||||
|
String result = "";
|
||||||
|
for (int i = 0; i < stringArray.length; i++) {
|
||||||
|
String string = stringArray[i];
|
||||||
|
if (string != null && string.length() > 0) {
|
||||||
|
for (int j = 0; j < patterns.length; j++) {
|
||||||
|
String pattern = patterns[j];
|
||||||
|
if (string.indexOf(pattern) >= 0) {
|
||||||
|
if (j + 1 == patterns.length) {
|
||||||
|
// found all patterns in the current string
|
||||||
|
result = string;
|
||||||
|
i = stringArray.length;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns count of strings in stringArray which contain
|
||||||
|
* all of the pattern strings.
|
||||||
|
*/
|
||||||
|
public int find (Vector<String> patternVector) {
|
||||||
|
if (patternVector.isEmpty()) {
|
||||||
|
throw new Failure("Empty vector as input parameter for Paragrep.find(patternVector) method");
|
||||||
|
}
|
||||||
|
String[] patterns = new String[patternVector.size()];
|
||||||
|
patternVector.toArray(patterns);
|
||||||
|
int counter = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < stringArray.length; i++) {
|
||||||
|
String string = stringArray[i];
|
||||||
|
if (string != null && string.length() > 0) {
|
||||||
|
for (int j = 0; j < patterns.length; j++) {
|
||||||
|
String pattern = patterns[j];
|
||||||
|
if (string.indexOf(pattern) >= 0) {
|
||||||
|
if (j + 1 == patterns.length) {
|
||||||
|
// found all patterns in the current string
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
}
|
54
test/hotspot/jtreg/vmTestbase/nsk/share/PrintProperties.java
Normal file
54
test/hotspot/jtreg/vmTestbase/nsk/share/PrintProperties.java
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This program prints system properties.
|
||||||
|
*/
|
||||||
|
public class PrintProperties {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Properties pr = System.getProperties();
|
||||||
|
switch (args.length) {
|
||||||
|
case 0:
|
||||||
|
pr.list(System.out);
|
||||||
|
System.exit(0);
|
||||||
|
case 1:
|
||||||
|
String value = pr.getProperty(args[0]);
|
||||||
|
if (value == null) {
|
||||||
|
System.err.println("Not found");
|
||||||
|
System.exit(1);
|
||||||
|
} else {
|
||||||
|
System.out.println(value);
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
System.out.println("Usage:");
|
||||||
|
System.out.println(" PrintProperties");
|
||||||
|
System.out.println(" PrintProperties <property name>");
|
||||||
|
System.exit(255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
376
test/hotspot/jtreg/vmTestbase/nsk/share/RASagent.java
Normal file
376
test/hotspot/jtreg/vmTestbase/nsk/share/RASagent.java
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2002, 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.share;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used as an agent for Java serviceability reliability testing (RAS).
|
||||||
|
* It sets different RAS options and/or modes for a special agent which
|
||||||
|
* actually performs the specified RAS testing.<br>
|
||||||
|
* The agent recognizes arguments, started with ''<code>-ras.</code>''. They
|
||||||
|
* may be as follows:<p>
|
||||||
|
* <li><code>-ras.help</code> - print usage message and exit
|
||||||
|
* <li><code>-ras.verbose</code> - verbose mode
|
||||||
|
* <li><code>-ras.invoke_run</code> - invoke the method <i>run(String[],PrintStream)</i>
|
||||||
|
* of the test instead of <i>main(String[])</i> which is invoked by default.
|
||||||
|
* <li><code>-ras.hotswap=<stress_level></code> - enable JVMTI hotswap of
|
||||||
|
* the currently running test classes. Here are the possible HotSwap stress
|
||||||
|
* levels:<br>
|
||||||
|
* 0 - HotSwap off<br>
|
||||||
|
* 2 - HotSwap tested class in every JVMTI method entry event of running test
|
||||||
|
* (default mode)<br>
|
||||||
|
* 20 - HotSwap tested class in every JVMTI method entry event of every class<br>
|
||||||
|
* 3 - HotSwap tested class in every JVMTI single step event of running test<br>
|
||||||
|
* 4 - HotSwap tested class in every JVMTI exception event of running test<br>
|
||||||
|
* 40 - HotSwap tested class in every JVMTI exception event of every class<p>
|
||||||
|
*/
|
||||||
|
public class RASagent {
|
||||||
|
static final int HOTSWAP_OFF = 0;
|
||||||
|
static final int HOTSWAP_EVERY_METHOD_ENTRY = 2;
|
||||||
|
static final int HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS = 20;
|
||||||
|
static final int HOTSWAP_EVERY_SINGLE_STEP = 3;
|
||||||
|
static final int HOTSWAP_EVERY_EXCEPTION = 4;
|
||||||
|
static final int HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS = 40;
|
||||||
|
|
||||||
|
// path to the directory with class files of the invoked test
|
||||||
|
static String clfBasePath = null;
|
||||||
|
|
||||||
|
private static boolean verbose = false;
|
||||||
|
|
||||||
|
private static PrintStream out;
|
||||||
|
|
||||||
|
native static int setHotSwapMode(boolean vrb, int stress_lev,
|
||||||
|
String shortName);
|
||||||
|
|
||||||
|
public static void main(String argv[]) {
|
||||||
|
System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int run(String argv[], PrintStream out) {
|
||||||
|
return new RASagent().runThis(argv, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int runThis(String argv[], PrintStream out) {
|
||||||
|
int skipArgs = 1; // number of arguments which must be skipped
|
||||||
|
// for the invoked test
|
||||||
|
boolean invokeRun = false; // invoke the method "main" by default
|
||||||
|
int hotSwapMode = HOTSWAP_EVERY_METHOD_ENTRY; // HotSwap default stress level
|
||||||
|
int res;
|
||||||
|
String hotSwapModeName = "HOTSWAP_EVERY_METHOD_ENTRY";
|
||||||
|
|
||||||
|
RASagent.out = out;
|
||||||
|
|
||||||
|
if (argv.length != 0) {
|
||||||
|
// parse arguments for the RASagent and then skip them
|
||||||
|
while(argv[skipArgs-1].startsWith("-ras.")) {
|
||||||
|
if (argv[skipArgs-1].equals("-ras.verbose")) {
|
||||||
|
verbose = true;
|
||||||
|
} else if (argv[skipArgs-1].equals("-ras.help")) {
|
||||||
|
printHelp();
|
||||||
|
return Consts.TEST_FAILED;
|
||||||
|
} else if (argv[skipArgs-1].equals("-ras.invoke_run")) {
|
||||||
|
invokeRun = true;
|
||||||
|
} else if (argv[skipArgs-1].startsWith("-ras.hotswap=")) {
|
||||||
|
try {
|
||||||
|
hotSwapMode = Integer.parseInt(
|
||||||
|
argv[skipArgs-1].substring(argv[skipArgs-1].lastIndexOf("=")+1));
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
out.println("\nERROR: RASagent: specified HotSwap mode \""
|
||||||
|
+ hotSwapMode + "\" is not an integer");
|
||||||
|
printHelp();
|
||||||
|
return Consts.TEST_FAILED;
|
||||||
|
}
|
||||||
|
switch(hotSwapMode) {
|
||||||
|
case HOTSWAP_EVERY_METHOD_ENTRY:
|
||||||
|
hotSwapModeName = "HOTSWAP_EVERY_METHOD_ENTRY";
|
||||||
|
break;
|
||||||
|
case HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS:
|
||||||
|
hotSwapModeName = "HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS";
|
||||||
|
break;
|
||||||
|
case HOTSWAP_EVERY_SINGLE_STEP:
|
||||||
|
hotSwapModeName = "HOTSWAP_EVERY_SINGLE_STEP";
|
||||||
|
break;
|
||||||
|
case HOTSWAP_EVERY_EXCEPTION:
|
||||||
|
hotSwapModeName = "HOTSWAP_EVERY_EXCEPTION";
|
||||||
|
break;
|
||||||
|
case HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS:
|
||||||
|
hotSwapModeName = "HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
out.println("\nERROR: RASagent: specified HotSwap mode \""
|
||||||
|
+ hotSwapMode + "\" is unrecognized");
|
||||||
|
printHelp();
|
||||||
|
return Consts.TEST_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
skipArgs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
String shortTestName = getTestNameAndPath(argv[skipArgs-1]);
|
||||||
|
|
||||||
|
display("\n#### RASagent: setting hotswap mode \""
|
||||||
|
+ hotSwapModeName + "\" for class \""
|
||||||
|
+ shortTestName + "\" ...");
|
||||||
|
if ((res = setHotSwapMode(verbose, hotSwapMode, shortTestName)) != 0) {
|
||||||
|
out.println("\nERROR: RASagent: unable to set HotSwap stress level for \""
|
||||||
|
+ shortTestName + "\", exiting");
|
||||||
|
return Consts.TEST_FAILED;
|
||||||
|
}
|
||||||
|
display("\n#### RASagent: ... setting hotswap mode done");
|
||||||
|
|
||||||
|
try {
|
||||||
|
Class testCls = Class.forName(argv[skipArgs-1]);
|
||||||
|
display("\n#### RASagent: main class \""
|
||||||
|
+ testCls.toString() + "\" loaded");
|
||||||
|
|
||||||
|
// copy arguments for the invoked test
|
||||||
|
String args[] = new String[argv.length-skipArgs];
|
||||||
|
System.arraycopy(argv, skipArgs, args, 0, args.length);
|
||||||
|
|
||||||
|
// invoke the test
|
||||||
|
if (invokeRun)
|
||||||
|
return invokeRunMethod(testCls, args);
|
||||||
|
else
|
||||||
|
return invokeMainMethod(testCls, args);
|
||||||
|
} catch(ClassNotFoundException e) {
|
||||||
|
// just pass: the invoked test is already a RAS specific one
|
||||||
|
out.println("\nWARNING: the test was not really run due to the following error:"
|
||||||
|
+ "\n\tunable to get the Class object for \""
|
||||||
|
+ argv[skipArgs-1] + "\"\n\tcaught: " + e);
|
||||||
|
return Consts.TEST_PASSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
out.println("\nERROR: RASagent: required test name is absent in parameters list");
|
||||||
|
return Consts.TEST_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify that test's class file exists with a path given as a parameter
|
||||||
|
* and, if so, store that path in the static field "clfBasePath".
|
||||||
|
*/
|
||||||
|
private boolean pathValid(String pathToCheck, String testName) {
|
||||||
|
String fullPath = pathToCheck + File.separator
|
||||||
|
+ testName.replace('.', File.separatorChar) + ".class";
|
||||||
|
File classFile = null;
|
||||||
|
|
||||||
|
display("\n#### RASagent: verifying class path\n<RASagent>\t"
|
||||||
|
+ pathToCheck + " ...");
|
||||||
|
try {
|
||||||
|
classFile = new File(fullPath);
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
out.println("\nERROR: RASagent: verification of class file "
|
||||||
|
+ fullPath + " failed: caught " + e);
|
||||||
|
System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classFile.exists()) {
|
||||||
|
clfBasePath = pathToCheck;
|
||||||
|
display("<RASagent>\tthe class file exists:\n<RASagent>\t\t"
|
||||||
|
+ fullPath + "\n<RASagent>\tclass file base directory found:\n"
|
||||||
|
+ "<RASagent>\t\t" + clfBasePath
|
||||||
|
+ "\n#### RASagent: ... class path verification done\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
display("<RASagent>\tno class file at location :\n\t\t"
|
||||||
|
+ fullPath
|
||||||
|
+ "\n#### RASagent: ... class path verification done\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get short name of an invoked test (i.e. without package name) and
|
||||||
|
* store path to the directory with the test's class files.
|
||||||
|
*/
|
||||||
|
private String getTestNameAndPath(String testName) {
|
||||||
|
String shortTestName = testName;
|
||||||
|
String packageName = "";
|
||||||
|
|
||||||
|
// if '.' occurs, it means that current test is inside a package
|
||||||
|
if (testName.lastIndexOf(".") != -1) {
|
||||||
|
shortTestName = testName.substring(testName.lastIndexOf(".")+1);
|
||||||
|
packageName = testName.substring(0, testName.lastIndexOf("."));
|
||||||
|
}
|
||||||
|
|
||||||
|
StringTokenizer clPathes = new StringTokenizer(
|
||||||
|
System.getProperty("java.class.path"), File.pathSeparator);
|
||||||
|
|
||||||
|
while(clPathes.hasMoreTokens()) {
|
||||||
|
String clPath = clPathes.nextToken();
|
||||||
|
|
||||||
|
// trying to load a class file defining the current test from
|
||||||
|
// this entry of "java.class.path": the class file may locate
|
||||||
|
// at the test's work directory or if it's already compiled,
|
||||||
|
// at any directory in classpath
|
||||||
|
if (pathValid(clPath, testName))
|
||||||
|
return shortTestName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// directory with the test's class files was not found.
|
||||||
|
// Actually, it means that the invoked test has own Java
|
||||||
|
// options such as, for example, "-verify"
|
||||||
|
out.println("\nWARNING: the test was not really run due to the following reason:"
|
||||||
|
+ "\n\tthe invoked test has the own Java option: "
|
||||||
|
+ testName);
|
||||||
|
System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_PASSED);
|
||||||
|
|
||||||
|
return null; // fake return for too smart javac
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoke the method <i>main(String[])</i> of the test.
|
||||||
|
*/
|
||||||
|
private int invokeMainMethod(Class testCls, String args[]) {
|
||||||
|
Class[] methType = { String[].class };
|
||||||
|
Object[] methArgs = { args };
|
||||||
|
|
||||||
|
return invokeMethod(testCls, "main", methType, methArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoke the method <i>run(String[], PrintStream)</i> of the test.
|
||||||
|
*/
|
||||||
|
private int invokeRunMethod(Class testCls, String args[]) {
|
||||||
|
Class[] methType = { String[].class, PrintStream.class };
|
||||||
|
Object[] methArgs = { args, out };
|
||||||
|
|
||||||
|
return invokeMethod(testCls, "run", methType, methArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Low level invocation of the test.
|
||||||
|
*/
|
||||||
|
private int invokeMethod(Class<?> testCls, String methodName,
|
||||||
|
Class methType[], Object methArgs[]) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Method testMeth = testCls.getMethod(methodName, methType);
|
||||||
|
display("\n#### RASagent: invoking method \""
|
||||||
|
+ testMeth.toString() + "\" ...");
|
||||||
|
|
||||||
|
Object result = testMeth.invoke(null, methArgs);
|
||||||
|
|
||||||
|
display("\n#### RASagent: ... invocation of \""
|
||||||
|
+ testMeth.toString() + "\" done");
|
||||||
|
if (result instanceof Integer) {
|
||||||
|
Integer retCode = (Integer) result;
|
||||||
|
return retCode.intValue();
|
||||||
|
}
|
||||||
|
} catch(NoSuchMethodException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
out.println("\nFAILURE: RASagent: unable to get method \""
|
||||||
|
+ methodName + "\" in class "
|
||||||
|
+ testCls + "\n\tcaught " + e);
|
||||||
|
return Consts.TEST_FAILED;
|
||||||
|
} catch(Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
out.println("\nFAILURE: RASagent: caught during invokation of the test class "
|
||||||
|
+ testCls + " " + e);
|
||||||
|
return Consts.TEST_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load class bytes for HotSwap.
|
||||||
|
*/
|
||||||
|
static byte[] loadFromClassFile(String signature) {
|
||||||
|
String testPath = clfBasePath + File.separator + signature.substring(
|
||||||
|
1, signature.length()-1).replace('/', File.separatorChar) + ".class";
|
||||||
|
File classFile = null;
|
||||||
|
|
||||||
|
display("\n#### RASagent: looking for class file\n<RASagent>\t"
|
||||||
|
+ testPath + " ...");
|
||||||
|
|
||||||
|
try {
|
||||||
|
classFile = new File(testPath);
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
out.println("\nFAILURE: RASagent: path name to the redefining class file is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
display("\n#### RASagent: loading " + classFile.length()
|
||||||
|
+ " bytes from class file "+ testPath + " ...");
|
||||||
|
byte[] buf = new byte[(int) classFile.length()];
|
||||||
|
try {
|
||||||
|
InputStream in = new FileInputStream(classFile);
|
||||||
|
in.read(buf);
|
||||||
|
in.close();
|
||||||
|
} catch(FileNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
out.println("\nFAILURE: RASagent: loadFromClassFile: file " +
|
||||||
|
classFile.getName() + " not found");
|
||||||
|
System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
out.println("\nFAILURE: RASagent: unable to load bytes from the file:\n");
|
||||||
|
out.println("\t" + testPath + ": caught " + e);
|
||||||
|
System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
display("\n#### RASagent: ... " + classFile.length() + " bytes loaded");
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is used in verbose mode. It prints paramter string only
|
||||||
|
* in case of verbose mode.
|
||||||
|
*/
|
||||||
|
private static void display(String msg) {
|
||||||
|
if (verbose)
|
||||||
|
out.println(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method prints out RASagent usage message.
|
||||||
|
*/
|
||||||
|
private static void printHelp() {
|
||||||
|
out.println("\nRASagent usage: RASagent [option, ...] test" +
|
||||||
|
"\n\t-ras.help print this message and exit" +
|
||||||
|
"\n\t-ras.verbose verbose mode (off by default)" +
|
||||||
|
"\n\t-ras.hotswap=mode enable HotSwap of the running test classes" +
|
||||||
|
"\n\t\twhere mode is:" +
|
||||||
|
"\n\t\t\t" + HOTSWAP_EVERY_METHOD_ENTRY
|
||||||
|
+ " - hotswap tested class in its every method entry event" +
|
||||||
|
"\n\t\t\t" + HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS
|
||||||
|
+ " - hotswap tested class in every method entry event for every class" +
|
||||||
|
"\n\t\t\t" + HOTSWAP_EVERY_SINGLE_STEP
|
||||||
|
+ " - hotswap tested class in its every single step event" +
|
||||||
|
"\n\t\t\t" + HOTSWAP_EVERY_EXCEPTION
|
||||||
|
+ " - hotswap tested class in its every exception event" +
|
||||||
|
"\n\t\t\t" + HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS
|
||||||
|
+ " - hotswap tested class in every exception event for every class\n" +
|
||||||
|
"\n\t-ras.invoke_run invoke the method run() of the test" +
|
||||||
|
"\n\t\tinstead of main() by default");
|
||||||
|
}
|
||||||
|
}
|
128
test/hotspot/jtreg/vmTestbase/nsk/share/README
Normal file
128
test/hotspot/jtreg/vmTestbase/nsk/share/README
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
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.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This directory contains source files of NSK tests framework
|
||||||
|
shared between all NSK tests.
|
||||||
|
|
||||||
|
Files located directly in this directory provide general support
|
||||||
|
for all tests.
|
||||||
|
|
||||||
|
Files in the subdirectories provide specific support for tests of
|
||||||
|
particular subsuites.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Short description of files:
|
||||||
|
|
||||||
|
common exceptions:
|
||||||
|
Failure,java, TestBug.java, Oddity.java
|
||||||
|
common constants:
|
||||||
|
Consts.java
|
||||||
|
parsing command line arguments:
|
||||||
|
ArgumentPareser.java
|
||||||
|
output of errors and messages:
|
||||||
|
Log.java
|
||||||
|
process running:
|
||||||
|
LocalProcess.java, IORedirector.java
|
||||||
|
class loading/unloading:
|
||||||
|
DummyClassLoader.java, ZipClassLoader.java,
|
||||||
|
CustomClassLoader.java, ClassUnloder.java
|
||||||
|
objects finalization:
|
||||||
|
Finalizable.java, FinalizableObject.java, Finalizer.java
|
||||||
|
threads synchronization:
|
||||||
|
Wicket.java
|
||||||
|
text processing:
|
||||||
|
Grep.java, Paragrep.java
|
||||||
|
timeouts handling:
|
||||||
|
Harakiri.java, TimeoutHandler.java
|
||||||
|
tree structures support:
|
||||||
|
Denotation.java, TreeNodesDenotation.java
|
||||||
|
RAS mode support:
|
||||||
|
RASagent.java, JVMTIagent.c
|
||||||
|
JVMDI tests support:
|
||||||
|
JVMDITools.h, JVMDITools.c
|
||||||
|
|
||||||
|
Short description of subdirectories:
|
||||||
|
|
||||||
|
Alien - support for accessing external tests (JCK)
|
||||||
|
native - support for native part of NSK tests
|
||||||
|
jni - support for JNI tests and accessing JNI API
|
||||||
|
jvmti - support for JVMTI tests and accessing JVMTI API
|
||||||
|
jpda - support for two-VMs JPDA tests
|
||||||
|
jdwp - support for JDWP tests and accessing JDWP API
|
||||||
|
jdi - support for JDI tests and accesing JDI API
|
||||||
|
jdb - support for JDB tests and accessing JDB tool
|
||||||
|
monitoring - support for monitoring tests and accessing Java Monitoring&Management API
|
||||||
|
sysdict - support for System Dictionary tests
|
||||||
|
gc - support for GC tests
|
||||||
|
regression - support for regression tests for known bugs
|
||||||
|
split_verifier - support for Split Verifier tests
|
||||||
|
|
||||||
|
For more detailed description see README files in subdirectories.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Naming conventions
|
||||||
|
|
||||||
|
Classes:
|
||||||
|
|
||||||
|
All shared classes are groupped into packages to prevent
|
||||||
|
name collision.
|
||||||
|
|
||||||
|
All classes exported directly from this directory are
|
||||||
|
of package:
|
||||||
|
|
||||||
|
nsk.share
|
||||||
|
|
||||||
|
All classes exported from subdirectories are of particular
|
||||||
|
subpackage, e.g.:
|
||||||
|
|
||||||
|
nsk.share.jpda
|
||||||
|
nsk.share.jdwp
|
||||||
|
nsk.share.jdi
|
||||||
|
nsk.share.jdb
|
||||||
|
nsk.share.monitoring
|
||||||
|
nsk.share.sysdict
|
||||||
|
|
||||||
|
Native functions and macroses:
|
||||||
|
|
||||||
|
Most native functions have special prefix to prevent linking collisions.
|
||||||
|
Most macroses also have special prefix and are wrote in upper register.
|
||||||
|
|
||||||
|
Here is typical naming scheme used for native functions and macroses:
|
||||||
|
|
||||||
|
share/native
|
||||||
|
functions: nsk_*
|
||||||
|
macroses: NSK_*
|
||||||
|
|
||||||
|
share/jni
|
||||||
|
functions: nsk_jni_*
|
||||||
|
macroses: NSK_JNI_*
|
||||||
|
|
||||||
|
share/jvmti
|
||||||
|
functions: nsk_jvmti_*
|
||||||
|
macroses: NSK_JVMTI_*
|
||||||
|
|
||||||
|
However, some native functions and macroses do not follow this scheme,
|
||||||
|
in order to preserve compatibility with old tests.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------
|
265
test/hotspot/jtreg/vmTestbase/nsk/share/ReferringObject.java
Normal file
265
test/hotspot/jtreg/vmTestbase/nsk/share/ReferringObject.java
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006, 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.share;
|
||||||
|
|
||||||
|
import java.lang.ref.PhantomReference;
|
||||||
|
import java.lang.ref.ReferenceQueue;
|
||||||
|
import java.lang.ref.SoftReference;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This class create/delete reference with given type.
|
||||||
|
*
|
||||||
|
* Supported reference types are:
|
||||||
|
* - strong
|
||||||
|
* - soft
|
||||||
|
* - weak
|
||||||
|
* - phantom
|
||||||
|
* - jni local
|
||||||
|
* - jni global
|
||||||
|
* - jni weak
|
||||||
|
*/
|
||||||
|
public class ReferringObject
|
||||||
|
{
|
||||||
|
static
|
||||||
|
{
|
||||||
|
System.loadLibrary("JNIreferences");
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static int maxJNIGlobalReferences = 1000;
|
||||||
|
public final static int maxJNIWeakReferences = 1000;
|
||||||
|
|
||||||
|
private Object reference;
|
||||||
|
|
||||||
|
private String referenceType;
|
||||||
|
|
||||||
|
//used for storing jni global and jni weak references
|
||||||
|
private int referenceIndex;
|
||||||
|
|
||||||
|
public ReferringObject(Object object, String referenceType)
|
||||||
|
{
|
||||||
|
this.referenceType = referenceType;
|
||||||
|
|
||||||
|
if(referenceType.equals(ObjectInstancesManager.STRONG_REFERENCE))
|
||||||
|
{
|
||||||
|
createStrongReference(object);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(referenceType.equals(ObjectInstancesManager.SOFT_REFERENCE))
|
||||||
|
{
|
||||||
|
createSoftReference(object);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(referenceType.equals(ObjectInstancesManager.WEAK_REFERENCE))
|
||||||
|
{
|
||||||
|
createWeakReference(object);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(referenceType.equals(ObjectInstancesManager.PHANTOM_REFERENCE))
|
||||||
|
{
|
||||||
|
createPhantomReference(object);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(referenceType.equals(ObjectInstancesManager.JNI_GLOBAL_REFERENCE))
|
||||||
|
{
|
||||||
|
createJNIGlobalReference(object);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(referenceType.equals(ObjectInstancesManager.JNI_LOCAL_REFERENCE))
|
||||||
|
{
|
||||||
|
createJNILocalReference(object);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(referenceType.equals(ObjectInstancesManager.JNI_WEAK_REFERENCE))
|
||||||
|
{
|
||||||
|
createJNIWeakReference(object);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new IllegalArgumentException("Invalid reference type: " + referenceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete()
|
||||||
|
{
|
||||||
|
if(referenceType == null)
|
||||||
|
{
|
||||||
|
throw new TestBug("Reference type is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(referenceType.equals(ObjectInstancesManager.SOFT_REFERENCE))
|
||||||
|
{
|
||||||
|
if(reference == null)
|
||||||
|
{
|
||||||
|
throw new TestBug("Reference is null for SoftReference");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(((SoftReference)reference).get() == null)
|
||||||
|
{
|
||||||
|
// throw new TestBug("Test execution error: SoftReference was collected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(referenceType.equals(ObjectInstancesManager.WEAK_REFERENCE))
|
||||||
|
{
|
||||||
|
if(reference == null)
|
||||||
|
{
|
||||||
|
throw new TestBug("Reference is null for WeakReference");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(((WeakReference)reference).get() == null)
|
||||||
|
{
|
||||||
|
// throw new TestBug("Test execution error: WeakReference was collected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(referenceType.equals(ObjectInstancesManager.PHANTOM_REFERENCE))
|
||||||
|
{
|
||||||
|
if(reference == null)
|
||||||
|
{
|
||||||
|
throw new TestBug("Reference is null for PhantomReference");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(referenceType.equals(ObjectInstancesManager.JNI_GLOBAL_REFERENCE))
|
||||||
|
{
|
||||||
|
deleteJNIGlobalReferenceNative(referenceIndex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(referenceType.equals(ObjectInstancesManager.JNI_LOCAL_REFERENCE))
|
||||||
|
{
|
||||||
|
deleteJNILocalReference();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(referenceType.equals(ObjectInstancesManager.JNI_WEAK_REFERENCE))
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
deleteJNIWeakReferenceNative(referenceIndex);
|
||||||
|
} catch (Throwable t)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reference = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createStrongReference(Object object)
|
||||||
|
{
|
||||||
|
reference = object;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createSoftReference(Object object)
|
||||||
|
{
|
||||||
|
reference = new SoftReference<Object>(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createWeakReference(Object object)
|
||||||
|
{
|
||||||
|
reference = new WeakReference<Object>(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createPhantomReference(Object object)
|
||||||
|
{
|
||||||
|
reference = new PhantomReference<Object>(object, new ReferenceQueue<Object>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createJNIGlobalReference(Object object)
|
||||||
|
{
|
||||||
|
referenceIndex = createJNIGlobalReferenceNative(object, maxJNIGlobalReferences);
|
||||||
|
|
||||||
|
if(referenceIndex < 0)
|
||||||
|
{
|
||||||
|
throw new TestBug("Error on creation of JNI_Global reference, Possible number of JNI_Global references exceeded max available value!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since jni local reference valid only for duration of native method call, to create jni local reference
|
||||||
|
* special thread is created which enter in native method, create jni local reference and wait
|
||||||
|
*/
|
||||||
|
private void createJNILocalReference(Object object)
|
||||||
|
{
|
||||||
|
this.reference = object;
|
||||||
|
|
||||||
|
jniLocalReferenceThread = new JNILocalReferenceThread();
|
||||||
|
jniLocalReferenceThread.start();
|
||||||
|
|
||||||
|
// wait till JNI local reference will be created
|
||||||
|
jniLocalReferenceThread.createWhicket.waitFor();
|
||||||
|
|
||||||
|
reference = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteJNILocalReference()
|
||||||
|
{
|
||||||
|
// notify JNI method that JNI local reference is not needed any more and could be released
|
||||||
|
jniLocalReferenceThread.deleteWhicket.unlock();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
jniLocalReferenceThread.join(1000 * 60 * 2);
|
||||||
|
|
||||||
|
if(jniLocalReferenceThread.isAlive())
|
||||||
|
{
|
||||||
|
throw new TestBug("JNI_Local_Reference thread can't finish execution");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(InterruptedException e)
|
||||||
|
{
|
||||||
|
throw new TestBug("deleteJNILocalReference was interrupted");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createJNIWeakReference(Object object)
|
||||||
|
{
|
||||||
|
referenceIndex = createJNIWeakReferenceNative(object, maxJNIWeakReferences);
|
||||||
|
|
||||||
|
if(referenceIndex < 0)
|
||||||
|
{
|
||||||
|
throw new TestBug("Error on creation of JNI_Weak reference. Possible number of JNI_Weak references exceeded max available value!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class JNILocalReferenceThread
|
||||||
|
extends Thread
|
||||||
|
{
|
||||||
|
Wicket createWhicket = new Wicket();
|
||||||
|
Wicket deleteWhicket = new Wicket();
|
||||||
|
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
createJNILocalReferenceNative(reference, createWhicket, deleteWhicket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private JNILocalReferenceThread jniLocalReferenceThread;
|
||||||
|
|
||||||
|
private native int createJNIGlobalReferenceNative(Object object, int maxJNIGlobalReferences);
|
||||||
|
|
||||||
|
private native void deleteJNIGlobalReferenceNative(int index);
|
||||||
|
|
||||||
|
private native void createJNILocalReferenceNative(Object object, Wicket createWhicket, Wicket deleteWhicket);
|
||||||
|
|
||||||
|
private native int createJNIWeakReferenceNative(Object object, int maxJNIWeakReferences);
|
||||||
|
|
||||||
|
private native void deleteJNIWeakReferenceNative(int index);
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006, 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.share;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class create a number of referrers to given object
|
||||||
|
*/
|
||||||
|
public class ReferringObjectSet
|
||||||
|
{
|
||||||
|
private Collection<ReferringObject> referringObjects;
|
||||||
|
private String referenceType;
|
||||||
|
|
||||||
|
public ReferringObjectSet(Object object, int referringCount, String referenceType)
|
||||||
|
{
|
||||||
|
this.referenceType = referenceType;
|
||||||
|
referringObjects = new ArrayList<ReferringObject>(referringCount);
|
||||||
|
|
||||||
|
for(int i = 0; i < referringCount; i++)
|
||||||
|
referringObjects.add(new ReferringObject(object, referenceType));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete(int count)
|
||||||
|
{
|
||||||
|
if((count < 0) || (count > referringObjects.size()))
|
||||||
|
{
|
||||||
|
throw new TestBug("Invalid 'count' value: " + count + ", size=" + referringObjects.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<ReferringObject> iterator = referringObjects.iterator();
|
||||||
|
|
||||||
|
for(int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
ReferringObject referringObject = iterator.next();
|
||||||
|
referringObject.delete();
|
||||||
|
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteAll()
|
||||||
|
{
|
||||||
|
delete(referringObjects.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReferenceType() {
|
||||||
|
return referenceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getReferrerCount()
|
||||||
|
{
|
||||||
|
return referringObjects.size();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2008, 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.share;
|
||||||
|
|
||||||
|
public class StringGoldChecker extends AbstractGoldChecker {
|
||||||
|
|
||||||
|
private final String goldenString;
|
||||||
|
|
||||||
|
public StringGoldChecker(String goldenString) {
|
||||||
|
this.goldenString = goldenString;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getGoldenString() {
|
||||||
|
return goldenString;
|
||||||
|
}
|
||||||
|
}
|
46
test/hotspot/jtreg/vmTestbase/nsk/share/TestBug.java
Normal file
46
test/hotspot/jtreg/vmTestbase/nsk/share/TestBug.java
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2001, 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.share;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when it becomes obvious that the test algorithm
|
||||||
|
* works incorrectly (for example - tries to write to debugee's
|
||||||
|
* stdin after it is already redirected, or something of the
|
||||||
|
* kind).
|
||||||
|
*/
|
||||||
|
public class TestBug extends Failure {
|
||||||
|
/** Explain particular failure. */
|
||||||
|
public TestBug(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Enwrap another throwable. */
|
||||||
|
public TestBug(Throwable throwable) {
|
||||||
|
super(throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestBug(String message, Throwable throwable) {
|
||||||
|
super(message, throwable);
|
||||||
|
}
|
||||||
|
}
|
41
test/hotspot/jtreg/vmTestbase/nsk/share/TestFailure.java
Normal file
41
test/hotspot/jtreg/vmTestbase/nsk/share/TestFailure.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share;
|
||||||
|
|
||||||
|
public class TestFailure extends RuntimeException {
|
||||||
|
public TestFailure() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestFailure(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestFailure(String message, Throwable e) {
|
||||||
|
super(message, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestFailure(Throwable e) {
|
||||||
|
super(e);
|
||||||
|
}
|
||||||
|
}
|
32
test/hotspot/jtreg/vmTestbase/nsk/share/TestJNIError.java
Normal file
32
test/hotspot/jtreg/vmTestbase/nsk/share/TestJNIError.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006, 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.share;
|
||||||
|
|
||||||
|
public class TestJNIError
|
||||||
|
extends Error
|
||||||
|
{
|
||||||
|
public TestJNIError(String message)
|
||||||
|
{
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
60
test/hotspot/jtreg/vmTestbase/nsk/share/TimeoutHandler.java
Normal file
60
test/hotspot/jtreg/vmTestbase/nsk/share/TimeoutHandler.java
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2001, 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.share;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class can be used to set timeout for test execution.
|
||||||
|
*/
|
||||||
|
public class TimeoutHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test execution timeout in minutes.
|
||||||
|
*/
|
||||||
|
private int waitTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make new <code>TimeoutHandler</code> object for timeout value
|
||||||
|
* specified in command line arguments.
|
||||||
|
*/
|
||||||
|
public TimeoutHandler(ArgumentParser argumentHandler) {
|
||||||
|
this.waitTime = argumentHandler.getWaitTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform test execution in separate thread and wait for
|
||||||
|
* thread finishes or timeout exceeds.
|
||||||
|
*/
|
||||||
|
public void runTest(Thread testThread) {
|
||||||
|
long millisec = waitTime * 60 * 1000;
|
||||||
|
testThread.start();
|
||||||
|
try {
|
||||||
|
testThread.join(millisec);
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
throw new Failure(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
175
test/hotspot/jtreg/vmTestbase/nsk/share/TreeNodesDenotation.java
Normal file
175
test/hotspot/jtreg/vmTestbase/nsk/share/TreeNodesDenotation.java
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2002, 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.share;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This denotation provides naming and indexing for nodes
|
||||||
|
* of a binary, or ternary, or <tt>n</tt>-ary tree.
|
||||||
|
*
|
||||||
|
* <p>Here, <tt>n</tt> would be the length of a symbols
|
||||||
|
* string used as an alphabeth for nodes naming. For a
|
||||||
|
* binary tree, <tt>n=2</tt>, and an aplhabeth could be
|
||||||
|
* the <tt>"LR"</tt> string. This implies the following
|
||||||
|
* naming for tree nodes:
|
||||||
|
* <pre>
|
||||||
|
* (empty)
|
||||||
|
* / \
|
||||||
|
* L R
|
||||||
|
* / \ / \
|
||||||
|
* LL LR RL RR
|
||||||
|
* / \ / \ / \ / \
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* <p>Anyway, the tree root node is named with the empty
|
||||||
|
* string <tt>""</tt> and is indexed with 2-zeroes array
|
||||||
|
* <tt>{0,0}</tt>.
|
||||||
|
*
|
||||||
|
* <p>Index for a tree node is 2-elements <tt>int[]</tt>
|
||||||
|
* array. The 1st element is the node's level in a tree.
|
||||||
|
* The 2nd element is the item's number among all nodes of
|
||||||
|
* that level; provided that node items are enumerated from
|
||||||
|
* <tt>0</tt> to <tt>n</tt><sup>level</sup><tt>-1</tt>.
|
||||||
|
* Given a level, lexicographic order is assumed for the
|
||||||
|
* nodes of the same level.
|
||||||
|
*
|
||||||
|
* <p>For example: given the above sample tree, the node
|
||||||
|
* <tt>"L"</tt> has the index <tt>{1,0}</tt>, while the
|
||||||
|
* node <tt>"RL"</tt> has the index <tt>{2,2}</tt>.
|
||||||
|
*
|
||||||
|
* <p>In general case, ordering of characters used for nodes
|
||||||
|
* naming is implied by the given alphabeth. This may differ
|
||||||
|
* from the ``natural'' ordering. For example, if alphabeth
|
||||||
|
* is <tt>"ZYX...CBA"</tt>, then ordering for nodes would be
|
||||||
|
* opposite to ``natural''.
|
||||||
|
*/
|
||||||
|
public class TreeNodesDenotation extends Denotation {
|
||||||
|
/**
|
||||||
|
* Symbols to denote tree nodes.
|
||||||
|
*
|
||||||
|
* @see #TreeNodeDenotation(String)
|
||||||
|
*/
|
||||||
|
private String alphabeth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standard denotation for a binary tree; alphabeth
|
||||||
|
* is <tt>"LR"</tt>.
|
||||||
|
*
|
||||||
|
* @see #TreeNodesDenotation(String)
|
||||||
|
*/
|
||||||
|
public TreeNodesDenotation() {
|
||||||
|
this("LR");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Denotation for nodes of a tree.
|
||||||
|
*
|
||||||
|
* <p>Each tree node is marked with a string of symbols
|
||||||
|
* from the given <tt>alphabeth</tt>. A string length
|
||||||
|
* equals to the node's level. The root node is always
|
||||||
|
* denoted with the empty string.
|
||||||
|
*
|
||||||
|
* <p>For example, an <tt>alphabeth</tt> for a binary
|
||||||
|
* tree could be <tt>"LR"</tt>, or <tt>"01"</tt>, or
|
||||||
|
* any 2-symbols string. However, <tt>"lL"</tt> or
|
||||||
|
* <tt>"rR"</tt> would be illegal because of collision
|
||||||
|
* between upper- and lower- case letters.
|
||||||
|
*
|
||||||
|
* <p>In general case, it is illegal for <tt>alphabeth</tt>
|
||||||
|
* to contain two or several copies of the same symbol.
|
||||||
|
* This constructor deems lower- and upper-case variants
|
||||||
|
* of the same letter are the same symbol.
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException If the <tt>alphabeth</tt>
|
||||||
|
* looks illegal.
|
||||||
|
*/
|
||||||
|
public TreeNodesDenotation(String alphabeth) {
|
||||||
|
if (alphabeth.length() == 0)
|
||||||
|
throw new IllegalArgumentException("empty alphabeth");
|
||||||
|
// Check for lower- to upper- case collision:
|
||||||
|
this.alphabeth = alphabeth.toUpperCase();
|
||||||
|
int length = this.alphabeth.length();
|
||||||
|
Set<Character> pool = new HashSet<Character>(); // still empty
|
||||||
|
for (int i=0; i<length; i++)
|
||||||
|
pool.add(new Character(this.alphabeth.charAt(i)));
|
||||||
|
if (pool.size() != length)
|
||||||
|
throw new IllegalArgumentException("collision: " + alphabeth);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the <tt>name</tt> is legal, and return the
|
||||||
|
* numeric index for the tree node denoted by the given
|
||||||
|
* <tt>name</tt>.
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException If the <tt>name</tt>
|
||||||
|
* is illegal.
|
||||||
|
*/
|
||||||
|
public int[] indexFor(String name) {
|
||||||
|
int level = name.length();
|
||||||
|
int factor = alphabeth.length();
|
||||||
|
long item = 0;
|
||||||
|
for (int i=0; i<level; i++) {
|
||||||
|
char symbol = Character.toUpperCase(name.charAt(i));
|
||||||
|
int position = alphabeth.indexOf(symbol);
|
||||||
|
if (position < 0)
|
||||||
|
throw new IllegalArgumentException("unknown symbol: " + name);
|
||||||
|
item = item*factor + position;
|
||||||
|
if (item < 0 || item > Integer.MAX_VALUE)
|
||||||
|
throw new IllegalArgumentException("too long name: " + name);
|
||||||
|
};
|
||||||
|
int[] index = new int [] { level, (int)item };
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the <tt>index[]</tt> is legal, and return
|
||||||
|
* a symbolic name for the tree node denoted by the
|
||||||
|
* given <tt>index[]</tt>.
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException If the <tt>index[]</tt>
|
||||||
|
* is illegal.
|
||||||
|
*/
|
||||||
|
public String nameFor(int[] index) {
|
||||||
|
if (index.length != 2)
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"index dimention: " + index.length);
|
||||||
|
StringBuffer name = new StringBuffer(); // still empty
|
||||||
|
int level = index[0];
|
||||||
|
int item = index[1];
|
||||||
|
if (level < 0 || item < 0)
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"negative index: " + level + ", " + item);
|
||||||
|
int factor = alphabeth.length();
|
||||||
|
for (int i=0; i<level; i++) {
|
||||||
|
int k = item % factor;
|
||||||
|
name.append(alphabeth.charAt(k));
|
||||||
|
item = item / factor;
|
||||||
|
};
|
||||||
|
if (item != 0)
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"out of range: {"+ index[0] + "," + index[1] + "}");
|
||||||
|
return new String(name.reverse());
|
||||||
|
}
|
||||||
|
}
|
229
test/hotspot/jtreg/vmTestbase/nsk/share/Wicket.java
Normal file
229
test/hotspot/jtreg/vmTestbase/nsk/share/Wicket.java
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wicket provides a means for one or more threads to suspend execution
|
||||||
|
* (to wait) until notified by one or more other threads that some set
|
||||||
|
* of locks is now open.
|
||||||
|
*
|
||||||
|
* <p>Wicket instances are intended to be used generally in the following
|
||||||
|
* scenarios:
|
||||||
|
*
|
||||||
|
* <ul><li>One thread starts one or more child threads and waits until the
|
||||||
|
* child threads to be started.
|
||||||
|
*
|
||||||
|
* <li>One thread starts one or more child threads and waits until at least
|
||||||
|
* one of the child threads to be started.
|
||||||
|
*
|
||||||
|
* <li>One or more child threads wait until a main thread lets them
|
||||||
|
* to finish.
|
||||||
|
*
|
||||||
|
* <li>Disable the current thread for thread scheduling purposes, for up to
|
||||||
|
* the specified waiting time.</ul>
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Wicket {
|
||||||
|
|
||||||
|
/** Number of closed locks, can be greater or equal to zero */
|
||||||
|
private int count;
|
||||||
|
|
||||||
|
/** Number of waiters **/
|
||||||
|
private int waiters = 0;
|
||||||
|
|
||||||
|
/** Enable debug output */
|
||||||
|
private PrintStream debugOutput = null;
|
||||||
|
|
||||||
|
/** Wicket's string identifier */
|
||||||
|
private String name = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a Wicket with only one closed lock.
|
||||||
|
*/
|
||||||
|
public Wicket() {
|
||||||
|
this(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a Wicket with the given number of closed locks.
|
||||||
|
*
|
||||||
|
* @param _name Wicket's identifier
|
||||||
|
* @param _count the initial number of closed locks
|
||||||
|
* @param _debugOutput whether to print debug info or not
|
||||||
|
* @throws IllegalArgumentException if count is less than 1
|
||||||
|
*/
|
||||||
|
public Wicket(String _name, int _count, PrintStream _debugOutput) {
|
||||||
|
this(_count);
|
||||||
|
name = _name;
|
||||||
|
debugOutput = _debugOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a Wicket with the given number of closed locks.
|
||||||
|
*
|
||||||
|
* @param count the initial number of closed locks
|
||||||
|
* @throws IllegalArgumentException if count is less than 1
|
||||||
|
*/
|
||||||
|
public Wicket(int count) {
|
||||||
|
if (count < 1)
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"count is less than one: " + count);
|
||||||
|
this.count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for all locks of this Wicket to be open.
|
||||||
|
*
|
||||||
|
* <p>If all locks are already open then returns immediately.
|
||||||
|
*
|
||||||
|
* <p>If at least one lock is still closed then the current thread becomes
|
||||||
|
* disabled for thread scheduling purposes and lies dormant until all
|
||||||
|
* the locks will be open by some other threads. One lock can be open
|
||||||
|
* by invoking the unlock method for this Wicket.
|
||||||
|
*
|
||||||
|
* <p>Please note, that the method would ignore Thread.interrupt() requests.
|
||||||
|
*/
|
||||||
|
public synchronized void waitFor() {
|
||||||
|
++waiters;
|
||||||
|
if (debugOutput != null) {
|
||||||
|
debugOutput.printf("Wicket %s: waitFor()\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (count > 0) {
|
||||||
|
try {
|
||||||
|
wait();
|
||||||
|
} catch (InterruptedException e) {}
|
||||||
|
}
|
||||||
|
--waiters;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for all locks of this Wicket to be open within the given
|
||||||
|
* period of time.
|
||||||
|
*
|
||||||
|
* <p>If all locks are already open then returns immediately with zero.
|
||||||
|
*
|
||||||
|
* <p>If the time is equal to zero, the method will not
|
||||||
|
* wait and returns a number of closed locks,
|
||||||
|
* if all locks are open, the return value is zero.
|
||||||
|
*
|
||||||
|
* <p>If at least one lock is still closed then the current thread becomes
|
||||||
|
* disabled for thread scheduling purposes and lies dormant until
|
||||||
|
* of the two things happens:
|
||||||
|
*
|
||||||
|
* <ul><li>Some other threads invoke the unlock method for this Wicket
|
||||||
|
* to open all the closed locks; or
|
||||||
|
*
|
||||||
|
* <li>The specified waiting time elapses.</ul>
|
||||||
|
*
|
||||||
|
* <p>If all locks are open then the return value is 0.
|
||||||
|
*
|
||||||
|
* <p>If the specified waiting time elapses and some locks are still closed
|
||||||
|
* then the return value is equal to number of closed locks.
|
||||||
|
*
|
||||||
|
* <p>Please note, that the method would ignore Thread.interrupt() requests.
|
||||||
|
*
|
||||||
|
* @param timeout the maximum time to wait in milliseconds
|
||||||
|
* @return the number of closed locks
|
||||||
|
* @throws IllegalArgumentException if timeout is less than 0
|
||||||
|
*/
|
||||||
|
public synchronized int waitFor(long timeout) {
|
||||||
|
if (debugOutput != null) {
|
||||||
|
debugOutput.printf("Wicket %s: waitFor(%d)\n", name, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeout < 0)
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"timeout value is negative: " + timeout);
|
||||||
|
++waiters;
|
||||||
|
long waitTime = timeout;
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
while (count > 0 && waitTime > 0) {
|
||||||
|
try {
|
||||||
|
wait(waitTime);
|
||||||
|
} catch (InterruptedException e) {}
|
||||||
|
waitTime = timeout - (System.currentTimeMillis() - startTime);
|
||||||
|
}
|
||||||
|
--waiters;
|
||||||
|
return (count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlock one closed lock.
|
||||||
|
*
|
||||||
|
* <p>Open a lock, reducing the number of closed locks by one.
|
||||||
|
*
|
||||||
|
* <p>If last closed lock is opened then all of the threads waiting
|
||||||
|
* by invoking the waitFor method for this Wicket will be released
|
||||||
|
* and re-enabled for thread scheduling purposes.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException if there is no one closed lock
|
||||||
|
*/
|
||||||
|
public synchronized void unlock() {
|
||||||
|
if (debugOutput != null) {
|
||||||
|
debugOutput.printf("Wicket %s: unlock()\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
throw new IllegalStateException("locks are already open");
|
||||||
|
|
||||||
|
--count;
|
||||||
|
if (count == 0) {
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlock all closed locks.
|
||||||
|
*
|
||||||
|
* <p>Open all closed locks, setting the number of closed locks to zero.
|
||||||
|
*
|
||||||
|
* <p>If any threads are waiting by invoking the waitFor method for
|
||||||
|
* this Wicket then they will be released and re-enabled for thread
|
||||||
|
* scheduling purposes.
|
||||||
|
*/
|
||||||
|
public synchronized void unlockAll() {
|
||||||
|
if (debugOutput != null) {
|
||||||
|
debugOutput.printf("Wicket %s: unlockAll()\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return current number of waiters - threads that are currently
|
||||||
|
* waiting using one of waitFor methods.
|
||||||
|
*
|
||||||
|
* @return number of waiters
|
||||||
|
*/
|
||||||
|
public synchronized int getWaiters() {
|
||||||
|
if (debugOutput != null) {
|
||||||
|
debugOutput.printf("Wicket %s: getWaiters()\n", name);
|
||||||
|
}
|
||||||
|
return waiters;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2008, 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.share.aod;
|
||||||
|
|
||||||
|
import nsk.share.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class AODRunnerArgParser extends ArgumentParser {
|
||||||
|
|
||||||
|
public static final String jarAgentParam = "ja";
|
||||||
|
|
||||||
|
public static final String nativeAgentParam = "na";
|
||||||
|
|
||||||
|
public static final String targetAppParam = "target";
|
||||||
|
|
||||||
|
public static final String javaOptsParam = "javaOpts";
|
||||||
|
|
||||||
|
public static final String testedJdkParam = "jdk";
|
||||||
|
|
||||||
|
private static List<String> supportedOptions;
|
||||||
|
|
||||||
|
static {
|
||||||
|
supportedOptions = new ArrayList<String>();
|
||||||
|
supportedOptions.add(jarAgentParam);
|
||||||
|
supportedOptions.add(nativeAgentParam);
|
||||||
|
supportedOptions.add(targetAppParam);
|
||||||
|
supportedOptions.add(javaOptsParam);
|
||||||
|
supportedOptions.add(testedJdkParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<AgentInformation> agents;
|
||||||
|
|
||||||
|
public AODRunnerArgParser(String[] args) {
|
||||||
|
super(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean checkOption(String option, String value) {
|
||||||
|
if (super.checkOption(option, value))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!supportedOptions.contains(option))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (option.equals(jarAgentParam)) {
|
||||||
|
addAgentInfo(true, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option.equals(nativeAgentParam)) {
|
||||||
|
addAgentInfo(false, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void checkOptions() {
|
||||||
|
if (agents == null) {
|
||||||
|
agents = new ArrayList<AgentInformation>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addAgentInfo(boolean jarAgent, String unsplittedAgentsString) {
|
||||||
|
if (agents == null) {
|
||||||
|
agents = new ArrayList<AgentInformation>();
|
||||||
|
}
|
||||||
|
|
||||||
|
String agentStrings[];
|
||||||
|
|
||||||
|
if (unsplittedAgentsString.contains(","))
|
||||||
|
agentStrings = unsplittedAgentsString.split(",");
|
||||||
|
else
|
||||||
|
agentStrings = new String[]{unsplittedAgentsString};
|
||||||
|
|
||||||
|
for (String agentString : agentStrings) {
|
||||||
|
int index = agentString.indexOf('=');
|
||||||
|
|
||||||
|
if (index > 0) {
|
||||||
|
String pathToAgent = agentString.substring(0, index);
|
||||||
|
String options = agentString.substring(index + 1);
|
||||||
|
agents.add(new AgentInformation(jarAgent, pathToAgent, options));
|
||||||
|
} else {
|
||||||
|
agents.add(new AgentInformation(jarAgent, agentString, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTargetApp() {
|
||||||
|
if (!options.containsKey(targetAppParam))
|
||||||
|
throw new TestBug("Target application isn't specified");
|
||||||
|
|
||||||
|
return options.getProperty(targetAppParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTestedJDK() {
|
||||||
|
if (!options.containsKey(testedJdkParam))
|
||||||
|
throw new TestBug("Tested JDK isn't specified");
|
||||||
|
|
||||||
|
return options.getProperty(testedJdkParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJavaOpts() {
|
||||||
|
return options.getProperty(javaOptsParam, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AgentInformation> getAgents() {
|
||||||
|
return agents;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2008, 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.share.aod;
|
||||||
|
|
||||||
|
import nsk.share.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class AODTargetArgParser extends ArgumentParser {
|
||||||
|
|
||||||
|
public static final String agentsNumberParam = "agentsNumber";
|
||||||
|
|
||||||
|
public static final String socketPortParam = "port";
|
||||||
|
|
||||||
|
private int expectedAgentsNumber;
|
||||||
|
|
||||||
|
private int port;
|
||||||
|
|
||||||
|
private static List<String> supportedOptions;
|
||||||
|
|
||||||
|
static {
|
||||||
|
supportedOptions = new ArrayList<String>();
|
||||||
|
supportedOptions.add(agentsNumberParam);
|
||||||
|
supportedOptions.add(socketPortParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AODTargetArgParser(String[] args) {
|
||||||
|
super(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean checkOption(String option, String value) {
|
||||||
|
if (super.checkOption(option, value))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!supportedOptions.contains(option))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (option.equals(agentsNumberParam)) {
|
||||||
|
expectedAgentsNumber = Integer.parseInt(value);
|
||||||
|
if (expectedAgentsNumber < 0)
|
||||||
|
throw new TestBug("Invalid value of '" + option + "'");
|
||||||
|
} else if (option.equals(socketPortParam)) {
|
||||||
|
port = Integer.parseInt(value);
|
||||||
|
if (port <= 0 || port > 65535)
|
||||||
|
throw new TestBug("Invalid value of '" + option + "':" + port +" (it is expected to be in the range [1..65535]");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getExpectedAgentsNumber() {
|
||||||
|
if (!options.containsKey(agentsNumberParam))
|
||||||
|
throw new TestBug("Number of expected agents isn't specified");
|
||||||
|
|
||||||
|
return expectedAgentsNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPort() {
|
||||||
|
if (!options.containsKey(socketPortParam))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
}
|
186
test/hotspot/jtreg/vmTestbase/nsk/share/aod/AODTestRunner.java
Normal file
186
test/hotspot/jtreg/vmTestbase/nsk/share/aod/AODTestRunner.java
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2008, 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.share.aod;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import nsk.share.*;
|
||||||
|
import nsk.share.jpda.SocketIOPipe;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Class AODTestRunner is part of the framework used in the AttachOnDemand tests
|
||||||
|
(tests against Attach API, API from package com.sun.tools.attach).
|
||||||
|
|
||||||
|
AODTestRunner is used as main class in AttachOnDemand tests, it performs following
|
||||||
|
actions:
|
||||||
|
- starts target application
|
||||||
|
|
||||||
|
- finds VM id for target VM (this id is needed for dynamic attach)
|
||||||
|
|
||||||
|
- by default AODTestRunner tries to attach specified via command line agents to target VM
|
||||||
|
(subclasses can override this default behavior)
|
||||||
|
|
||||||
|
- waits for target application completion
|
||||||
|
|
||||||
|
Target application class, agents that should be attached, JDK used to run target application and
|
||||||
|
VM options passed to target VM should be specified via command line.
|
||||||
|
*/
|
||||||
|
public class AODTestRunner {
|
||||||
|
|
||||||
|
public static final String targetAppIdProperty = "vmsqe.aod.targetAppId";
|
||||||
|
public static final String appIdProperty = "vmsqe.aod.AppId";
|
||||||
|
|
||||||
|
public static final long TARGET_APP_CONNECT_TIMEOUT = 5 * 60 * 1000; // 5 min
|
||||||
|
|
||||||
|
public static final long TARGET_APP_WORK_TIMEOUT = 30 * 60 * 1000; // 30 min (standard VM testbase test timeout)
|
||||||
|
|
||||||
|
protected Log log;
|
||||||
|
|
||||||
|
protected SocketIOPipe pipe;
|
||||||
|
|
||||||
|
protected ProcessExecutor targetAppExecutor;
|
||||||
|
|
||||||
|
// target application ready for attach
|
||||||
|
public static final String SIGNAL_READY_FOR_ATTACH = "ready";
|
||||||
|
|
||||||
|
// target application may finish execution
|
||||||
|
public static final String SIGNAL_FINISH = "finish";
|
||||||
|
|
||||||
|
protected AODRunnerArgParser argParser;
|
||||||
|
|
||||||
|
protected AODTestRunner(String[] args) {
|
||||||
|
log = new Log(System.out, true);
|
||||||
|
|
||||||
|
argParser = createArgParser(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This method is introduced to let subclasses to create its own parsers
|
||||||
|
*/
|
||||||
|
protected AODRunnerArgParser createArgParser(String[] args) {
|
||||||
|
return new AODRunnerArgParser(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doTestActions(String targetVMId) throws Throwable {
|
||||||
|
AgentsAttacher attacher = new AgentsAttacher(targetVMId, argParser.getAgents(), log);
|
||||||
|
attacher.attachAgents();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getCurrentVMId() {
|
||||||
|
String currentVMId = "" + ProcessHandle.current().pid();
|
||||||
|
log.display("Current VM id was identified: " + currentVMId);
|
||||||
|
|
||||||
|
return currentVMId;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void runTest() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
String targetAppId = System.getProperty(targetAppIdProperty);
|
||||||
|
if(targetAppId == null || targetAppId.isEmpty()) {
|
||||||
|
// use PID as default appID
|
||||||
|
targetAppId = "" + ProcessHandle.current().pid();
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Create target application id required by the Utils.findVMIdUsingJPS
|
||||||
|
*/
|
||||||
|
String targetAppCmd =
|
||||||
|
// path to java
|
||||||
|
argParser.getTestedJDK() + File.separator + "bin" + File.separator + "java " +
|
||||||
|
// VM property to identify VM running target application
|
||||||
|
"-D" + appIdProperty + "=" + targetAppId + " " +
|
||||||
|
// VM opts
|
||||||
|
argParser.getJavaOpts() + " -XX:+EnableDynamicAgentLoading " +
|
||||||
|
// target application class
|
||||||
|
argParser.getTargetApp() + " " +
|
||||||
|
// additional target application parameter - number of
|
||||||
|
// agents that will be attached
|
||||||
|
"-" + AODTargetArgParser.agentsNumberParam + " " + argParser.getAgents().size();
|
||||||
|
|
||||||
|
pipe = SocketIOPipe.createServerIOPipe(log, 0, TARGET_APP_CONNECT_TIMEOUT);
|
||||||
|
targetAppCmd += " -" + AODTargetArgParser.socketPortParam + " " + pipe.getPort();
|
||||||
|
|
||||||
|
log.display("Starting target application: " + targetAppCmd);
|
||||||
|
targetAppExecutor = new ProcessExecutor(targetAppCmd, TARGET_APP_WORK_TIMEOUT, "TargetApp");
|
||||||
|
targetAppExecutor.startProcess();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't try to attach agents until target application isn't initialized
|
||||||
|
*/
|
||||||
|
String signal = pipe.readln();
|
||||||
|
log.display("Signal received: '" + signal + "'");
|
||||||
|
if ((signal == null) || !signal.equals(SIGNAL_READY_FOR_ATTACH))
|
||||||
|
throw new TestBug("Unexpected TargetApplication signal: '" + signal + "'");
|
||||||
|
|
||||||
|
String targetVMId = Long.toString(targetAppExecutor.pid());
|
||||||
|
log.display("Target VM id was identified: " + targetVMId);
|
||||||
|
|
||||||
|
doTestActions(targetVMId);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When test actions finished let target application finish execution
|
||||||
|
*/
|
||||||
|
log.display("Sending signal: '" + SIGNAL_FINISH + "'");
|
||||||
|
pipe.println(SIGNAL_FINISH);
|
||||||
|
|
||||||
|
targetAppExecutor.waitForProcess();
|
||||||
|
|
||||||
|
File file = new File(targetAppId);
|
||||||
|
if (file.exists()) {
|
||||||
|
file.deleteOnExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetAppExecutor.getExitCode() != 0) {
|
||||||
|
throw new Failure("Target application finished with non-zero code " + targetAppExecutor.getExitCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
postTargetExitHook();
|
||||||
|
|
||||||
|
} catch (Failure f) {
|
||||||
|
throw f;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
throw new Failure("Unexpected exception during test execution: " + t, t);
|
||||||
|
} finally {
|
||||||
|
if (pipe != null) {
|
||||||
|
pipe.close();
|
||||||
|
}
|
||||||
|
if (targetAppExecutor != null) {
|
||||||
|
targetAppExecutor.destroyProcess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allow users of this class to specify actions to be taken after the target exits
|
||||||
|
*/
|
||||||
|
protected void postTargetExitHook() {
|
||||||
|
// do nothing by default
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String createApplicationId() {
|
||||||
|
return new Long(System.currentTimeMillis()).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new AODTestRunner(args).runTest();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,257 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2008, 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.share.aod;
|
||||||
|
|
||||||
|
import java.lang.instrument.*;
|
||||||
|
import java.io.*;
|
||||||
|
import nsk.share.*;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
AbstractJarAgent is base class for java agents used in AttachOnDemand tests
|
||||||
|
(tests against Attach API, API from package com.sun.tools.attach).
|
||||||
|
|
||||||
|
In all AttachOnDemand tests the same algorithm is used:
|
||||||
|
- java application where agent is loaded to (target application) based on
|
||||||
|
class nsk.share.aod.TargetApplicationWaitingAgents starts and waits when
|
||||||
|
test agents will be loaded
|
||||||
|
|
||||||
|
- special application (nsk.share.jvmti.aod.AgentsAttacher) loads test agents
|
||||||
|
in the target application using Attach API
|
||||||
|
|
||||||
|
- when agent is loaded it notifies target application about that and executes
|
||||||
|
test-specific actions. When agent execution is completed it also notifies
|
||||||
|
target application about that
|
||||||
|
|
||||||
|
- when all test agents finish execution target application checks its status
|
||||||
|
(passed or failed) and also finishes
|
||||||
|
|
||||||
|
Each java agent should have method 'agentmain' where only agent initialization should be done,
|
||||||
|
main agent's actions should be executed in special thread started from 'agentmain'.
|
||||||
|
Class AbstractJarAgent incapsulates actions common for all java agents: agent initialization,
|
||||||
|
starting thread executing agent's actions and communication with target application.
|
||||||
|
|
||||||
|
In most cases test agents should override only method 'agentActions' and its 'agentmain'
|
||||||
|
should contain only call of the method 'AbstractJarAgent.runJarAgent'.
|
||||||
|
|
||||||
|
Typical agent class looks like this:
|
||||||
|
|
||||||
|
public class agentExample extends AbstractJarAgent {
|
||||||
|
|
||||||
|
protected void init(String[] args) {
|
||||||
|
// parse agent's options and do test-specific initialization
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void agentActions() {
|
||||||
|
// do test specific actions
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void agentmain(final String options, Instrumentation inst) {
|
||||||
|
new agentExample().runJarAgent(options, inst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
abstract public class AbstractJarAgent {
|
||||||
|
|
||||||
|
private boolean finishedSuccessfully = true;
|
||||||
|
|
||||||
|
private Log log;
|
||||||
|
|
||||||
|
protected void display(String message) {
|
||||||
|
log.display(outputPrefix + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void complain(String message) {
|
||||||
|
log.complain(outputPrefix + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void logThrowable(Throwable t) {
|
||||||
|
t.printStackTrace(log.getOutStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Instrumentation object passed to the 'agentmain' method
|
||||||
|
*/
|
||||||
|
protected Instrumentation inst;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String outputPrefix;
|
||||||
|
|
||||||
|
private String pathToNewByteCode;
|
||||||
|
|
||||||
|
protected String pathToNewByteCode() {
|
||||||
|
return pathToNewByteCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Subclasses should report about test failures using this method
|
||||||
|
*/
|
||||||
|
protected void setStatusFailed(String errorMessage) {
|
||||||
|
finishedSuccessfully = false;
|
||||||
|
complain("ERROR: " + errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialization method, called from agentmain before method agentActions is called
|
||||||
|
* (it introduced for overriding in subclasses)
|
||||||
|
*/
|
||||||
|
protected void init(String[] args) {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class AgentOption {
|
||||||
|
public String name;
|
||||||
|
public String value;
|
||||||
|
public AgentOption(String name, String value) {
|
||||||
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AgentOption parseAgentArgument(String arg) {
|
||||||
|
int index = arg.indexOf('=');
|
||||||
|
if (index <= 0) {
|
||||||
|
throw new TestBug("Invalid agent parameters format");
|
||||||
|
}
|
||||||
|
return new AgentOption(arg.substring(0, index), arg.substring(index + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static protected final String agentNameOption = "-agentName";
|
||||||
|
|
||||||
|
static protected final String pathToNewByteCodeOption = "-pathToNewByteCode";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse agent's options, initialize common parameters
|
||||||
|
*/
|
||||||
|
private void defaultInit(String[] args) {
|
||||||
|
for (int i = 0; i < args.length; i++) {
|
||||||
|
AgentOption option = parseAgentArgument(args[i]);
|
||||||
|
if (option.name.equals(agentNameOption)) {
|
||||||
|
name = option.value;
|
||||||
|
outputPrefix = name + ": ";
|
||||||
|
} else if (option.name.equals(pathToNewByteCodeOption)) {
|
||||||
|
pathToNewByteCode = option.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name == null)
|
||||||
|
throw new TestBug("Agent name wasn't specified");
|
||||||
|
|
||||||
|
log = new Log(System.out, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Special thread which is started from agentmain method and executing main
|
||||||
|
* agent's actions. When agent completes execution AgentThread notifies
|
||||||
|
* target application about that.
|
||||||
|
*/
|
||||||
|
class AgentThread extends Thread {
|
||||||
|
|
||||||
|
AgentThread() {
|
||||||
|
super("Jar agent thread (agent: " + name + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
agentActions();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
setStatusFailed("Unexpected exception in the JarAgent: " + t);
|
||||||
|
logThrowable(t);
|
||||||
|
} finally {
|
||||||
|
TargetApplicationWaitingAgents.agentFinished(name, finishedSuccessfully);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This methods parses agent's options, initializes agent, notifies target application
|
||||||
|
* that agent is started and starts thread executing main agent's actions.
|
||||||
|
* Agents used in AttachOnDemand tests should call this method from its agentmain methods.
|
||||||
|
*/
|
||||||
|
public final void runJarAgent(String options, Instrumentation inst) {
|
||||||
|
if (options == null)
|
||||||
|
throw new TestBug("Agent options weren't specified");
|
||||||
|
|
||||||
|
this.inst = inst;
|
||||||
|
|
||||||
|
String[] args = options.split(" ");
|
||||||
|
|
||||||
|
// initialize common parameters
|
||||||
|
defaultInit(args);
|
||||||
|
|
||||||
|
// test-specific initialization
|
||||||
|
init(args);
|
||||||
|
|
||||||
|
// notify target application that agent was loaded and initialized
|
||||||
|
TargetApplicationWaitingAgents.agentLoaded(name);
|
||||||
|
|
||||||
|
// start special thread executing test-specific actions
|
||||||
|
new AgentThread().start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Actions specific for test should be realized in this method.
|
||||||
|
* This method is called from special thread started from agentmain method
|
||||||
|
* after agent initialization
|
||||||
|
*/
|
||||||
|
abstract protected void agentActions() throws Throwable;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create ClassDefinition object for given class, path to the new class file
|
||||||
|
* is specified in the parameter 'pathToByteCode'
|
||||||
|
*/
|
||||||
|
protected static ClassDefinition createClassDefinition(Class<?> klass,
|
||||||
|
String pathToByteCode) throws IOException {
|
||||||
|
File classFile = new File(pathToByteCode + File.separator +
|
||||||
|
klass.getName().replace(".", File.separator) +
|
||||||
|
".class");
|
||||||
|
|
||||||
|
if (classFile.length() > Integer.MAX_VALUE)
|
||||||
|
throw new Failure("Class file '" + classFile.getName() + " 'too large");
|
||||||
|
|
||||||
|
byte data[] = new byte[(int)classFile.length()];
|
||||||
|
|
||||||
|
DataInputStream in = null;
|
||||||
|
try {
|
||||||
|
in = new DataInputStream(new FileInputStream(classFile));
|
||||||
|
in.readFully(data);
|
||||||
|
} finally {
|
||||||
|
if (in != null)
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ClassDefinition(klass, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Redefine given class using path to byte code specified with options -pathToNewByteCode
|
||||||
|
*/
|
||||||
|
protected void redefineClass(Class<?> klass) throws Throwable {
|
||||||
|
if (pathToNewByteCode() == null)
|
||||||
|
throw new TestBug("Path to new class files wasn't specified");
|
||||||
|
|
||||||
|
ClassDefinition newClassDef = createClassDefinition(klass, pathToNewByteCode());
|
||||||
|
inst.redefineClasses(newClassDef);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2008, 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.share.aod;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class contains information about dynamically attached agent
|
||||||
|
*/
|
||||||
|
public class AgentInformation {
|
||||||
|
|
||||||
|
// counters used for unique agent names generation
|
||||||
|
|
||||||
|
private static int jarAgentsCounter;
|
||||||
|
|
||||||
|
private static int nativeAgentsCounter;
|
||||||
|
|
||||||
|
public boolean jarAgent;
|
||||||
|
|
||||||
|
public String pathToAgent;
|
||||||
|
|
||||||
|
public String agentOptions;
|
||||||
|
|
||||||
|
public AgentInformation(boolean jarAgent, String pathToAgent, String options, boolean addAgentNameOption) {
|
||||||
|
this.jarAgent = jarAgent;
|
||||||
|
this.pathToAgent = pathToAgent;
|
||||||
|
this.agentOptions = options;
|
||||||
|
|
||||||
|
// add to agent options additional parameter - agent name (it used by nsk.share.aod framework)
|
||||||
|
|
||||||
|
String name;
|
||||||
|
|
||||||
|
if (jarAgent)
|
||||||
|
name = "JarAgent-" + jarAgentsCounter++;
|
||||||
|
else
|
||||||
|
name = "NativeAgent-" + nativeAgentsCounter++;
|
||||||
|
|
||||||
|
if (addAgentNameOption) {
|
||||||
|
if (this.agentOptions == null) {
|
||||||
|
this.agentOptions = "-agentName=" + name;
|
||||||
|
} else {
|
||||||
|
this.agentOptions += " -agentName=" + name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AgentInformation(boolean jarAgent, String pathToAgent, String options) {
|
||||||
|
this(jarAgent, pathToAgent, options, true);
|
||||||
|
}
|
||||||
|
}
|
137
test/hotspot/jtreg/vmTestbase/nsk/share/aod/AgentsAttacher.java
Normal file
137
test/hotspot/jtreg/vmTestbase/nsk/share/aod/AgentsAttacher.java
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2008, 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.share.aod;
|
||||||
|
|
||||||
|
import nsk.share.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
import com.sun.tools.attach.*;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This class loads java and native agents in the running VM using Attach API
|
||||||
|
* (API from package com.sun.tools.attach).
|
||||||
|
*/
|
||||||
|
public class AgentsAttacher {
|
||||||
|
|
||||||
|
protected String targetVMId;
|
||||||
|
|
||||||
|
protected List<AgentInformation> agents;
|
||||||
|
|
||||||
|
protected Log log;
|
||||||
|
|
||||||
|
public AgentsAttacher(String targetVMId, List<AgentInformation> agents, Log log) {
|
||||||
|
this.targetVMId = targetVMId;
|
||||||
|
this.agents = agents;
|
||||||
|
this.log = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void attachAgents() {
|
||||||
|
VirtualMachine vm = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
log.display("Trying to get VirtualMachine object");
|
||||||
|
vm = VirtualMachine.attach(targetVMId);
|
||||||
|
} catch (AttachNotSupportedException e) {
|
||||||
|
log.complain("Unexpected AttachNotSupportedException during VirtualMachine.attach: " + e);
|
||||||
|
e.printStackTrace(log.getOutStream());
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.complain("Unexpected IOException during VirtualMachine.attach: " + e);
|
||||||
|
e.printStackTrace(log.getOutStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm == null) {
|
||||||
|
failed("Unable to create VirtualMachine object");
|
||||||
|
}
|
||||||
|
|
||||||
|
log.display("VirtualMachine was created: " + vm);
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (AgentInformation agentInfo : agents) {
|
||||||
|
tryToLoadAgent(vm, agentInfo.pathToAgent, agentInfo.agentOptions, agentInfo.jarAgent);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
log.display("Detaching from the VM '" + vm + "'");
|
||||||
|
vm.detach();
|
||||||
|
} catch (IOException e) {
|
||||||
|
failed("Unexpected IOException during detaching: " + e, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void tryToLoadAgent(VirtualMachine vm, String agent, String agentOptions, boolean jarAgent) {
|
||||||
|
boolean agentLoaded = false;
|
||||||
|
|
||||||
|
Throwable failureCause = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (jarAgent) {
|
||||||
|
log.display("Trying to load jar agent: '" + agent + "' (agent options: '" + agentOptions + "')");
|
||||||
|
vm.loadAgent(agent, agentOptions);
|
||||||
|
} else {
|
||||||
|
log.display("Trying to load native agent: '" + agent + "' (agent options: '" + agentOptions + "')");
|
||||||
|
vm.loadAgentLibrary(agent, agentOptions);
|
||||||
|
}
|
||||||
|
log.display("Agent was loaded");
|
||||||
|
agentLoaded = true;
|
||||||
|
} catch (AgentLoadException e) {
|
||||||
|
failureCause = e;
|
||||||
|
log.complain("Unexpected AgentLoadException during agent loading: " + e);
|
||||||
|
if (jarAgent) {
|
||||||
|
log.complain("(probably the agent does not exist, or cannot be started in the manner specified in "
|
||||||
|
+ "the java.lang.instrument specification)");
|
||||||
|
} else {
|
||||||
|
log.complain("(probably agent library does not exist, or cannot be loaded for another reason)");
|
||||||
|
}
|
||||||
|
e.printStackTrace(log.getOutStream());
|
||||||
|
} catch (AgentInitializationException e) {
|
||||||
|
failureCause = e;
|
||||||
|
log.complain("Unexpected AgentInitializationException during agent loading: " + e);
|
||||||
|
if (jarAgent) {
|
||||||
|
log.complain("(agentmain have thrown an exception)");
|
||||||
|
} else {
|
||||||
|
log.complain("Agent_OnAttach function returned an error: " + e.returnValue());
|
||||||
|
}
|
||||||
|
e.printStackTrace(log.getOutStream());
|
||||||
|
} catch (IOException e) {
|
||||||
|
failureCause = e;
|
||||||
|
log.complain("Unexpected IOException during agent loading: " + e);
|
||||||
|
e.printStackTrace(log.getOutStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!agentLoaded) {
|
||||||
|
if (failureCause != null)
|
||||||
|
failed("Couldn't attach agent to the target application", failureCause);
|
||||||
|
else
|
||||||
|
failed("Couldn't attach agent to the target application");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void failed(String errorMessage) {
|
||||||
|
throw new Failure(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void failed(String errorMessage, Throwable t) {
|
||||||
|
throw new Failure(errorMessage, t);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2008, 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.share.aod;
|
||||||
|
|
||||||
|
import nsk.share.*;
|
||||||
|
import nsk.share.jpda.SocketIOPipe;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Class TargetApplication is part of the framework used in the AttachOnDemand tests
|
||||||
|
(tests against Attach API, API from package com.sun.tools.attach).
|
||||||
|
|
||||||
|
This class is used in tests where main test application uses Attach API, but doesn't load agents to the another VM.
|
||||||
|
In these test there are 2 java applications: main application using Attach API and another
|
||||||
|
'dummy' application which should be alive while main application is working.
|
||||||
|
|
||||||
|
To synchronize main and dummy application SocketIOPipe is used: when DummyTargetApplication starts
|
||||||
|
it sends signal that it is ready for test and waits for signal permitting finish execution
|
||||||
|
(socket number used for connection establishing should be passed via command line).
|
||||||
|
*/
|
||||||
|
public class DummyTargetApplication {
|
||||||
|
|
||||||
|
protected Log log = new Log(System.out, true);
|
||||||
|
|
||||||
|
protected AODTargetArgParser argParser;
|
||||||
|
|
||||||
|
protected SocketIOPipe pipe;
|
||||||
|
|
||||||
|
public DummyTargetApplication(String[] args) {
|
||||||
|
argParser = new AODTargetArgParser(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void targetApplicationActions() {
|
||||||
|
// do nothing by default
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runTargetApplication() {
|
||||||
|
pipe = SocketIOPipe.createClientIOPipe(log, "localhost", argParser.getPort(), 0);
|
||||||
|
log.display("Sending signal '" + AODTestRunner.SIGNAL_READY_FOR_ATTACH + "'");
|
||||||
|
pipe.println(AODTestRunner.SIGNAL_READY_FOR_ATTACH);
|
||||||
|
|
||||||
|
targetApplicationActions();
|
||||||
|
|
||||||
|
String signal = pipe.readln();
|
||||||
|
log.display("Signal received: '" + signal + "'");
|
||||||
|
|
||||||
|
if ((signal == null) || !signal.equals(AODTestRunner.SIGNAL_FINISH))
|
||||||
|
throw new TestBug("Unexpected signal: '" + signal + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new DummyTargetApplication(args).runTargetApplication();
|
||||||
|
}
|
||||||
|
}
|
251
test/hotspot/jtreg/vmTestbase/nsk/share/aod/ProcessExecutor.java
Normal file
251
test/hotspot/jtreg/vmTestbase/nsk/share/aod/ProcessExecutor.java
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2008, 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.share.aod;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import nsk.share.*;
|
||||||
|
|
||||||
|
public class ProcessExecutor {
|
||||||
|
|
||||||
|
private String[] cmdLine;
|
||||||
|
|
||||||
|
private long timeout;
|
||||||
|
|
||||||
|
private boolean printProcessOutput;
|
||||||
|
|
||||||
|
private String processOutputPrefix;
|
||||||
|
|
||||||
|
private InputStreamReaderThread outReader;
|
||||||
|
|
||||||
|
private InputStreamReaderThread errReader;
|
||||||
|
|
||||||
|
private Process startedProcess;
|
||||||
|
|
||||||
|
private ProcessWaiterThread processWaiter;
|
||||||
|
|
||||||
|
private long expectedFinishTime;
|
||||||
|
|
||||||
|
private volatile boolean executionCompleted;
|
||||||
|
|
||||||
|
private int exitCode;
|
||||||
|
|
||||||
|
private class InputStreamReaderThread extends Thread {
|
||||||
|
private BufferedReader in;
|
||||||
|
|
||||||
|
private String outputPrefix;
|
||||||
|
|
||||||
|
private List<String> output = new ArrayList<String>();
|
||||||
|
|
||||||
|
private volatile boolean streamWasAbruptlyClosed;
|
||||||
|
|
||||||
|
private Throwable unexpectedException;
|
||||||
|
|
||||||
|
public InputStreamReaderThread(InputStream in, String prefix) {
|
||||||
|
this.in = new BufferedReader(new InputStreamReader(in));
|
||||||
|
this.outputPrefix = prefix;
|
||||||
|
setDaemon(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void streamWasAbruptlyClosed(boolean newValue) {
|
||||||
|
streamWasAbruptlyClosed = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
String line = in.readLine();
|
||||||
|
if (line == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
output.add(line);
|
||||||
|
|
||||||
|
if (printProcessOutput)
|
||||||
|
System.out.println(outputPrefix + line);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (!streamWasAbruptlyClosed) {
|
||||||
|
unexpectedException = e;
|
||||||
|
e.printStackTrace( );
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
unexpectedException = t;
|
||||||
|
t.printStackTrace( );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkStatus() {
|
||||||
|
if (unexpectedException != null)
|
||||||
|
throw new Failure("Exception was thrown during InputStreamReaderThread work: " + unexpectedException,
|
||||||
|
unexpectedException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ProcessWaiterThread extends Thread {
|
||||||
|
|
||||||
|
private Throwable unexpectedException;
|
||||||
|
|
||||||
|
private Process process;
|
||||||
|
|
||||||
|
private InputStreamReaderThread outReader;
|
||||||
|
|
||||||
|
private InputStreamReaderThread errReader;
|
||||||
|
|
||||||
|
ProcessWaiterThread(Process process, InputStreamReaderThread outReader, InputStreamReaderThread errReader) {
|
||||||
|
this.process = process;
|
||||||
|
this.outReader = outReader;
|
||||||
|
this.errReader = errReader;
|
||||||
|
|
||||||
|
setDaemon(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
exitCode = process.waitFor();
|
||||||
|
outReader.join();
|
||||||
|
errReader.join();
|
||||||
|
|
||||||
|
synchronized (ProcessWaiterThread.this) {
|
||||||
|
executionCompleted = true;
|
||||||
|
ProcessWaiterThread.this.notify();
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
/*
|
||||||
|
* ProcessWaiterThread is interrupted if started process
|
||||||
|
* didn't finish in expected time
|
||||||
|
*/
|
||||||
|
} catch (Throwable t) {
|
||||||
|
unexpectedException = t;
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkStatus() {
|
||||||
|
if (unexpectedException != null)
|
||||||
|
throw new Failure("Exception was thrown during ProcessWaiterThread work: "
|
||||||
|
+ unexpectedException, unexpectedException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProcessExecutor(String cmdLine, long timeout) {
|
||||||
|
this.cmdLine = new String[]{cmdLine};
|
||||||
|
this.timeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProcessExecutor(String cmdLine, long timeout, String outputPrefix) {
|
||||||
|
this(cmdLine, timeout);
|
||||||
|
this.printProcessOutput = true;
|
||||||
|
this.processOutputPrefix = outputPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startProcess() throws IOException {
|
||||||
|
if (cmdLine.length == 1)
|
||||||
|
startedProcess = Runtime.getRuntime().exec(cmdLine[0]);
|
||||||
|
else
|
||||||
|
startedProcess = Runtime.getRuntime().exec(cmdLine);
|
||||||
|
|
||||||
|
expectedFinishTime = System.currentTimeMillis() + timeout;
|
||||||
|
|
||||||
|
outReader = new InputStreamReaderThread(startedProcess.getInputStream(),
|
||||||
|
processOutputPrefix == null ? "" : processOutputPrefix + " (stdout): ");
|
||||||
|
errReader = new InputStreamReaderThread(startedProcess.getErrorStream(),
|
||||||
|
processOutputPrefix == null ? "" : processOutputPrefix + " (stderr): ");
|
||||||
|
|
||||||
|
outReader.start();
|
||||||
|
errReader.start();
|
||||||
|
|
||||||
|
processWaiter = new ProcessWaiterThread(startedProcess, outReader, errReader);
|
||||||
|
processWaiter.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void waitForProcess() throws InterruptedException {
|
||||||
|
synchronized (processWaiter) {
|
||||||
|
while ((System.currentTimeMillis() < expectedFinishTime) && !executionCompleted) {
|
||||||
|
processWaiter.wait(expectedFinishTime - System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!executionCompleted) {
|
||||||
|
destroyProcessAndWaitThreads();
|
||||||
|
|
||||||
|
executionCompleted = true;
|
||||||
|
|
||||||
|
throw new Failure("Execution timed out (timeout: " + timeout + "ms)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void destroyProcessAndWaitThreads() {
|
||||||
|
outReader.streamWasAbruptlyClosed(true);
|
||||||
|
errReader.streamWasAbruptlyClosed(true);
|
||||||
|
|
||||||
|
processWaiter.interrupt();
|
||||||
|
startedProcess.destroy();
|
||||||
|
|
||||||
|
try {
|
||||||
|
outReader.join();
|
||||||
|
errReader.join();
|
||||||
|
processWaiter.join();
|
||||||
|
|
||||||
|
outReader.checkStatus();
|
||||||
|
errReader.checkStatus();
|
||||||
|
processWaiter.checkStatus();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new Failure("Unexpected InterruptedException", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkProcessState() {
|
||||||
|
if (!executionCompleted)
|
||||||
|
throw new IllegalStateException("Process didn't finish execution");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroyProcess() {
|
||||||
|
if (executionCompleted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
destroyProcessAndWaitThreads();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long pid() {
|
||||||
|
return startedProcess.pid();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getExitCode() {
|
||||||
|
checkProcessState();
|
||||||
|
|
||||||
|
return exitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getProcessOut() {
|
||||||
|
checkProcessState();
|
||||||
|
|
||||||
|
return outReader.output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getProcessErr() {
|
||||||
|
checkProcessState();
|
||||||
|
|
||||||
|
return errReader.output;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,400 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2008, 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.share.aod;
|
||||||
|
|
||||||
|
import nsk.share.*;
|
||||||
|
import nsk.share.jpda.SocketIOPipe;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Class TargetApplicationWaitingAgents is part of the framework used in the AttachOnDemand tests
|
||||||
|
(tests against Attach API, API from package com.sun.tools.attach).
|
||||||
|
|
||||||
|
Attach API allows to load so called 'agents' in the running VM. In terms of this framework
|
||||||
|
application running in the VM where agent is loaded to is called 'target application'.
|
||||||
|
|
||||||
|
TargetApplicationWaitingAgents is base class for target applications used in the AttachOnDemand tests
|
||||||
|
(also TargetApplicationWaitingAgents can be used without modifications in tests where target
|
||||||
|
application shouldn't execute some test-specific actions).
|
||||||
|
|
||||||
|
AttachOnDemand tests requires synchronization between test agents and target application:
|
||||||
|
- before target application can start to execute test-specific actions it
|
||||||
|
should wait when all tests agents will be loaded
|
||||||
|
|
||||||
|
- target application shouldn't finish until all agents finish their work
|
||||||
|
|
||||||
|
TargetApplicationWaitingAgents incapsulates actions common for all target applications. TargetApplicationWaitingAgents
|
||||||
|
provides 2 methods: 'agentLoaded' and 'agentFinished', test agents use these methods to notify
|
||||||
|
target application about its status. When target application based on the TargetApplicationWaitingAgents
|
||||||
|
starts it first waits when all test agents will be loaded (number of expected test agents is
|
||||||
|
passed via parameter -agentsNumber). After this target application executes test-specific actions,
|
||||||
|
waits when all test agents will finish, checks agent's status (passed of failed) and
|
||||||
|
finishes.
|
||||||
|
|
||||||
|
In most cases test target applications should override only method 'targetApplicationActions' and
|
||||||
|
its 'main' method should contain only call of the method 'TargetApplicationWaitingAgents.runTargetApplication'.
|
||||||
|
|
||||||
|
Typical target application class looks like this:
|
||||||
|
|
||||||
|
public class targetExample extends TargetApplicationWaitingAgents {
|
||||||
|
|
||||||
|
protected void targetApplicationActions() {
|
||||||
|
// do test-specific actions
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new targetExample().runTargetApplication(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
public class TargetApplicationWaitingAgents {
|
||||||
|
|
||||||
|
private volatile static boolean testFailed = false;
|
||||||
|
|
||||||
|
private static long AGENTS_CONNECTION_TIMEOUT = 5 * 60 * 1000; // 5 min
|
||||||
|
|
||||||
|
private static long AGENTS_FINISHING_TIMEOUT = 5 * 60 * 1000; // 5 min
|
||||||
|
|
||||||
|
private static boolean allAgentsAttached;
|
||||||
|
|
||||||
|
private static List<String> attachedAgents = new ArrayList<String>();
|
||||||
|
|
||||||
|
private static boolean allAgentsFinished;
|
||||||
|
|
||||||
|
private static List<String> finishedAgents = new ArrayList<String>();
|
||||||
|
|
||||||
|
private static boolean targetApplicationInitialized;
|
||||||
|
|
||||||
|
static protected AODTargetArgParser argParser;
|
||||||
|
|
||||||
|
protected static Log log;
|
||||||
|
|
||||||
|
static private Object monitor = new Object();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Methods
|
||||||
|
* - agentLoaded(String agentName) and
|
||||||
|
* - agentFinished(String agentName, boolean finishedSuccessfully)
|
||||||
|
* are called from test agents to notify target application about its status
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static void agentLoaded(String agentName) {
|
||||||
|
synchronized (monitor) {
|
||||||
|
if (!targetApplicationInitialized)
|
||||||
|
waitForTargetApplicationInitialization();
|
||||||
|
|
||||||
|
// check test logic
|
||||||
|
if (attachedAgents.contains(agentName)) {
|
||||||
|
setStatusFailed("Agent '" + agentName + "' already attached");
|
||||||
|
|
||||||
|
// let TargetApplication complete execution in case of error
|
||||||
|
allAgentsAttached = true;
|
||||||
|
monitor.notifyAll();
|
||||||
|
|
||||||
|
throw new TestBug("Agent '" + agentName + "' calls method 'agentLoaded' more than 1 time");
|
||||||
|
} else {
|
||||||
|
attachedAgents.add(agentName);
|
||||||
|
|
||||||
|
log.display("Agent '" + agentName + "' was loaded");
|
||||||
|
|
||||||
|
allAgentsAttached = (attachedAgents.size() == argParser.getExpectedAgentsNumber());
|
||||||
|
|
||||||
|
if (allAgentsAttached)
|
||||||
|
monitor.notifyAll();
|
||||||
|
|
||||||
|
// check test logic
|
||||||
|
if (attachedAgents.size() > argParser.getExpectedAgentsNumber()) {
|
||||||
|
setStatusFailed("Unexpected agent attached (expected agents number: " +
|
||||||
|
argParser.getExpectedAgentsNumber() +
|
||||||
|
", but " + attachedAgents.size() + " agents were loaded)");
|
||||||
|
|
||||||
|
throw new TestBug("More agents attached than it was expected" +
|
||||||
|
" (expected: " + argParser.getExpectedAgentsNumber() +
|
||||||
|
", attached: " + attachedAgents.size() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void agentFinished(String agentName, boolean finishedSuccessfully) {
|
||||||
|
synchronized (monitor) {
|
||||||
|
// check test logic
|
||||||
|
if (!targetApplicationInitialized)
|
||||||
|
throw new TestBug("Method 'agentFinished' was called before TargetApplication was initialized");
|
||||||
|
|
||||||
|
boolean algorithmError = false;
|
||||||
|
String errorMessage = "Test algorithm error:";
|
||||||
|
|
||||||
|
if (!attachedAgents.contains(agentName)) {
|
||||||
|
algorithmError = true;
|
||||||
|
errorMessage += " agent '" + agentName + "' didn't call method 'agentLoaded';";
|
||||||
|
log.complain(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finishedAgents.contains(agentName)) {
|
||||||
|
algorithmError = true;
|
||||||
|
errorMessage += " agent '" + agentName + "' already called method 'agentFinished';";
|
||||||
|
log.complain(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (algorithmError) {
|
||||||
|
// let TargetApplication complete execution in case of error
|
||||||
|
allAgentsFinished = true;
|
||||||
|
monitor.notifyAll();
|
||||||
|
|
||||||
|
throw new TestBug(errorMessage);
|
||||||
|
} else {
|
||||||
|
finishedAgents.add(agentName);
|
||||||
|
|
||||||
|
log.display("Agent '" + agentName + "' finished execution (finishedSuccessfully: " + finishedSuccessfully + ")");
|
||||||
|
|
||||||
|
if (!finishedSuccessfully)
|
||||||
|
setStatusFailed("Agent '" + agentName + " finished with error status");
|
||||||
|
|
||||||
|
allAgentsFinished = (finishedAgents.size() == argParser.getExpectedAgentsNumber());
|
||||||
|
|
||||||
|
if (allAgentsAttached)
|
||||||
|
monitor.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This method is called from the method 'agentLoaded' in case
|
||||||
|
* when target application isn't initialized yet at the moment
|
||||||
|
* when agent is connecting
|
||||||
|
*/
|
||||||
|
static private void waitForTargetApplicationInitialization() {
|
||||||
|
synchronized (monitor) {
|
||||||
|
while (!targetApplicationInitialized) {
|
||||||
|
try {
|
||||||
|
monitor.wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// should never happen
|
||||||
|
exitAsFailed(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This method is introduced to let subclasses to create its own parsers
|
||||||
|
*/
|
||||||
|
protected AODTargetArgParser createArgParser(String[] args) {
|
||||||
|
return new AODTargetArgParser(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Target application initialization
|
||||||
|
*/
|
||||||
|
private void initTargetApplication(String[] args) {
|
||||||
|
synchronized (monitor) {
|
||||||
|
if (targetApplicationInitialized)
|
||||||
|
throw new TestBug("TargetApplication already initialized");
|
||||||
|
|
||||||
|
log = new Log(System.out, true);
|
||||||
|
|
||||||
|
argParser = createArgParser(args);
|
||||||
|
|
||||||
|
// test-specific initialization
|
||||||
|
init(args);
|
||||||
|
|
||||||
|
targetApplicationInitialized = true;
|
||||||
|
monitor.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static private void waitAgentsConnection() {
|
||||||
|
synchronized (monitor) {
|
||||||
|
long waitFinishTime = System.currentTimeMillis() + AGENTS_CONNECTION_TIMEOUT;
|
||||||
|
|
||||||
|
while (!allAgentsAttached && (System.currentTimeMillis() < waitFinishTime)) {
|
||||||
|
try {
|
||||||
|
monitor.wait(AGENTS_CONNECTION_TIMEOUT);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// should never happen
|
||||||
|
exitAsFailed(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!allAgentsAttached) {
|
||||||
|
exitAsFailed("Agents didn't attach in " + AGENTS_CONNECTION_TIMEOUT + "ms, stop execution " +
|
||||||
|
"(expected agents number: " + argParser.getExpectedAgentsNumber() +
|
||||||
|
", attached agents number: " + attachedAgents.size() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static private void waitAgentsFinishing() {
|
||||||
|
synchronized (monitor) {
|
||||||
|
long waitFinishTime = System.currentTimeMillis() + AGENTS_FINISHING_TIMEOUT;
|
||||||
|
|
||||||
|
while (!allAgentsFinished && (System.currentTimeMillis() < waitFinishTime)) {
|
||||||
|
try {
|
||||||
|
monitor.wait(AGENTS_FINISHING_TIMEOUT);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// should never happen
|
||||||
|
exitAsFailed(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!allAgentsFinished)
|
||||||
|
exitAsFailed("Agents didn't finish in " + AGENTS_FINISHING_TIMEOUT + "ms, stop execution " +
|
||||||
|
"(attached agents number: " + attachedAgents.size() +
|
||||||
|
", finished agents number: " + finishedAgents.size() + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print error message and set failed status, but don't exit
|
||||||
|
*/
|
||||||
|
|
||||||
|
static public void setStatusFailed(String message) {
|
||||||
|
testFailed = true;
|
||||||
|
log.complain(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public void setStatusFailed(Throwable t) {
|
||||||
|
testFailed = true;
|
||||||
|
log.complain("Unexpected exception: " + t);
|
||||||
|
t.printStackTrace(log.getOutStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print error message and exit with fail status
|
||||||
|
*/
|
||||||
|
static protected void exitAsFailed(String errorMessage) {
|
||||||
|
try {
|
||||||
|
log.complain(errorMessage);
|
||||||
|
log.complain("Stop execution");
|
||||||
|
} finally {
|
||||||
|
System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print error message and exit with fail status
|
||||||
|
*/
|
||||||
|
static protected void exitAsFailed(Throwable t) {
|
||||||
|
try {
|
||||||
|
log.complain("Unexpected exception was thrown during TargetApplication execution: " + t);
|
||||||
|
t.printStackTrace(log.getOutStream());
|
||||||
|
log.display("Stop execution");
|
||||||
|
} finally {
|
||||||
|
System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Following 3 methods can be overridden in subclasses:
|
||||||
|
*
|
||||||
|
* - init(String[] args)
|
||||||
|
*
|
||||||
|
* - targetApplicationActions()
|
||||||
|
*
|
||||||
|
* - afterAgentsFinished()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test-specific initialization
|
||||||
|
*/
|
||||||
|
protected void init(String[] args) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void targetApplicationActions() throws Throwable {
|
||||||
|
// do nothing by default
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void afterAgentsFinished() {
|
||||||
|
// do nothing by default
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void runTargetApplication(String[] args) {
|
||||||
|
initTargetApplication(args);
|
||||||
|
|
||||||
|
SocketIOPipe pipe = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (argParser.getPort() > 0) {
|
||||||
|
/*
|
||||||
|
* When target application initialized send signal to AODTestRunner
|
||||||
|
*/
|
||||||
|
pipe = SocketIOPipe.createClientIOPipe(log, "localhost", argParser.getPort(), 0);
|
||||||
|
log.display("Sending signal '" + AODTestRunner.SIGNAL_READY_FOR_ATTACH + "'");
|
||||||
|
pipe.println(AODTestRunner.SIGNAL_READY_FOR_ATTACH);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.display("Waiting for agents connection");
|
||||||
|
waitAgentsConnection();
|
||||||
|
log.display("All expected agents connected");
|
||||||
|
|
||||||
|
try {
|
||||||
|
targetApplicationActions();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
/*
|
||||||
|
* If something goes wrong during test execution it is better
|
||||||
|
* to exit without waiting for agents
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (pipe != null)
|
||||||
|
pipe.close();
|
||||||
|
|
||||||
|
exitAsFailed(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.display("Waiting for agents finishing");
|
||||||
|
waitAgentsFinishing();
|
||||||
|
log.display("All agents finished execution");
|
||||||
|
|
||||||
|
afterAgentsFinished();
|
||||||
|
|
||||||
|
if (pipe != null) {
|
||||||
|
/*
|
||||||
|
* Don't finish execution until AODTestRunner attached agents
|
||||||
|
*/
|
||||||
|
String signal = pipe.readln();
|
||||||
|
log.display("Signal received: '" + signal + "'");
|
||||||
|
if ((signal == null) || !signal.equals(AODTestRunner.SIGNAL_FINISH))
|
||||||
|
throw new TestBug("Unexpected AODTestRunner signal: '" + signal + "'");
|
||||||
|
|
||||||
|
if (testFailed) {
|
||||||
|
if (pipe != null)
|
||||||
|
pipe.close();
|
||||||
|
|
||||||
|
exitAsFailed("Error happened during TargetApplication execution (see error messages for details)");
|
||||||
|
} else {
|
||||||
|
log.display("Test passed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (pipe != null)
|
||||||
|
pipe.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new TargetApplicationWaitingAgents().runTargetApplication(args);
|
||||||
|
}
|
||||||
|
}
|
95
test/hotspot/jtreg/vmTestbase/nsk/share/aod/Utils.java
Normal file
95
test/hotspot/jtreg/vmTestbase/nsk/share/aod/Utils.java
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2008, 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.share.aod;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import nsk.share.*;
|
||||||
|
|
||||||
|
public class Utils {
|
||||||
|
|
||||||
|
// prevent class instantiation
|
||||||
|
private Utils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final long JPS_WORK_TIMEOUT = 60000; // 1 min
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find id of VM with certain value of property key. Method findVMIdUsingJPS
|
||||||
|
* runs 'jps -v' and seeks in jps output line containing this unique string,
|
||||||
|
* discovered string should also contain VM id.
|
||||||
|
*
|
||||||
|
* @param jdkPath - path to jdk
|
||||||
|
* @param key - name of property
|
||||||
|
* @param value - value of property
|
||||||
|
* @return VM id
|
||||||
|
*/
|
||||||
|
public static String findVMIdUsingJPS(String jdkPath, String key, String value) {
|
||||||
|
try {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String idString = key + "=" + value;
|
||||||
|
String jpsPath = jdkPath + File.separator + "bin" + File.separator + "jps";
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
ProcessExecutor executor = new ProcessExecutor(jpsPath + " -v", JPS_WORK_TIMEOUT, "jps -v");
|
||||||
|
executor.startProcess();
|
||||||
|
executor.waitForProcess();
|
||||||
|
|
||||||
|
if (executor.getExitCode() != 0) {
|
||||||
|
throw new Failure("jps finished with non-zero code " + executor.getExitCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String jpsOutLine : executor.getProcessOut()) {
|
||||||
|
if (jpsOutLine.contains(idString)) {
|
||||||
|
if (jpsOutLine.indexOf(' ') < 0)
|
||||||
|
throw new Failure("Unexpected format of the jps output '" + jpsOutLine + " (line doesn't contain space)");
|
||||||
|
|
||||||
|
return jpsOutLine.substring(0, jpsOutLine.indexOf(' '));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
} catch (Failure f) {
|
||||||
|
throw f;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
throw new Failure("Unexpected exception during jps execution: " + t, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String findCurrentVMIdUsingJPS(String jdkPath) {
|
||||||
|
/*
|
||||||
|
* VM should be run with special property which allows to find VM id using jps
|
||||||
|
* (see comments for method Utils.findVMIdUsingJPS)
|
||||||
|
*/
|
||||||
|
String applicationId = System.getProperty(AODTestRunner.targetAppIdProperty);
|
||||||
|
if (applicationId == null)
|
||||||
|
throw new TestBug("Property '" + AODTestRunner.targetAppIdProperty + "' isn't defined");
|
||||||
|
|
||||||
|
String targetVMId = Utils.findVMIdUsingJPS(jdkPath, AODTestRunner.targetAppIdProperty, applicationId);
|
||||||
|
|
||||||
|
return targetVMId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
288
test/hotspot/jtreg/vmTestbase/nsk/share/aod/aod.c
Normal file
288
test/hotspot/jtreg/vmTestbase/nsk/share/aod/aod.c
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2008, 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 <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <jni.h>
|
||||||
|
#include <jni_tools.h>
|
||||||
|
#include <nsk_tools.h>
|
||||||
|
#include <aod.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static volatile int internalError = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function can be used to inform AOD framework that some non critical for test logic
|
||||||
|
* error happened inside shared function (e.g. JVMTI Deallocate failed).
|
||||||
|
*
|
||||||
|
* If this function was called status of all finishing AOD agents is changed to failed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void nsk_aod_internal_error() {
|
||||||
|
NSK_COMPLAIN0("WARNING: some error happened inside common function, see log for details\n");
|
||||||
|
internalError = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsk_free_options(Options* options) {
|
||||||
|
if (options != NULL) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < NSK_AOD_MAX_OPTIONS; i++) {
|
||||||
|
if (options->names[i] != NULL) {
|
||||||
|
free(options->names[i]);
|
||||||
|
}
|
||||||
|
if (options->values[i] != NULL) {
|
||||||
|
free(options->values[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Work with agent options
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse options and create structure Options
|
||||||
|
*/
|
||||||
|
static Options* nsk_aod_createOptionsObject(char* optionsString) {
|
||||||
|
int i = 0;
|
||||||
|
Options* options;
|
||||||
|
char* name;
|
||||||
|
char* value;
|
||||||
|
char* sep;
|
||||||
|
|
||||||
|
if (optionsString == NULL) {
|
||||||
|
NSK_COMPLAIN0("options were not passed to the native agent\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
options = (Options*) malloc(sizeof(Options));
|
||||||
|
memset(options, 0, sizeof(Options));
|
||||||
|
options->size = 0;
|
||||||
|
name = optionsString;
|
||||||
|
while (name != NULL && i < NSK_AOD_MAX_OPTIONS) {
|
||||||
|
sep = strchr(name, '=');
|
||||||
|
if (sep == NULL) { // name not found
|
||||||
|
NSK_COMPLAIN1("Invalid options format: '%s'\n", optionsString);
|
||||||
|
nsk_free_options(options);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*sep = '\0';
|
||||||
|
options->names[i] = strdup(name);
|
||||||
|
value = sep + 1;
|
||||||
|
if (*value == '\0') { // value not found
|
||||||
|
NSK_COMPLAIN1("Option '%s' is empty\n", options->names[i]);
|
||||||
|
nsk_free_options(options);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
sep = strchr(value, ' ');
|
||||||
|
if (sep != NULL) {
|
||||||
|
*sep = '\0';
|
||||||
|
name = sep + 1;
|
||||||
|
} else {
|
||||||
|
name = strchr(value, '\0');
|
||||||
|
}
|
||||||
|
options->values[i] = strdup(value);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (*name == '\0') {
|
||||||
|
name = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (name != NULL) {
|
||||||
|
NSK_COMPLAIN1("WARNING: not all options were parsed, only %d options can be specified\n",
|
||||||
|
NSK_AOD_MAX_OPTIONS);
|
||||||
|
}
|
||||||
|
options->size = i;
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
Options* nsk_aod_createOptions(char* optionsString) {
|
||||||
|
Options* options;
|
||||||
|
|
||||||
|
if (!NSK_VERIFY((options = (Options*) nsk_aod_createOptionsObject(optionsString)) != NULL))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!NSK_VERIFY(nsk_aod_optionSpecified(options, NSK_AOD_AGENT_NAME_OPTION))) {
|
||||||
|
NSK_COMPLAIN0("Agent name wasn't specified\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* verbose mode is true by default
|
||||||
|
*/
|
||||||
|
nsk_setVerboseMode(NSK_TRUE);
|
||||||
|
|
||||||
|
if (nsk_aod_optionSpecified(options, NSK_AOD_VERBOSE_OPTION)) {
|
||||||
|
if (strcmp(nsk_aod_getOptionValue(options, NSK_AOD_VERBOSE_OPTION), "false") == 0)
|
||||||
|
nsk_setVerboseMode(NSK_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* nsk_aod_getOptionValue(Options* options, const char* option) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!NSK_VERIFY(options != NULL)) {
|
||||||
|
NSK_COMPLAIN0("Options NULL\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < options->size; i++) {
|
||||||
|
if (strcmp(option, options->names[i]) == 0) {
|
||||||
|
return options->values[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NSK_COMPLAIN1("Option '%s' isn't defined\n", option);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nsk_aod_optionSpecified(Options* options, const char* option) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!NSK_VERIFY(options != NULL)) {
|
||||||
|
NSK_COMPLAIN0("Options NULL\n");
|
||||||
|
return NSK_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < options->size; i++) {
|
||||||
|
if (strcmp(option, options->names[i]) == 0) {
|
||||||
|
return NSK_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NSK_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Agent synchronization with target application
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const char* TARGET_APP_CLASS_NAME = "nsk/share/aod/TargetApplicationWaitingAgents";
|
||||||
|
|
||||||
|
static const char* AGENT_LOADED_METHOD_NAME = "agentLoaded";
|
||||||
|
static const char* AGENT_LOADED_METHOD_SIGNATURE = "(Ljava/lang/String;)V";
|
||||||
|
|
||||||
|
static const char* AGENT_FINISHED_METHOD_NAME = "agentFinished";
|
||||||
|
static const char* AGENT_FINISHED_METHOD_SIGNATURE = "(Ljava/lang/String;Z)V";
|
||||||
|
|
||||||
|
static jclass targetAppClass = NULL;
|
||||||
|
static jmethodID agentLoadedMethod = NULL;
|
||||||
|
static jmethodID agentFinishedMethod = NULL;
|
||||||
|
|
||||||
|
// this function is used to notify target application that native agent has been loaded
|
||||||
|
int nsk_aod_agentLoaded(JNIEnv* jni, const char* agentName) {
|
||||||
|
jstring agentNameString;
|
||||||
|
|
||||||
|
NSK_DISPLAY1("Agent %s is loaded\n", agentName);
|
||||||
|
|
||||||
|
if (targetAppClass == NULL) {
|
||||||
|
/*
|
||||||
|
* FindClass returns local reference, to cache reference to target application class
|
||||||
|
* global reference should be created
|
||||||
|
*/
|
||||||
|
jclass localTargetAppClass;
|
||||||
|
if (!NSK_JNI_VERIFY(jni, (localTargetAppClass =
|
||||||
|
NSK_CPP_STUB2(FindClass, jni, TARGET_APP_CLASS_NAME)) != NULL)) {
|
||||||
|
return NSK_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NSK_JNI_VERIFY(jni, (targetAppClass =
|
||||||
|
NSK_CPP_STUB2(NewGlobalRef, jni, localTargetAppClass)) != NULL)) {
|
||||||
|
return NSK_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (agentLoadedMethod == NULL) {
|
||||||
|
if (!NSK_JNI_VERIFY(jni, (agentLoadedMethod =
|
||||||
|
NSK_CPP_STUB4(GetStaticMethodID, jni, targetAppClass,
|
||||||
|
AGENT_LOADED_METHOD_NAME, AGENT_LOADED_METHOD_SIGNATURE)) != NULL))
|
||||||
|
return NSK_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NSK_JNI_VERIFY(jni, (agentNameString =
|
||||||
|
NSK_CPP_STUB2(NewStringUTF, jni, agentName)) != NULL))
|
||||||
|
return NSK_FALSE;
|
||||||
|
|
||||||
|
NSK_CPP_STUB4(CallStaticVoidMethod, jni, targetAppClass, agentLoadedMethod, agentNameString);
|
||||||
|
|
||||||
|
return NSK_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this function is used to notify target application that native agent has been finished execution
|
||||||
|
int nsk_aod_agentFinished(JNIEnv* jni, const char* agentName, int success) {
|
||||||
|
jstring agentNameString;
|
||||||
|
|
||||||
|
if (!targetAppClass) {
|
||||||
|
NSK_COMPLAIN1("%s: TEST LOGIC ERROR: method 'agentFinished' was called before "\
|
||||||
|
"targetAppClass was initialized\n", agentName);
|
||||||
|
return NSK_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (internalError && success) {
|
||||||
|
success = 0;
|
||||||
|
NSK_COMPLAIN1("Status of agent '%s' is 'passed', but some error happened during test execution "\
|
||||||
|
"(see log for details), change agent status to 'failed'\n",
|
||||||
|
agentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
NSK_DISPLAY2("Agent %s finished (success: %d)\n", agentName, success);
|
||||||
|
|
||||||
|
if (agentFinishedMethod == NULL) {
|
||||||
|
if (!NSK_JNI_VERIFY(jni, (agentFinishedMethod =
|
||||||
|
NSK_CPP_STUB4(GetStaticMethodID, jni, targetAppClass,
|
||||||
|
AGENT_FINISHED_METHOD_NAME, AGENT_FINISHED_METHOD_SIGNATURE)) != NULL))
|
||||||
|
return NSK_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NSK_JNI_VERIFY(jni, (agentNameString = NSK_CPP_STUB2(NewStringUTF, jni, agentName)) != NULL))
|
||||||
|
return NSK_FALSE;
|
||||||
|
|
||||||
|
NSK_CPP_STUB5(CallStaticVoidMethod, jni, targetAppClass,
|
||||||
|
agentFinishedMethod, agentNameString, success ? JNI_TRUE : JNI_FALSE);
|
||||||
|
|
||||||
|
return NSK_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Auxiliary functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
// JNI env creation
|
||||||
|
|
||||||
|
JNIEnv* nsk_aod_createJNIEnv(JavaVM* vm) {
|
||||||
|
JNIEnv* jni;
|
||||||
|
NSK_CPP_STUB3(GetEnv, vm, (void**)&jni, JNI_VERSION_1_2);
|
||||||
|
|
||||||
|
NSK_VERIFY(jni != NULL);
|
||||||
|
|
||||||
|
return jni;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
83
test/hotspot/jtreg/vmTestbase/nsk/share/aod/aod.h
Normal file
83
test/hotspot/jtreg/vmTestbase/nsk/share/aod/aod.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2008, 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.
|
||||||
|
*/
|
||||||
|
#ifndef NSK_SHARE_AOD_H
|
||||||
|
#define NSK_SHARE_AOD_H
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
#include <jni_tools.h>
|
||||||
|
#include <nsk_tools.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function can be used to inform AOD framework that some non-critical for test logic
|
||||||
|
* error happened inside shared function (e.g. JVMTI Deallocate failed).
|
||||||
|
*
|
||||||
|
* If this function was called status of all finishing AOD agents is changed to failed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void nsk_aod_internal_error();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Work with agent options
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NSK_AOD_MAX_OPTIONS 10
|
||||||
|
|
||||||
|
#define NSK_AOD_AGENT_NAME_OPTION "-agentName"
|
||||||
|
#define NSK_AOD_VERBOSE_OPTION "-verbose"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char* names[NSK_AOD_MAX_OPTIONS];
|
||||||
|
char* values[NSK_AOD_MAX_OPTIONS];
|
||||||
|
int size;
|
||||||
|
} Options;
|
||||||
|
|
||||||
|
Options* nsk_aod_createOptions(char* optionsString);
|
||||||
|
|
||||||
|
const char* nsk_aod_getOptionValue(Options* options, const char* option);
|
||||||
|
|
||||||
|
int nsk_aod_optionSpecified(Options* options, const char* option);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Agent synchronization with target application
|
||||||
|
*/
|
||||||
|
|
||||||
|
// this function is used to notify target application that native agent has been loaded
|
||||||
|
int nsk_aod_agentLoaded(JNIEnv* jni, const char* agentName);
|
||||||
|
|
||||||
|
// this function is used to notify target application that native agent has been finished execution
|
||||||
|
int nsk_aod_agentFinished(JNIEnv* jni, const char* agentName, int success);
|
||||||
|
|
||||||
|
|
||||||
|
// JNI env creation
|
||||||
|
|
||||||
|
JNIEnv* nsk_aod_createJNIEnv(JavaVM* vm);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* END OF NSK_SHARE_AOD_H */
|
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.classload;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import nsk.share.FileUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom classloader that does not delegate to it's parent.
|
||||||
|
*
|
||||||
|
* It can load classes from classpath that have name containing
|
||||||
|
* "Class" (any package).
|
||||||
|
*/
|
||||||
|
public class ClassPathNonDelegatingClassLoader extends ClassLoader {
|
||||||
|
private String [] classPath;
|
||||||
|
|
||||||
|
public ClassPathNonDelegatingClassLoader() {
|
||||||
|
classPath = System.getProperty("java.class.path").split(File.pathSeparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized Class loadClass(String name, boolean resolve)
|
||||||
|
throws ClassNotFoundException {
|
||||||
|
Class c = findLoadedClass(name);
|
||||||
|
if (c != null) {
|
||||||
|
System.out.println("Found class: " + name);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
if (name.contains("Class")) {
|
||||||
|
String newName = name.replace('.', '/');
|
||||||
|
return loadClassFromFile(name, newName + ".class", resolve);
|
||||||
|
} else {
|
||||||
|
return findSystemClass(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Class loadClassFromFile(String name, String fname, boolean resolve)
|
||||||
|
throws ClassNotFoundException {
|
||||||
|
try {
|
||||||
|
File target = new File("");
|
||||||
|
|
||||||
|
for(int i = 0; i < classPath.length; ++i) {
|
||||||
|
target = new File(classPath[i] + File.separator + fname);
|
||||||
|
if (target.exists())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!target.exists())
|
||||||
|
throw new java.io.FileNotFoundException();
|
||||||
|
byte[] buffer = FileUtils.readFile(target);
|
||||||
|
Class c = defineClass(name, buffer, 0, buffer.length);
|
||||||
|
if (resolve)
|
||||||
|
resolveClass(c);
|
||||||
|
return c;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ClassNotFoundException("Exception while reading classfile data", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,185 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.classload;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import nsk.share.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classloader that generates classes on the fly.
|
||||||
|
*
|
||||||
|
* This classloader can load classes with name starting with 'Class'.
|
||||||
|
* It will use nsk.share.classload.TemplateClass as template and will
|
||||||
|
* replace class name in the bytecode of template class. It can be used
|
||||||
|
* for example to detect memory leaks in class loading or to quickly
|
||||||
|
* fill PermGen.
|
||||||
|
*/
|
||||||
|
public class GeneratingClassLoader extends ClassLoader {
|
||||||
|
public static final String DEFAULT_CLASSNAME = TemplateClass.class.getName();
|
||||||
|
public static final String PREFIX = "Class";
|
||||||
|
|
||||||
|
private final String [] classPath;
|
||||||
|
private byte[] bytecode;
|
||||||
|
private int[] offsets;
|
||||||
|
private final String encoding = "UTF8";
|
||||||
|
private final String templateClassName;
|
||||||
|
private final byte[] templateClassNameBytes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create generating class loader that will use class file
|
||||||
|
* for given class from classpath as template.
|
||||||
|
*/
|
||||||
|
public GeneratingClassLoader(String templateClassName) {
|
||||||
|
this.templateClassName = templateClassName;
|
||||||
|
classPath = System.getProperty("java.class.path").split(File.pathSeparator);
|
||||||
|
try {
|
||||||
|
templateClassNameBytes = templateClassName.getBytes(encoding);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new TestBug(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create generating class loader that will use class file
|
||||||
|
* for nsk.share.classload.TemplateClass as template.
|
||||||
|
*/
|
||||||
|
public GeneratingClassLoader() {
|
||||||
|
this("nsk.share.classload.TemplateClass");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNameLength() {
|
||||||
|
return templateClassName.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrefix() {
|
||||||
|
return PREFIX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClassName(int number) {
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
sb.append(PREFIX);
|
||||||
|
sb.append(number);
|
||||||
|
int n = templateClassName.length() - sb.length();
|
||||||
|
for (int i = 0; i < n; ++i)
|
||||||
|
sb.append("_");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized Class loadClass(String name) throws ClassNotFoundException {
|
||||||
|
return loadClass(name, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized Class loadClass(String name, boolean resolve)
|
||||||
|
throws ClassNotFoundException {
|
||||||
|
Class c = findLoadedClass(name);
|
||||||
|
if (c != null)
|
||||||
|
return c;
|
||||||
|
if (!name.startsWith(PREFIX))
|
||||||
|
return super.loadClass(name, resolve);
|
||||||
|
if (name.length() != templateClassName.length())
|
||||||
|
throw new ClassNotFoundException("Only can load classes with name.length() = " + getNameLength() + " got: '" + name + "' length: " + name.length());
|
||||||
|
byte[] bytecode = getPatchedByteCode(name);
|
||||||
|
c = defineClass(name, bytecode, 0, bytecode.length);
|
||||||
|
if (resolve)
|
||||||
|
resolveClass(c);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] getPatchedByteCode(String name) throws ClassNotFoundException {
|
||||||
|
try {
|
||||||
|
byte[] bytecode = getByteCode();
|
||||||
|
String fname = name.replace(".", File.separator);
|
||||||
|
byte[] replaceBytes = fname.getBytes(encoding);
|
||||||
|
for (int offset : offsets) {
|
||||||
|
for (int i = 0; i < replaceBytes.length; ++i)
|
||||||
|
bytecode[offset + i] = replaceBytes[i];
|
||||||
|
}
|
||||||
|
return bytecode;
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new TestBug(e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new TestBug(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] getByteCode() throws ClassNotFoundException {
|
||||||
|
if (bytecode == null)
|
||||||
|
readByteCode();
|
||||||
|
if (offsets == null) {
|
||||||
|
getOffsets(bytecode);
|
||||||
|
if (offsets == null)
|
||||||
|
throw new TestBug("Class name not found in template class file");
|
||||||
|
}
|
||||||
|
return (byte[]) bytecode.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readByteCode() throws ClassNotFoundException {
|
||||||
|
String fname = templateClassName.replace(".", File.separator) + ".class";
|
||||||
|
File target = null;
|
||||||
|
for (int i = 0; i < classPath.length; ++i) {
|
||||||
|
target = new File(classPath[i] + File.separator + fname);
|
||||||
|
if (target.exists())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target == null || !target.exists())
|
||||||
|
throw new ClassNotFoundException("File not found: " + target);
|
||||||
|
try {
|
||||||
|
bytecode = FileUtils.readFile(target);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ClassNotFoundException(templateClassName, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getOffsets(byte[] bytecode) {
|
||||||
|
List<Integer> offsets = new ArrayList<Integer>();
|
||||||
|
if (this.offsets == null) {
|
||||||
|
String pname = templateClassName.replace(".", "/");
|
||||||
|
try {
|
||||||
|
byte[] pnameb = pname.getBytes(encoding);
|
||||||
|
int i = 0;
|
||||||
|
while (true) {
|
||||||
|
while (i < bytecode.length) {
|
||||||
|
int j = 0;
|
||||||
|
while (j < pnameb.length && bytecode[i + j] == pnameb[j])
|
||||||
|
++j;
|
||||||
|
if (j == pnameb.length)
|
||||||
|
break;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (i == bytecode.length)
|
||||||
|
break;
|
||||||
|
offsets.add(new Integer(i));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new TestBug(e);
|
||||||
|
}
|
||||||
|
this.offsets = new int[offsets.size()];
|
||||||
|
for (int i = 0; i < offsets.size(); ++i)
|
||||||
|
this.offsets[i] = offsets.get(i).intValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.classload;
|
||||||
|
|
||||||
|
public class TemplateClass {
|
||||||
|
}
|
206
test/hotspot/jtreg/vmTestbase/nsk/share/gc/Algorithms.java
Normal file
206
test/hotspot/jtreg/vmTestbase/nsk/share/gc/Algorithms.java
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import nsk.share.*;
|
||||||
|
import nsk.share.gc.gp.*;
|
||||||
|
import nsk.share.test.ExecutionController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <tt>Algorithms</tt> class collects main algorithms that are used in
|
||||||
|
* GC testing.
|
||||||
|
*/
|
||||||
|
public class Algorithms {
|
||||||
|
/** Number of threads that one CPU can manage. */
|
||||||
|
public final static long THREADS_MANAGED_BY_ONE_CPU = 100;
|
||||||
|
|
||||||
|
/** Number of threads that one block of memory can manage. */
|
||||||
|
public final static long THREADS_MANAGED_BY_ONE_BLOCK = 200;
|
||||||
|
|
||||||
|
/** Default maximum number of elements in array. */
|
||||||
|
public final static int MAX_ARRAY_SIZE = 65535;
|
||||||
|
|
||||||
|
// Block of memory is 64M
|
||||||
|
private final static long BLOCK_SIZE = 64 * 1024 * 1024; // 64M
|
||||||
|
|
||||||
|
// Minimal memory chunk size to eat
|
||||||
|
private final static int MIN_MEMORY_CHUNK = 512; // Bytes
|
||||||
|
|
||||||
|
// Number of attempts to print a string. Print may fail because of
|
||||||
|
// OutOfMemoryError, so this constat specifies the number of attemts
|
||||||
|
// to print despite of OOME.
|
||||||
|
private final static int ATTEMPTS_TO_PRINT = 3;
|
||||||
|
|
||||||
|
// This object stores any Failure that is thrown in Gourmand class
|
||||||
|
// and used in eatMemory(int) method
|
||||||
|
private static Failure failure = null;
|
||||||
|
|
||||||
|
// This object is intended for wait()
|
||||||
|
private static Object object = new Object();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor.
|
||||||
|
*/
|
||||||
|
private Algorithms() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stresses memory by allocating arrays of bytes. The method allocates
|
||||||
|
* objects in the same thread and does not invoke GC explicitly by
|
||||||
|
* calling <tt>System.gc()</tt>.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* Note that this method can throw Failure if any exception
|
||||||
|
* is thrown while eating memory. To avoid OOM while allocating
|
||||||
|
* exception we preallocate it before the lunch starts. It means
|
||||||
|
* that exception stack trace does not correspond to the place
|
||||||
|
* where exception is thrown, but points at start of the method.
|
||||||
|
*
|
||||||
|
* This method uses nsk.share.test.Stresser class to control
|
||||||
|
* it's execution. Consumed number of iterations depends on
|
||||||
|
* available memory.
|
||||||
|
*
|
||||||
|
* @throws <tt>nsk.share.Failure</tt> if any unexpected exception is
|
||||||
|
* thrown during allocating of the objects.
|
||||||
|
*
|
||||||
|
* @see nsk.share.test.Stresser
|
||||||
|
*/
|
||||||
|
public static void eatMemory(ExecutionController stresser) {
|
||||||
|
GarbageUtils.eatMemory(stresser, 50, MIN_MEMORY_CHUNK, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates and returns recomended number of threads to start in the
|
||||||
|
* particular machine (with particular amount of memory and number of CPUs).
|
||||||
|
* The returned value is minimum of two values:
|
||||||
|
* {@link #THREADS_MANAGED_BY_ONE_CPU} * (number of processors) and
|
||||||
|
* {@link #THREADS_MANAGED_BY_ONE_BLOCK} * (number of blocks of the memory).
|
||||||
|
*
|
||||||
|
* @return recomended number of threads to start.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static int getThreadsCount() {
|
||||||
|
Runtime runtime = Runtime.getRuntime();
|
||||||
|
int processors = runtime.availableProcessors();
|
||||||
|
long maxMemory = runtime.maxMemory();
|
||||||
|
long blocks = Math.round((double) maxMemory / BLOCK_SIZE);
|
||||||
|
|
||||||
|
return (int) Math.min(THREADS_MANAGED_BY_ONE_CPU * processors,
|
||||||
|
THREADS_MANAGED_BY_ONE_BLOCK * blocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of processors available to the Java virtual machine.
|
||||||
|
*
|
||||||
|
* @return number of processors available to the Java virtual machine.
|
||||||
|
*
|
||||||
|
* @see Runtime#availableProcessors
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static int availableProcessors() {
|
||||||
|
Runtime runtime = Runtime.getRuntime();
|
||||||
|
return runtime.availableProcessors();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes a few attempts to print the string into specified PrintStream.
|
||||||
|
* If <code>PrintStream.println(String)</code> throws OutOfMemoryError,
|
||||||
|
* the method waits for a few milliseconds and repeats the attempt.
|
||||||
|
*
|
||||||
|
* @param out PrintStream to print the string.
|
||||||
|
* @param s the string to print.
|
||||||
|
*/
|
||||||
|
public static void tryToPrintln(PrintStream out, String s) {
|
||||||
|
for (int i = 0; i < ATTEMPTS_TO_PRINT; i++) {
|
||||||
|
try {
|
||||||
|
out.println(s);
|
||||||
|
|
||||||
|
// The string is printed into the PrintStream
|
||||||
|
return;
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
|
||||||
|
// Catch the error and wait for a while
|
||||||
|
synchronized(object) {
|
||||||
|
try {
|
||||||
|
object.wait(500);
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
|
||||||
|
// Ignore the exception
|
||||||
|
}
|
||||||
|
} // synchronized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // tryToPrintln()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes a few attempts to print each stack trace of <code>Throwable</code>
|
||||||
|
* into specified PrintStream. If <code>PrintStream.println(String)</code>
|
||||||
|
* throws OutOfMemoryError, the method waits for a few milliseconds and
|
||||||
|
* repeats the attempt.
|
||||||
|
*
|
||||||
|
* @param out PrintStream to print the string.
|
||||||
|
* @param t the throwable to print.
|
||||||
|
*
|
||||||
|
* @see #tryToPrintln
|
||||||
|
*/
|
||||||
|
public static void tryToPrintStack(PrintStream out, Throwable t) {
|
||||||
|
StackTraceElement[] trace = t.getStackTrace();
|
||||||
|
|
||||||
|
for (int i = 0; i < trace.length; i++) {
|
||||||
|
for (int j = 0; j < ATTEMPTS_TO_PRINT; j++) {
|
||||||
|
try {
|
||||||
|
out.println(trace[i].toString());
|
||||||
|
|
||||||
|
// The string is printed into the PrintStream
|
||||||
|
return;
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
|
||||||
|
// Catch the error and wait for a while
|
||||||
|
synchronized(object) {
|
||||||
|
try {
|
||||||
|
object.wait(500);
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
|
||||||
|
// Ignore the exception
|
||||||
|
}
|
||||||
|
} // synchronized
|
||||||
|
} // try
|
||||||
|
} // for j
|
||||||
|
} // for i
|
||||||
|
} // tryToPrintStack()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns recommended size for an array. Default implemetation returns
|
||||||
|
* minimum between <code>size</code> and
|
||||||
|
* {@link #MAX_ARRAY_SIZE MAX_ARRAY_SIZE}.
|
||||||
|
*
|
||||||
|
* @return recommended size for an array.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static int getArraySize(long size) {
|
||||||
|
long min = Math.min(MAX_ARRAY_SIZE, size);
|
||||||
|
return (int) min;
|
||||||
|
} // getArraySize()
|
||||||
|
} // class Algorithms
|
53
test/hotspot/jtreg/vmTestbase/nsk/share/gc/AllDiag.java
Normal file
53
test/hotspot/jtreg/vmTestbase/nsk/share/gc/AllDiag.java
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share.gc;
|
||||||
|
|
||||||
|
import nsk.share.runner.RunParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper that prints information about AllMemoryObjects.
|
||||||
|
*/
|
||||||
|
public class AllDiag implements Runnable {
|
||||||
|
private long sleepTime;
|
||||||
|
|
||||||
|
public AllDiag() {
|
||||||
|
this(RunParams.getInstance().getSleepTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
public AllDiag(long sleepTime) {
|
||||||
|
this.sleepTime = sleepTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
AllMemoryObject.dumpStatistics();
|
||||||
|
// Ensure that interrupt status is not lost
|
||||||
|
if (Thread.currentThread().isInterrupted())
|
||||||
|
return;
|
||||||
|
try {
|
||||||
|
Thread.sleep(sleepTime);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share.gc;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object that occupies approximately given number of bytes in memory
|
||||||
|
* and also records number of allocated instances.
|
||||||
|
*/
|
||||||
|
public class AllMemoryObject extends MemoryObject {
|
||||||
|
private static int allocatedCount;
|
||||||
|
|
||||||
|
public AllMemoryObject(int size) {
|
||||||
|
super(size);
|
||||||
|
synchronized (AllMemoryObject.class) {
|
||||||
|
++allocatedCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of allocated FinMemoryObjects.
|
||||||
|
*/
|
||||||
|
public static int getAllocatedCount() {
|
||||||
|
return allocatedCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void dumpStatistics(PrintStream out) {
|
||||||
|
out.println("Object count: " + getAllocatedCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void dumpStatistics() {
|
||||||
|
dumpStatistics(System.out);
|
||||||
|
}
|
||||||
|
}
|
363
test/hotspot/jtreg/vmTestbase/nsk/share/gc/ArgumentHandler.java
Normal file
363
test/hotspot/jtreg/vmTestbase/nsk/share/gc/ArgumentHandler.java
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc;
|
||||||
|
|
||||||
|
import nsk.share.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser for GC tests' arguments.
|
||||||
|
* <p>
|
||||||
|
* <code>ArgumentHandler</code> handles specific command line arguments
|
||||||
|
* related to way of execution of a test in addition to general arguments
|
||||||
|
* recognized by {@link ArgumentParser <code>ArgumentParser</code>}.
|
||||||
|
* <p>
|
||||||
|
* Following is the list of specific options for <code>ArgumentHandler</code>:
|
||||||
|
* <ul>
|
||||||
|
* <li><code>-iterations="<i>value</i>"</code>, where <i>value</i> must either
|
||||||
|
* be "infinity", or an integer number, greater than 0. This parameter
|
||||||
|
* specifies the number of iterations to run the testcase. If the value is
|
||||||
|
* "infinity", then the test will be run for at least <code>gcTimeout</code>
|
||||||
|
* minutes. Otherwise, the testcase will be repeated for
|
||||||
|
* <code>iterations</code> times.
|
||||||
|
* <li><code>-gcTimeout="<i>value</i>"</code>, where <i>value</i> must be an
|
||||||
|
* integer number, greater than 0. If <i>infinity</i> is set to
|
||||||
|
* <code>iterations</code>, then the test consider <code>gcTimeout</code>
|
||||||
|
* argument to run the test for at least specified number of minutes.
|
||||||
|
* <li><code>-threads="<i>value</i>"</code>, where <i>value</i> must be an
|
||||||
|
* integer number, greater than 0. A user may specify the number of threads
|
||||||
|
* to start in the test with that paramenter. However, a test may ignore
|
||||||
|
* this value, if it does know the number of threads to start. It
|
||||||
|
* depends on a test: read its README file.
|
||||||
|
* <li><code>-memoryEater="<i>value</i>"</code>, where <i>value</i> must be
|
||||||
|
* either "single", or "multi" string. This argument specifies if a single
|
||||||
|
* thread should be used to eat the whole heap or not. If "multi" string is
|
||||||
|
* assigned to <code>-memoryEater</code>, then a number of threads will be
|
||||||
|
* started to eat the heap. The number is equal to number of available
|
||||||
|
* processors plus 1.
|
||||||
|
* <li><code>-largeClassesPath="<i>value</i>"</code>, where <i>value</i> is a
|
||||||
|
* directory to load large classes from.
|
||||||
|
* <li><code>-fieldsLimitation="<i>value</i>"</code>, where <i>value</i> must
|
||||||
|
* be either "over", or "under" string. This argument specifies what classes
|
||||||
|
* should be loaded from <code>largeClassesPath</code> directory. If
|
||||||
|
* <i>over</i> is set, then the classes that have number of fileds over
|
||||||
|
* JVM limitation should be loaded, otherwise -- classes that have number
|
||||||
|
* of fileds under limitation.
|
||||||
|
* </ul>
|
||||||
|
* @see ArgumentParser
|
||||||
|
*/
|
||||||
|
public class ArgumentHandler extends ArgumentParser {
|
||||||
|
|
||||||
|
// Define all possible arguments
|
||||||
|
private final static String ITERATIONS = "iterations";
|
||||||
|
private final static String AGGREGATION_DEPTH = "aggregationDepth";
|
||||||
|
private final static String GC_TIMEOUT = "gcTimeout";
|
||||||
|
private final static String THREADS = "threads";
|
||||||
|
private final static String MEM_EATER = "memoryEater";
|
||||||
|
private final static String LARGE_CLASSES_PATH = "largeClassesPath";
|
||||||
|
private final static String FIELDS_LIMITATION = "fieldsLimitation";
|
||||||
|
|
||||||
|
// An acceptible value for ITERATIONS
|
||||||
|
private final static String INFINITY = "infinity";
|
||||||
|
|
||||||
|
// Acceptible values for MEM_EATER
|
||||||
|
private final static String ME_SINGLE = "single";
|
||||||
|
private final static String ME_MULTI = "multi";
|
||||||
|
|
||||||
|
// Acceptible values for FIELDS_LIMITATION
|
||||||
|
private final static String FL_OVER = "over";
|
||||||
|
private final static String FL_UNDER = "under";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep a copy of raw command-line arguments and parse them;
|
||||||
|
* but throw an exception on parsing error.
|
||||||
|
*
|
||||||
|
* @param args Array of the raw command-line arguments.
|
||||||
|
*
|
||||||
|
* @throws BadOption If unknown option or illegal option value found
|
||||||
|
*
|
||||||
|
* @see ArgumentParser
|
||||||
|
*/
|
||||||
|
public ArgumentHandler(String args[]) {
|
||||||
|
super(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns number of iterations.
|
||||||
|
* <p>
|
||||||
|
* If <code>-iterations="<i>infinity</i>"</code>, the method returns -1.
|
||||||
|
* If the argument is not set, the method returns 1. Otherwise, the
|
||||||
|
* specified number is returned.
|
||||||
|
*
|
||||||
|
* @return number of iterations.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public int getIterations() {
|
||||||
|
String value = options.getProperty(ITERATIONS, "1");
|
||||||
|
|
||||||
|
if (INFINITY.equals(value))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new TestBug("Not an integer value of \"" + ITERATIONS
|
||||||
|
+ "\" argument: " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the depth of object aggregation.
|
||||||
|
* <p>
|
||||||
|
* If the argument is not set, the method returns 0. Otherwise, the
|
||||||
|
* specified number is returned.
|
||||||
|
*
|
||||||
|
* @return number of aggregation depth.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public int getAggregationDepth() {
|
||||||
|
String value = options.getProperty(AGGREGATION_DEPTH, "0");
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new TestBug("Not an integer value of \"" + AGGREGATION_DEPTH
|
||||||
|
+ "\" argument: " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns number of minutes to run the test.
|
||||||
|
* <p>
|
||||||
|
* @return number of minutes to run the test.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public int getGCTimeout() {
|
||||||
|
String value = options.getProperty(GC_TIMEOUT);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new TestBug("\"" + GC_TIMEOUT + "\" argument is not defined "
|
||||||
|
+ "or is not integer: " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a directory to load large classes from.
|
||||||
|
* <p>
|
||||||
|
* @return a directory to load large classes from.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public String getLargeClassesPath() {
|
||||||
|
return options.getProperty(LARGE_CLASSES_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns number of threads to start in a test. If <code>threads</code>
|
||||||
|
* is not set, the method returns specified number of threads.
|
||||||
|
* <p>
|
||||||
|
* @param defaultValue default value, if <code>threads</code> is not set.
|
||||||
|
* @return number of threads to start in a test.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public int getThreads(int defaultValue) {
|
||||||
|
String value = options.getProperty(THREADS);
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
return defaultValue;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new TestBug("Not an integer value of \"" + THREADS
|
||||||
|
+ "\" argument: " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if single thread should be used to eat the whole heap,
|
||||||
|
* false otherwise.
|
||||||
|
*
|
||||||
|
* @return true if single thread should be used to eat the whole heap,
|
||||||
|
* false otherwise.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public boolean isSingleMemoryEater() {
|
||||||
|
String value = options.getProperty(MEM_EATER);
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
return true;
|
||||||
|
else if (value.equals(ME_SINGLE))
|
||||||
|
return true;
|
||||||
|
else if (value.equals(ME_MULTI))
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
throw new TestBug("Value for \"" + MEM_EATER + "\" must be either "
|
||||||
|
+ ME_SINGLE + ", or " + ME_MULTI);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if classes with number of fileds over limitation should be
|
||||||
|
* loaded, false otherwise.
|
||||||
|
*
|
||||||
|
* @return true if classes with number of fileds over limitation should be
|
||||||
|
* loaded, false otherwise.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public boolean isOverFieldsLimitation() {
|
||||||
|
String value = options.getProperty(FIELDS_LIMITATION);
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
return false;
|
||||||
|
else if (value.equals(FL_OVER))
|
||||||
|
return true;
|
||||||
|
else if (value.equals(FL_UNDER))
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
throw new TestBug("Value for \"" + FIELDS_LIMITATION + "\" must be "
|
||||||
|
+ "either " + FL_OVER + ", or " + FL_UNDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an option is allowed and has proper value.
|
||||||
|
* This method is invoked by <code>parseArguments()</code>
|
||||||
|
*
|
||||||
|
* @param option option name
|
||||||
|
* @param value string representation of value
|
||||||
|
* (could be an empty string too)
|
||||||
|
* null if this option has no value
|
||||||
|
* @return <i>true</i> if option is allowed and has proper value,
|
||||||
|
* <i>false</i> if option is not admissible
|
||||||
|
*
|
||||||
|
* @throws <i>BadOption</i> if option has an illegal value
|
||||||
|
*
|
||||||
|
* @see #parseArguments()
|
||||||
|
*/
|
||||||
|
protected boolean checkOption(String option, String value) {
|
||||||
|
|
||||||
|
// Define iterations
|
||||||
|
if (option.equals(ITERATIONS)) {
|
||||||
|
if (INFINITY.equals(value))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
int number = Integer.parseInt(value);
|
||||||
|
|
||||||
|
if (number < 1)
|
||||||
|
throw new BadOption(option + ": value must be greater than "
|
||||||
|
+ "zero.");
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new BadOption("Value for option \"" + option + "\" must "
|
||||||
|
+ "be integer or \"" + INFINITY + "\": "
|
||||||
|
+ value);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define timeout
|
||||||
|
if (option.equals(GC_TIMEOUT)) {
|
||||||
|
try {
|
||||||
|
int number = Integer.parseInt(value);
|
||||||
|
|
||||||
|
if (number < 0)
|
||||||
|
throw new BadOption(option + ": value must be a positive "
|
||||||
|
+ "integer");
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new BadOption("Value for option \"" + option + "\" must "
|
||||||
|
+ "be integer: " + value);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define threads
|
||||||
|
if (option.equals(THREADS)) {
|
||||||
|
try {
|
||||||
|
int number = Integer.parseInt(value);
|
||||||
|
|
||||||
|
if (number < 0)
|
||||||
|
throw new BadOption(option + ": value must be a positive "
|
||||||
|
+ "integer");
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new BadOption("Value for option \"" + option + "\" must "
|
||||||
|
+ "be integer: " + value);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define path to large classes
|
||||||
|
if (option.equals(LARGE_CLASSES_PATH))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Define memory eater
|
||||||
|
if (option.equals(MEM_EATER)) {
|
||||||
|
if ( (ME_SINGLE.equals(value)) || (ME_MULTI.equals(value)) )
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
throw new BadOption("Value for option \"" + option + "\" must "
|
||||||
|
+ "be either " + ME_SINGLE + ", or "
|
||||||
|
+ ME_MULTI + ": " + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define fields limitation
|
||||||
|
if (option.equals(FIELDS_LIMITATION)) {
|
||||||
|
if ( (FL_OVER.equals(value)) || (FL_UNDER.equals(value)) )
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
throw new BadOption("Value for option \"" + option + "\" must "
|
||||||
|
+ "be either " + FL_OVER + ", or "
|
||||||
|
+ FL_UNDER + ": " + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define aggregationDepth
|
||||||
|
if (option.equals(AGGREGATION_DEPTH)) {
|
||||||
|
try {
|
||||||
|
int number = Integer.parseInt(value);
|
||||||
|
|
||||||
|
if (number < 0)
|
||||||
|
throw new BadOption(option + ": value must be a positive "
|
||||||
|
+ "integer");
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new BadOption("Value for option \"" + option + "\" must "
|
||||||
|
+ "be integer: " + value);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.checkOption(option, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the values of all options are consistent.
|
||||||
|
* This method is invoked by <code>parseArguments()</code>
|
||||||
|
*
|
||||||
|
* @throws <i>BadOption</i> if options have inconsistent values
|
||||||
|
*
|
||||||
|
* @see ArgumentParser#parseArguments()
|
||||||
|
*/
|
||||||
|
protected void checkOptions() {
|
||||||
|
super.checkOptions();
|
||||||
|
}
|
||||||
|
} // ArgumentHandler
|
43
test/hotspot/jtreg/vmTestbase/nsk/share/gc/Cell.java
Normal file
43
test/hotspot/jtreg/vmTestbase/nsk/share/gc/Cell.java
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share.gc;
|
||||||
|
|
||||||
|
import nsk.share.gc.MemoryObject;
|
||||||
|
|
||||||
|
public class Cell extends MemoryObject {
|
||||||
|
private int number;
|
||||||
|
|
||||||
|
public Cell(int size, int number) {
|
||||||
|
super(size - 4);
|
||||||
|
setNumber(number);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int getNumber() {
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setNumber(int number) {
|
||||||
|
this.number = number;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share.gc;
|
||||||
|
|
||||||
|
public class CircularLinkedList {
|
||||||
|
private int objectSize;
|
||||||
|
private LinkedMemoryObject root;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create empty circular linked list.
|
||||||
|
*
|
||||||
|
* @param objectSize size of each node in the list
|
||||||
|
*/
|
||||||
|
public CircularLinkedList(int objectSize) {
|
||||||
|
this.objectSize = objectSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert new node in the list.
|
||||||
|
*/
|
||||||
|
public void grow() {
|
||||||
|
LinkedMemoryObject newnode = new LinkedMemoryObject(objectSize);
|
||||||
|
if (root == null){
|
||||||
|
root = newnode;
|
||||||
|
root.setNext(root);
|
||||||
|
root.setPrev(root);
|
||||||
|
} else {
|
||||||
|
newnode.setNext(root.getNext());
|
||||||
|
root.getNext().setPrev(newnode);
|
||||||
|
root.setNext(newnode);
|
||||||
|
newnode.setPrev(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get length of the list.
|
||||||
|
*
|
||||||
|
* @return length
|
||||||
|
*/
|
||||||
|
public int getLength() {
|
||||||
|
return Memory.getListLength(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get length of another list.
|
||||||
|
*
|
||||||
|
* @param list another list
|
||||||
|
* @return length of list
|
||||||
|
*/
|
||||||
|
public int getLength(CircularLinkedList list) {
|
||||||
|
return Memory.getListLength(list.root);
|
||||||
|
}
|
||||||
|
}
|
5035
test/hotspot/jtreg/vmTestbase/nsk/share/gc/ClassChain.java
Normal file
5035
test/hotspot/jtreg/vmTestbase/nsk/share/gc/ClassChain.java
Normal file
File diff suppressed because it is too large
Load Diff
53
test/hotspot/jtreg/vmTestbase/nsk/share/gc/FinDiag.java
Normal file
53
test/hotspot/jtreg/vmTestbase/nsk/share/gc/FinDiag.java
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share.gc;
|
||||||
|
|
||||||
|
import nsk.share.runner.RunParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper that prints information about FinMemoryObjects.
|
||||||
|
*/
|
||||||
|
public class FinDiag implements Runnable {
|
||||||
|
private long sleepTime;
|
||||||
|
|
||||||
|
public FinDiag() {
|
||||||
|
this(RunParams.getInstance().getSleepTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
public FinDiag(long sleepTime) {
|
||||||
|
this.sleepTime = sleepTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
FinMemoryObject.dumpStatistics();
|
||||||
|
// Ensure that interrupt status is not lost
|
||||||
|
if (Thread.currentThread().isInterrupted())
|
||||||
|
return;
|
||||||
|
try {
|
||||||
|
Thread.sleep(sleepTime);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share.gc;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object that occupies approximately given number of bytes in memory
|
||||||
|
* and also records number of allocated and finalized instances.
|
||||||
|
*/
|
||||||
|
public class FinMemoryObject extends FinMemoryObject1 {
|
||||||
|
private static int finalizedCount;
|
||||||
|
|
||||||
|
public FinMemoryObject(int size) {
|
||||||
|
super(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void finalize() {
|
||||||
|
synchronized (FinMemoryObject.class) {
|
||||||
|
++finalizedCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of finalized FinMemoryObjects.
|
||||||
|
*/
|
||||||
|
public static int getFinalizedCount() {
|
||||||
|
return finalizedCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of live FinMemoryObjects (allocated but not finalized).
|
||||||
|
*/
|
||||||
|
public static int getLiveCount() {
|
||||||
|
return allocatedCount - finalizedCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void dumpStatistics(PrintStream out) {
|
||||||
|
Algorithms.tryToPrintln(out, "Object count: " + getLiveCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void dumpStatistics() {
|
||||||
|
dumpStatistics(System.out);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isAllFinalized() {
|
||||||
|
return getLiveCount() == 0;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share.gc;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import nsk.share.gc.Algorithms;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object that occupies approximately given number of bytes in memory
|
||||||
|
* and also has finalizer that does nothing.
|
||||||
|
*/
|
||||||
|
public class FinMemoryObject1 extends MemoryObject {
|
||||||
|
protected static int allocatedCount;
|
||||||
|
|
||||||
|
public FinMemoryObject1(int size) {
|
||||||
|
super(size);
|
||||||
|
synchronized (FinMemoryObject.class) {
|
||||||
|
++allocatedCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void finalize() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of allocated FinMemoryObjects.
|
||||||
|
*/
|
||||||
|
public static int getAllocatedCount() {
|
||||||
|
return allocatedCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void dumpStatistics(PrintStream out) {
|
||||||
|
Algorithms.tryToPrintln(out, "Object count: " + getAllocatedCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void dumpStatistics() {
|
||||||
|
dumpStatistics(System.out);
|
||||||
|
}
|
||||||
|
}
|
116
test/hotspot/jtreg/vmTestbase/nsk/share/gc/GC.java
Normal file
116
test/hotspot/jtreg/vmTestbase/nsk/share/gc/GC.java
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share.gc;
|
||||||
|
|
||||||
|
import nsk.share.test.*;
|
||||||
|
import nsk.share.runner.*;
|
||||||
|
import nsk.share.gc.gp.GarbageProducer;
|
||||||
|
import nsk.share.gc.gp.GarbageProducerAware;
|
||||||
|
import nsk.share.gc.gp.GarbageProducer1Aware;
|
||||||
|
import nsk.share.gc.gp.MemoryStrategy;
|
||||||
|
import nsk.share.gc.gp.MemoryStrategyAware;
|
||||||
|
import nsk.share.gc.gp.GarbageUtils;
|
||||||
|
import nsk.share.gc.lock.Lockers;
|
||||||
|
import nsk.share.gc.lock.LockersAware;
|
||||||
|
import nsk.share.gc.lock.LockerUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods for GC tests.
|
||||||
|
*/
|
||||||
|
public class GC extends nsk.share.test.Tests {
|
||||||
|
protected static class GCTestRunner extends TestRunner {
|
||||||
|
private GCParams gcParams;
|
||||||
|
private GarbageProducer garbageProducer;
|
||||||
|
private GarbageProducer garbageProducer1;
|
||||||
|
private MemoryStrategy memoryStrategy;
|
||||||
|
private Lockers lockers;
|
||||||
|
|
||||||
|
public GCTestRunner(Test test, String[] args) {
|
||||||
|
super(test, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GCParams getGCParams(String[] args) {
|
||||||
|
if (gcParams == null) {
|
||||||
|
gcParams = GCParams.getInstance();
|
||||||
|
gcParams.parseCommandLine(args);
|
||||||
|
}
|
||||||
|
return gcParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
private GarbageProducer getGarbageProducer(String[] args) {
|
||||||
|
if (garbageProducer == null) {
|
||||||
|
garbageProducer = GarbageUtils.getGarbageProducer(getGCParams(args).getGarbageProducerId());
|
||||||
|
configure(garbageProducer);
|
||||||
|
}
|
||||||
|
return garbageProducer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private GarbageProducer getGarbageProducer1(String[] args) {
|
||||||
|
if (garbageProducer1 == null) {
|
||||||
|
garbageProducer1 = GarbageUtils.getGarbageProducer(getGCParams(args).getGarbageProducer1Id());
|
||||||
|
configure(garbageProducer1);
|
||||||
|
}
|
||||||
|
return garbageProducer1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MemoryStrategy getMemoryStrategy(String[] args) {
|
||||||
|
if (memoryStrategy == null) {
|
||||||
|
memoryStrategy = MemoryStrategy.fromString(getGCParams(args).getMemoryStrategyId());
|
||||||
|
configure(memoryStrategy);
|
||||||
|
}
|
||||||
|
return memoryStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Lockers getLockers(String[] args) {
|
||||||
|
if (lockers == null) {
|
||||||
|
lockers = LockerUtils.getLockers(getGCParams(args).getLockersId());
|
||||||
|
configure(lockers);
|
||||||
|
}
|
||||||
|
return lockers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void configure(Object test) {
|
||||||
|
super.configure(test);
|
||||||
|
if (test instanceof GCParamsAware)
|
||||||
|
((GCParamsAware) test).setGCParams(getGCParams(args));
|
||||||
|
if (test instanceof GarbageProducerAware)
|
||||||
|
((GarbageProducerAware) test).setGarbageProducer(getGarbageProducer(args));
|
||||||
|
if (test instanceof GarbageProducer1Aware)
|
||||||
|
((GarbageProducer1Aware) test).setGarbageProducer1(getGarbageProducer1(args));
|
||||||
|
if (test instanceof MemoryStrategyAware)
|
||||||
|
((MemoryStrategyAware) test).setMemoryStrategy(getMemoryStrategy(args));
|
||||||
|
if (test instanceof LockersAware)
|
||||||
|
((LockersAware) test).setLockers(getLockers(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private GC() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runTest(Test test, String[] args) {
|
||||||
|
new GCTestRunner(test, args).run();
|
||||||
|
}
|
||||||
|
}
|
103
test/hotspot/jtreg/vmTestbase/nsk/share/gc/GCParams.java
Normal file
103
test/hotspot/jtreg/vmTestbase/nsk/share/gc/GCParams.java
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share.gc;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
public class GCParams {
|
||||||
|
private String garbageProducerId;
|
||||||
|
private String garbageProducer1Id;
|
||||||
|
private String memoryStrategyId;
|
||||||
|
private String lockersId;
|
||||||
|
|
||||||
|
public final String getGarbageProducerId() {
|
||||||
|
return garbageProducerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setGarbageProducerId(String garbageProducerId) {
|
||||||
|
this.garbageProducerId = garbageProducerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String getGarbageProducer1Id() {
|
||||||
|
return garbageProducer1Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setGarbageProducer1Id(String garbageProducer1Id) {
|
||||||
|
this.garbageProducer1Id = garbageProducer1Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String getMemoryStrategyId() {
|
||||||
|
return memoryStrategyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setMemoryStrategyId(String memoryStrategyId) {
|
||||||
|
this.memoryStrategyId = memoryStrategyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String getLockersId() {
|
||||||
|
return lockersId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setLockersId(String lockersId) {
|
||||||
|
this.lockersId = lockersId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parseCommandLine(String[] args) {
|
||||||
|
if (args == null)
|
||||||
|
return;
|
||||||
|
for (int i = 0; i < args.length; ++i) {
|
||||||
|
if (args[i].equals("-gp"))
|
||||||
|
garbageProducerId = args[++i];
|
||||||
|
else if (args[i].equals("-gp1"))
|
||||||
|
garbageProducer1Id = args[++i];
|
||||||
|
else if (args[i].equals("-ms"))
|
||||||
|
memoryStrategyId = args[++i];
|
||||||
|
else if (args[i].equals("-lockers"))
|
||||||
|
lockersId = args[++i];
|
||||||
|
}
|
||||||
|
printConfig(System.out);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void prinUsage() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printConfig(PrintStream out) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GCParams instance;
|
||||||
|
|
||||||
|
public static GCParams getInstance() {
|
||||||
|
synchronized (GCParams.class) {
|
||||||
|
if (instance == null)
|
||||||
|
instance = new GCParams();
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setInstance(GCParams gcParams) {
|
||||||
|
synchronized (GCParams.class) {
|
||||||
|
instance = gcParams;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share.gc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marker interface to signify that run params are needed.
|
||||||
|
*/
|
||||||
|
public interface GCParamsAware {
|
||||||
|
public void setGCParams(GCParams gcParams);
|
||||||
|
}
|
41
test/hotspot/jtreg/vmTestbase/nsk/share/gc/GCTestBase.java
Normal file
41
test/hotspot/jtreg/vmTestbase/nsk/share/gc/GCTestBase.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share.gc;
|
||||||
|
|
||||||
|
import nsk.share.test.TestBase;
|
||||||
|
import nsk.share.runner.RunParams;
|
||||||
|
import nsk.share.runner.RunParamsAware;
|
||||||
|
|
||||||
|
public abstract class GCTestBase extends TestBase implements RunParamsAware, GCParamsAware {
|
||||||
|
protected RunParams runParams;
|
||||||
|
protected GCParams gcParams;
|
||||||
|
|
||||||
|
public final void setRunParams(RunParams runParams) {
|
||||||
|
this.runParams = runParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setGCParams(GCParams gcParams) {
|
||||||
|
this.gcParams = gcParams;
|
||||||
|
}
|
||||||
|
}
|
61
test/hotspot/jtreg/vmTestbase/nsk/share/gc/IndexPair.java
Normal file
61
test/hotspot/jtreg/vmTestbase/nsk/share/gc/IndexPair.java
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share.gc;
|
||||||
|
|
||||||
|
public final class IndexPair {
|
||||||
|
private int i, j;
|
||||||
|
|
||||||
|
public IndexPair(int i, int j) {
|
||||||
|
setI(i);
|
||||||
|
setJ(j);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getI() {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setI(int i) {
|
||||||
|
this.i = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getJ() {
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJ(int j) {
|
||||||
|
this.j = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(IndexPair pair) {
|
||||||
|
return (this.i == pair.i && this.j == pair.j);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
return o instanceof IndexPair && equals((IndexPair) o);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
return i << 16 + j;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share.gc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object that occupies approximately given number of bytes in memory
|
||||||
|
* and has forward and backward links to other objects.
|
||||||
|
*/
|
||||||
|
public class LinkedMemoryObject extends MemoryObject {
|
||||||
|
private LinkedMemoryObject next;
|
||||||
|
private LinkedMemoryObject prev;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an object that occupies given number of bytes.
|
||||||
|
*
|
||||||
|
* @param arraySize size
|
||||||
|
*/
|
||||||
|
public LinkedMemoryObject(int size) {
|
||||||
|
super(size - 2 * Memory.getReferenceSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
public LinkedMemoryObject(int size, LinkedMemoryObject next) {
|
||||||
|
super(size - 2 * Memory.getReferenceSize());
|
||||||
|
setNext(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LinkedMemoryObject(int size, LinkedMemoryObject next, LinkedMemoryObject prev) {
|
||||||
|
super(size - 2 * Memory.getReferenceSize());
|
||||||
|
setNext(next);
|
||||||
|
setPrev(prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setNext(LinkedMemoryObject next) {
|
||||||
|
this.next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setPrev(LinkedMemoryObject prev) {
|
||||||
|
this.prev = prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final LinkedMemoryObject getNext() {
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final LinkedMemoryObject getPrev() {
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
}
|
68
test/hotspot/jtreg/vmTestbase/nsk/share/gc/Matrix.java
Normal file
68
test/hotspot/jtreg/vmTestbase/nsk/share/gc/Matrix.java
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share.gc;
|
||||||
|
|
||||||
|
public class Matrix {
|
||||||
|
private int cellSize;
|
||||||
|
private int matrixSize;
|
||||||
|
private Cell matrix[][];
|
||||||
|
private int nKnockedOut; // number of cells "nulled out"
|
||||||
|
|
||||||
|
public Matrix(int matrixSize, int cellSize) {
|
||||||
|
this.matrixSize = matrixSize;
|
||||||
|
this.cellSize = cellSize;
|
||||||
|
matrix = new Cell[matrixSize][matrixSize];
|
||||||
|
populate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void populate() {
|
||||||
|
for (int i = 0; i < matrixSize ; i++) {
|
||||||
|
for( int j = 0 ; j < matrixSize ; j++) {
|
||||||
|
matrix[i][j] = new Cell(cellSize, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int returnArrayBound() {
|
||||||
|
return matrixSize - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void clear(int i, int j) {
|
||||||
|
matrix[i][j] = null;
|
||||||
|
++nKnockedOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void repopulate(int i, int j) {
|
||||||
|
matrix[i][j] = new Cell(cellSize, i + j);
|
||||||
|
--nKnockedOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void resetCellCount() {
|
||||||
|
nKnockedOut = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized int getCellCount() {
|
||||||
|
return nKnockedOut;
|
||||||
|
}
|
||||||
|
}
|
513
test/hotspot/jtreg/vmTestbase/nsk/share/gc/Memory.java
Normal file
513
test/hotspot/jtreg/vmTestbase/nsk/share/gc/Memory.java
Normal file
@ -0,0 +1,513 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share.gc;
|
||||||
|
|
||||||
|
import nsk.share.test.LocalRandom;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import nsk.share.gc.gp.GarbageProducer;
|
||||||
|
import nsk.share.gc.tree.*;
|
||||||
|
import nsk.share.gc.gp.MemoryStrategy;
|
||||||
|
import nsk.share.log.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Different utility methods to work with memory objects.
|
||||||
|
*/
|
||||||
|
public final class Memory {
|
||||||
|
private static int bits = 0;
|
||||||
|
private static int referenceSize = 0;
|
||||||
|
private static int objectExtraSize = 0;
|
||||||
|
|
||||||
|
private Memory() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getBits() {
|
||||||
|
if (bits == 0)
|
||||||
|
bits = Integer.parseInt(System.getProperty("sun.arch.data.model"));
|
||||||
|
return bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get size of one object reference.
|
||||||
|
*
|
||||||
|
* TODO: somehow determine the real value
|
||||||
|
*/
|
||||||
|
public static int getReferenceSize() {
|
||||||
|
if (referenceSize == 0)
|
||||||
|
referenceSize = (getBits() == 64) ? 8 : 4;
|
||||||
|
return referenceSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get size of primitive type int.
|
||||||
|
*/
|
||||||
|
public static int getIntSize() {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get size of primitive type boolean.
|
||||||
|
*/
|
||||||
|
public static int getBooleanSize() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get size of primitive type byte.
|
||||||
|
*/
|
||||||
|
public static int getByteSize() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get size of primitive type char.
|
||||||
|
*/
|
||||||
|
public static int getCharSize() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get size of primitive type short.
|
||||||
|
*/
|
||||||
|
public static int getShortSize() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get size of primitive type long.
|
||||||
|
*/
|
||||||
|
public static int getLongSize() {
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get size of primitive type float.
|
||||||
|
*/
|
||||||
|
public static int getFloatSize() {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get size of primitive type double.
|
||||||
|
*/
|
||||||
|
public static int getDoubleSize() {
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get how many extra bytes an object occupies in the heap
|
||||||
|
* compared to sum of it's fields.
|
||||||
|
*
|
||||||
|
* TODO: somehow determine the real value
|
||||||
|
*/
|
||||||
|
public static int getObjectExtraSize() {
|
||||||
|
if (objectExtraSize == 0)
|
||||||
|
objectExtraSize = 2 * getReferenceSize();
|
||||||
|
return objectExtraSize;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get how many extra bytes an array occupies in the heap
|
||||||
|
* compared to sum of it's fields.
|
||||||
|
*
|
||||||
|
* TODO: somehow determine the real value
|
||||||
|
*/
|
||||||
|
public static int getArrayExtraSize() {
|
||||||
|
return getObjectExtraSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return size of reference object (SoftReference, WeakReference, PhantomReference)
|
||||||
|
*/
|
||||||
|
public static int getReferenceObjectSize() {
|
||||||
|
return getReferenceSize() + getObjectExtraSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an approximate length of array that will occupy a given memory.
|
||||||
|
*
|
||||||
|
* @param memory size of memory
|
||||||
|
* @param objectSize size of each object in array
|
||||||
|
* @return length of array
|
||||||
|
*/
|
||||||
|
public static int getArrayLength(long memory, long objectSize) {
|
||||||
|
int referenceSize = getReferenceSize();
|
||||||
|
int arrayExtraSize = getArrayExtraSize();
|
||||||
|
return (int) Math.min(
|
||||||
|
(memory - arrayExtraSize) / (objectSize + referenceSize),
|
||||||
|
Integer.MAX_VALUE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an approximate size of array of given length and object size.
|
||||||
|
*
|
||||||
|
* @param length length of arary
|
||||||
|
* @param objectSize size of object in array
|
||||||
|
* @return size of array
|
||||||
|
*/
|
||||||
|
public static long getArraySize(int length, long objectSize) {
|
||||||
|
return getObjectExtraSize() + length * (objectSize + getReferenceSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate approximate size of biggest of MemoryObjects.
|
||||||
|
*/
|
||||||
|
public static long getMemoryObjectSize(long size) {
|
||||||
|
return size + 2 * getReferenceSize() + getObjectExtraSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate approximate size of linked list in memory.
|
||||||
|
*
|
||||||
|
* @param length length of list
|
||||||
|
* @param size size of object
|
||||||
|
* @return size
|
||||||
|
*/
|
||||||
|
public static long getListSize(int length, int size) {
|
||||||
|
return getObjectExtraSize() + length * (getReferenceSize() + getMemoryObjectSize(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate length of linear or circular linked list.
|
||||||
|
*
|
||||||
|
* @param mobj head of list
|
||||||
|
* @return length of list
|
||||||
|
*/
|
||||||
|
public static int getListLength(LinkedMemoryObject mobj) {
|
||||||
|
LinkedMemoryObject tobj = mobj;
|
||||||
|
int length = 0;
|
||||||
|
do {
|
||||||
|
++length;
|
||||||
|
tobj = tobj.getNext();
|
||||||
|
} while (tobj != null && tobj != mobj);
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate length of array of linear or circular linked lists.
|
||||||
|
*
|
||||||
|
* @param mobjs array containting heads of lists
|
||||||
|
* @return length of all lists
|
||||||
|
*/
|
||||||
|
public static int getListsLength(LinkedMemoryObject[] mobjs) {
|
||||||
|
int length = 0;
|
||||||
|
for (int i = 0; i < mobjs.length; ++i) {
|
||||||
|
LinkedMemoryObject mobj = mobjs[i];
|
||||||
|
if (mobj != null)
|
||||||
|
length += getListLength(mobj);
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate size of all objects in linear or circular linked list.
|
||||||
|
*
|
||||||
|
* @param mobj head of list
|
||||||
|
* @return size of list
|
||||||
|
*/
|
||||||
|
public static long getListSize(LinkedMemoryObject mobj) {
|
||||||
|
LinkedMemoryObject tobj = mobj;
|
||||||
|
long size = 0;
|
||||||
|
do {
|
||||||
|
size += tobj.getSize();
|
||||||
|
tobj = tobj.getNext();
|
||||||
|
} while (tobj != null && tobj != mobj);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate size of array of linear or circular linked lists.
|
||||||
|
*
|
||||||
|
* @param mobjs array containting heads of lists
|
||||||
|
* @return size of all lists
|
||||||
|
*/
|
||||||
|
public static long getListsSize(LinkedMemoryObject[] mobjs) {
|
||||||
|
long size = 0;
|
||||||
|
for (int i = 0; i < mobjs.length; ++i) {
|
||||||
|
LinkedMemoryObject mobj = mobjs[i];
|
||||||
|
if (mobj != null)
|
||||||
|
size += getListSize(mobj);
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create singly linked linear list of objects of fixed size.
|
||||||
|
*
|
||||||
|
* @param depth length of list
|
||||||
|
* @param size size of each object
|
||||||
|
* @return head of created list or null if depth = 0
|
||||||
|
*/
|
||||||
|
public static LinkedMemoryObject makeLinearList(int depth, int size) {
|
||||||
|
LinkedMemoryObject mobj = null;
|
||||||
|
for (int i = 0; i < depth; ++i)
|
||||||
|
mobj = new LinkedMemoryObject(size, mobj);
|
||||||
|
return mobj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create singly linked linear list of objects of varying size.
|
||||||
|
*
|
||||||
|
* @param depth length of list
|
||||||
|
* @param size maximum size of each object
|
||||||
|
* @return head of created list or null if depth = 0
|
||||||
|
*/
|
||||||
|
public static LinkedMemoryObject makeRandomLinearList(int depth, int size) {
|
||||||
|
if (depth == 0)
|
||||||
|
return null;
|
||||||
|
LinkedMemoryObject mobj = new LinkedMemoryObject(size);
|
||||||
|
for (int i = 0; i < depth - 1; ++i)
|
||||||
|
mobj = new LinkedMemoryObject(LocalRandom.nextInt(size), mobj);
|
||||||
|
return mobj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create singly linked circular linear list of objects of fixed size.
|
||||||
|
*
|
||||||
|
* @param depth length of list
|
||||||
|
* @param size size of each object
|
||||||
|
* @return head of created list or null if depth = 0
|
||||||
|
*/
|
||||||
|
public static LinkedMemoryObject makeCircularList(int depth, int size) {
|
||||||
|
if (depth == 0)
|
||||||
|
return null;
|
||||||
|
LinkedMemoryObject mobj = new LinkedMemoryObject(size);
|
||||||
|
LinkedMemoryObject tmpobj = mobj;
|
||||||
|
for (int i = 1; i < depth; i++)
|
||||||
|
mobj = new LinkedMemoryObject(size, mobj);
|
||||||
|
tmpobj.setNext(mobj);
|
||||||
|
return tmpobj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create singly linked circular linear list of objects of varying size.
|
||||||
|
*
|
||||||
|
* @param depth length of list
|
||||||
|
* @param size maximum size of each object
|
||||||
|
* @return head of created list or null if depth = 0
|
||||||
|
*/
|
||||||
|
public static LinkedMemoryObject makeRandomCircularList(int depth, int size) {
|
||||||
|
if (depth == 0)
|
||||||
|
return null;
|
||||||
|
LinkedMemoryObject mobj = new LinkedMemoryObject(size);
|
||||||
|
LinkedMemoryObject tmpobj = mobj;
|
||||||
|
for (int i = 0; i < depth - 1; i++)
|
||||||
|
mobj = new LinkedMemoryObject(LocalRandom.nextInt(size), mobj);
|
||||||
|
tmpobj.setNext(mobj);
|
||||||
|
return tmpobj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new nonbranchy binary tree.
|
||||||
|
*
|
||||||
|
* Each node in the tree except leaves always has left son. A node
|
||||||
|
* will have right son with probability branchiness.
|
||||||
|
*
|
||||||
|
* @param numberOfNodes number of nodes
|
||||||
|
* @param branchiness branchiness
|
||||||
|
* @param size size of each node
|
||||||
|
* @return root of created tree
|
||||||
|
*/
|
||||||
|
public static LinkedMemoryObject makeNonbranchyTree(int numberOfNodes, float branchiness, int size) {
|
||||||
|
LinkedMemoryObject root = null;
|
||||||
|
LinkedMemoryObject current = null;
|
||||||
|
if (numberOfNodes == 0)
|
||||||
|
return null;
|
||||||
|
else if (numberOfNodes == 1)
|
||||||
|
return new LinkedMemoryObject(size);
|
||||||
|
else if (numberOfNodes == 2)
|
||||||
|
return new LinkedMemoryObject(size, makeNonbranchyTree(1, branchiness, size));
|
||||||
|
else {
|
||||||
|
if (LocalRandom.nextFloat() < branchiness) {
|
||||||
|
int numberOfLeftNodes = LocalRandom.nextInt(1, numberOfNodes - 1);
|
||||||
|
int numberOfRightNodes = numberOfNodes - 1 - numberOfLeftNodes;
|
||||||
|
return new LinkedMemoryObject(
|
||||||
|
size,
|
||||||
|
makeNonbranchyTree(numberOfLeftNodes, branchiness, size),
|
||||||
|
makeNonbranchyTree(numberOfRightNodes, branchiness, size)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return new LinkedMemoryObject(size, makeNonbranchyTree(numberOfNodes - 1, branchiness, size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a balanced tree of given height.
|
||||||
|
*
|
||||||
|
* @param height height of the tree
|
||||||
|
* @param size size of each node
|
||||||
|
* @return created tree
|
||||||
|
*/
|
||||||
|
public static Tree makeBalancedTree(int height, long size) {
|
||||||
|
return new Tree(makeBalancedTreeNode(height, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a number of nodes in balanced tree of given height.
|
||||||
|
*
|
||||||
|
* @param heigh height of the tree
|
||||||
|
* @return number of nodes
|
||||||
|
*/
|
||||||
|
public static int balancedTreeNodes(int height) {
|
||||||
|
if (height == 0)
|
||||||
|
return 0;
|
||||||
|
int n = 1;
|
||||||
|
while (height > 1) {
|
||||||
|
n *= 2;
|
||||||
|
height--;
|
||||||
|
}
|
||||||
|
return n * 2 - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get approximate memory size occupied by balanced tree
|
||||||
|
* of given height and given node size.
|
||||||
|
*
|
||||||
|
* @param height height of the tree
|
||||||
|
* @param nodeSize size of each node
|
||||||
|
* @return memory size
|
||||||
|
*/
|
||||||
|
public static long balancedTreeSize(int height, long nodeSize) {
|
||||||
|
return balancedTreeNodes(height) * nodeSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a height of balanced tree with given number of nodes.
|
||||||
|
*
|
||||||
|
* @param nodes number of nodes
|
||||||
|
* @return height of the tree
|
||||||
|
*/
|
||||||
|
public static int balancedTreeHeightFromNodes(int nodes) {
|
||||||
|
if (nodes == 0)
|
||||||
|
return 0;
|
||||||
|
int h = 1;
|
||||||
|
long n = 1;
|
||||||
|
while (n + n - 1 <= nodes) {
|
||||||
|
n = n + n;
|
||||||
|
h = h + 1;
|
||||||
|
}
|
||||||
|
return h - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get approximate height of balanced tree which will occupy
|
||||||
|
* given memory with given node size.
|
||||||
|
*
|
||||||
|
* @param memory memory size
|
||||||
|
* @param nodeSize size of each node
|
||||||
|
* @return approximate height of the tree
|
||||||
|
*/
|
||||||
|
public static int balancedTreeHeightFromMemory(long memory, long nodeSize) {
|
||||||
|
return balancedTreeHeightFromNodes((int) (memory / nodeSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create balanced tree of given height and node size.
|
||||||
|
*
|
||||||
|
* @param height height of the tree
|
||||||
|
* @param size size of each node
|
||||||
|
* @return root of created tree
|
||||||
|
*/
|
||||||
|
public static TreeNode makeBalancedTreeNode(int height, long size) {
|
||||||
|
if (height == 0)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return new TreeNode(size, makeBalancedTreeNode(height - 1, size), makeBalancedTreeNode(height - 1, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create balanced tree of given height and node size.
|
||||||
|
*
|
||||||
|
* @param height height of the tree
|
||||||
|
* @param size size of each node
|
||||||
|
* @return root of created tree
|
||||||
|
*/
|
||||||
|
public static TreeNode makeBalancedTreeNode(int height, long size, GarbageProducer gp) {
|
||||||
|
if (height == 0)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return new TreeNode(size, gp, makeBalancedTreeNode(height - 1, size), makeBalancedTreeNode(height - 1, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if given tree is a balanced tree.
|
||||||
|
*
|
||||||
|
* @param tree tree
|
||||||
|
* @return true if tree is balanced
|
||||||
|
*/
|
||||||
|
public static boolean isBalancedTree(TreeNode tree) {
|
||||||
|
return
|
||||||
|
tree.getActualHeight() == tree.getHeight() &&
|
||||||
|
tree.getShortestPath() == tree.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill an array of MemoryObject's with new objects of given size.
|
||||||
|
*
|
||||||
|
* @param array array
|
||||||
|
* @param count number of objects to create
|
||||||
|
* @param size size of each object
|
||||||
|
*/
|
||||||
|
public static void fillArray(MemoryObject[] array, int count, int size) {
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
array[i] = new MemoryObject(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill an array of MemoryObject's with new objects of random size.
|
||||||
|
*
|
||||||
|
* @param array array
|
||||||
|
* @param count number of objects to create
|
||||||
|
* @param size maximum size of each object
|
||||||
|
*/
|
||||||
|
public static void fillArrayRandom(MemoryObject[] array, int count, int size) {
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
array[i] = new MemoryObject(LocalRandom.nextInt(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill an array of MemoryObject's with new objects of random size.
|
||||||
|
*
|
||||||
|
* @param array array
|
||||||
|
* @param count number of objects to create
|
||||||
|
* @param size maximum size of each object
|
||||||
|
*/
|
||||||
|
public static void fillArrayRandom(LinkedMemoryObject[] array, int count, int size) {
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
array[i] = new LinkedMemoryObject(LocalRandom.nextInt(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void dumpStatistics(PrintStream out) {
|
||||||
|
out.println(Runtime.getRuntime().freeMemory());
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void dumpStatistics(Log log) {
|
||||||
|
log.info(Runtime.getRuntime().freeMemory());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void dumpStatistics() {
|
||||||
|
dumpStatistics(System.out);
|
||||||
|
}
|
||||||
|
}
|
50
test/hotspot/jtreg/vmTestbase/nsk/share/gc/MemoryObject.java
Normal file
50
test/hotspot/jtreg/vmTestbase/nsk/share/gc/MemoryObject.java
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share.gc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object that occupies approximately given number of bytes in memory.
|
||||||
|
*/
|
||||||
|
public class MemoryObject {
|
||||||
|
private static int diff = (int) Memory.getObjectExtraSize();
|
||||||
|
private byte storage[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an object that occupies given number of bytes.
|
||||||
|
*
|
||||||
|
* @param size size
|
||||||
|
*/
|
||||||
|
public MemoryObject(int size) {
|
||||||
|
if (size > diff)
|
||||||
|
storage = new byte[size - diff];
|
||||||
|
}
|
||||||
|
|
||||||
|
public final byte[] getStorage() {
|
||||||
|
return storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int getSize() {
|
||||||
|
return storage.length;
|
||||||
|
}
|
||||||
|
}
|
206
test/hotspot/jtreg/vmTestbase/nsk/share/gc/NonbranchyTree.java
Normal file
206
test/hotspot/jtreg/vmTestbase/nsk/share/gc/NonbranchyTree.java
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import nsk.share.test.ExecutionController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <tt>NonbranchyTree</tt> defines a tree structure. Each node of the tree
|
||||||
|
* always has one son. A node may have the second son with probability
|
||||||
|
* <tt>branchiness</tt>.
|
||||||
|
*/
|
||||||
|
public class NonbranchyTree {
|
||||||
|
|
||||||
|
/** Minimal size of each node (in bytes) */
|
||||||
|
public final static int MIN_NODE_SIZE = 20;
|
||||||
|
private Node root;
|
||||||
|
private Random random;
|
||||||
|
private int numberOfNodes;
|
||||||
|
private float branchiness;
|
||||||
|
private int size;
|
||||||
|
private ExecutionController controller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new tree with number of nodes not more than
|
||||||
|
* <tt>numberOfNodes</tt>. The implementation uses recursion to build the
|
||||||
|
* tree, so if <tt>StackOverflowError</tt> or <tt>OutOfMemoryError</tt> is
|
||||||
|
* thrown, the recursion is stopped and the method finishes building of the
|
||||||
|
* tree. Each node consists of <tt>byte[]</tt> of length <tt>size</tt>.
|
||||||
|
*
|
||||||
|
* @param numberOfNodes maximum number of nodes for the tree.
|
||||||
|
* @param branchiness probability for each node to have the second son.
|
||||||
|
* @param size number of bytes to store in a node.
|
||||||
|
*
|
||||||
|
* @throws <i>IllegalArgumentException</i> if <tt>numberOfNodes</tt> is
|
||||||
|
* less than 1; or <tt>branchiness</tt> is greater than 1, or less
|
||||||
|
* or equal than 0; or <tt>size</tt> is less than 1.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public NonbranchyTree(int numberOfNodes, float branchiness, int size) {
|
||||||
|
this(numberOfNodes, branchiness, size, new Random(System.currentTimeMillis()), null);
|
||||||
|
initTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
public NonbranchyTree(int numberOfNodes, float branchiness, int size, ExecutionController controller) {
|
||||||
|
this(numberOfNodes, branchiness, size, new Random(System.currentTimeMillis()), controller);
|
||||||
|
initTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
private NonbranchyTree(int numberOfNodes, float branchiness, int size, Random random, ExecutionController controller) {
|
||||||
|
this.numberOfNodes = numberOfNodes;
|
||||||
|
this.branchiness = branchiness;
|
||||||
|
this.size = size;
|
||||||
|
this.random = random;
|
||||||
|
this.controller = controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initTree() {
|
||||||
|
if (numberOfNodes < 1) {
|
||||||
|
throw new IllegalArgumentException("Illegal number of nodes: "
|
||||||
|
+ numberOfNodes + ", must be at "
|
||||||
|
+ "least 1.");
|
||||||
|
}
|
||||||
|
if ( (branchiness >= 1) || (branchiness <= 0) ) {
|
||||||
|
throw new IllegalArgumentException("Illegal value of branchiness: "
|
||||||
|
+ numberOfNodes + ", must be at "
|
||||||
|
+ "greater than 0 and less than "
|
||||||
|
+ " 1.");
|
||||||
|
}
|
||||||
|
if (size < 1) {
|
||||||
|
throw new IllegalArgumentException("Illegal size of nodes: "
|
||||||
|
+ size + ", must be at least 1.");
|
||||||
|
}
|
||||||
|
root = createTree(numberOfNodes, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new tree with specified number of nodes and size of each node
|
||||||
|
private Node createTree(int numberOfNodes, int size) {
|
||||||
|
// Make sure we respect the controller and stop test after
|
||||||
|
// given time.
|
||||||
|
if (controller != null && !controller.continueExecution()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node node = new Node(size);
|
||||||
|
try {
|
||||||
|
if (numberOfNodes == 0) {
|
||||||
|
// No more nodes need to be built
|
||||||
|
return null;
|
||||||
|
} else if (numberOfNodes == 1) {
|
||||||
|
return node;
|
||||||
|
} else if (numberOfNodes == 2) {
|
||||||
|
node.left = createTree(1, size);
|
||||||
|
return node;
|
||||||
|
} else {
|
||||||
|
// Create a few nodes
|
||||||
|
if (makeRightNode()) {
|
||||||
|
// The node will have two sons
|
||||||
|
int leftNodes = 1 + random.nextInt(numberOfNodes - 2);
|
||||||
|
int rightNodes = numberOfNodes - 1 - leftNodes;
|
||||||
|
|
||||||
|
node.left = createTree(leftNodes, size);
|
||||||
|
node.right = createTree(rightNodes, size);
|
||||||
|
} else {
|
||||||
|
// The node will have just one son
|
||||||
|
Node leftTree = createTree(numberOfNodes - 1, size);
|
||||||
|
node.left = leftTree;
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
} // if
|
||||||
|
} catch(StackOverflowError e) {
|
||||||
|
// No more memory for such long tree
|
||||||
|
return node;
|
||||||
|
} catch(OutOfMemoryError e) {
|
||||||
|
// No more memory for such long tree
|
||||||
|
return node;
|
||||||
|
} // try
|
||||||
|
} // createTree()
|
||||||
|
|
||||||
|
// Define the "branchiness" of the tree
|
||||||
|
private boolean makeRightNode() {
|
||||||
|
return (random.nextFloat() < branchiness);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bends the tree. A son of a leaf of the tree is set to the root node.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void bend() {
|
||||||
|
bend(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bend the tree: make a reference from a leat of the tree to the specified
|
||||||
|
// node
|
||||||
|
private void bend(Node markedNode) {
|
||||||
|
Node node = root;
|
||||||
|
|
||||||
|
while ( (node.left != null) || (node.right != null) )
|
||||||
|
node = node.left;
|
||||||
|
node.right = markedNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints the whole tree from the root to the defined PrintStream.
|
||||||
|
*
|
||||||
|
* @param out PrintStream to print the tree in
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void print(PrintStream out) {
|
||||||
|
print(out, root);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the sub-tree from the specified node and down
|
||||||
|
private void print(PrintStream out, Node node) {
|
||||||
|
node.print(out);
|
||||||
|
if (node.left != null)
|
||||||
|
print(out, node.left);
|
||||||
|
if (node.right != null)
|
||||||
|
print(out, node.right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The class defines a node of a tree
|
||||||
|
class Node {
|
||||||
|
Node left;
|
||||||
|
Node right;
|
||||||
|
byte[] core;
|
||||||
|
|
||||||
|
Node(int size) {
|
||||||
|
left = null;
|
||||||
|
right = null;
|
||||||
|
core = new byte[size];
|
||||||
|
|
||||||
|
// Initizlize the core array
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
core[i] = (byte) i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the node info
|
||||||
|
void print(PrintStream out) {
|
||||||
|
out.println("node = " + this + " (" + left + ", " + right + ")");
|
||||||
|
}
|
||||||
|
}
|
30
test/hotspot/jtreg/vmTestbase/nsk/share/gc/OOMStress.java
Normal file
30
test/hotspot/jtreg/vmTestbase/nsk/share/gc/OOMStress.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, 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.share.gc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marker interface to tell that a something stresses OOM.
|
||||||
|
*/
|
||||||
|
public interface OOMStress {
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 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.share.gc;
|
||||||
|
|
||||||
|
import nsk.share.runner.*;
|
||||||
|
import nsk.share.test.ExecutionController;
|
||||||
|
import nsk.share.Consts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that executes a number of tasks.
|
||||||
|
*
|
||||||
|
* How these tasks are used is determined by MultiRunner.
|
||||||
|
* Usually they are executed in separate threads in cycle
|
||||||
|
* for some time or for some iterations.
|
||||||
|
*
|
||||||
|
* @see nsk.share.runner.MultiRunner
|
||||||
|
* @see nsk.share.runner.ThreadsRunner
|
||||||
|
*/
|
||||||
|
public abstract class ThreadedGCTest extends GCTestBase implements MultiRunnerAware {
|
||||||
|
private MultiRunner runner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a task with index i.
|
||||||
|
*
|
||||||
|
* Subclasses should to override this method
|
||||||
|
* to created neccessary tasks.
|
||||||
|
*
|
||||||
|
* @param i index of task
|
||||||
|
* @return task to run or null
|
||||||
|
*/
|
||||||
|
protected abstract Runnable createRunnable(int i);
|
||||||
|
|
||||||
|
protected ExecutionController getExecutionController() {
|
||||||
|
return runner.getExecutionController();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final boolean runThreads() {
|
||||||
|
for (int i = 0; i < runParams.getNumberOfThreads(); ++i) {
|
||||||
|
Runnable runnable = createRunnable(i);
|
||||||
|
if (runnable != null)
|
||||||
|
runner.add(runnable);
|
||||||
|
}
|
||||||
|
runner.run();
|
||||||
|
return runner.isSuccessful();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
if (!runThreads())
|
||||||
|
setFailed(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setRunner(MultiRunner runner) {
|
||||||
|
this.runner = runner;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
package nsk.share.gc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object with two fields of same type.
|
||||||
|
*/
|
||||||
|
public class TwoFieldsObject<T> {
|
||||||
|
private T left, right;
|
||||||
|
|
||||||
|
public TwoFieldsObject(T left, T right) {
|
||||||
|
setLeft(left);
|
||||||
|
setRight(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setLeft(T left) {
|
||||||
|
this.left = left;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setRight(T right) {
|
||||||
|
this.right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final T getLeft() {
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final T getRight() {
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
}
|
5024
test/hotspot/jtreg/vmTestbase/nsk/share/gc/classes/Classes.java
Normal file
5024
test/hotspot/jtreg/vmTestbase/nsk/share/gc/classes/Classes.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc.gp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Garbage producer that uses another garbage producer
|
||||||
|
* to implement it's functionality.
|
||||||
|
*/
|
||||||
|
public abstract class DerivedProducer<T, P> implements GarbageProducer<T> {
|
||||||
|
private GarbageProducer<P> parent;
|
||||||
|
|
||||||
|
public DerivedProducer(GarbageProducer<P> parent) {
|
||||||
|
setParent(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected P createParent(long memory) {
|
||||||
|
return parent.create(memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void validateParent(P obj) {
|
||||||
|
parent.validate(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final GarbageProducer<P> getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setParent(GarbageProducer<P> parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc.gp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derived garbage producer that uses a memory strategy.
|
||||||
|
*/
|
||||||
|
public abstract class DerivedStrategyProducer<T, P> extends DerivedProducer<T, P> {
|
||||||
|
protected MemoryStrategy memoryStrategy;
|
||||||
|
|
||||||
|
public DerivedStrategyProducer(GarbageProducer<P> parent, MemoryStrategy memoryStrategy) {
|
||||||
|
super(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setMemoryStrategy(MemoryStrategy memoryStrategy) {
|
||||||
|
this.memoryStrategy = memoryStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final MemoryStrategy getMemoryStrategy() {
|
||||||
|
return memoryStrategy;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc.gp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface that defines a way to produce garbage.
|
||||||
|
*/
|
||||||
|
public interface GarbageProducer<T> {
|
||||||
|
/**
|
||||||
|
* Produce garbage of given size.
|
||||||
|
*
|
||||||
|
* @param memory size in bytes
|
||||||
|
* @return produced garbage
|
||||||
|
*/
|
||||||
|
public T create(long memory);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate earlier produced object.
|
||||||
|
*
|
||||||
|
* @param obj earlier produced garbage
|
||||||
|
* @throws TestFailure if validation fails
|
||||||
|
*/
|
||||||
|
public void validate(T obj);
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc.gp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marker interface for getting GarbageProducer.
|
||||||
|
*/
|
||||||
|
public interface GarbageProducer1Aware {
|
||||||
|
public void setGarbageProducer1(GarbageProducer gp);
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc.gp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marker interface for getting GarbageProducer.
|
||||||
|
*/
|
||||||
|
public interface GarbageProducerAware {
|
||||||
|
public void setGarbageProducer(GarbageProducer gp);
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc.gp;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import nsk.share.gc.gp.array.*;
|
||||||
|
import nsk.share.gc.gp.string.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for garbage producers
|
||||||
|
*/
|
||||||
|
public class GarbageProducers {
|
||||||
|
private List<GarbageProducer> primitiveArrayProducers;
|
||||||
|
private List<GarbageProducer> arrayProducers;
|
||||||
|
private List<GarbageProducer<String>> stringProducers;
|
||||||
|
private List<GarbageProducer> allProducers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all primitive array producers.
|
||||||
|
*/
|
||||||
|
public List<GarbageProducer> getPrimitiveArrayProducers() {
|
||||||
|
if (primitiveArrayProducers == null) {
|
||||||
|
primitiveArrayProducers = new ArrayList<GarbageProducer>();
|
||||||
|
primitiveArrayProducers.add(new ByteArrayProducer());
|
||||||
|
primitiveArrayProducers.add(new BooleanArrayProducer());
|
||||||
|
primitiveArrayProducers.add(new ShortArrayProducer());
|
||||||
|
primitiveArrayProducers.add(new CharArrayProducer());
|
||||||
|
primitiveArrayProducers.add(new IntArrayProducer());
|
||||||
|
primitiveArrayProducers.add(new LongArrayProducer());
|
||||||
|
primitiveArrayProducers.add(new FloatArrayProducer());
|
||||||
|
primitiveArrayProducers.add(new DoubleArrayProducer());
|
||||||
|
}
|
||||||
|
return primitiveArrayProducers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all array producers.
|
||||||
|
*/
|
||||||
|
public List<GarbageProducer> getArrayProducers() {
|
||||||
|
if (arrayProducers == null) {
|
||||||
|
arrayProducers = new ArrayList<GarbageProducer>();
|
||||||
|
arrayProducers.addAll(getPrimitiveArrayProducers());
|
||||||
|
arrayProducers.add(new ObjectArrayProducer());
|
||||||
|
}
|
||||||
|
return arrayProducers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all string producers.
|
||||||
|
*/
|
||||||
|
public List<GarbageProducer<String>> getStringProducers() {
|
||||||
|
if (stringProducers == null) {
|
||||||
|
stringProducers = new ArrayList<GarbageProducer<String>>();
|
||||||
|
stringProducers.add(new RandomStringProducer());
|
||||||
|
stringProducers.add(new InternedStringProducer());
|
||||||
|
}
|
||||||
|
return stringProducers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GarbageProducer> getAllProducers() {
|
||||||
|
if (allProducers == null) {
|
||||||
|
allProducers = new ArrayList<GarbageProducer>();
|
||||||
|
allProducers.addAll(getArrayProducers());
|
||||||
|
allProducers.addAll(getStringProducers());
|
||||||
|
}
|
||||||
|
return allProducers;
|
||||||
|
}
|
||||||
|
}
|
398
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/GarbageUtils.java
Normal file
398
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/GarbageUtils.java
Normal file
@ -0,0 +1,398 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc.gp;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.util.*;
|
||||||
|
import nsk.share.gc.gp.array.*;
|
||||||
|
import nsk.share.gc.gp.string.*;
|
||||||
|
import nsk.share.gc.gp.list.*;
|
||||||
|
import nsk.share.gc.gp.tree.*;
|
||||||
|
import nsk.share.gc.gp.misc.*;
|
||||||
|
import nsk.share.gc.gp.classload.*;
|
||||||
|
import nsk.share.gc.Memory;
|
||||||
|
import nsk.share.TestBug;
|
||||||
|
import nsk.share.test.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods for garbage producers.
|
||||||
|
*/
|
||||||
|
public final class GarbageUtils {
|
||||||
|
private static final int ALLOCATION_LIMIT = 50000000; //50 Mb
|
||||||
|
private static GarbageProducers garbageProducers;
|
||||||
|
private static List<GarbageProducer> primitiveArrayProducers;
|
||||||
|
private static List<GarbageProducer> arrayProducers;
|
||||||
|
private static final GarbageProducer byteArrayProducer = new ByteArrayProducer();
|
||||||
|
public static enum OOM_TYPE {
|
||||||
|
ANY (),
|
||||||
|
HEAP("Java heap space"),
|
||||||
|
METASPACE("Metaspace", "Compressed class space");
|
||||||
|
|
||||||
|
private final String[] expectedStrings;
|
||||||
|
OOM_TYPE(String... expectedStrings) {
|
||||||
|
this.expectedStrings = expectedStrings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given error message matches
|
||||||
|
* one of expected strings.
|
||||||
|
*/
|
||||||
|
public boolean accept(String errorMessage) {
|
||||||
|
if (expectedStrings == null || expectedStrings.length == 0 || errorMessage == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (String s: expectedStrings) {
|
||||||
|
if (errorMessage.indexOf(s) != -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Force loading of OOM_TYPE and calling of enum contrusctors when loading GarbageUtils class.
|
||||||
|
public static final Object[] thisIsGarbageArray_theOnlyPurposeForCreatingItAndDeclaringItPublicIsToInitializeIntancesOfOOMEnumberation = new Object[] { OOM_TYPE.ANY, OOM_TYPE.HEAP, OOM_TYPE.METASPACE };
|
||||||
|
|
||||||
|
// Force early loading of classes that might otherwise unexpectedly fail
|
||||||
|
// class loading during testing due to high memory pressure.
|
||||||
|
public static final StringWriter preloadStringWriter = new StringWriter(1);
|
||||||
|
public static final PrintWriter preloadPrintWriter = new PrintWriter(preloadStringWriter);
|
||||||
|
|
||||||
|
private GarbageUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eat memory using execution controller that waits for 2 minutes.
|
||||||
|
* @return number of OOME occured
|
||||||
|
*/
|
||||||
|
public static int eatMemory() {
|
||||||
|
return eatMemory(2 * 60 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eat memory using execution controller that waits for timeout.
|
||||||
|
* @return number of OOME occured
|
||||||
|
*/
|
||||||
|
public static int eatMemory(final long timeout) {
|
||||||
|
return eatMemory(new ExecutionController() {
|
||||||
|
final long initialTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(long stdIterations) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean iteration() {return false;}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean continueExecution() {
|
||||||
|
return System.currentTimeMillis() - initialTime < timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getIteration() {return 0;}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finish() {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eat memory using given execution controller and garbage producer.
|
||||||
|
*
|
||||||
|
* @param stresser execution controller
|
||||||
|
* @param gp garbage producer
|
||||||
|
* @return number of OOME occured
|
||||||
|
*/
|
||||||
|
public static int eatMemory(ExecutionController stresser) {
|
||||||
|
return eatMemory(stresser, byteArrayProducer, 50, 100, 2, OOM_TYPE.ANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eat memory using given execution controller and garbage producer.
|
||||||
|
*
|
||||||
|
* @param stresser execution controller
|
||||||
|
* @param gp garbage producer
|
||||||
|
* @return number of OOME occured
|
||||||
|
*/
|
||||||
|
public static int eatMemory(ExecutionController stresser, GarbageProducer gp) {
|
||||||
|
return eatMemory(stresser, gp, 50, 100, 2, OOM_TYPE.ANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eat memory using given garbage producer and given factor.
|
||||||
|
*
|
||||||
|
* @param gp garbage producer
|
||||||
|
* @param factor factor to divide the array size by
|
||||||
|
* @return number of OOME occured
|
||||||
|
*/
|
||||||
|
public static int eatMemory(ExecutionController stresser, GarbageProducer gp, long factor) {
|
||||||
|
return eatMemory(stresser, gp, 50, 100, factor, OOM_TYPE.ANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eat memory using default(byte[]) garbage producer.
|
||||||
|
*
|
||||||
|
* Note that this method can throw Failure if any exception
|
||||||
|
* is thrown while eating memory. To avoid OOM while allocating
|
||||||
|
* exception we preallocate it before the lunch starts. It means
|
||||||
|
* that exception stack trace does not correspond to the place
|
||||||
|
* where exception is thrown, but points at start of the method.
|
||||||
|
*
|
||||||
|
* @param stresser stresser
|
||||||
|
* @param initialFactor determines which portion of initial memory initial chunk will be
|
||||||
|
* @param minMemoryChunk determines when to stop
|
||||||
|
* @param factor factor to divide the array size by
|
||||||
|
* @return number of OOME occured
|
||||||
|
*/
|
||||||
|
public static int eatMemory(ExecutionController stresser,long initialFactor, long minMemoryChunk, long factor) {
|
||||||
|
return eatMemory(stresser, byteArrayProducer, initialFactor, minMemoryChunk, factor, OOM_TYPE.ANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eat memory using given garbage producer.
|
||||||
|
*
|
||||||
|
* Note that this method can throw Failure if any exception
|
||||||
|
* is thrown while eating memory. To avoid OOM while allocating
|
||||||
|
* exception we preallocate it before the lunch starts. It means
|
||||||
|
* that exception stack trace does not correspond to the place
|
||||||
|
* where exception is thrown, but points at start of the method.
|
||||||
|
*
|
||||||
|
* @param stresser stresser to use
|
||||||
|
* @param gp garbage producer
|
||||||
|
* @param initialFactor determines which portion of initial memory initial chunk will be
|
||||||
|
* @param minMemoryChunk determines when to stop
|
||||||
|
* @param factor factor to divide the array size by. A value of 0 means that method returns after first OOME
|
||||||
|
* @param type of OutOfMemory Exception: Java heap space or Metadata space
|
||||||
|
* @return number of OOME occured
|
||||||
|
*/
|
||||||
|
public static int eatMemory(ExecutionController stresser, GarbageProducer gp, long initialFactor, long minMemoryChunk, long factor) {
|
||||||
|
return eatMemory(stresser, gp, initialFactor, minMemoryChunk, factor, OOM_TYPE.ANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eat memory using given garbage producer.
|
||||||
|
*
|
||||||
|
* Note that this method can throw Failure if any exception
|
||||||
|
* is thrown while eating memory. To avoid OOM while allocating
|
||||||
|
* exception we preallocate it before the lunch starts. It means
|
||||||
|
* that exception stack trace does not correspond to the place
|
||||||
|
* where exception is thrown, but points at start of the method.
|
||||||
|
*
|
||||||
|
* @param stresser stresser to use
|
||||||
|
* @param gp garbage producer
|
||||||
|
* @param initialFactor determines which portion of initial memory initial chunk will be
|
||||||
|
* @param minMemoryChunk determines when to stop
|
||||||
|
* @param factor factor to divide the array size by. A value of 0 means that method returns after first OOME
|
||||||
|
* @param type of OutOfMemory Exception: Java heap space or Metadata space
|
||||||
|
* @return number of OOME occured
|
||||||
|
*/
|
||||||
|
public static int eatMemory(ExecutionController stresser, GarbageProducer gp, long initialFactor, long minMemoryChunk, long factor, OOM_TYPE type) {
|
||||||
|
int numberOfOOMEs = 0;
|
||||||
|
try {
|
||||||
|
StringWriter sw = new StringWriter(10000);
|
||||||
|
PrintWriter pw = new PrintWriter(sw);
|
||||||
|
byte[] someMemory = new byte[200000]; //200 Kb
|
||||||
|
try {
|
||||||
|
Runtime runtime = Runtime.getRuntime();
|
||||||
|
long maxMemory = runtime.maxMemory();
|
||||||
|
long maxMemoryChunk = maxMemory / initialFactor;
|
||||||
|
long chunk = maxMemoryChunk;
|
||||||
|
chunk = chunk > ALLOCATION_LIMIT ? ALLOCATION_LIMIT : chunk;
|
||||||
|
int allocations = 0;
|
||||||
|
List<Object> storage = new ArrayList<Object>();
|
||||||
|
|
||||||
|
while (chunk > minMemoryChunk && stresser.continueExecution()) {
|
||||||
|
try {
|
||||||
|
storage.add(gp.create(chunk));
|
||||||
|
if (Thread.currentThread().isInterrupted()) {
|
||||||
|
return numberOfOOMEs;
|
||||||
|
}
|
||||||
|
// if we are able to eat chunk*factor let
|
||||||
|
// try to increase size of chunk
|
||||||
|
if (chunk * factor < maxMemoryChunk
|
||||||
|
&& factor != 0 && allocations++ == factor + 1) {
|
||||||
|
chunk = chunk * factor;
|
||||||
|
allocations = 0;
|
||||||
|
}
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
someMemory = null;
|
||||||
|
if (type != OOM_TYPE.ANY) {
|
||||||
|
e.printStackTrace(pw);
|
||||||
|
pw.close();
|
||||||
|
if (type.accept(sw.toString())) {
|
||||||
|
numberOfOOMEs++;
|
||||||
|
} else {
|
||||||
|
// Trying to catch situation when Java generates OOM different type that test trying to catch
|
||||||
|
throw new TestBug("Test throw OOM of unexpected type." + sw.toString());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
numberOfOOMEs++;
|
||||||
|
}
|
||||||
|
allocations = 0;
|
||||||
|
if (factor == 0) {
|
||||||
|
return numberOfOOMEs;
|
||||||
|
} else {
|
||||||
|
chunk = chunk / factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
someMemory = null;
|
||||||
|
if (type != OOM_TYPE.ANY) {
|
||||||
|
e.printStackTrace(pw);
|
||||||
|
pw.close();
|
||||||
|
if (type.accept(sw.toString())) {
|
||||||
|
numberOfOOMEs++;
|
||||||
|
} else {
|
||||||
|
// Trying to catch situation when Java generates OOM different type that test trying to catch
|
||||||
|
throw new TestBug("Test throw OOM of unexpected type." + sw.toString());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
numberOfOOMEs++;
|
||||||
|
}
|
||||||
|
// all memory is eaten now even before we start, just return
|
||||||
|
}
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
numberOfOOMEs++;
|
||||||
|
}
|
||||||
|
return numberOfOOMEs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all primitive array producers.
|
||||||
|
*/
|
||||||
|
public static List<GarbageProducer> getPrimitiveArrayProducers() {
|
||||||
|
return getGarbageProducers().getPrimitiveArrayProducers();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all array producers.
|
||||||
|
*/
|
||||||
|
public static List<GarbageProducer> getArrayProducers() {
|
||||||
|
return getGarbageProducers().getArrayProducers();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine size of each object in array which will occupy given
|
||||||
|
* memory with distribution determined by given memory strategy.
|
||||||
|
*/
|
||||||
|
public static long getArraySize(long memory, MemoryStrategy memoryStrategy) {
|
||||||
|
return memoryStrategy.getSize(memory - Memory.getArrayExtraSize(), Memory.getReferenceSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine object count in array which will occupy given
|
||||||
|
* memory with distribution determined by given memory strategy.
|
||||||
|
*/
|
||||||
|
public static int getArrayCount(long memory, MemoryStrategy memoryStrategy) {
|
||||||
|
return memoryStrategy.getCount(memory - Memory.getArrayExtraSize(), Memory.getReferenceSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get garbage producer by identifier.
|
||||||
|
*
|
||||||
|
* @param id identifier
|
||||||
|
* @return garbage producer for this identifier
|
||||||
|
*/
|
||||||
|
public static GarbageProducer getGarbageProducer(String id) {
|
||||||
|
if (id == null || id.equals("byteArr"))
|
||||||
|
return new ByteArrayProducer();
|
||||||
|
else if (id.equals("booleanArr"))
|
||||||
|
return new BooleanArrayProducer();
|
||||||
|
else if (id.equals("shortArr"))
|
||||||
|
return new ShortArrayProducer();
|
||||||
|
else if (id.equals("charArr"))
|
||||||
|
return new CharArrayProducer();
|
||||||
|
else if (id.equals("intArr"))
|
||||||
|
return new IntArrayProducer();
|
||||||
|
else if (id.equals("longArr"))
|
||||||
|
return new LongArrayProducer();
|
||||||
|
else if (id.equals("floatArr"))
|
||||||
|
return new FloatArrayProducer();
|
||||||
|
else if (id.equals("doubleArr"))
|
||||||
|
return new DoubleArrayProducer();
|
||||||
|
else if (id.equals("objectArr"))
|
||||||
|
return new ObjectArrayProducer();
|
||||||
|
else if (id.equals("randomString"))
|
||||||
|
return new RandomStringProducer();
|
||||||
|
else if (id.equals("simpleString"))
|
||||||
|
return new SimpleStringProducer();
|
||||||
|
else if (id.startsWith("interned("))
|
||||||
|
return new InternedStringProducer(getGarbageProducer(getInBrackets(id)));
|
||||||
|
else if (id.startsWith("linearList("))
|
||||||
|
return new LinearListProducer(MemoryStrategy.fromString(getInBrackets(id)));
|
||||||
|
else if (id.startsWith("circularList("))
|
||||||
|
return new CircularListProducer(MemoryStrategy.fromString(getInBrackets(id)));
|
||||||
|
else if (id.startsWith("nonbranchyTree("))
|
||||||
|
return new NonbranchyTreeProducer(MemoryStrategy.fromString(getInBrackets(id)));
|
||||||
|
else if (id.equals("class"))
|
||||||
|
return new GeneratedClassProducer();
|
||||||
|
else if (id.startsWith("hashed("))
|
||||||
|
return new HashedGarbageProducer(getGarbageProducer(getInBrackets(id)));
|
||||||
|
else if (id.startsWith("random("))
|
||||||
|
return new RandomProducer(getGarbageProducerList(getInBrackets(id)));
|
||||||
|
else if (id.startsWith("twofields("))
|
||||||
|
return new TwoFieldsObjectProducer(getGarbageProducer(getInBrackets(id)));
|
||||||
|
else if (id.startsWith("arrayof("))
|
||||||
|
return new ArrayOfProducer(getGarbageProducer(getInBrackets(id)));
|
||||||
|
else if (id.startsWith("trace("))
|
||||||
|
return new TraceProducer(getGarbageProducer(getInBrackets(id)));
|
||||||
|
else
|
||||||
|
throw new TestBug("Invalid garbage producer identifier: " + id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getInBrackets(String s) {
|
||||||
|
int n1 = s.indexOf('(');
|
||||||
|
if (n1 == -1)
|
||||||
|
throw new TestBug("Opening bracket not found: " + s);
|
||||||
|
int n2 = s.lastIndexOf(')');
|
||||||
|
if (n2 == -1)
|
||||||
|
throw new TestBug("Closing bracket not found: " + s);
|
||||||
|
return s.substring(n1 + 1, n2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<GarbageProducer> getGarbageProducerList(String s) {
|
||||||
|
if (s.equals("primitiveArrays"))
|
||||||
|
return getPrimitiveArrayProducers();
|
||||||
|
else if (s.equals("arrays"))
|
||||||
|
return getArrayProducers();
|
||||||
|
else {
|
||||||
|
String[] ids = s.split(",");
|
||||||
|
List<GarbageProducer> garbageProducers = new ArrayList<GarbageProducer>(ids.length);
|
||||||
|
for (int i = 0; i < ids.length; ++i)
|
||||||
|
garbageProducers.add(getGarbageProducer(ids[i]));
|
||||||
|
return garbageProducers;
|
||||||
|
//throw new TestBug("Invalid id for list of garbage producers: " + id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GarbageProducers getGarbageProducers() {
|
||||||
|
if (garbageProducers == null)
|
||||||
|
garbageProducers = new GarbageProducers();
|
||||||
|
return garbageProducers;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc.gp;
|
||||||
|
|
||||||
|
import nsk.share.TestBug;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class encapsulates notions like "many objects of small size",
|
||||||
|
* "small number of objects of big size".
|
||||||
|
*/
|
||||||
|
public abstract class MemoryStrategy {
|
||||||
|
private static int smallNumber = 100;
|
||||||
|
public abstract long getSize(long memory);
|
||||||
|
public abstract long getSize(long memory, long objectExtra);
|
||||||
|
public abstract int getCount(long memory);
|
||||||
|
public abstract int getCount(long memory, long objectExtra);
|
||||||
|
|
||||||
|
protected MemoryStrategy() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Small object size, big number of objects.
|
||||||
|
*/
|
||||||
|
public static final MemoryStrategy LOW = new MemoryStrategy() {
|
||||||
|
public long getSize(long memory) {
|
||||||
|
return getSize(memory, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSize(long memory, long objectExtra) {
|
||||||
|
return smallNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCount(long memory) {
|
||||||
|
return getCount(memory, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCount(long memory, long objectExtra) {
|
||||||
|
return (int) Math.min(Integer.MAX_VALUE, memory / (getSize(memory) + objectExtra));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "low";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Medium object size, medium number of objects.
|
||||||
|
*/
|
||||||
|
public static final MemoryStrategy MEDIUM = new MemoryStrategy() {
|
||||||
|
public long getSize(long memory) {
|
||||||
|
return getSize(memory, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSize(long memory, long objectExtra) {
|
||||||
|
return Math.round(Math.floor(Math.sqrt(memory)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCount(long memory) {
|
||||||
|
return getCount(memory, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCount(long memory, long objectExtra) {
|
||||||
|
return (int) Math.min(Integer.MAX_VALUE, memory / (getSize(memory) + objectExtra));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "medium";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Big object size, small number of objects.
|
||||||
|
*/
|
||||||
|
public static final MemoryStrategy HIGH = new MemoryStrategy() {
|
||||||
|
public long getSize(long memory) {
|
||||||
|
return getSize(memory, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSize(long memory, long objectExtra) {
|
||||||
|
return memory / getCount(memory, objectExtra);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCount(long memory) {
|
||||||
|
return getCount(memory, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCount(long memory, long objectExtra) {
|
||||||
|
return smallNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "high";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get memory strategy by identifier.
|
||||||
|
*
|
||||||
|
* @param id identifier
|
||||||
|
* @return memory strategy for this identifier
|
||||||
|
* @throws TestBug if id is invalid
|
||||||
|
*/
|
||||||
|
public static MemoryStrategy fromString(String id) {
|
||||||
|
if (id.equalsIgnoreCase("low"))
|
||||||
|
return LOW;
|
||||||
|
else if (id.equalsIgnoreCase("medium"))
|
||||||
|
return MEDIUM;
|
||||||
|
else if (id.equalsIgnoreCase("high"))
|
||||||
|
return HIGH;
|
||||||
|
else
|
||||||
|
throw new TestBug("Unknown memory strategy identifier: " + id);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc.gp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marker interface for getting MemoryStrategy.
|
||||||
|
*/
|
||||||
|
public interface MemoryStrategyAware {
|
||||||
|
public void setMemoryStrategy(MemoryStrategy memoryStrategy);
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc.gp;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import nsk.share.test.LocalRandom;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Garbage producer that randomly creates objects using
|
||||||
|
* one garbage producer from the list.
|
||||||
|
*/
|
||||||
|
public class RandomProducer<T> implements GarbageProducer<T> {
|
||||||
|
private List<GarbageProducer<T>> producers;
|
||||||
|
|
||||||
|
public RandomProducer(List<GarbageProducer<T>> producers) {
|
||||||
|
this.producers = producers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T create(long memory) {
|
||||||
|
return producers.get(LocalRandom.nextInt(producers.size())).create(memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validate(T obj) {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc.gp.array;
|
||||||
|
|
||||||
|
import nsk.share.gc.gp.GarbageProducer;
|
||||||
|
import nsk.share.gc.gp.DerivedProducer;
|
||||||
|
import nsk.share.gc.gp.GarbageUtils;
|
||||||
|
import nsk.share.gc.gp.MemoryStrategy;
|
||||||
|
import nsk.share.gc.Memory;
|
||||||
|
import nsk.share.TestFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GarbageProducer implementation that produces arrays of objects
|
||||||
|
* determined by parent garbage producer. A memory strategy is
|
||||||
|
* used to determine how memory is distributed between array size
|
||||||
|
* and size of each object in array.
|
||||||
|
*/
|
||||||
|
public class ArrayOfProducer<T> extends DerivedProducer<Object[], T> {
|
||||||
|
private int n;
|
||||||
|
|
||||||
|
public ArrayOfProducer(GarbageProducer<T> parent, int n) {
|
||||||
|
super(parent);
|
||||||
|
this.n = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayOfProducer(GarbageProducer<T> parent) {
|
||||||
|
this(parent, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] create(long memory) {
|
||||||
|
Object[] array = new Object[n];
|
||||||
|
long objectSize = (memory - Memory.getArrayExtraSize() - Memory.getReferenceSize() * n) / n;
|
||||||
|
for (int i = 0; i < n; ++i)
|
||||||
|
array[i] = createParent(objectSize);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validate(Object[] obj) {
|
||||||
|
for (int i = 0; i < obj.length; ++i)
|
||||||
|
validateParent((T) obj[i]);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc.gp.array;
|
||||||
|
|
||||||
|
import nsk.share.gc.gp.GarbageProducer;
|
||||||
|
import nsk.share.gc.gp.DerivedStrategyProducer;
|
||||||
|
import nsk.share.gc.gp.GarbageUtils;
|
||||||
|
import nsk.share.gc.gp.MemoryStrategy;
|
||||||
|
import nsk.share.gc.Memory;
|
||||||
|
import nsk.share.TestFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GarbageProducer implementation that produces arrays of objects
|
||||||
|
* determined by parent garbage producer. A memory strategy is
|
||||||
|
* used to determine how memory is distributed between array size
|
||||||
|
* and size of each object in array.
|
||||||
|
*/
|
||||||
|
public class ArrayProducer<T> extends DerivedStrategyProducer<Object[], T> {
|
||||||
|
public ArrayProducer(GarbageProducer<T> parent, MemoryStrategy memoryStrategy) {
|
||||||
|
super(parent, memoryStrategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] create(long memory) {
|
||||||
|
long objectSize = GarbageUtils.getArraySize(memory, memoryStrategy);
|
||||||
|
int objectCount = GarbageUtils.getArrayCount(memory, memoryStrategy);
|
||||||
|
Object[] array = new Object[objectCount];
|
||||||
|
for (int i = 0; i < objectCount; ++i)
|
||||||
|
array[i] = createParent(objectSize);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validate(Object[] obj) {
|
||||||
|
for (int i = 0; i < obj.length; ++i)
|
||||||
|
validateParent((T) obj[i]);
|
||||||
|
}
|
||||||
|
}
|
@ -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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc.gp.array;
|
||||||
|
|
||||||
|
import nsk.share.test.LocalRandom;
|
||||||
|
import nsk.share.gc.gp.GarbageProducer;
|
||||||
|
import nsk.share.gc.Memory;
|
||||||
|
import nsk.share.TestFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GarbageProducer implementation that produces byte arrays.
|
||||||
|
*/
|
||||||
|
public class BooleanArrayProducer implements GarbageProducer<boolean[]> {
|
||||||
|
public boolean[] create(long memory) {
|
||||||
|
boolean[] arr = new boolean[Memory.getArrayLength(memory, Memory.getBooleanSize())];
|
||||||
|
LocalRandom.nextBooleans(arr);
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validate(boolean[] arr) {
|
||||||
|
LocalRandom.validate(arr);
|
||||||
|
}
|
||||||
|
}
|
@ -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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc.gp.array;
|
||||||
|
|
||||||
|
import nsk.share.test.LocalRandom;
|
||||||
|
import nsk.share.gc.gp.GarbageProducer;
|
||||||
|
import nsk.share.gc.Memory;
|
||||||
|
import nsk.share.TestFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GarbageProducer implementation that produces byte arrays.
|
||||||
|
*/
|
||||||
|
public class ByteArrayProducer implements GarbageProducer<byte[]> {
|
||||||
|
public byte[] create(long memory) {
|
||||||
|
byte[] arr = new byte[Memory.getArrayLength(memory, 1)];
|
||||||
|
LocalRandom.nextBytes(arr);
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validate(byte[] arr) {
|
||||||
|
LocalRandom.validate(arr);
|
||||||
|
}
|
||||||
|
}
|
@ -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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc.gp.array;
|
||||||
|
|
||||||
|
import nsk.share.test.LocalRandom;
|
||||||
|
import nsk.share.gc.gp.GarbageProducer;
|
||||||
|
import nsk.share.gc.Memory;
|
||||||
|
import nsk.share.TestFailure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GarbageProducer implementation that produces int arrays.
|
||||||
|
*/
|
||||||
|
public class CharArrayProducer implements GarbageProducer<char[]> {
|
||||||
|
public char[] create(long memory) {
|
||||||
|
char[] arr = new char[Memory.getArrayLength(memory, Memory.getCharSize())];
|
||||||
|
LocalRandom.nextChars(arr);
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validate(char[] arr) {
|
||||||
|
LocalRandom.validate(arr);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc.gp.array;
|
||||||
|
|
||||||
|
import nsk.share.test.LocalRandom;
|
||||||
|
import nsk.share.gc.gp.GarbageProducer;
|
||||||
|
import nsk.share.gc.Memory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GarbageProducer implementation that produces double arrays.
|
||||||
|
*/
|
||||||
|
public class DoubleArrayProducer implements GarbageProducer<double[]> {
|
||||||
|
public double[] create(long memory) {
|
||||||
|
double[] arr = new double[Memory.getArrayLength(memory, Memory.getDoubleSize())];
|
||||||
|
LocalRandom.nextDoubles(arr);
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validate(double[] arr) {
|
||||||
|
LocalRandom.validate(arr);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nsk.share.gc.gp.array;
|
||||||
|
|
||||||
|
import nsk.share.test.LocalRandom;
|
||||||
|
import nsk.share.gc.gp.GarbageProducer;
|
||||||
|
import nsk.share.gc.Memory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GarbageProducer implementation that produces float arrays.
|
||||||
|
*/
|
||||||
|
public class FloatArrayProducer implements GarbageProducer<float[]> {
|
||||||
|
public float[] create(long memory) {
|
||||||
|
float[] arr = new float[Memory.getArrayLength(memory, Memory.getFloatSize())];
|
||||||
|
LocalRandom.nextFloats(arr);
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validate(float[] arr) {
|
||||||
|
LocalRandom.validate(arr);
|
||||||
|
}
|
||||||
|
}
|
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