8199643: [TESTBUG] Open source common VM testbase code

Reviewed-by: vlivanov, erikj, mseledtsov, gthornbr
This commit is contained in:
Igor Ignatyev 2018-04-30 18:10:24 -07:00
parent 1298458a1d
commit 08855df46a
331 changed files with 58155 additions and 0 deletions

View File

@ -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

View 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();
}
}

View 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();
}
}

View 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.

View 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);
}
}

View 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&nbsp;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>&lt;<i>${ARCH}</i>&gt; -
* architecture name
* <li> <code>-waittime=</code>&lt;<i>minutes</i>&gt; -
* 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);
}
}
}

View 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);
}
}

View 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) {
}
}
}
}

View 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;
}

View 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();
}
}

View 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());
}
}

View 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() {
}
}

View File

@ -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);
}
}

View 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);
}
}

View 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));
}
}

View 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;
}

View File

@ -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();
}
}

View 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

View 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 );
}
}
}

View 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;
}
}

View 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();
}
}

View 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;
}
}

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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();
}
}

View 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));
}
}
}

View 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();
}

View File

@ -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);
}
}
}

View 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);
}
}

View 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 + ")";
}
}

View 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;
}
}

View 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);
}
}
}

View 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=&lt;stress_level&gt;</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");
}
}

View 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.
---------------------------------------------------------------------------------

View 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);
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View 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);
}
}

View 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);
}
}

View 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);
}
}

View 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);
}
}
}

View 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());
}
}

View 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;
}
}

View File

@ -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;
}
}

View 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.
*/
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;
}
}

View 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();
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View 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);
}
}

View File

@ -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();
}
}

View 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;
}
}

View File

@ -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);
}
}

View 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;
}
}

View 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

View 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 */

View File

@ -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);
}
}
}

View File

@ -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();
}
}
}

View File

@ -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 {
}

View 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

View 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();
}
}
}

View File

@ -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);
}
}

View 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

View 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;
}
}

View File

@ -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);
}
}

File diff suppressed because it is too large Load Diff

View 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();
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View 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();
}
}

View 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;
}
}
}

View File

@ -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);
}

View 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;
}
}

View 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;
}
}

View File

@ -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;
}
}

View 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;
}
}

View 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);
}
}

View 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;
}
}

View 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 + ")");
}
}

View 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 {
}

View File

@ -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;
}
}

View File

@ -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;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}
}

View 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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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) {
}
}

View File

@ -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]);
}
}

View File

@ -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]);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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