--- a/make/common/TestFilesCompilation.gmk Wed Jul 05 22:08:56 2017 +0200
+++ b/make/common/TestFilesCompilation.gmk Fri Aug 26 10:02:44 2016 -0700
@@ -86,6 +86,7 @@
LANG := C, \
CFLAGS := $$($1_CFLAGS) $$($1_CFLAGS_$$($1_PREFIX)$$(name)), \
LDFLAGS := $$($1_LDFLAGS) $$($1_LDFLAGS_$$($1_PREFIX)$$(name)), \
+ LIBS := $$($1_LIBS_$$($1_PREFIX)$$(name)), \
OPTIMIZATION := LOW, \
)) \
$$(eval $1 += $$(BUILD_TEST_$$(name)) ) \
--- a/make/test/BuildTestLib.gmk Wed Jul 05 22:08:56 2017 +0200
+++ b/make/test/BuildTestLib.gmk Fri Aug 26 10:02:44 2016 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -48,7 +48,7 @@
# test-lib.jar will contain only hprof classes until JDK-8081381 is resolved
$(eval $(call SetupJavaCompilation, BUILD_TEST_LIB_JAR, \
SETUP := GENERATE_USINGJDKBYTECODE, \
- SRC := $(TEST_LIB_SOURCE_DIR)/share/classes/jdk/test/lib/hprof, \
+ SRC := $(TEST_LIB_SOURCE_DIR)/jdk/test/lib/hprof, \
BIN := $(TEST_LIB_SUPPORT)/test-lib_classes, \
JAR := $(TEST_LIB_SUPPORT)/test-lib.jar, \
))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/ClassFileInstaller.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.ByteArrayInputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * Dump a class file for a class on the class path in the current directory, or
+ * in the specified JAR file. This class is usually used when you build a class
+ * from a test library, but want to use this class in a sub-process.
+ *
+ * For example, to build the following library class:
+ * test/lib/sun/hotspot/WhiteBox.java
+ *
+ * You would use the following tags:
+ *
+ * @library /test/lib
+ * @build sun.hotspot.WhiteBox
+ *
+ * JTREG would build the class file under
+ * ${JTWork}/classes/test/lib/sun/hotspot/WhiteBox.class
+ *
+ * With you run your main test class using "@run main MyMainClass", JTREG would setup the
+ * -classpath to include "${JTWork}/classes/test/lib/", so MyMainClass would be able to
+ * load the WhiteBox class.
+ *
+ * However, if you run a sub process, and do not wish to use the exact same -classpath,
+ * You can use ClassFileInstaller to ensure that WhiteBox is available in the current
+ * directory of your test:
+ *
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *
+ * Or, you can use the -jar option to store the class in the specified JAR file. If a relative
+ * path name is given, the JAR file would be relative to the current directory of
+ *
+ * @run main ClassFileInstaller -jar myjar.jar sun.hotspot.WhiteBox
+ */
+public class ClassFileInstaller {
+ /**
+ * You can enable debug tracing of ClassFileInstaller by running JTREG with
+ * jtreg -DClassFileInstaller.debug=true ... <names of tests>
+ */
+ public static boolean DEBUG = Boolean.getBoolean("ClassFileInstaller.debug");
+
+ /**
+ * @param args The names of the classes to dump
+ * @throws Exception
+ */
+ public static void main(String... args) throws Exception {
+ if (args.length > 1 && args[0].equals("-jar")) {
+ if (args.length < 2) {
+ throw new RuntimeException("Usage: ClassFileInstaller <options> <classes>\n" +
+ "where possible options include:\n" +
+ " -jar <path> Write to the JAR file <path>");
+ }
+ writeJar(args[1], null, args, 2, args.length);
+ } else {
+ if (DEBUG) {
+ System.out.println("ClassFileInstaller: Writing to " + System.getProperty("user.dir"));
+ }
+ for (String arg : args) {
+ writeClassToDisk(arg);
+ }
+ }
+ }
+
+ public static class Manifest {
+ private InputStream in;
+
+ private Manifest(InputStream in) {
+ this.in = in;
+ }
+
+ static Manifest fromSourceFile(String fileName) throws Exception {
+ String pathName = System.getProperty("test.src") + File.separator + fileName;
+ return new Manifest(new FileInputStream(pathName));
+ }
+
+ // Example:
+ // String manifest = "Premain-Class: RedefineClassHelper\n" +
+ // "Can-Redefine-Classes: true\n";
+ // ClassFileInstaller.writeJar("redefineagent.jar",
+ // ClassFileInstaller.Manifest.fromString(manifest),
+ // "RedefineClassHelper");
+ static Manifest fromString(String manifest) throws Exception {
+ return new Manifest(new ByteArrayInputStream(manifest.getBytes()));
+ }
+
+ public InputStream getInputStream() {
+ return in;
+ }
+ }
+
+ private static void writeJar(String jarFile, Manifest manifest, String classes[], int from, int to) throws Exception {
+ if (DEBUG) {
+ System.out.println("ClassFileInstaller: Writing to " + getJarPath(jarFile));
+ }
+
+ (new File(jarFile)).delete();
+ FileOutputStream fos = new FileOutputStream(jarFile);
+ ZipOutputStream zos = new ZipOutputStream(fos);
+
+ // The manifest must be the first or second entry. See comments in JarInputStream
+ // constructor and JDK-5046178.
+ if (manifest != null) {
+ writeToDisk(zos, "META-INF/MANIFEST.MF", manifest.getInputStream());
+ }
+
+ for (int i=from; i<to; i++) {
+ writeClassToDisk(zos, classes[i]);
+ }
+
+ zos.close();
+ fos.close();
+ }
+
+ /*
+ * You can call ClassFileInstaller.writeJar() from your main test class instead of
+ * using "@run ClassFileInstaller -jar ...". E.g.,
+ *
+ * String jarPath = ClassFileInstaller.getJarPath("myjar.jar", "sun.hotspot.WhiteBox")
+ *
+ * If you call this API, make sure you build ClassFileInstaller with the following tags:
+ *
+ * @library testlibrary
+ * @build ClassFileInstaller
+ */
+ public static String writeJar(String jarFile, String... classes) throws Exception {
+ writeJar(jarFile, null, classes, 0, classes.length);
+ return getJarPath(jarFile);
+ }
+
+ public static String writeJar(String jarFile, Manifest manifest, String... classes) throws Exception {
+ writeJar(jarFile, manifest, classes, 0, classes.length);
+ return getJarPath(jarFile);
+ }
+
+ /**
+ * This returns the absolute path to the file specified in "@ClassFileInstaller -jar myjar.jar",
+ * In your test program, instead of using the JAR file name directly:
+ *
+ * String jarPath = "myjar.jar";
+ *
+ * you should call this function, like:
+ *
+ * String jarPath = ClassFileInstaller.getJarPath("myjar.jar")
+ *
+ * The reasons are:
+ * (1) Using absolute path makes it easy to cut-and-paste from the JTR file and rerun your
+ * test in any directory.
+ * (2) In the future, we may make the JAR file name unique to avoid clobbering
+ * during parallel JTREG execution.
+ *
+ */
+ public static String getJarPath(String jarFileName) {
+ return new File(jarFileName).getAbsolutePath();
+ }
+
+ public static void writeClassToDisk(String className) throws Exception {
+ writeClassToDisk((ZipOutputStream)null, className);
+ }
+ private static void writeClassToDisk(ZipOutputStream zos, String className) throws Exception {
+ writeClassToDisk(zos, className, "");
+ }
+
+ public static void writeClassToDisk(String className, String prependPath) throws Exception {
+ writeClassToDisk(null, className, prependPath);
+ }
+ private static void writeClassToDisk(ZipOutputStream zos, String className, String prependPath) throws Exception {
+ ClassLoader cl = ClassFileInstaller.class.getClassLoader();
+
+ // Convert dotted class name to a path to a class file
+ String pathName = className.replace('.', '/').concat(".class");
+ InputStream is = cl.getResourceAsStream(pathName);
+ if (is == null) {
+ throw new RuntimeException("Failed to find " + pathName);
+ }
+ if (prependPath.length() > 0) {
+ pathName = prependPath + "/" + pathName;
+ }
+ writeToDisk(zos, pathName, is);
+ }
+
+ public static void writeClassToDisk(String className, byte[] bytecode) throws Exception {
+ writeClassToDisk(null, className, bytecode);
+ }
+ private static void writeClassToDisk(ZipOutputStream zos, String className, byte[] bytecode) throws Exception {
+ writeClassToDisk(zos, className, bytecode, "");
+ }
+
+ public static void writeClassToDisk(String className, byte[] bytecode, String prependPath) throws Exception {
+ writeClassToDisk(null, className, bytecode, prependPath);
+ }
+ private static void writeClassToDisk(ZipOutputStream zos, String className, byte[] bytecode, String prependPath) throws Exception {
+ // Convert dotted class name to a path to a class file
+ String pathName = className.replace('.', '/').concat(".class");
+ if (prependPath.length() > 0) {
+ pathName = prependPath + "/" + pathName;
+ }
+ writeToDisk(zos, pathName, new ByteArrayInputStream(bytecode));
+ }
+
+ private static void writeToDisk(ZipOutputStream zos, String pathName, InputStream is) throws Exception {
+ if (DEBUG) {
+ System.out.println("ClassFileInstaller: Writing " + pathName);
+ }
+ if (zos != null) {
+ ZipEntry ze = new ZipEntry(pathName);
+ zos.putNextEntry(ze);
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = is.read(buf))>0){
+ zos.write(buf, 0, len);
+ }
+ } else {
+ // Create the class file's package directory
+ Path p = Paths.get(pathName);
+ if (pathName.contains("/")) {
+ Files.createDirectories(p.getParent());
+ }
+ // Create the class file
+ Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING);
+ }
+ is.close();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/RedefineClassHelper.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.PrintWriter;
+import java.lang.instrument.*;
+import jdk.test.lib.InMemoryJavaCompiler;
+
+/*
+ * Helper class to write tests that redefine classes.
+ * When main method is run, it will create a redefineagent.jar that can be used
+ * with the -javaagent option to support redefining classes in jtreg tests.
+ *
+ * See sample test in test/testlibrary_tests/RedefineClassTest.java
+ */
+public class RedefineClassHelper {
+
+ public static Instrumentation instrumentation;
+ public static void premain(String agentArgs, Instrumentation inst) {
+ instrumentation = inst;
+ }
+
+ /**
+ * Redefine a class
+ *
+ * @param clazz Class to redefine
+ * @param javacode String with the new java code for the class to be redefined
+ */
+ public static void redefineClass(Class clazz, String javacode) throws Exception {
+ byte[] bytecode = InMemoryJavaCompiler.compile(clazz.getName(), javacode);
+ redefineClass(clazz, bytecode);
+ }
+
+ /**
+ * Redefine a class
+ *
+ * @param clazz Class to redefine
+ * @param bytecode byte[] with the new class
+ */
+ public static void redefineClass(Class clazz, byte[] bytecode) throws Exception {
+ instrumentation.redefineClasses(new ClassDefinition(clazz, bytecode));
+ }
+
+ /**
+ * Main method to be invoked before test to create the redefineagent.jar
+ */
+ public static void main(String[] args) throws Exception {
+ ClassFileInstaller.main("RedefineClassHelper");
+
+ PrintWriter pw = new PrintWriter("MANIFEST.MF");
+ pw.println("Premain-Class: RedefineClassHelper");
+ pw.println("Can-Redefine-Classes: true");
+ pw.close();
+
+ sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+ if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineClassHelper.class" })) {
+ throw new Exception("jar operation failed");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/Asserts.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,620 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib;
+
+import java.util.Objects;
+
+/**
+ * Asserts that can be used for verifying assumptions in tests.
+ *
+ * An assertion will throw a {@link RuntimeException} if the assertion isn't true.
+ * All the asserts can be imported into a test by using a static import:
+ *
+ * <pre>
+ * {@code
+ * import static jdk.testlibrary.Asserts.*;
+ * }
+ *
+ * Always provide a message describing the assumption if the line number of the
+ * failing assertion isn't enough to understand why the assumption failed. For
+ * example, if the assertion is in a loop or in a method that is called
+ * multiple times, then the line number won't provide enough context to
+ * understand the failure.
+ * </pre>
+ */
+public class Asserts {
+
+ /**
+ * Shorthand for {@link #assertLessThan(Comparable, Comparable)}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertLessThan(Comparable, Comparable)
+ */
+ public static <T extends Comparable<T>> void assertLT(T lhs, T rhs) {
+ assertLessThan(lhs, rhs);
+ }
+
+ /**
+ * Shorthand for {@link #assertLessThan(Comparable, Comparable, String)}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @see #assertLessThan(Comparable, Comparable, String)
+ */
+ public static <T extends Comparable<T>> void assertLT(T lhs, T rhs, String msg) {
+ assertLessThan(lhs, rhs, msg);
+ }
+
+ /**
+ * Calls {@link #assertLessThan(Comparable, Comparable, String)} with a default message.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertLessThan(Comparable, Comparable, String)
+ */
+ public static <T extends Comparable<T>> void assertLessThan(T lhs, T rhs) {
+ assertLessThan(lhs, rhs, null);
+ }
+
+ /**
+ * Asserts that {@code lhs} is less than {@code rhs}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static <T extends Comparable<T>>void assertLessThan(T lhs, T rhs, String msg) {
+ if (!(compare(lhs, rhs, msg) < 0)) {
+ msg = Objects.toString(msg, "assertLessThan")
+ + ": expected that " + Objects.toString(lhs)
+ + " < " + Objects.toString(rhs);
+ fail(msg);
+ }
+ }
+
+ /**
+ * Shorthand for {@link #assertLessThanOrEqual(Comparable, Comparable)}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertLessThanOrEqual(Comparable, Comparable)
+ */
+ public static <T extends Comparable<T>> void assertLTE(T lhs, T rhs) {
+ assertLessThanOrEqual(lhs, rhs);
+ }
+
+ /**
+ * Shorthand for {@link #assertLessThanOrEqual(Comparable, Comparable, String)}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @see #assertLessThanOrEqual(Comparable, Comparable, String)
+ */
+ public static <T extends Comparable<T>> void assertLTE(T lhs, T rhs, String msg) {
+ assertLessThanOrEqual(lhs, rhs, msg);
+ }
+
+ /**
+ * Calls {@link #assertLessThanOrEqual(Comparable, Comparable, String)} with a default message.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertLessThanOrEqual(Comparable, Comparable, String)
+ */
+ public static <T extends Comparable<T>> void assertLessThanOrEqual(T lhs, T rhs) {
+ assertLessThanOrEqual(lhs, rhs, null);
+ }
+
+ /**
+ * Asserts that {@code lhs} is less than or equal to {@code rhs}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static <T extends Comparable<T>> void assertLessThanOrEqual(T lhs, T rhs, String msg) {
+ if (!(compare(lhs, rhs, msg) <= 0)) {
+ msg = Objects.toString(msg, "assertLessThanOrEqual")
+ + ": expected that " + Objects.toString(lhs)
+ + " <= " + Objects.toString(rhs);
+ fail(msg);
+ }
+ }
+
+ /**
+ * Shorthand for {@link #assertEquals(Object, Object)}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertEquals(Object, Object)
+ */
+ public static void assertEQ(Object lhs, Object rhs) {
+ assertEquals(lhs, rhs);
+ }
+
+ /**
+ * Shorthand for {@link #assertEquals(Object, Object, String)}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @see #assertEquals(Object, Object, String)
+ */
+ public static void assertEQ(Object lhs, Object rhs, String msg) {
+ assertEquals(lhs, rhs, msg);
+ }
+
+ /**
+ * Calls {@link #assertEquals(java.lang.Object, java.lang.Object, java.lang.String)} with a default message.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertEquals(Object, Object, String)
+ */
+ public static void assertEquals(Object lhs, Object rhs) {
+ assertEquals(lhs, rhs, null);
+ }
+
+ /**
+ * Asserts that {@code lhs} is equal to {@code rhs}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static void assertEquals(Object lhs, Object rhs, String msg) {
+ if ((lhs != rhs) && ((lhs == null) || !(lhs.equals(rhs)))) {
+ msg = Objects.toString(msg, "assertEquals")
+ + ": expected " + Objects.toString(lhs)
+ + " to equal " + Objects.toString(rhs);
+ fail(msg);
+ }
+ }
+
+ /**
+ * Calls {@link #assertSame(java.lang.Object, java.lang.Object, java.lang.String)} with a default message.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertSame(Object, Object, String)
+ */
+ public static void assertSame(Object lhs, Object rhs) {
+ assertSame(lhs, rhs, null);
+ }
+
+ /**
+ * Asserts that {@code lhs} is the same as {@code rhs}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static void assertSame(Object lhs, Object rhs, String msg) {
+ if (lhs != rhs) {
+ msg = Objects.toString(msg, "assertSame")
+ + ": expected " + Objects.toString(lhs)
+ + " to equal " + Objects.toString(rhs);
+ fail(msg);
+ }
+ }
+
+ /**
+ * Shorthand for {@link #assertGreaterThanOrEqual(Comparable, Comparable)}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertGreaterThanOrEqual(Comparable, Comparable)
+ */
+ public static <T extends Comparable<T>> void assertGTE(T lhs, T rhs) {
+ assertGreaterThanOrEqual(lhs, rhs);
+ }
+
+ /**
+ * Shorthand for {@link #assertGreaterThanOrEqual(Comparable, Comparable, String)}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @see #assertGreaterThanOrEqual(Comparable, Comparable, String)
+ */
+ public static <T extends Comparable<T>> void assertGTE(T lhs, T rhs, String msg) {
+ assertGreaterThanOrEqual(lhs, rhs, msg);
+ }
+
+ /**
+ * Calls {@link #assertGreaterThanOrEqual(Comparable, Comparable, String)} with a default message.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertGreaterThanOrEqual(Comparable, Comparable, String)
+ */
+ public static <T extends Comparable<T>> void assertGreaterThanOrEqual(T lhs, T rhs) {
+ assertGreaterThanOrEqual(lhs, rhs, null);
+ }
+
+ /**
+ * Asserts that {@code lhs} is greater than or equal to {@code rhs}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static <T extends Comparable<T>> void assertGreaterThanOrEqual(T lhs, T rhs, String msg) {
+ if (!(compare(lhs, rhs, msg) >= 0)) {
+ msg = Objects.toString(msg, "assertGreaterThanOrEqual")
+ + ": expected " + Objects.toString(lhs)
+ + " >= " + Objects.toString(rhs);
+ fail(msg);
+ }
+ }
+
+ /**
+ * Shorthand for {@link #assertGreaterThan(Comparable, Comparable)}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertGreaterThan(Comparable, Comparable)
+ */
+ public static <T extends Comparable<T>> void assertGT(T lhs, T rhs) {
+ assertGreaterThan(lhs, rhs);
+ }
+
+ /**
+ * Shorthand for {@link #assertGreaterThan(Comparable, Comparable, String)}.
+ *
+ * @param <T> a type
+ * @param lhs the left hand value
+ * @param rhs the right hand value
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @see #assertGreaterThan(Comparable, Comparable, String)
+ */
+ public static <T extends Comparable<T>> void assertGT(T lhs, T rhs, String msg) {
+ assertGreaterThan(lhs, rhs, msg);
+ }
+
+ /**
+ * Calls {@link #assertGreaterThan(Comparable, Comparable, String)} with a default message.
+ *
+ * @param <T> a type
+ * @param lhs the left hand value
+ * @param rhs the right hand value
+ * @see #assertGreaterThan(Comparable, Comparable, String)
+ */
+ public static <T extends Comparable<T>> void assertGreaterThan(T lhs, T rhs) {
+ assertGreaterThan(lhs, rhs, null);
+ }
+
+ /**
+ * Asserts that {@code lhs} is greater than {@code rhs}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static <T extends Comparable<T>> void assertGreaterThan(T lhs, T rhs, String msg) {
+ if (!(compare(lhs, rhs, msg) > 0)) {
+ msg = Objects.toString(msg, "assertGreaterThan")
+ + ": expected " + Objects.toString(lhs)
+ + " > " + Objects.toString(rhs);
+ fail(msg);
+ }
+ }
+
+ /**
+ * Shorthand for {@link #assertNotEquals(Object, Object)}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertNotEquals(Object, Object)
+ */
+ public static void assertNE(Object lhs, Object rhs) {
+ assertNotEquals(lhs, rhs);
+ }
+
+ /**
+ * Shorthand for {@link #assertNotEquals(Object, Object, String)}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @see #assertNotEquals(Object, Object, String)
+ */
+ public static void assertNE(Object lhs, Object rhs, String msg) {
+ assertNotEquals(lhs, rhs, msg);
+ }
+
+ /**
+ * Calls {@link #assertNotEquals(Object, Object, String)} with a default message.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertNotEquals(Object, Object, String)
+ */
+ public static void assertNotEquals(Object lhs, Object rhs) {
+ assertNotEquals(lhs, rhs, null);
+ }
+
+ /**
+ * Asserts that {@code lhs} is not equal to {@code rhs}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static void assertNotEquals(Object lhs, Object rhs, String msg) {
+ if ((lhs == rhs) || (lhs != null && lhs.equals(rhs))) {
+ msg = Objects.toString(msg, "assertNotEquals")
+ + ": expected " + Objects.toString(lhs)
+ + " to not equal " + Objects.toString(rhs);
+ fail(msg);
+ }
+ }
+
+ /**
+ * Calls {@link #assertNull(Object, String)} with a default message.
+ *
+ * @param o The reference assumed to be null.
+ * @see #assertNull(Object, String)
+ */
+ public static void assertNull(Object o) {
+ assertNull(o, null);
+ }
+
+ /**
+ * Asserts that {@code o} is null.
+ *
+ * @param o The reference assumed to be null.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static void assertNull(Object o, String msg) {
+ assertEquals(o, null, msg);
+ }
+
+ /**
+ * Calls {@link #assertNotNull(Object, String)} with a default message.
+ *
+ * @param o The reference assumed <i>not</i> to be null,
+ * @see #assertNotNull(Object, String)
+ */
+ public static void assertNotNull(Object o) {
+ assertNotNull(o, null);
+ }
+
+ /**
+ * Asserts that {@code o} is <i>not</i> null.
+ *
+ * @param o The reference assumed <i>not</i> to be null,
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static void assertNotNull(Object o, String msg) {
+ assertNotEquals(o, null, msg);
+ }
+
+ /**
+ * Calls {@link #assertFalse(boolean, String)} with a default message.
+ *
+ * @param value The value assumed to be false.
+ * @see #assertFalse(boolean, String)
+ */
+ public static void assertFalse(boolean value) {
+ assertFalse(value, null);
+ }
+
+ /**
+ * Asserts that {@code value} is {@code false}.
+ *
+ * @param value The value assumed to be false.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static void assertFalse(boolean value, String msg) {
+ if (value) {
+ msg = Objects.toString(msg, "assertFalse")
+ + ": expected false, was true";
+ fail(msg);
+ }
+ }
+
+ /**
+ * Calls {@link #assertTrue(boolean, String)} with a default message.
+ *
+ * @param value The value assumed to be true.
+ * @see #assertTrue(boolean, String)
+ */
+ public static void assertTrue(boolean value) {
+ assertTrue(value, null);
+ }
+
+ /**
+ * Asserts that {@code value} is {@code true}.
+ *
+ * @param value The value assumed to be true.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static void assertTrue(boolean value, String msg) {
+ if (!value) {
+ msg = Objects.toString(msg, "assertTrue")
+ + ": expected true, was false";
+ fail(msg);
+ }
+ }
+
+ private static <T extends Comparable<T>> int compare(T lhs, T rhs, String msg) {
+ if (lhs == null || rhs == null) {
+ fail(lhs, rhs, msg + ": values must be non-null:", ",");
+ }
+ return lhs.compareTo(rhs);
+ }
+
+/**
+ * Asserts that two strings are equal.
+ *
+ * If strings are not equals, then exception message
+ * will contain {@code msg} followed by list of mismatched lines.
+ *
+ * @param str1 First string to compare.
+ * @param str2 Second string to compare.
+ * @param msg A description of the assumption.
+ * @throws RuntimeException if strings are not equal.
+ */
+ public static void assertStringsEqual(String str1, String str2,
+ String msg) {
+ String lineSeparator = System.getProperty("line.separator");
+ String str1Lines[] = str1.split(lineSeparator);
+ String str2Lines[] = str2.split(lineSeparator);
+
+ int minLength = Math.min(str1Lines.length, str2Lines.length);
+ String longestStringLines[] = ((str1Lines.length == minLength) ?
+ str2Lines : str1Lines);
+
+ boolean stringsAreDifferent = false;
+
+ StringBuilder messageBuilder = new StringBuilder(msg);
+
+ messageBuilder.append("\n");
+
+ for (int line = 0; line < minLength; line++) {
+ if (!str1Lines[line].equals(str2Lines[line])) {
+ messageBuilder.append(String.
+ format("[line %d] '%s' differs " +
+ "from '%s'\n",
+ line,
+ str1Lines[line],
+ str2Lines[line]));
+ stringsAreDifferent = true;
+ }
+ }
+
+ if (minLength < longestStringLines.length) {
+ String stringName = ((longestStringLines == str1Lines) ?
+ "first" : "second");
+ messageBuilder.append(String.format("Only %s string contains " +
+ "following lines:\n",
+ stringName));
+ stringsAreDifferent = true;
+ for(int line = minLength; line < longestStringLines.length; line++) {
+ messageBuilder.append(String.
+ format("[line %d] '%s'", line,
+ longestStringLines[line]));
+ }
+ }
+
+ if (stringsAreDifferent) {
+ fail(messageBuilder.toString());
+ }
+ }
+
+ /**
+ * Returns a string formatted with a message and expected and actual values.
+ * @param lhs the actual value
+ * @param rhs the expected value
+ * @param message the actual value
+ * @param relation the asserted relationship between lhs and rhs
+ * @return a formatted string
+ */
+ public static String format(Object lhs, Object rhs, String message, String relation) {
+ StringBuilder sb = new StringBuilder(80);
+ if (message != null) {
+ sb.append(message);
+ sb.append(' ');
+ }
+ sb.append("<");
+ sb.append(Objects.toString(lhs));
+ sb.append("> ");
+ sb.append(Objects.toString(relation, ","));
+ sb.append(" <");
+ sb.append(Objects.toString(rhs));
+ sb.append(">");
+ return sb.toString();
+ }
+
+ /**
+ * Fail reports a failure with message fail.
+ *
+ * @throws RuntimeException always
+ */
+ public static void fail() {
+ fail("fail");
+ }
+
+ /**
+ * Fail reports a failure with a message.
+ * @param message for the failure
+ * @throws RuntimeException always
+ */
+ public static void fail(String message) {
+ throw new RuntimeException(message);
+ }
+
+ /**
+ * Fail reports a failure with a formatted message.
+ *
+ * @param lhs the actual value
+ * @param rhs the expected value
+ * @param message to be format before the expected and actual values
+ * @param relation the asserted relationship between lhs and rhs
+ * @throws RuntimeException always
+ */
+ public static void fail(Object lhs, Object rhs, String message, String relation) {
+ throw new RuntimeException(format(lhs, rhs, message, relation));
+ }
+
+ /**
+ * Fail reports a failure with a message and a cause.
+ * @param message to be format before the expected and actual values
+ * @param cause the exception that caused this failure
+ * @throws RuntimeException always
+ */
+ public static void fail(String message, Throwable cause) {
+ throw new RuntimeException(message, cause);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/BuildHelper.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib;
+
+import java.io.File;
+import java.io.FileReader;
+import java.util.Properties;
+
+public class BuildHelper {
+
+ /**
+ * Commercial builds should have the BUILD_TYPE set to commercial
+ * within the release file, found at the root of the JDK.
+ */
+ public static boolean isCommercialBuild() throws Exception {
+ String buildType = getReleaseProperty("BUILD_TYPE","notFound");
+ return buildType.equals("commercial");
+ }
+
+
+ /**
+ * Return the value for property key, or defaultValue if no property not found.
+ * If present, double quotes are trimmed.
+ */
+ public static String getReleaseProperty(String key, String defaultValue) throws Exception {
+ Properties properties = getReleaseProperties();
+ String value = properties.getProperty(key, defaultValue);
+ return trimDoubleQuotes(value);
+ }
+
+ /**
+ * Return the value for property key, or null if no property not found.
+ * If present, double quotes are trimmed.
+ */
+ public static String getReleaseProperty(String key) throws Exception {
+ return getReleaseProperty(key, null);
+ }
+
+ /**
+ * Get properties from the release file
+ */
+ public static Properties getReleaseProperties() throws Exception {
+ Properties properties = new Properties();
+ properties.load(new FileReader(getReleaseFile()));
+ return properties;
+ }
+
+ /**
+ * Every JDK has a release file in its root.
+ * @return A handler to the release file.
+ */
+ public static File getReleaseFile() throws Exception {
+ String jdkPath = getJDKRoot();
+ File releaseFile = new File(jdkPath,"release");
+ if ( ! releaseFile.canRead() ) {
+ throw new Exception("Release file is not readable, or it is absent: " +
+ releaseFile.getCanonicalPath());
+ }
+ return releaseFile;
+ }
+
+ /**
+ * Returns path to the JDK under test.
+ * This path is obtained through the test.jdk property, usually set by JTREG.
+ */
+ public static String getJDKRoot() {
+ String jdkPath = System.getProperty("test.jdk");
+ if (jdkPath == null) {
+ throw new RuntimeException("System property 'test.jdk' not set. This property is normally set by jtreg. "
+ + "When running test separately, set this property using '-Dtest.jdk=/path/to/jdk'.");
+ }
+ return jdkPath;
+ }
+
+ /**
+ * Trim double quotes from the beginning and the end of the given string.
+ * @param original string to trim.
+ * @return a new trimmed string.
+ */
+ public static String trimDoubleQuotes(String original) {
+ if (original == null) { return null; }
+ String trimmed = original.replaceAll("^\"+|\"+$", "");
+ return trimmed;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/ByteCodeLoader.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib;
+
+import java.security.SecureClassLoader;
+
+/**
+ * {@code ByteCodeLoader} can be used for easy loading of byte code already
+ * present in memory.
+ *
+ * {@code InMemoryCompiler} can be used for compiling source code in a string
+ * into byte code, which then can be loaded with {@code ByteCodeLoader}.
+ *
+ * @see InMemoryCompiler
+ */
+public class ByteCodeLoader extends SecureClassLoader {
+ private final String className;
+ private final byte[] byteCode;
+ private volatile Class<?> holder;
+
+ /**
+ * Creates a new {@code ByteCodeLoader} ready to load a class with the
+ * given name and the given byte code.
+ *
+ * @param className The name of the class
+ * @param byteCode The byte code of the class
+ */
+ public ByteCodeLoader(String className, byte[] byteCode) {
+ this.className = className;
+ this.byteCode = byteCode;
+ }
+
+ @Override
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ if (!name.equals(className)) {
+ return super.loadClass(name);
+ }
+ if (holder == null) {
+ synchronized(this) {
+ if (holder == null) {
+ holder = findClass(name);
+ }
+ }
+ }
+ return holder;
+ }
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ if (!name.equals(className)) {
+ throw new ClassNotFoundException(name);
+ }
+
+ return defineClass(name, byteCode, 0, byteCode.length);
+ }
+
+ /**
+ * Utility method for creating a new {@code ByteCodeLoader} and then
+ * directly load the given byte code.
+ *
+ * @param className The name of the class
+ * @param byteCode The byte code for the class
+ * @throws ClassNotFoundException if the class can't be loaded
+ * @return A {@see Class} object representing the class
+ */
+ public static Class<?> load(String className, byte[] byteCode) throws ClassNotFoundException {
+ return new ByteCodeLoader(className, byteCode).loadClass(className);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/DynamicVMOption.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import java.lang.management.ManagementFactory;
+
+/**
+ * A utility class to work with VM options which could be altered during
+ * execution.
+ *
+ * This class is a wrapper around {@code com.sun.management.VMOption}.
+ * It provides more convenient interface to read/write the values.
+ *
+ */
+public class DynamicVMOption {
+
+ private final HotSpotDiagnosticMXBean mxBean;
+
+ /**
+ * VM option name, like "MinHeapFreeRatio".
+ */
+ public final String name;
+
+ /**
+ * Creates an instance of DynamicVMOption.
+ *
+ * @param name the VM option name
+ */
+ public DynamicVMOption(String name) {
+ this.name = name;
+ mxBean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
+ }
+
+ /**
+ * Sets a new value for the option.
+ * Trying to set not applicable value will cause IllegalArgumentException.
+ * Behavior with null is undefined, most likely NPE will be thrown.
+ *
+ * @param newValue the value to be set
+ * @see #getValue()
+ * @throws IllegalArgumentException if newValue is not applicable to the option
+ */
+ public final void setValue(String newValue) {
+ mxBean.setVMOption(name, newValue);
+ }
+
+ /**
+ * Returns the value of option.
+ *
+ * @return the current option value
+ * @see #setValue(java.lang.String)
+ */
+ public final String getValue() {
+ return mxBean.getVMOption(name).getValue();
+ }
+
+ /**
+ * Returns true, if option is writable, false otherwise.
+ *
+ * @return true, if option is writable, false otherwise
+ */
+ public final boolean isWriteable() {
+ return mxBean.getVMOption(name).isWriteable();
+ }
+
+ /**
+ * Checks if the given value is applicable for the option.
+ *
+ * This method tries to set the option to the new value. If no exception
+ * has been thrown the value is treated as valid.
+ *
+ * Calling this method will not change the option value. After an attempt
+ * to set a new value, the option will be restored to its previous value.
+ *
+ * @param value the value to verify
+ * @return true if option could be set to the given value
+ */
+ public boolean isValidValue(String value) {
+ boolean isValid = true;
+ String oldValue = getValue();
+ try {
+ setValue(value);
+ } catch (NullPointerException e) {
+ if (value == null) {
+ isValid = false;
+ }
+ } catch (IllegalArgumentException e) {
+ isValid = false;
+ } finally {
+ setValue(oldValue);
+ }
+ return isValid;
+ }
+
+ /**
+ * Returns the value of the given VM option as String.
+ *
+ * This is a simple shortcut for {@code new DynamicVMOption(name).getValue()}
+ *
+ * @param name the name of VM option
+ * @return value as a string
+ * @see #getValue()
+ */
+ public static String getString(String name) {
+ return new DynamicVMOption(name).getValue();
+ }
+
+ /**
+ * Returns the value of the given option as int.
+ *
+ * @param name the name of VM option
+ * @return value parsed as integer
+ * @see #getString(java.lang.String)
+ *
+ */
+ public static int getInt(String name) {
+ return Integer.parseInt(getString(name));
+ }
+
+ /**
+ * Sets the VM option to a new value.
+ *
+ * This is a simple shortcut for {@code new DynamicVMOption(name).setValue(value)}
+ *
+ * @param name the name of VM option
+ * @param value the value to be set
+ * @see #setValue(java.lang.String)
+ */
+ public static void setString(String name, String value) {
+ new DynamicVMOption(name).setValue(value);
+ }
+
+ /**
+ * Sets the VM option value to a new integer value.
+ *
+ * @param name the name of VM option
+ * @param value the integer value to be set
+ * @see #setString(java.lang.String, java.lang.String)
+ */
+ public static void setInt(String name, int value) {
+ new DynamicVMOption(name).setValue(Integer.toString(value));
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/FileInstaller.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib;
+
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.attribute.BasicFileAttributes;
+
+/**
+ * Copy a resource: file or directory recursively, using relative path(src and dst)
+ * which are applied to test source directory(src) and current directory(dst)
+ */
+public class FileInstaller {
+ /**
+ * @param args source and destination
+ * @throws IOException if an I/O error occurs
+ */
+ public static void main(String[] args) throws IOException {
+ if (args.length != 2) {
+ throw new IllegalArgumentException("Unexpected number of arguments for file copy");
+ }
+ Path src = Paths.get(Utils.TEST_SRC, args[0]).toAbsolutePath();
+ Path dst = Paths.get(args[1]).toAbsolutePath();
+ if (src.toFile().exists()) {
+ if (src.toFile().isDirectory()) {
+ Files.walkFileTree(src, new CopyFileVisitor(src, dst));
+ } else {
+ Path dstDir = dst.getParent();
+ if (!dstDir.toFile().exists()) {
+ Files.createDirectories(dstDir);
+ }
+ Files.copy(src, dst, StandardCopyOption.REPLACE_EXISTING);
+ }
+ } else {
+ throw new IOException("Can't find source " + src);
+ }
+ }
+
+ private static class CopyFileVisitor extends SimpleFileVisitor<Path> {
+ private final Path copyFrom;
+ private final Path copyTo;
+
+ public CopyFileVisitor(Path copyFrom, Path copyTo) {
+ this.copyFrom = copyFrom;
+ this.copyTo = copyTo;
+ }
+
+ @Override
+ public FileVisitResult preVisitDirectory(Path file,
+ BasicFileAttributes attrs) throws IOException {
+ Path relativePath = file.relativize(copyFrom);
+ Path destination = copyTo.resolve(relativePath);
+ if (!destination.toFile().exists()) {
+ Files.createDirectories(destination);
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file,
+ BasicFileAttributes attrs) throws IOException {
+ if (!file.toFile().isFile()) {
+ return FileVisitResult.CONTINUE;
+ }
+ Path relativePath = copyFrom.relativize(file);
+ Path destination = copyTo.resolve(relativePath);
+ Files.copy(file, destination, StandardCopyOption.COPY_ATTRIBUTES);
+ return FileVisitResult.CONTINUE;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/InMemoryJavaCompiler.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.net.URI;
+import java.util.Arrays;
+
+import javax.tools.ForwardingJavaFileManager;
+import javax.tools.FileObject;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaCompiler.CompilationTask;
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.ToolProvider;
+
+/**
+ * {@code InMemoryJavaCompiler} can be used for compiling a {@link
+ * CharSequence} to a {@code byte[]}.
+ *
+ * The compiler will not use the file system at all, instead using a {@link
+ * ByteArrayOutputStream} for storing the byte code. For the source code, any
+ * kind of {@link CharSequence} can be used, e.g. {@link String}, {@link
+ * StringBuffer} or {@link StringBuilder}.
+ *
+ * The {@code InMemoryCompiler} can easily be used together with a {@code
+ * ByteClassLoader} to easily compile and load source code in a {@link String}:
+ *
+ * <pre>
+ * {@code
+ * import jdk.test.lib.InMemoryJavaCompiler;
+ * import jdk.test.lib.ByteClassLoader;
+ *
+ * class Example {
+ * public static void main(String[] args) {
+ * String className = "Foo";
+ * String sourceCode = "public class " + className + " {" +
+ * " public void bar() {" +
+ * " System.out.println("Hello from bar!");" +
+ * " }" +
+ * "}";
+ * byte[] byteCode = InMemoryJavaCompiler.compile(className, sourceCode);
+ * Class fooClass = ByteClassLoader.load(className, byteCode);
+ * }
+ * }
+ * }
+ * </pre>
+ */
+public class InMemoryJavaCompiler {
+ private static class MemoryJavaFileObject extends SimpleJavaFileObject {
+ private final String className;
+ private final CharSequence sourceCode;
+ private final ByteArrayOutputStream byteCode;
+
+ public MemoryJavaFileObject(String className, CharSequence sourceCode) {
+ super(URI.create("string:///" + className.replace('.','/') + Kind.SOURCE.extension), Kind.SOURCE);
+ this.className = className;
+ this.sourceCode = sourceCode;
+ this.byteCode = new ByteArrayOutputStream();
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+ return sourceCode;
+ }
+
+ @Override
+ public OutputStream openOutputStream() throws IOException {
+ return byteCode;
+ }
+
+ public byte[] getByteCode() {
+ return byteCode.toByteArray();
+ }
+
+ public String getClassName() {
+ return className;
+ }
+ }
+
+ private static class FileManagerWrapper extends ForwardingJavaFileManager {
+ private MemoryJavaFileObject file;
+
+ public FileManagerWrapper(MemoryJavaFileObject file) {
+ super(getCompiler().getStandardFileManager(null, null, null));
+ this.file = file;
+ }
+
+ @Override
+ public JavaFileObject getJavaFileForOutput(Location location, String className,
+ Kind kind, FileObject sibling)
+ throws IOException {
+ if (!file.getClassName().equals(className)) {
+ throw new IOException("Expected class with name " + file.getClassName() +
+ ", but got " + className);
+ }
+ return file;
+ }
+ }
+
+ /**
+ * Compiles the class with the given name and source code.
+ *
+ * @param className The name of the class
+ * @param sourceCode The source code for the class with name {@code className}
+ * @param options additional command line options
+ * @throws RuntimeException if the compilation did not succeed
+ * @return The resulting byte code from the compilation
+ */
+ public static byte[] compile(String className, CharSequence sourceCode, String... options) {
+ MemoryJavaFileObject file = new MemoryJavaFileObject(className, sourceCode);
+ CompilationTask task = getCompilationTask(file, options);
+
+ if(!task.call()) {
+ throw new RuntimeException("Could not compile " + className + " with source code " + sourceCode);
+ }
+
+ return file.getByteCode();
+ }
+
+ private static JavaCompiler getCompiler() {
+ return ToolProvider.getSystemJavaCompiler();
+ }
+
+ private static CompilationTask getCompilationTask(MemoryJavaFileObject file, String... options) {
+ return getCompiler().getTask(null, new FileManagerWrapper(file), null, Arrays.asList(options), null, Arrays.asList(file));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/JDKToolFinder.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib;
+
+import java.io.FileNotFoundException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public final class JDKToolFinder {
+
+ private JDKToolFinder() {
+ }
+
+ /**
+ * Returns the full path to an executable in jdk/bin based on System
+ * property {@code test.jdk} or {@code compile.jdk} (both are set by the jtreg test suite)
+ *
+ * @return Full path to an executable in jdk/bin
+ */
+ public static String getJDKTool(String tool) {
+
+ // First try to find the executable in test.jdk
+ try {
+ return getTool(tool, "test.jdk");
+ } catch (FileNotFoundException e) {
+
+ }
+
+ // Now see if it's available in compile.jdk
+ try {
+ return getTool(tool, "compile.jdk");
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("Failed to find " + tool +
+ ", looked in test.jdk (" + System.getProperty("test.jdk") +
+ ") and compile.jdk (" + System.getProperty("compile.jdk") + ")");
+ }
+ }
+
+ /**
+ * Returns the full path to an executable in jdk/bin based on System
+ * property {@code compile.jdk}
+ *
+ * @return Full path to an executable in jdk/bin
+ */
+ public static String getCompileJDKTool(String tool) {
+ try {
+ return getTool(tool, "compile.jdk");
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Returns the full path to an executable in jdk/bin based on System
+ * property {@code test.jdk}
+ *
+ * @return Full path to an executable in jdk/bin
+ */
+ public static String getTestJDKTool(String tool) {
+ try {
+ return getTool(tool, "test.jdk");
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static String getTool(String tool, String property) throws FileNotFoundException {
+ String jdkPath = System.getProperty(property);
+
+ if (jdkPath == null) {
+ throw new RuntimeException(
+ "System property '" + property + "' not set. This property is normally set by jtreg. "
+ + "When running test separately, set this property using '-D" + property + "=/path/to/jdk'.");
+ }
+
+ Path toolName = Paths.get("bin", tool + (Platform.isWindows() ? ".exe" : ""));
+
+ Path jdkTool = Paths.get(jdkPath, toolName.toString());
+ if (!jdkTool.toFile().exists()) {
+ throw new FileNotFoundException("Could not find file " + jdkTool.toAbsolutePath());
+ }
+
+ return jdkTool.toAbsolutePath().toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/JDKToolLauncher.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import jdk.test.lib.process.ProcessTools;
+
+/**
+ * A utility for constructing command lines for starting JDK tool processes.
+ *
+ * The JDKToolLauncher can in particular be combined with a
+ * java.lang.ProcessBuilder to easily run a JDK tool. For example, the following
+ * code run {@code jmap -heap} against a process with GC logging turned on for
+ * the {@code jmap} process:
+ *
+ * <pre>
+ * {@code
+ * JDKToolLauncher jmap = JDKToolLauncher.create("jmap")
+ * .addVMArg("-XX:+PrintGC");
+ * .addVMArg("-XX:+PrintGCDetails")
+ * .addToolArg("-heap")
+ * .addToolArg(pid);
+ * ProcessBuilder pb = new ProcessBuilder(jmap.getCommand());
+ * Process p = pb.start();
+ * }
+ * </pre>
+ */
+public class JDKToolLauncher {
+ private final String executable;
+ private final List<String> vmArgs = new ArrayList<String>();
+ private final List<String> toolArgs = new ArrayList<String>();
+
+ private JDKToolLauncher(String tool, boolean useCompilerJDK) {
+ if (useCompilerJDK) {
+ executable = JDKToolFinder.getJDKTool(tool);
+ } else {
+ executable = JDKToolFinder.getTestJDKTool(tool);
+ }
+ vmArgs.addAll(Arrays.asList(ProcessTools.getPlatformSpecificVMArgs()));
+ }
+
+ /**
+ * Creates a new JDKToolLauncher for the specified tool. Using tools path
+ * from the compiler JDK.
+ *
+ * @param tool
+ * The name of the tool
+ * @return A new JDKToolLauncher
+ */
+ public static JDKToolLauncher create(String tool) {
+ return new JDKToolLauncher(tool, true);
+ }
+
+ /**
+ * Creates a new JDKToolLauncher for the specified tool in the Tested JDK.
+ *
+ * @param tool
+ * The name of the tool
+ *
+ * @return A new JDKToolLauncher
+ */
+ public static JDKToolLauncher createUsingTestJDK(String tool) {
+ return new JDKToolLauncher(tool, false);
+ }
+
+ /**
+ * Adds an argument to the JVM running the tool.
+ *
+ * The JVM arguments are passed to the underlying JVM running the tool.
+ * Arguments will automatically be prepended with "-J".
+ *
+ * Any platform specific arguments required for running the tool are
+ * automatically added.
+ *
+ *
+ * @param arg
+ * The argument to VM running the tool
+ * @return The JDKToolLauncher instance
+ */
+ public JDKToolLauncher addVMArg(String arg) {
+ vmArgs.add(arg);
+ return this;
+ }
+
+ /**
+ * Adds an argument to the tool.
+ *
+ * @param arg
+ * The argument to the tool
+ * @return The JDKToolLauncher instance
+ */
+ public JDKToolLauncher addToolArg(String arg) {
+ toolArgs.add(arg);
+ return this;
+ }
+
+ /**
+ * Returns the command that can be used for running the tool.
+ *
+ * @return An array whose elements are the arguments of the command.
+ */
+ public String[] getCommand() {
+ List<String> command = new ArrayList<String>();
+ command.add(executable);
+ // Add -J in front of all vmArgs
+ for (String arg : vmArgs) {
+ command.add("-J" + arg);
+ }
+ command.addAll(toolArgs);
+ return command.toArray(new String[command.size()]);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/Platform.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib;
+
+import java.util.regex.Pattern;
+
+public class Platform {
+ public static final String vmName = System.getProperty("java.vm.name");
+ public static final String vmInfo = System.getProperty("java.vm.info");
+ private static final String osName = System.getProperty("os.name");
+ private static final String dataModel = System.getProperty("sun.arch.data.model");
+ private static final String vmVersion = System.getProperty("java.vm.version");
+ private static final String jdkDebug = System.getProperty("jdk.debug");
+ private static final String osArch = System.getProperty("os.arch");
+ private static final String userName = System.getProperty("user.name");
+ private static final String compiler = System.getProperty("sun.management.compiler");
+
+ public static boolean isClient() {
+ return vmName.endsWith(" Client VM");
+ }
+
+ public static boolean isServer() {
+ return vmName.endsWith(" Server VM");
+ }
+
+ public static boolean isGraal() {
+ return vmName.endsWith(" Graal VM");
+ }
+
+ public static boolean isZero() {
+ return vmName.endsWith(" Zero VM");
+ }
+
+ public static boolean isMinimal() {
+ return vmName.endsWith(" Minimal VM");
+ }
+
+ public static boolean isEmbedded() {
+ return vmName.contains("Embedded");
+ }
+
+ public static boolean isTieredSupported() {
+ return compiler.contains("Tiered Compilers");
+ }
+
+ public static boolean isInt() {
+ return vmInfo.contains("interpreted");
+ }
+
+ public static boolean isMixed() {
+ return vmInfo.contains("mixed");
+ }
+
+ public static boolean isComp() {
+ return vmInfo.contains("compiled");
+ }
+
+ public static boolean is32bit() {
+ return dataModel.equals("32");
+ }
+
+ public static boolean is64bit() {
+ return dataModel.equals("64");
+ }
+
+ public static boolean isAix() {
+ return isOs("aix");
+ }
+
+ public static boolean isLinux() {
+ return isOs("linux");
+ }
+
+ public static boolean isOSX() {
+ return isOs("mac");
+ }
+
+ public static boolean isSolaris() {
+ return isOs("sunos");
+ }
+
+ public static boolean isWindows() {
+ return isOs("win");
+ }
+
+ private static boolean isOs(String osname) {
+ return osName.toLowerCase().startsWith(osname.toLowerCase());
+ }
+
+ public static String getOsName() {
+ return osName;
+ }
+
+ public static boolean isDebugBuild() {
+ return (jdkDebug.toLowerCase().contains("debug"));
+ }
+
+ public static String getVMVersion() {
+ return vmVersion;
+ }
+
+ // Returns true for sparc and sparcv9.
+ public static boolean isSparc() {
+ return isArch("sparc.*");
+ }
+
+ public static boolean isARM() {
+ return isArch("arm.*");
+ }
+
+ public static boolean isPPC() {
+ return isArch("ppc.*");
+ }
+
+ public static boolean isX86() {
+ // On Linux it's 'i386', Windows 'x86' without '_64' suffix.
+ return isArch("(i386)|(x86(?!_64))");
+ }
+
+ public static boolean isX64() {
+ // On OSX it's 'x86_64' and on other (Linux, Windows and Solaris) platforms it's 'amd64'
+ return isArch("(amd64)|(x86_64)");
+ }
+
+ public static boolean isAArch64() {
+ return isArch("aarch64");
+ }
+
+ public static String getOsArch() {
+ return osArch;
+ }
+
+ /**
+ * Return a boolean for whether we expect to be able to attach
+ * the SA to our own processes on this system.
+ */
+ public static boolean shouldSAAttach() throws Exception {
+
+ if (isAix()) {
+ return false; // SA not implemented.
+ } else if (isLinux()) {
+ return canPtraceAttachLinux();
+ } else if (isOSX()) {
+ return canAttachOSX();
+ } else {
+ // Other platforms expected to work:
+ return true;
+ }
+ }
+
+ /**
+ * On Linux, first check the SELinux boolean "deny_ptrace" and return false
+ * as we expect to be denied if that is "1". Then expect permission to attach
+ * if we are root, so return true. Then return false for an expected denial
+ * if "ptrace_scope" is 1, and true otherwise.
+ */
+ public static boolean canPtraceAttachLinux() throws Exception {
+
+ // SELinux deny_ptrace:
+ String deny_ptrace = Utils.fileAsString("/sys/fs/selinux/booleans/deny_ptrace");
+ if (deny_ptrace != null && deny_ptrace.contains("1")) {
+ // ptrace will be denied:
+ return false;
+ }
+
+ // YAMA enhanced security ptrace_scope:
+ // 0 - a process can PTRACE_ATTACH to any other process running under the same uid
+ // 1 - restricted ptrace: a process must be a children of the inferior or user is root
+ // 2 - only processes with CAP_SYS_PTRACE may use ptrace or user is root
+ // 3 - no attach: no processes may use ptrace with PTRACE_ATTACH
+ String ptrace_scope = Utils.fileAsString("/proc/sys/kernel/yama/ptrace_scope");
+ if (ptrace_scope != null) {
+ if (ptrace_scope.startsWith("3")) {
+ return false;
+ }
+ if (!userName.equals("root") && !ptrace_scope.startsWith("0")) {
+ // ptrace will be denied:
+ return false;
+ }
+ }
+ // Otherwise expect to be permitted:
+ return true;
+ }
+
+ /**
+ * On OSX, expect permission to attach only if we are root.
+ */
+ public static boolean canAttachOSX() throws Exception {
+ return userName.equals("root");
+ }
+
+ private static boolean isArch(String archnameRE) {
+ return Pattern.compile(archnameRE, Pattern.CASE_INSENSITIVE)
+ .matcher(osArch)
+ .matches();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/Utils.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,694 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.ServerSocket;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.UnknownHostException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Objects;
+import java.util.Random;
+import java.util.function.BooleanSupplier;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import jdk.internal.misc.Unsafe;
+
+import static jdk.test.lib.Asserts.assertTrue;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+
+/**
+ * Common library for various test helper functions.
+ */
+public final class Utils {
+
+ /**
+ * Returns the value of 'test.class.path' system property.
+ */
+ public static final String TEST_CLASS_PATH = System.getProperty("test.class.path", ".");
+
+ /**
+ * Returns the sequence used by operating system to separate lines.
+ */
+ public static final String NEW_LINE = System.getProperty("line.separator");
+
+ /**
+ * Returns the value of 'test.vm.opts' system property.
+ */
+ public static final String VM_OPTIONS = System.getProperty("test.vm.opts", "").trim();
+
+ /**
+ * Returns the value of 'test.java.opts' system property.
+ */
+ public static final String JAVA_OPTIONS = System.getProperty("test.java.opts", "").trim();
+
+ /**
+ * Returns the value of 'test.src' system property.
+ */
+ public static final String TEST_SRC = System.getProperty("test.src", "").trim();
+
+ private static Unsafe unsafe = null;
+
+ /**
+ * Defines property name for seed value.
+ */
+ public static final String SEED_PROPERTY_NAME = "jdk.test.lib.random.seed";
+
+ /* (non-javadoc)
+ * Random generator with (or without) predefined seed. Depends on
+ * "jdk.test.lib.random.seed" property value.
+ */
+ private static volatile Random RANDOM_GENERATOR;
+
+ /**
+ * Contains the seed value used for {@link java.util.Random} creation.
+ */
+ public static final long SEED = Long.getLong(SEED_PROPERTY_NAME, new Random().nextLong());
+ /**
+ * Returns the value of 'test.timeout.factor' system property
+ * converted to {@code double}.
+ */
+ public static final double TIMEOUT_FACTOR;
+ static {
+ String toFactor = System.getProperty("test.timeout.factor", "1.0");
+ TIMEOUT_FACTOR = Double.parseDouble(toFactor);
+ }
+
+ /**
+ * Returns the value of JTREG default test timeout in milliseconds
+ * converted to {@code long}.
+ */
+ public static final long DEFAULT_TEST_TIMEOUT = TimeUnit.SECONDS.toMillis(120);
+
+ private Utils() {
+ // Private constructor to prevent class instantiation
+ }
+
+ /**
+ * Returns the list of VM options.
+ *
+ * @return List of VM options
+ */
+ public static List<String> getVmOptions() {
+ return Arrays.asList(safeSplitString(VM_OPTIONS));
+ }
+
+ /**
+ * Returns the list of VM options with -J prefix.
+ *
+ * @return The list of VM options with -J prefix
+ */
+ public static List<String> getForwardVmOptions() {
+ String[] opts = safeSplitString(VM_OPTIONS);
+ for (int i = 0; i < opts.length; i++) {
+ opts[i] = "-J" + opts[i];
+ }
+ return Arrays.asList(opts);
+ }
+
+ /**
+ * Returns the default JTReg arguments for a jvm running a test.
+ * This is the combination of JTReg arguments test.vm.opts and test.java.opts.
+ * @return An array of options, or an empty array if no options.
+ */
+ public static String[] getTestJavaOpts() {
+ List<String> opts = new ArrayList<String>();
+ Collections.addAll(opts, safeSplitString(VM_OPTIONS));
+ Collections.addAll(opts, safeSplitString(JAVA_OPTIONS));
+ return opts.toArray(new String[0]);
+ }
+
+ /**
+ * Combines given arguments with default JTReg arguments for a jvm running a test.
+ * This is the combination of JTReg arguments test.vm.opts and test.java.opts
+ * @return The combination of JTReg test java options and user args.
+ */
+ public static String[] addTestJavaOpts(String... userArgs) {
+ List<String> opts = new ArrayList<String>();
+ Collections.addAll(opts, getTestJavaOpts());
+ Collections.addAll(opts, userArgs);
+ return opts.toArray(new String[0]);
+ }
+
+ /**
+ * Removes any options specifying which GC to use, for example "-XX:+UseG1GC".
+ * Removes any options matching: -XX:(+/-)Use*GC
+ * Used when a test need to set its own GC version. Then any
+ * GC specified by the framework must first be removed.
+ * @return A copy of given opts with all GC options removed.
+ */
+ private static final Pattern useGcPattern = Pattern.compile(
+ "(?:\\-XX\\:[\\+\\-]Use.+GC)"
+ + "|(?:\\-Xconcgc)");
+ public static List<String> removeGcOpts(List<String> opts) {
+ List<String> optsWithoutGC = new ArrayList<String>();
+ for (String opt : opts) {
+ if (useGcPattern.matcher(opt).matches()) {
+ System.out.println("removeGcOpts: removed " + opt);
+ } else {
+ optsWithoutGC.add(opt);
+ }
+ }
+ return optsWithoutGC;
+ }
+
+ /**
+ * Returns the default JTReg arguments for a jvm running a test without
+ * options that matches regular expressions in {@code filters}.
+ * This is the combination of JTReg arguments test.vm.opts and test.java.opts.
+ * @param filters Regular expressions used to filter out options.
+ * @return An array of options, or an empty array if no options.
+ */
+ public static String[] getFilteredTestJavaOpts(String... filters) {
+ String options[] = getTestJavaOpts();
+
+ if (filters.length == 0) {
+ return options;
+ }
+
+ List<String> filteredOptions = new ArrayList<String>(options.length);
+ Pattern patterns[] = new Pattern[filters.length];
+ for (int i = 0; i < filters.length; i++) {
+ patterns[i] = Pattern.compile(filters[i]);
+ }
+
+ for (String option : options) {
+ boolean matched = false;
+ for (int i = 0; i < patterns.length && !matched; i++) {
+ Matcher matcher = patterns[i].matcher(option);
+ matched = matcher.find();
+ }
+ if (!matched) {
+ filteredOptions.add(option);
+ }
+ }
+
+ return filteredOptions.toArray(new String[filteredOptions.size()]);
+ }
+
+ /**
+ * Splits a string by white space.
+ * Works like String.split(), but returns an empty array
+ * if the string is null or empty.
+ */
+ private static String[] safeSplitString(String s) {
+ if (s == null || s.trim().isEmpty()) {
+ return new String[] {};
+ }
+ return s.trim().split("\\s+");
+ }
+
+ /**
+ * @return The full command line for the ProcessBuilder.
+ */
+ public static String getCommandLine(ProcessBuilder pb) {
+ StringBuilder cmd = new StringBuilder();
+ for (String s : pb.command()) {
+ cmd.append(s).append(" ");
+ }
+ return cmd.toString();
+ }
+
+ /**
+ * Returns the free port on the local host.
+ * The function will spin until a valid port number is found.
+ *
+ * @return The port number
+ * @throws InterruptedException if any thread has interrupted the current thread
+ * @throws IOException if an I/O error occurs when opening the socket
+ */
+ public static int getFreePort() throws InterruptedException, IOException {
+ int port = -1;
+
+ while (port <= 0) {
+ Thread.sleep(100);
+
+ ServerSocket serverSocket = null;
+ try {
+ serverSocket = new ServerSocket(0);
+ port = serverSocket.getLocalPort();
+ } finally {
+ serverSocket.close();
+ }
+ }
+
+ return port;
+ }
+
+ /**
+ * Returns the name of the local host.
+ *
+ * @return The host name
+ * @throws UnknownHostException if IP address of a host could not be determined
+ */
+ public static String getHostname() throws UnknownHostException {
+ InetAddress inetAddress = InetAddress.getLocalHost();
+ String hostName = inetAddress.getHostName();
+
+ assertTrue((hostName != null && !hostName.isEmpty()),
+ "Cannot get hostname");
+
+ return hostName;
+ }
+
+ /**
+ * Uses "jcmd -l" to search for a jvm pid. This function will wait
+ * forever (until jtreg timeout) for the pid to be found.
+ * @param key Regular expression to search for
+ * @return The found pid.
+ */
+ public static int waitForJvmPid(String key) throws Throwable {
+ final long iterationSleepMillis = 250;
+ System.out.println("waitForJvmPid: Waiting for key '" + key + "'");
+ System.out.flush();
+ while (true) {
+ int pid = tryFindJvmPid(key);
+ if (pid >= 0) {
+ return pid;
+ }
+ Thread.sleep(iterationSleepMillis);
+ }
+ }
+
+ /**
+ * Searches for a jvm pid in the output from "jcmd -l".
+ *
+ * Example output from jcmd is:
+ * 12498 sun.tools.jcmd.JCmd -l
+ * 12254 /tmp/jdk8/tl/jdk/JTwork/classes/com/sun/tools/attach/Application.jar
+ *
+ * @param key A regular expression to search for.
+ * @return The found pid, or -1 if not found.
+ * @throws Exception If multiple matching jvms are found.
+ */
+ public static int tryFindJvmPid(String key) throws Throwable {
+ OutputAnalyzer output = null;
+ try {
+ JDKToolLauncher jcmdLauncher = JDKToolLauncher.create("jcmd");
+ jcmdLauncher.addToolArg("-l");
+ output = ProcessTools.executeProcess(jcmdLauncher.getCommand());
+ output.shouldHaveExitValue(0);
+
+ // Search for a line starting with numbers (pid), follwed by the key.
+ Pattern pattern = Pattern.compile("([0-9]+)\\s.*(" + key + ").*\\r?\\n");
+ Matcher matcher = pattern.matcher(output.getStdout());
+
+ int pid = -1;
+ if (matcher.find()) {
+ pid = Integer.parseInt(matcher.group(1));
+ System.out.println("findJvmPid.pid: " + pid);
+ if (matcher.find()) {
+ throw new Exception("Found multiple JVM pids for key: " + key);
+ }
+ }
+ return pid;
+ } catch (Throwable t) {
+ System.out.println(String.format("Utils.findJvmPid(%s) failed: %s", key, t));
+ throw t;
+ }
+ }
+
+ /**
+ * Adjusts the provided timeout value for the TIMEOUT_FACTOR
+ * @param tOut the timeout value to be adjusted
+ * @return The timeout value adjusted for the value of "test.timeout.factor"
+ * system property
+ */
+ public static long adjustTimeout(long tOut) {
+ return Math.round(tOut * Utils.TIMEOUT_FACTOR);
+ }
+
+ /**
+ * Return the contents of the named file as a single String,
+ * or null if not found.
+ * @param filename name of the file to read
+ * @return String contents of file, or null if file not found.
+ * @throws IOException
+ * if an I/O error occurs reading from the file or a malformed or
+ * unmappable byte sequence is read
+ */
+ public static String fileAsString(String filename) throws IOException {
+ Path filePath = Paths.get(filename);
+ if (!Files.exists(filePath)) return null;
+ return new String(Files.readAllBytes(filePath));
+ }
+
+ /**
+ * @return Unsafe instance.
+ */
+ public static synchronized Unsafe getUnsafe() {
+ if (unsafe == null) {
+ try {
+ Field f = Unsafe.class.getDeclaredField("theUnsafe");
+ f.setAccessible(true);
+ unsafe = (Unsafe) f.get(null);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new RuntimeException("Unable to get Unsafe instance.", e);
+ }
+ }
+ return unsafe;
+ }
+ private static final char[] hexArray = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+ /**
+ * Returns hex view of byte array
+ *
+ * @param bytes byte array to process
+ * @return Space separated hexadecimal string representation of bytes
+ */
+
+ public static String toHexString(byte[] bytes) {
+ char[] hexView = new char[bytes.length * 3];
+ int i = 0;
+ for (byte b : bytes) {
+ hexView[i++] = hexArray[(b >> 4) & 0x0F];
+ hexView[i++] = hexArray[b & 0x0F];
+ hexView[i++] = ' ';
+ }
+ return new String(hexView);
+ }
+
+ /**
+ * Returns {@link java.util.Random} generator initialized with particular seed.
+ * The seed could be provided via system property {@link Utils#SEED_PROPERTY_NAME}
+ * In case no seed is provided, the method uses a random number.
+ * The used seed printed to stdout.
+ * @return {@link java.util.Random} generator with particular seed.
+ */
+ public static Random getRandomInstance() {
+ if (RANDOM_GENERATOR == null) {
+ synchronized (Utils.class) {
+ if (RANDOM_GENERATOR == null) {
+ RANDOM_GENERATOR = new Random(SEED);
+ System.out.printf("For random generator using seed: %d%n", SEED);
+ System.out.printf("To re-run test with same seed value please add \"-D%s=%d\" to command line.%n", SEED_PROPERTY_NAME, SEED);
+ }
+ }
+ }
+ return RANDOM_GENERATOR;
+ }
+
+ /**
+ * Returns random element of non empty collection
+ *
+ * @param <T> a type of collection element
+ * @param collection collection of elements
+ * @return random element of collection
+ * @throws IllegalArgumentException if collection is empty
+ */
+ public static <T> T getRandomElement(Collection<T> collection)
+ throws IllegalArgumentException {
+ if (collection.isEmpty()) {
+ throw new IllegalArgumentException("Empty collection");
+ }
+ Random random = getRandomInstance();
+ int elementIndex = 1 + random.nextInt(collection.size() - 1);
+ Iterator<T> iterator = collection.iterator();
+ while (--elementIndex != 0) {
+ iterator.next();
+ }
+ return iterator.next();
+ }
+
+ /**
+ * Returns random element of non empty array
+ *
+ * @param <T> a type of array element
+ * @param array array of elements
+ * @return random element of array
+ * @throws IllegalArgumentException if array is empty
+ */
+ public static <T> T getRandomElement(T[] array)
+ throws IllegalArgumentException {
+ if (array == null || array.length == 0) {
+ throw new IllegalArgumentException("Empty or null array");
+ }
+ Random random = getRandomInstance();
+ return array[random.nextInt(array.length)];
+ }
+
+ /**
+ * Wait for condition to be true
+ *
+ * @param condition, a condition to wait for
+ */
+ public static final void waitForCondition(BooleanSupplier condition) {
+ waitForCondition(condition, -1L, 100L);
+ }
+
+ /**
+ * Wait until timeout for condition to be true
+ *
+ * @param condition, a condition to wait for
+ * @param timeout a time in milliseconds to wait for condition to be true
+ * specifying -1 will wait forever
+ * @return condition value, to determine if wait was successful
+ */
+ public static final boolean waitForCondition(BooleanSupplier condition,
+ long timeout) {
+ return waitForCondition(condition, timeout, 100L);
+ }
+
+ /**
+ * Wait until timeout for condition to be true for specified time
+ *
+ * @param condition, a condition to wait for
+ * @param timeout a time in milliseconds to wait for condition to be true,
+ * specifying -1 will wait forever
+ * @param sleepTime a time to sleep value in milliseconds
+ * @return condition value, to determine if wait was successful
+ */
+ public static final boolean waitForCondition(BooleanSupplier condition,
+ long timeout, long sleepTime) {
+ long startTime = System.currentTimeMillis();
+ while (!(condition.getAsBoolean() || (timeout != -1L
+ && ((System.currentTimeMillis() - startTime) > timeout)))) {
+ try {
+ Thread.sleep(sleepTime);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new Error(e);
+ }
+ }
+ return condition.getAsBoolean();
+ }
+
+ /**
+ * Interface same as java.lang.Runnable but with
+ * method {@code run()} able to throw any Throwable.
+ */
+ public static interface ThrowingRunnable {
+ void run() throws Throwable;
+ }
+
+ /**
+ * Filters out an exception that may be thrown by the given
+ * test according to the given filter.
+ *
+ * @param test - method that is invoked and checked for exception.
+ * @param filter - function that checks if the thrown exception matches
+ * criteria given in the filter's implementation.
+ * @return - exception that matches the filter if it has been thrown or
+ * {@code null} otherwise.
+ * @throws Throwable - if test has thrown an exception that does not
+ * match the filter.
+ */
+ public static Throwable filterException(ThrowingRunnable test,
+ Function<Throwable, Boolean> filter) throws Throwable {
+ try {
+ test.run();
+ } catch (Throwable t) {
+ if (filter.apply(t)) {
+ return t;
+ } else {
+ throw t;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Ensures a requested class is loaded
+ * @param aClass class to load
+ */
+ public static void ensureClassIsLoaded(Class<?> aClass) {
+ if (aClass == null) {
+ throw new Error("Requested null class");
+ }
+ try {
+ Class.forName(aClass.getName(), /* initialize = */ true,
+ ClassLoader.getSystemClassLoader());
+ } catch (ClassNotFoundException e) {
+ throw new Error("Class not found", e);
+ }
+ }
+ /**
+ * @param parent a class loader to be the parent for the returned one
+ * @return an UrlClassLoader with urls made of the 'test.class.path' jtreg
+ * property and with the given parent
+ */
+ public static URLClassLoader getTestClassPathURLClassLoader(ClassLoader parent) {
+ URL[] urls = Arrays.stream(TEST_CLASS_PATH.split(File.pathSeparator))
+ .map(Paths::get)
+ .map(Path::toUri)
+ .map(x -> {
+ try {
+ return x.toURL();
+ } catch (MalformedURLException ex) {
+ throw new Error("Test issue. JTREG property"
+ + " 'test.class.path'"
+ + " is not defined correctly", ex);
+ }
+ }).toArray(URL[]::new);
+ return new URLClassLoader(urls, parent);
+ }
+
+ /**
+ * Runs runnable and checks that it throws expected exception. If exceptionException is null it means
+ * that we expect no exception to be thrown.
+ * @param runnable what we run
+ * @param expectedException expected exception
+ */
+ public static void runAndCheckException(Runnable runnable, Class<? extends Throwable> expectedException) {
+ runAndCheckException(runnable, t -> {
+ if (t == null) {
+ if (expectedException != null) {
+ throw new AssertionError("Didn't get expected exception " + expectedException.getSimpleName());
+ }
+ } else {
+ String message = "Got unexpected exception " + t.getClass().getSimpleName();
+ if (expectedException == null) {
+ throw new AssertionError(message, t);
+ } else if (!expectedException.isAssignableFrom(t.getClass())) {
+ message += " instead of " + expectedException.getSimpleName();
+ throw new AssertionError(message, t);
+ }
+ }
+ });
+ }
+
+ /**
+ * Runs runnable and makes some checks to ensure that it throws expected exception.
+ * @param runnable what we run
+ * @param checkException a consumer which checks that we got expected exception and raises a new exception otherwise
+ */
+ public static void runAndCheckException(Runnable runnable, Consumer<Throwable> checkException) {
+ try {
+ runnable.run();
+ checkException.accept(null);
+ } catch (Throwable t) {
+ checkException.accept(t);
+ }
+ }
+
+ /**
+ * Converts to VM type signature
+ *
+ * @param type Java type to convert
+ * @return string representation of VM type
+ */
+ public static String toJVMTypeSignature(Class<?> type) {
+ if (type.isPrimitive()) {
+ if (type == boolean.class) {
+ return "Z";
+ } else if (type == byte.class) {
+ return "B";
+ } else if (type == char.class) {
+ return "C";
+ } else if (type == double.class) {
+ return "D";
+ } else if (type == float.class) {
+ return "F";
+ } else if (type == int.class) {
+ return "I";
+ } else if (type == long.class) {
+ return "J";
+ } else if (type == short.class) {
+ return "S";
+ } else if (type == void.class) {
+ return "V";
+ } else {
+ throw new Error("Unsupported type: " + type);
+ }
+ }
+ String result = type.getName().replaceAll("\\.", "/");
+ if (!type.isArray()) {
+ return "L" + result + ";";
+ }
+ return result;
+ }
+
+ public static Object[] getNullValues(Class<?>... types) {
+ Object[] result = new Object[types.length];
+ int i = 0;
+ for (Class<?> type : types) {
+ result[i++] = NULL_VALUES.get(type);
+ }
+ return result;
+ }
+ private static Map<Class<?>, Object> NULL_VALUES = new HashMap<>();
+ static {
+ NULL_VALUES.put(boolean.class, false);
+ NULL_VALUES.put(byte.class, (byte) 0);
+ NULL_VALUES.put(short.class, (short) 0);
+ NULL_VALUES.put(char.class, '\0');
+ NULL_VALUES.put(int.class, 0);
+ NULL_VALUES.put(long.class, 0L);
+ NULL_VALUES.put(float.class, 0.0f);
+ NULL_VALUES.put(double.class, 0.0d);
+ }
+
+ /**
+ * Returns mandatory property value
+ * @param propName is a name of property to request
+ * @return a String with requested property value
+ */
+ public static String getMandatoryProperty(String propName) {
+ Objects.requireNonNull(propName, "Requested null property");
+ String prop = System.getProperty(propName);
+ Objects.requireNonNull(prop,
+ String.format("A mandatory property '%s' isn't set", propName));
+ return prop;
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/apps/LingeredApp.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.apps;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * This is a framework to launch an app that could be synchronized with caller
+ * to make further attach actions reliable across supported platforms
+
+ * Caller example:
+ * SmartTestApp a = SmartTestApp.startApp(cmd);
+ * // do something
+ * a.stopApp();
+ *
+ * or fine grained control
+ *
+ * a = new SmartTestApp("MyLock.lck");
+ * a.createLock();
+ * a.runApp();
+ * a.waitAppReady();
+ * // do something
+ * a.deleteLock();
+ * a.waitAppTerminate();
+ *
+ * Then you can work with app output and process object
+ *
+ * output = a.getAppOutput();
+ * process = a.getProcess();
+ *
+ */
+public class LingeredApp {
+
+ private static final long spinDelay = 1000;
+ private static final int appWaitTime = 100;
+
+ private final String lockFileName;
+ private long lockCreationTime;
+ private Process appProcess;
+ private final ArrayList<String> storedAppOutput;
+
+ /*
+ * Drain child process output, store it into string array
+ */
+ class InputGobbler extends Thread {
+
+ InputStream is;
+ List<String> astr;
+
+ InputGobbler(InputStream is, List<String> astr) {
+ this.is = is;
+ this.astr = astr;
+ }
+
+ public void run() {
+ try {
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ String line = null;
+ while ((line = br.readLine()) != null) {
+ astr.add(line);
+ }
+ } catch (IOException ex) {
+ // pass
+ }
+ }
+ }
+
+ /**
+ * Create LingeredApp object on caller side. Lock file have be a valid filename
+ * at writable location
+ *
+ * @param lockFileName - the name of lock file
+ */
+ public LingeredApp(String lockFileName) {
+ this.lockFileName = lockFileName;
+ this.storedAppOutput = new ArrayList<String>();
+ }
+
+ public LingeredApp() {
+ final String lockName = UUID.randomUUID().toString() + ".lck";
+ this.lockFileName = lockName;
+ this.storedAppOutput = new ArrayList<String>();
+ }
+
+ /**
+ *
+ * @return name of lock file
+ */
+ public String getLockFileName() {
+ return this.lockFileName;
+ }
+
+ /**
+ *
+ * @return name of testapp
+ */
+ public String getAppName() {
+ return this.getClass().getName();
+ }
+
+ /**
+ *
+ * @return pid of java process running testapp
+ */
+ public long getPid() {
+ if (appProcess == null) {
+ throw new RuntimeException("Process is not alive");
+ }
+ return appProcess.getPid();
+ }
+
+ /**
+ *
+ * @return process object
+ */
+ public Process getProcess() {
+ return appProcess;
+ }
+
+ /**
+ *
+ * @return application output as string array. Empty array if application produced no output
+ */
+ public List<String> getAppOutput() {
+ if (appProcess.isAlive()) {
+ throw new RuntimeException("Process is still alive. Can't get its output.");
+ }
+ return storedAppOutput;
+ }
+
+ /* Make sure all part of the app use the same method to get dates,
+ as different methods could produce different results
+ */
+ private static long epoch() {
+ return new Date().getTime();
+ }
+
+ private static long lastModified(String fileName) throws IOException {
+ Path path = Paths.get(fileName);
+ BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class);
+ return attr.lastModifiedTime().toMillis();
+ }
+
+ private static void setLastModified(String fileName, long newTime) throws IOException {
+ Path path = Paths.get(fileName);
+ FileTime fileTime = FileTime.fromMillis(newTime);
+ Files.setLastModifiedTime(path, fileTime);
+ }
+
+ /**
+ * create lock
+ *
+ * @throws IOException
+ */
+ public void createLock() throws IOException {
+ Path path = Paths.get(lockFileName);
+ // Files.deleteIfExists(path);
+ Files.createFile(path);
+ lockCreationTime = lastModified(lockFileName);
+ }
+
+ /**
+ * Delete lock
+ *
+ * @throws IOException
+ */
+ public void deleteLock() throws IOException {
+ try {
+ Path path = Paths.get(lockFileName);
+ Files.delete(path);
+ } catch (NoSuchFileException ex) {
+ // Lock already deleted. Ignore error
+ }
+ }
+
+ public void waitAppTerminate() {
+ while (true) {
+ try {
+ appProcess.waitFor();
+ break;
+ } catch (InterruptedException ex) {
+ // pass
+ }
+ }
+ }
+
+ /**
+ * The app touches the lock file when it's started
+ * wait while it happens. Caller have to delete lock on wait error.
+ *
+ * @param timeout
+ * @throws java.io.IOException
+ */
+ public void waitAppReady(long timeout) throws IOException {
+ long here = epoch();
+ while (true) {
+ long epoch = epoch();
+ if (epoch - here > (timeout * 1000)) {
+ throw new IOException("App waiting timeout");
+ }
+
+ // Live process should touch lock file every second
+ long lm = lastModified(lockFileName);
+ if (lm > lockCreationTime) {
+ break;
+ }
+
+ // Make sure process didn't already exit
+ if (!appProcess.isAlive()) {
+ throw new IOException("App exited unexpectedly with " + appProcess.exitValue());
+ }
+
+ try {
+ Thread.sleep(spinDelay);
+ } catch (InterruptedException ex) {
+ // pass
+ }
+ }
+ }
+
+ /**
+ * Run the app
+ *
+ * @param vmArguments
+ * @throws IOException
+ */
+ public void runApp(List<String> vmArguments)
+ throws IOException {
+
+ // We should always use testjava or throw an exception,
+ // so we can't use JDKToolFinder.getJDKTool("java");
+ // that falls back to compile java on error
+ String jdkPath = System.getProperty("test.jdk");
+ if (jdkPath == null) {
+ // we are not under jtreg, try env
+ Map<String, String> env = System.getenv();
+ jdkPath = env.get("TESTJAVA");
+ }
+
+ if (jdkPath == null) {
+ throw new RuntimeException("Can't determine jdk path neither test.jdk property no TESTJAVA env are set");
+ }
+
+ String osname = System.getProperty("os.name");
+ String javapath = jdkPath + ((osname.startsWith("window")) ? "/bin/java.exe" : "/bin/java");
+
+ List<String> cmd = new ArrayList<String>();
+ cmd.add(javapath);
+
+
+ if (vmArguments == null) {
+ // Propagate test.vm.options to LingeredApp, filter out possible empty options
+ String testVmOpts[] = System.getProperty("test.vm.opts","").split("\\s+");
+ for (String s : testVmOpts) {
+ if (!s.equals("")) {
+ cmd.add(s);
+ }
+ }
+ }
+ else{
+ // Lets user manage LingeredApp options
+ cmd.addAll(vmArguments);
+ }
+
+ // Make sure we set correct classpath to run the app
+ cmd.add("-cp");
+ String classpath = System.getProperty("test.class.path");
+ cmd.add((classpath == null) ? "." : classpath);
+
+ cmd.add(this.getAppName());
+ cmd.add(lockFileName);
+
+ // Reporting
+ StringBuilder cmdLine = new StringBuilder();
+ for (String strCmd : cmd) {
+ cmdLine.append("'").append(strCmd).append("' ");
+ }
+
+ // A bit of verbosity
+ System.out.println("Command line: [" + cmdLine.toString() + "]");
+
+ ProcessBuilder pb = new ProcessBuilder(cmd);
+ // we don't expect any error output but make sure we are not stuck on pipe
+ // pb.redirectErrorStream(false);
+ pb.redirectError(ProcessBuilder.Redirect.INHERIT);
+
+ appProcess = pb.start();
+
+ // Create pipe reader for process, and read stdin and stderr to array of strings
+ InputGobbler gb = new InputGobbler(appProcess.getInputStream(), storedAppOutput);
+ gb.start();
+ }
+
+ /**
+ * Delete lock file that signals app to terminate, then
+ * wait until app is actually terminated.
+ * @throws IOException
+ */
+ public void stopApp() throws IOException {
+ deleteLock();
+ waitAppTerminate();
+ int exitcode = appProcess.exitValue();
+ if (exitcode != 0) {
+ throw new IOException("LingeredApp terminated with non-zero exit code " + exitcode);
+ }
+ }
+
+ /**
+ * High level interface for test writers
+ */
+ /**
+ * Factory method that creates LingeredApp object with ready to use application
+ * lock name is autogenerated
+ * @param cmd - vm options, could be null to auto add testvm.options
+ * @return LingeredApp object
+ * @throws IOException
+ */
+ public static LingeredApp startApp(List<String> cmd) throws IOException {
+ LingeredApp a = new LingeredApp();
+ a.createLock();
+ try {
+ a.runApp(cmd);
+ a.waitAppReady(appWaitTime);
+ } catch (Exception ex) {
+ a.deleteLock();
+ throw ex;
+ }
+
+ return a;
+ }
+
+ /**
+ * Factory method that starts pre-created LingeredApp
+ * lock name is autogenerated
+ * @param cmd - vm options, could be null to auto add testvm.options
+ * @param theApp - app to start
+ * @return LingeredApp object
+ * @throws IOException
+ */
+
+ public static void startApp(List<String> cmd, LingeredApp theApp) throws IOException {
+ theApp.createLock();
+ try {
+ theApp.runApp(cmd);
+ theApp.waitAppReady(appWaitTime);
+ } catch (Exception ex) {
+ theApp.deleteLock();
+ throw ex;
+ }
+ }
+
+ public static LingeredApp startApp() throws IOException {
+ return startApp(null);
+ }
+
+ public static void stopApp(LingeredApp app) throws IOException {
+ if (app != null) {
+ // LingeredApp can throw an exception during the intialization,
+ // make sure we don't have cascade NPE
+ app.stopApp();
+ }
+ }
+
+ /**
+ * LastModified time might not work correctly in some cases it might
+ * cause later failures
+ */
+
+ public static boolean isLastModifiedWorking() {
+ boolean sane = true;
+ try {
+ long lm = lastModified(".");
+ if (lm == 0) {
+ System.err.println("SANITY Warning! The lastModifiedTime() doesn't work on this system, it returns 0");
+ sane = false;
+ }
+
+ long now = epoch();
+ if (lm > now) {
+ System.err.println("SANITY Warning! The Clock is wrong on this system lastModifiedTime() > getTime()");
+ sane = false;
+ }
+
+ setLastModified(".", epoch());
+ long lm1 = lastModified(".");
+ if (lm1 <= lm) {
+ System.err.println("SANITY Warning! The setLastModified doesn't work on this system");
+ sane = false;
+ }
+ }
+ catch(IOException e) {
+ System.err.println("SANITY Warning! IOException during sanity check " + e);
+ sane = false;
+ }
+
+ return sane;
+ }
+
+ /**
+ * This part is the application it self
+ */
+ public static void main(String args[]) {
+
+ if (args.length != 1) {
+ System.err.println("Lock file name is not specified");
+ System.exit(7);
+ }
+
+ String theLockFileName = args[0];
+
+ try {
+ Path path = Paths.get(theLockFileName);
+
+ while (Files.exists(path)) {
+ // Touch the lock to indicate our readiness
+ setLastModified(theLockFileName, epoch());
+ Thread.sleep(spinDelay);
+ }
+ } catch (NoSuchFileException ex) {
+ // Lock deleted while we are setting last modified time.
+ // Ignore error and lets the app exits
+ } catch (Exception ex) {
+ System.err.println("LingeredApp ERROR: " + ex);
+ // Leave exit_code = 1 to Java launcher
+ System.exit(3);
+ }
+
+ System.exit(0);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/apps/LingeredAppWithDeadlock.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.apps;
+
+import java.util.concurrent.Phaser;
+
+public class LingeredAppWithDeadlock extends LingeredApp {
+
+ private static final Object Lock1 = new Object();
+ private static final Object Lock2 = new Object();
+
+ private static volatile int reachCount = 0;
+
+ private static final Phaser p = new Phaser(2);
+
+ private static class ThreadOne extends Thread {
+ public void run() {
+ // wait Lock2 is locked
+ p.arriveAndAwaitAdvance();
+ synchronized (Lock1) {
+ // signal Lock1 is locked
+ p.arriveAndAwaitAdvance();
+ synchronized (Lock2) {
+ reachCount += 1;
+ }
+ }
+ }
+ }
+
+ private static class ThreadTwo extends Thread {
+ public void run() {
+ synchronized (Lock2) {
+ // signal Lock2 is locked
+ p.arriveAndAwaitAdvance();
+ // wait Lock1 is locked
+ p.arriveAndAwaitAdvance();
+ synchronized (Lock1) {
+ reachCount += 1;
+ }
+ }
+ }
+ }
+
+ public static void main(String args[]) {
+ if (args.length != 1) {
+ System.err.println("Lock file name is not specified");
+ System.exit(7);
+ }
+
+ // Run two theads that should come to deadlock
+ new ThreadOne().start();
+ new ThreadTwo().start();
+
+ if (reachCount > 0) {
+ // Not able to deadlock, exiting
+ System.exit(3);
+ }
+
+ LingeredApp.main(args);
+ }
+ }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/cli/CPUSpecificCommandLineOptionTest.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.cli;
+
+import jdk.test.lib.cli.predicate.CPUSpecificPredicate;
+
+/**
+ * Base class for command line options tests that
+ * requires specific CPU arch or specific CPU features.
+ */
+public abstract class CPUSpecificCommandLineOptionTest
+ extends CommandLineOptionTest {
+ /**
+ * Creates new CPU specific test instance that does not
+ * require any CPU features.
+ *
+ * @param cpuArchPattern Regular expression that should
+ * match os.arch.
+ */
+ public CPUSpecificCommandLineOptionTest(String cpuArchPattern) {
+ this(cpuArchPattern, null, null);
+ }
+
+ /**
+ * Creates new CPU specific test instance that does not
+ * require from CPU support of {@code supportedCPUFeatures} features
+ * and no support of {@code unsupportedCPUFeatures}.
+ *
+ * @param cpuArchPattern Regular expression that should
+ * match os.arch.
+ * @param supportedCPUFeatures Array with names of features that
+ * should be supported by CPU. If {@code null},
+ * then no features have to be supported.
+ * @param unsupportedCPUFeatures Array with names of features that
+ * should not be supported by CPU.
+ * If {@code null}, then CPU may support any
+ * features.
+ */
+ public CPUSpecificCommandLineOptionTest(String cpuArchPattern,
+ String supportedCPUFeatures[], String unsupportedCPUFeatures[]) {
+ super(new CPUSpecificPredicate(cpuArchPattern, supportedCPUFeatures,
+ unsupportedCPUFeatures));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/cli/CommandLineOptionTest.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,524 @@
+/*
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.cli;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.function.BooleanSupplier;
+
+import jdk.test.lib.process.ExitCode;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.Platform;
+import jdk.test.lib.Utils;
+
+/**
+ * Base class for command line option tests.
+ */
+public abstract class CommandLineOptionTest {
+ public static final String UNLOCK_DIAGNOSTIC_VM_OPTIONS
+ = "-XX:+UnlockDiagnosticVMOptions";
+ public static final String UNLOCK_EXPERIMENTAL_VM_OPTIONS
+ = "-XX:+UnlockExperimentalVMOptions";
+ protected static final String UNRECOGNIZED_OPTION_ERROR_FORMAT
+ = "Unrecognized VM option '[+-]?%s(=.*)?'";
+ protected static final String EXPERIMENTAL_OPTION_ERROR_FORMAT
+ = "VM option '%s' is experimental and must be enabled via "
+ + "-XX:\\+UnlockExperimentalVMOptions.";
+ protected static final String DIAGNOSTIC_OPTION_ERROR_FORMAT
+ = " VM option '%s' is diagnostic and must be enabled via "
+ + "-XX:\\+UnlockDiagnosticVMOptions.";
+ private static final String PRINT_FLAGS_FINAL_FORMAT = "%s\\s*:?=\\s*%s";
+
+ /**
+ * Verifies that JVM startup behavior matches our expectations.
+ *
+ * @param option an option that should be passed to JVM
+ * @param expectedMessages an array of patterns that should occur
+ * in JVM output. If {@code null} then
+ * JVM output could be empty.
+ * @param unexpectedMessages an array of patterns that should not
+ * occur in JVM output. If {@code null} then
+ * JVM output could be empty.
+ * @param exitErrorMessage message that will be shown if exit code is not
+ * as expected.
+ * @param wrongWarningMessage message that will be shown if warning
+ * messages are not as expected.
+ * @param exitCode expected exit code.
+ * @throws Throwable if verification fails or some other issues occur.
+ */
+ public static void verifyJVMStartup(String option,
+ String expectedMessages[], String unexpectedMessages[],
+ String exitErrorMessage, String wrongWarningMessage,
+ ExitCode exitCode) throws Throwable {
+ CommandLineOptionTest.verifyJVMStartup(expectedMessages,
+ unexpectedMessages, exitErrorMessage,
+ wrongWarningMessage, exitCode, false, option);
+ }
+
+ /**
+ * Verifies that JVM startup behavior matches our expectations.
+ *
+ * @param expectedMessages an array of patterns that should occur
+ * in JVM output. If {@code null} then
+ * JVM output could be empty.
+ * @param unexpectedMessages an array of patterns that should not
+ * occur in JVM output. If {@code null} then
+ * JVM output could be empty.
+ * @param exitErrorMessage message that will be shown if exit code is not
+ * as expected.
+ * @param wrongWarningMessage message that will be shown if warning
+ * messages are not as expected.
+ * @param exitCode expected exit code.
+ * @param addTestVMOptions if {@code true} then test VM options will be
+ * passed to VM.
+ * @param options options that should be passed to VM in addition to mode
+ * flag.
+ * @throws Throwable if verification fails or some other issues occur.
+ */
+ public static void verifyJVMStartup(String expectedMessages[],
+ String unexpectedMessages[], String exitErrorMessage,
+ String wrongWarningMessage, ExitCode exitCode,
+ boolean addTestVMOptions, String... options)
+ throws Throwable {
+ List<String> finalOptions = new ArrayList<>();
+ if (addTestVMOptions) {
+ Collections.addAll(finalOptions, ProcessTools.getVmInputArgs());
+ Collections.addAll(finalOptions, Utils.getTestJavaOpts());
+ }
+ Collections.addAll(finalOptions, options);
+ finalOptions.add("-version");
+
+ ProcessBuilder processBuilder
+ = ProcessTools.createJavaProcessBuilder(finalOptions.toArray(
+ new String[finalOptions.size()]));
+ OutputAnalyzer outputAnalyzer
+ = new OutputAnalyzer(processBuilder.start());
+
+ try {
+ outputAnalyzer.shouldHaveExitValue(exitCode.value);
+ } catch (RuntimeException e) {
+ String errorMessage = String.format(
+ "JVM process should have exit value '%d'.%n%s",
+ exitCode.value, exitErrorMessage);
+ throw new AssertionError(errorMessage, e);
+ }
+
+ verifyOutput(expectedMessages, unexpectedMessages,
+ wrongWarningMessage, outputAnalyzer);
+ }
+
+ /**
+ * Verifies that JVM startup behavior matches our expectations.
+ *
+ * @param expectedMessages an array of patterns that should occur in JVM
+ * output. If {@code null} then
+ * JVM output could be empty.
+ * @param unexpectedMessages an array of patterns that should not occur
+ * in JVM output. If {@code null} then
+ * JVM output could be empty.
+ * @param wrongWarningMessage message that will be shown if messages are
+ * not as expected.
+ * @param outputAnalyzer OutputAnalyzer instance
+ * @throws AssertionError if verification fails.
+ */
+ public static void verifyOutput(String[] expectedMessages,
+ String[] unexpectedMessages, String wrongWarningMessage,
+ OutputAnalyzer outputAnalyzer) {
+ if (expectedMessages != null) {
+ for (String expectedMessage : expectedMessages) {
+ try {
+ outputAnalyzer.shouldMatch(expectedMessage);
+ } catch (RuntimeException e) {
+ String errorMessage = String.format(
+ "Expected message not found: '%s'.%n%s",
+ expectedMessage, wrongWarningMessage);
+ throw new AssertionError(errorMessage, e);
+ }
+ }
+ }
+
+ if (unexpectedMessages != null) {
+ for (String unexpectedMessage : unexpectedMessages) {
+ try {
+ outputAnalyzer.shouldNotMatch(unexpectedMessage);
+ } catch (RuntimeException e) {
+ String errorMessage = String.format(
+ "Unexpected message found: '%s'.%n%s",
+ unexpectedMessage, wrongWarningMessage);
+ throw new AssertionError(errorMessage, e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Verifies that JVM startup behavior matches our expectations when type
+ * of newly started VM is the same as the type of current.
+ *
+ * @param expectedMessages an array of patterns that should occur
+ * in JVM output. If {@code null} then
+ * JVM output could be empty.
+ * @param unexpectedMessages an array of patterns that should not
+ * occur in JVM output. If {@code null} then
+ * JVM output could be empty.
+ * @param exitErrorMessage Message that will be shown if exit value is not
+ * as expected.
+ * @param wrongWarningMessage message that will be shown if warning
+ * messages are not as expected.
+ * @param exitCode expected exit code.
+ * @param options options that should be passed to VM in addition to mode
+ * flag.
+ * @throws Throwable if verification fails or some other issues occur.
+ */
+ public static void verifySameJVMStartup(String expectedMessages[],
+ String unexpectedMessages[], String exitErrorMessage,
+ String wrongWarningMessage, ExitCode exitCode, String... options)
+ throws Throwable {
+ List<String> finalOptions = new ArrayList<>();
+ finalOptions.add(CommandLineOptionTest.getVMTypeOption());
+ Collections.addAll(finalOptions, options);
+
+ CommandLineOptionTest.verifyJVMStartup(expectedMessages,
+ unexpectedMessages, exitErrorMessage,
+ wrongWarningMessage, exitCode, false,
+ finalOptions.toArray(new String[finalOptions.size()]));
+ }
+
+ /**
+ * Verifies that value of specified JVM option is the same as
+ * expected value.
+ * This method filter out option with {@code optionName}
+ * name from test java options.
+ *
+ * @param optionName a name of tested option.
+ * @param expectedValue expected value of tested option.
+ * @param optionErrorString message will be shown if option value is not as
+ * expected.
+ * @param additionalVMOpts additional options that should be
+ * passed to JVM.
+ * @throws Throwable if verification fails or some other issues occur.
+ */
+ public static void verifyOptionValue(String optionName,
+ String expectedValue, String optionErrorString,
+ String... additionalVMOpts) throws Throwable {
+ verifyOptionValue(optionName, expectedValue, optionErrorString,
+ true, additionalVMOpts);
+ }
+
+ /**
+ * Verifies that value of specified JVM option is the same as
+ * expected value.
+ * This method filter out option with {@code optionName}
+ * name from test java options.
+ *
+ * @param optionName a name of tested option.
+ * @param expectedValue expected value of tested option.
+ * @param addTestVmOptions if {@code true}, then test VM options
+ * will be used.
+ * @param optionErrorString message will be shown if option value is not as
+ * expected.
+ * @param additionalVMOpts additional options that should be
+ * passed to JVM.
+ * @throws Throwable if verification fails or some other issues
+ * occur.
+ */
+ public static void verifyOptionValue(String optionName,
+ String expectedValue, String optionErrorString,
+ boolean addTestVmOptions, String... additionalVMOpts)
+ throws Throwable {
+ List<String> vmOpts = new ArrayList<>();
+
+ if (addTestVmOptions) {
+ Collections.addAll(vmOpts,
+ Utils.getFilteredTestJavaOpts(optionName));
+ }
+ Collections.addAll(vmOpts, additionalVMOpts);
+ Collections.addAll(vmOpts, "-XX:+PrintFlagsFinal", "-version");
+
+ ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
+ vmOpts.toArray(new String[vmOpts.size()]));
+
+ OutputAnalyzer outputAnalyzer
+ = new OutputAnalyzer(processBuilder.start());
+
+ try {
+ outputAnalyzer.shouldHaveExitValue(0);
+ } catch (RuntimeException e) {
+ String errorMessage = String.format(
+ "JVM should start with option '%s' without errors.",
+ optionName);
+ throw new AssertionError(errorMessage, e);
+ }
+ verifyOptionValue(optionName, expectedValue, optionErrorString,
+ outputAnalyzer);
+ }
+
+ /**
+ * Verifies that value of specified JVM option is the same as
+ * expected value.
+ *
+ * @param optionName a name of tested option.
+ * @param expectedValue expected value of tested option.
+ * @param optionErrorString message will be shown if option value is not
+ * as expected.
+ * @param outputAnalyzer OutputAnalyzer instance
+ * @throws AssertionError if verification fails
+ */
+ public static void verifyOptionValue(String optionName,
+ String expectedValue, String optionErrorString,
+ OutputAnalyzer outputAnalyzer) {
+ try {
+ outputAnalyzer.shouldMatch(String.format(
+ CommandLineOptionTest.PRINT_FLAGS_FINAL_FORMAT,
+ optionName, expectedValue));
+ } catch (RuntimeException e) {
+ String errorMessage = String.format(
+ "Option '%s' is expected to have '%s' value%n%s",
+ optionName, expectedValue,
+ optionErrorString);
+ throw new AssertionError(errorMessage, e);
+ }
+ }
+
+ /**
+ * Start VM with given options and values.
+ * Generates command line option flags from
+ * {@code optionNames} and {@code optionValues}.
+ *
+ * @param optionNames names of options to pass in
+ * @param optionValues values of option
+ * @param additionalVMOpts additional options that should be
+ * passed to JVM.
+ * @return output from vm process
+ */
+ public static OutputAnalyzer startVMWithOptions(String[] optionNames,
+ String[] optionValues,
+ String... additionalVMOpts) throws Throwable {
+ List<String> vmOpts = new ArrayList<>();
+ if (optionNames == null || optionValues == null || optionNames.length != optionValues.length) {
+ throw new IllegalArgumentException("optionNames and/or optionValues");
+ }
+
+ for (int i = 0; i < optionNames.length; i++) {
+ vmOpts.add(prepareFlag(optionNames[i], optionValues[i]));
+ }
+ Collections.addAll(vmOpts, additionalVMOpts);
+ Collections.addAll(vmOpts, "-version");
+
+ ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
+ vmOpts.toArray(new String[vmOpts.size()]));
+
+ return new OutputAnalyzer(processBuilder.start());
+ }
+
+ /**
+ * Verifies from the output that values of specified JVM options were the same as
+ * expected values.
+ *
+ * @param outputAnalyzer search output for expect options and values.
+ * @param optionNames names of tested options.
+ * @param expectedValues expected values of tested options.
+ * @throws Throwable if verification fails or some other issues occur.
+ */
+ public static void verifyOptionValuesFromOutput(OutputAnalyzer outputAnalyzer,
+ String[] optionNames,
+ String[] expectedValues) throws Throwable {
+ outputAnalyzer.shouldHaveExitValue(0);
+ for (int i = 0; i < optionNames.length; i++) {
+ outputAnalyzer.shouldMatch(String.format(
+ CommandLineOptionTest.PRINT_FLAGS_FINAL_FORMAT,
+ optionNames[i], expectedValues[i]));
+ }
+ }
+
+ /**
+ * Verifies that value of specified JVM options are the same as
+ * expected values.
+ * Generates command line option flags from
+ * {@code optionNames} and {@code expectedValues}.
+ *
+ * @param optionNames names of tested options.
+ * @param expectedValues expected values of tested options.
+ * @throws Throwable if verification fails or some other issues occur.
+ */
+ public static void verifyOptionValues(String[] optionNames,
+ String[] expectedValues) throws Throwable {
+ OutputAnalyzer outputAnalyzer = startVMWithOptions(optionNames, expectedValues, "-XX:+PrintFlagsFinal");
+ verifyOptionValuesFromOutput(outputAnalyzer, optionNames, expectedValues);
+ }
+
+ /**
+ * Verifies that value of specified JVM when type of newly started VM
+ * is the same as the type of current.
+ * This method filter out option with {@code optionName}
+ * name from test java options.
+ * Only mode flag will be passed to VM in addition to
+ * {@code additionalVMOpts}
+ *
+ * @param optionName name of tested option.
+ * @param expectedValue expected value of tested option.
+ * @param optionErrorString message to show if option has another value
+ * @param additionalVMOpts additional options that should be
+ * passed to JVM.
+ * @throws Throwable if verification fails or some other issues occur.
+ */
+ public static void verifyOptionValueForSameVM(String optionName,
+ String expectedValue, String optionErrorString,
+ String... additionalVMOpts) throws Throwable {
+ List<String> finalOptions = new ArrayList<>();
+ finalOptions.add(CommandLineOptionTest.getVMTypeOption());
+ Collections.addAll(finalOptions, additionalVMOpts);
+
+ CommandLineOptionTest.verifyOptionValue(optionName, expectedValue,
+ optionErrorString, false,
+ finalOptions.toArray(new String[finalOptions.size()]));
+ }
+
+ /**
+ * Prepares boolean command line flag with name {@code name} according
+ * to it's {@code value}.
+ *
+ * @param name the name of option to be prepared
+ * @param value the value of option
+ * @return prepared command line flag
+ */
+ public static String prepareBooleanFlag(String name, boolean value) {
+ return String.format("-XX:%c%s", (value ? '+' : '-'), name);
+ }
+
+ /**
+ * Prepares numeric command line flag with name {@code name} by setting
+ * it's value to {@code value}.
+ *
+ * @param name the name of option to be prepared
+ * @param value the value of option
+ * @return prepared command line flag
+ */
+ public static String prepareNumericFlag(String name, Number value) {
+ return String.format("-XX:%s=%s", name, value.toString());
+ }
+
+ /**
+ * Prepares generic command line flag with name {@code name} by setting
+ * it's value to {@code value}.
+ *
+ * @param name the name of option to be prepared
+ * @param value the value of option ("+" or "-" can be used instead of "true" or "false")
+ * @return prepared command line flag
+ */
+ public static String prepareFlag(String name, String value) {
+ if (value.equals("+") || value.equalsIgnoreCase("true")) {
+ return "-XX:+" + name;
+ } else if (value.equals("-") || value.equalsIgnoreCase("false")) {
+ return "-XX:-" + name;
+ } else {
+ return "-XX:" + name + "=" + value;
+ }
+ }
+
+ /**
+ * Returns message that should occur in VM output if option
+ * {@code optionName} if unrecognized.
+ *
+ * @param optionName the name of option for which message should be returned
+ * @return message saying that option {@code optionName} is unrecognized
+ */
+ public static String getUnrecognizedOptionErrorMessage(String optionName) {
+ return String.format(
+ CommandLineOptionTest.UNRECOGNIZED_OPTION_ERROR_FORMAT,
+ optionName);
+ }
+
+ /**
+ * Returns message that should occur in VM output if option
+ * {@code optionName} is experimental and
+ * -XX:+UnlockExperimentalVMOptions was not passed to VM.
+ *
+ * @param optionName the name of option for which message should be returned
+ * @return message saying that option {@code optionName} is experimental
+ */
+ public static String getExperimentalOptionErrorMessage(String optionName) {
+ return String.format(
+ CommandLineOptionTest.EXPERIMENTAL_OPTION_ERROR_FORMAT,
+ optionName);
+ }
+
+ /**
+ * Returns message that should occur in VM output if option
+ * {@code optionName} is diagnostic and -XX:+UnlockDiagnosticVMOptions
+ * was not passed to VM.
+ *
+ * @param optionName the name of option for which message should be returned
+ * @return message saying that option {@code optionName} is diganostic
+ */
+ public static String getDiagnosticOptionErrorMessage(String optionName) {
+ return String.format(
+ CommandLineOptionTest.DIAGNOSTIC_OPTION_ERROR_FORMAT,
+ optionName);
+ }
+
+ /**
+ * @return option required to start a new VM with the same type as current.
+ * @throws RuntimeException when VM type is unknown.
+ */
+ private static String getVMTypeOption() {
+ if (Platform.isServer()) {
+ return "-server";
+ } else if (Platform.isClient()) {
+ return "-client";
+ } else if (Platform.isMinimal()) {
+ return "-minimal";
+ } else if (Platform.isGraal()) {
+ return "-graal";
+ }
+ throw new RuntimeException("Unknown VM mode.");
+ }
+
+ private final BooleanSupplier predicate;
+
+ /**
+ * Constructs new CommandLineOptionTest that will be executed only if
+ * predicate {@code predicate} return {@code true}.
+ * @param predicate a predicate responsible for test's preconditions check.
+ */
+ public CommandLineOptionTest(BooleanSupplier predicate) {
+ this.predicate = predicate;
+ }
+
+ /**
+ * Runs command line option test.
+ */
+ public final void test() throws Throwable {
+ if (predicate.getAsBoolean()) {
+ runTestCases();
+ }
+ }
+
+ /**
+ * @throws Throwable if some issue happened during test cases execution.
+ */
+ protected abstract void runTestCases() throws Throwable;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/cli/predicate/AndPredicate.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.cli.predicate;
+
+import java.util.function.BooleanSupplier;
+
+public class AndPredicate implements BooleanSupplier {
+ private final BooleanSupplier a;
+ private final BooleanSupplier b;
+
+ public AndPredicate(BooleanSupplier a, BooleanSupplier b) {
+ this.a = a;
+ this.b = b;
+ }
+
+ @Override
+ public boolean getAsBoolean() {
+ return a.getAsBoolean() && b.getAsBoolean();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/cli/predicate/CPUSpecificPredicate.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.cli.predicate;
+
+import jdk.test.lib.Platform;
+import sun.hotspot.cpuinfo.CPUInfo;
+
+import java.util.function.BooleanSupplier;
+
+public class CPUSpecificPredicate implements BooleanSupplier {
+ private final String cpuArchPattern;
+ private final String supportedCPUFeatures[];
+ private final String unsupportedCPUFeatures[];
+
+ public CPUSpecificPredicate(String cpuArchPattern,
+ String supportedCPUFeatures[],
+ String unsupportedCPUFeatures[]) {
+ this.cpuArchPattern = cpuArchPattern;
+ this.supportedCPUFeatures = supportedCPUFeatures;
+ this.unsupportedCPUFeatures = unsupportedCPUFeatures;
+ }
+
+ @Override
+ public boolean getAsBoolean() {
+ if (!Platform.getOsArch().matches(cpuArchPattern)) {
+ System.out.println("CPU arch " + Platform.getOsArch() + " does not match " + cpuArchPattern);
+ return false;
+ }
+
+ if (supportedCPUFeatures != null) {
+ for (String feature : supportedCPUFeatures) {
+ if (!CPUInfo.hasFeature(feature)) {
+ System.out.println("CPU does not support " + feature
+ + " feature");
+ return false;
+ }
+ }
+ }
+
+ if (unsupportedCPUFeatures != null) {
+ for (String feature : unsupportedCPUFeatures) {
+ if (CPUInfo.hasFeature(feature)) {
+ System.out.println("CPU support " + feature + " feature");
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/cli/predicate/NotPredicate.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.cli.predicate;
+
+import java.util.function.BooleanSupplier;
+
+public class NotPredicate implements BooleanSupplier {
+ private final BooleanSupplier s;
+
+ public NotPredicate(BooleanSupplier s) {
+ this.s = s;
+ }
+
+ @Override
+ public boolean getAsBoolean() {
+ return !s.getAsBoolean();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/cli/predicate/OrPredicate.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.cli.predicate;
+
+import java.util.function.BooleanSupplier;
+
+public class OrPredicate implements BooleanSupplier {
+ private final BooleanSupplier a;
+ private final BooleanSupplier b;
+
+ public OrPredicate(BooleanSupplier a, BooleanSupplier b) {
+ this.a = a;
+ this.b = b;
+ }
+
+ @Override
+ public boolean getAsBoolean() {
+ return a.getAsBoolean() || b.getAsBoolean();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/dcmd/CommandExecutor.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.dcmd;
+
+import jdk.test.lib.process.OutputAnalyzer;
+
+/**
+ * Abstract base class for Diagnostic Command executors
+ */
+public abstract class CommandExecutor {
+
+ /**
+ * Execute a diagnostic command
+ *
+ * @param cmd The diagnostic command to execute
+ * @return an {@link jdk.testlibrary.OutputAnalyzer} encapsulating the output of the command
+ * @throws CommandExecutorException if there is an exception on the "calling side" while trying to execute the
+ * Diagnostic Command. Exceptions thrown on the remote side are available as textual representations in
+ * stderr, regardless of the specific executor used.
+ */
+ public final OutputAnalyzer execute(String cmd) throws CommandExecutorException {
+ return execute(cmd, false);
+ }
+
+ /**
+ * Execute a diagnostic command
+ *
+ * @param cmd The diagnostic command to execute
+ * @param silent Do not print the command output
+ * @return an {@link jdk.testlibrary.OutputAnalyzer} encapsulating the output of the command
+ * @throws CommandExecutorException if there is an exception on the "calling side" while trying to execute the
+ * Diagnostic Command. Exceptions thrown on the remote side are available as textual representations in
+ * stderr, regardless of the specific executor used.
+ */
+ public final OutputAnalyzer execute(String cmd, boolean silent) throws CommandExecutorException {
+ if (!silent) {
+ System.out.printf("Running DCMD '%s' through '%s'%n", cmd, this.getClass().getSimpleName());
+ }
+
+ OutputAnalyzer oa = executeImpl(cmd);
+
+ if (!silent) {
+ System.out.println("---------------- stdout ----------------");
+ System.out.println(oa.getStdout());
+ System.out.println("---------------- stderr ----------------");
+ System.out.println(oa.getStderr());
+ System.out.println("----------------------------------------");
+ System.out.println();
+ }
+ return oa;
+ }
+
+ protected abstract OutputAnalyzer executeImpl(String cmd) throws CommandExecutorException;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/dcmd/CommandExecutorException.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.dcmd;
+
+/**
+ * CommandExecutorException encapsulates exceptions thrown (on the "calling side") from the execution of Diagnostic
+ * Commands
+ */
+public class CommandExecutorException extends RuntimeException {
+ private static final long serialVersionUID = -7039597746579144280L;
+
+ public CommandExecutorException(String message, Throwable e) {
+ super(message, e);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/dcmd/FileJcmdExecutor.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.dcmd;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Executes Diagnostic Commands on the target VM (specified by pid) using the jcmd tool and its ability to read
+ * Diagnostic Commands from a file.
+ */
+public class FileJcmdExecutor extends PidJcmdExecutor {
+
+ /**
+ * Instantiates a new FileJcmdExecutor targeting the current VM
+ */
+ public FileJcmdExecutor() {
+ super();
+ }
+
+ /**
+ * Instantiates a new FileJcmdExecutor targeting the VM indicated by the given pid
+ *
+ * @param target Pid of the target VM
+ */
+ public FileJcmdExecutor(String target) {
+ super(target);
+ }
+
+ protected List<String> createCommandLine(String cmd) throws CommandExecutorException {
+ File cmdFile = createTempFile();
+ writeCommandToTemporaryFile(cmd, cmdFile);
+
+ return Arrays.asList(jcmdBinary, Long.toString(pid),
+ "-f", cmdFile.getAbsolutePath());
+ }
+
+ private void writeCommandToTemporaryFile(String cmd, File cmdFile) {
+ try (PrintWriter pw = new PrintWriter(cmdFile)) {
+ pw.println(cmd);
+ } catch (IOException e) {
+ String message = "Could not write to file: " + cmdFile.getAbsolutePath();
+ throw new CommandExecutorException(message, e);
+ }
+ }
+
+ private File createTempFile() {
+ try {
+ File cmdFile = File.createTempFile("input", "jcmd");
+ cmdFile.deleteOnExit();
+ return cmdFile;
+ } catch (IOException e) {
+ throw new CommandExecutorException("Could not create temporary file", e);
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/dcmd/JMXExecutor.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.dcmd;
+
+import jdk.test.lib.process.OutputAnalyzer;
+
+import javax.management.*;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import java.lang.management.ManagementFactory;
+
+import java.util.HashMap;
+
+/**
+ * Executes Diagnostic Commands on the target VM (specified by a host/port combination or a full JMX Service URL) using
+ * the JMX interface. If the target is not the current VM, the JMX Remote interface must be enabled beforehand.
+ */
+public class JMXExecutor extends CommandExecutor {
+
+ private final MBeanServerConnection mbs;
+
+ /**
+ * Instantiates a new JMXExecutor targeting the current VM
+ */
+ public JMXExecutor() {
+ super();
+ mbs = ManagementFactory.getPlatformMBeanServer();
+ }
+
+ /**
+ * Instantiates a new JMXExecutor targeting the VM indicated by the given host/port combination or a full JMX
+ * Service URL
+ *
+ * @param target a host/port combination on the format "host:port" or a full JMX Service URL of the target VM
+ */
+ public JMXExecutor(String target) {
+ String urlStr;
+
+ if (target.matches("^\\w[\\w\\-]*(\\.[\\w\\-]+)*:\\d+$")) {
+ /* Matches "hostname:port" */
+ urlStr = String.format("service:jmx:rmi:///jndi/rmi://%s/jmxrmi", target);
+ } else if (target.startsWith("service:")) {
+ urlStr = target;
+ } else {
+ throw new IllegalArgumentException("Could not recognize target string: " + target);
+ }
+
+ try {
+ JMXServiceURL url = new JMXServiceURL(urlStr);
+ JMXConnector c = JMXConnectorFactory.connect(url, new HashMap<>());
+ mbs = c.getMBeanServerConnection();
+ } catch (IOException e) {
+ throw new CommandExecutorException("Could not initiate connection to target: " + target, e);
+ }
+ }
+
+ protected OutputAnalyzer executeImpl(String cmd) throws CommandExecutorException {
+ String stdout = "";
+ String stderr = "";
+
+ String[] cmdParts = cmd.split(" ", 2);
+ String operation = commandToMethodName(cmdParts[0]);
+ Object[] dcmdArgs = produceArguments(cmdParts);
+ String[] signature = {String[].class.getName()};
+
+ ObjectName beanName = getMBeanName();
+
+ try {
+ stdout = (String) mbs.invoke(beanName, operation, dcmdArgs, signature);
+ }
+
+ /* Failures on the "local" side, the one invoking the command. */
+ catch (ReflectionException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof NoSuchMethodException) {
+ /* We want JMXExecutor to match the behavior of the other CommandExecutors */
+ String message = "Unknown diagnostic command: " + operation;
+ stderr = exceptionTraceAsString(new IllegalArgumentException(message, e));
+ } else {
+ rethrowExecutorException(operation, dcmdArgs, e);
+ }
+ }
+
+ /* Failures on the "local" side, the one invoking the command. */
+ catch (InstanceNotFoundException | IOException e) {
+ rethrowExecutorException(operation, dcmdArgs, e);
+ }
+
+ /* Failures on the remote side, the one executing the invoked command. */
+ catch (MBeanException e) {
+ stdout = exceptionTraceAsString(e);
+ }
+
+ return new OutputAnalyzer(stdout, stderr);
+ }
+
+ private void rethrowExecutorException(String operation, Object[] dcmdArgs,
+ Exception e) throws CommandExecutorException {
+ String message = String.format("Could not invoke: %s %s", operation,
+ String.join(" ", (String[]) dcmdArgs[0]));
+ throw new CommandExecutorException(message, e);
+ }
+
+ private ObjectName getMBeanName() throws CommandExecutorException {
+ String MBeanName = "com.sun.management:type=DiagnosticCommand";
+
+ try {
+ return new ObjectName(MBeanName);
+ } catch (MalformedObjectNameException e) {
+ String message = "MBean not found: " + MBeanName;
+ throw new CommandExecutorException(message, e);
+ }
+ }
+
+ private Object[] produceArguments(String[] cmdParts) {
+ Object[] dcmdArgs = {new String[0]}; /* Default: No arguments */
+
+ if (cmdParts.length == 2) {
+ dcmdArgs[0] = cmdParts[1].split(" ");
+ }
+ return dcmdArgs;
+ }
+
+ /**
+ * Convert from diagnostic command to MBean method name
+ *
+ * Examples:
+ * help --> help
+ * VM.version --> vmVersion
+ * VM.command_line --> vmCommandLine
+ */
+ private static String commandToMethodName(String cmd) {
+ String operation = "";
+ boolean up = false; /* First letter is to be lower case */
+
+ /*
+ * If a '.' or '_' is encountered it is not copied,
+ * instead the next character will be converted to upper case
+ */
+ for (char c : cmd.toCharArray()) {
+ if (('.' == c) || ('_' == c)) {
+ up = true;
+ } else if (up) {
+ operation = operation.concat(Character.toString(c).toUpperCase());
+ up = false;
+ } else {
+ operation = operation.concat(Character.toString(c).toLowerCase());
+ }
+ }
+
+ return operation;
+ }
+
+ private static String exceptionTraceAsString(Throwable cause) {
+ StringWriter sw = new StringWriter();
+ cause.printStackTrace(new PrintWriter(sw));
+ return sw.toString();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/dcmd/JcmdExecutor.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.dcmd;
+
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+import java.util.List;
+
+/**
+ * Base class for Diagnostic Command Executors using the jcmd tool
+ */
+public abstract class JcmdExecutor extends CommandExecutor {
+ protected String jcmdBinary;
+
+ protected abstract List<String> createCommandLine(String cmd) throws CommandExecutorException;
+
+ protected JcmdExecutor() {
+ jcmdBinary = JDKToolFinder.getJDKTool("jcmd");
+ }
+
+ protected OutputAnalyzer executeImpl(String cmd) throws CommandExecutorException {
+ List<String> commandLine = createCommandLine(cmd);
+
+ try {
+ System.out.printf("Executing command '%s'%n", commandLine);
+ OutputAnalyzer output = ProcessTools.executeProcess(new ProcessBuilder(commandLine));
+ System.out.printf("Command returned with exit code %d%n", output.getExitValue());
+
+ return output;
+ } catch (Exception e) {
+ String message = String.format("Caught exception while executing '%s'", commandLine);
+ throw new CommandExecutorException(message, e);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/dcmd/MainClassJcmdExecutor.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.dcmd;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Executes Diagnostic Commands on the target VM (specified by main class) using the jcmd tool
+ */
+public class MainClassJcmdExecutor extends JcmdExecutor {
+ private final String mainClass;
+
+ /**
+ * Instantiates a new MainClassJcmdExecutor targeting the current VM
+ */
+ public MainClassJcmdExecutor() {
+ super();
+ mainClass = System.getProperty("sun.java.command").split(" ")[0];
+ }
+
+ /**
+ * Instantiates a new MainClassJcmdExecutor targeting the VM indicated by the given main class
+ *
+ * @param target Main class of the target VM
+ */
+ public MainClassJcmdExecutor(String target) {
+ super();
+ mainClass = target;
+ }
+
+ protected List<String> createCommandLine(String cmd) throws CommandExecutorException {
+ return Arrays.asList(jcmdBinary, mainClass, cmd);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/dcmd/PidJcmdExecutor.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.dcmd;
+
+import jdk.test.lib.process.ProcessTools;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Executes Diagnostic Commands on the target VM (specified by pid) using the jcmd tool
+ */
+public class PidJcmdExecutor extends JcmdExecutor {
+ protected final long pid;
+
+ /**
+ * Instantiates a new PidJcmdExecutor targeting the current VM
+ */
+ public PidJcmdExecutor() {
+ super();
+ try {
+ pid = ProcessTools.getProcessId();
+ } catch (Exception e) {
+ throw new CommandExecutorException("Could not determine own pid", e);
+ }
+ }
+
+ /**
+ * Instantiates a new PidJcmdExecutor targeting the VM indicated by the given pid
+ *
+ * @param target Pid of the target VM
+ */
+ public PidJcmdExecutor(String target) {
+ super();
+ pid = Long.valueOf(target);
+ }
+
+ protected List<String> createCommandLine(String cmd) throws CommandExecutorException {
+ return Arrays.asList(jcmdBinary, Long.toString(pid), cmd);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/HprofParser.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.hprof;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+
+import jdk.test.lib.hprof.model.Snapshot;
+import jdk.test.lib.hprof.parser.Reader;
+
+/**
+ * Helper class to parse a java heap dump file.
+ */
+public class HprofParser {
+
+ public static void main(String[] args) throws Exception {
+ if (args.length < 1) {
+ System.out.println("No arguments supplied");
+ }
+ File dump = new File(args[0]);
+ if (!dump.exists() || !dump.isFile()) {
+ throw new RuntimeException("The dump file does not exist or not a file");
+ }
+ parse(dump);
+ }
+
+ /**
+ * @see #parse(File, boolean, boolean, boolean)
+ */
+ public static File parse(File dump) throws Exception {
+ return parse(dump, false, true, true);
+ }
+
+ /**
+ * @see #parse(File, boolean, boolean, boolean)
+ */
+ public static File parseWithDebugInfo(File dump) throws Exception {
+ return parse(dump, true, true, true);
+ }
+
+ /**
+ * Parse a java heap dump file
+ *
+ * @param dump Heap dump file to parse
+ * @param debug Turn on/off debug file parsing
+ * @param callStack Turn on/off tracking of object allocation call stack
+ * @param calculateRefs Turn on/off tracking object allocation call stack
+ * @throws Exception
+ * @return File containing output from the parser
+ */
+ public static File parse(File dump, boolean debug, boolean callStack, boolean calculateRefs) throws Exception {
+ File out = new File("hprof." + System.currentTimeMillis() + ".out");
+ if (out.exists()) {
+ out.delete();
+ }
+
+ PrintStream psSystemOut = System.out;
+ try (PrintStream psHprof = new PrintStream(new BufferedOutputStream(new FileOutputStream(out.getAbsolutePath())))) {
+ System.setOut(psHprof);
+
+ int debugLevel = debug ? 2 : 0;
+ try (Snapshot snapshot = Reader.readFile(dump.getAbsolutePath(), callStack, debugLevel)) {
+ System.out.println("Snapshot read, resolving...");
+ snapshot.resolve(calculateRefs);
+ System.out.println("Snapshot resolved.");
+ }
+ } finally {
+ System.setOut(psSystemOut);
+ }
+
+ return out;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/README Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,13 @@
+The jhat tool has been removed. jhat hprof file parser/validator
+are needed for tests. The old packages for jhat were moved here:
+com.sun.tools.hat.internal.model -> jdk.test.lib.hprof.model
+com.sun.tools.hat.internal.parser -> jdk.test.lib.hprof.parser
+com.sun.tools.hat.internal.util -> jdk.test.lib.hprof.util
+
+jhat was added in JDK 6 and its original implementation was from
+java.net HAT project [1]. jhat is an experimental, unsupported tool.
+There hasn't been much update to jhat tool in the JDK. In addition,
+there are several better heap dump visualizer/analyzer emerged since
+JDK 5/6 serviceability support.
+
+[1] https://java.net/projects/hat
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/AbstractJavaHeapObjectVisitor.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+/**
+ * A visitor for a JavaThing. @see JavaObject#visitReferencedObjects()
+ *
+ */
+
+
+abstract public class AbstractJavaHeapObjectVisitor
+ implements JavaHeapObjectVisitor {
+ abstract public void visit(JavaHeapObject other);
+
+ /**
+ * Should the given field be excluded from the set of things visited?
+ * @return true if it should.
+ */
+ public boolean exclude(JavaClass clazz, JavaField f) {
+ return false;
+ }
+
+ /**
+ * @return true iff exclude might ever return true
+ */
+ public boolean mightExclude() {
+ return false;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/ArrayTypeCodes.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+/**
+ * Primitive array type codes as defined by VM specification.
+ *
+ */
+public interface ArrayTypeCodes {
+ // Typecodes for array elements.
+ // Refer to newarray instruction in VM Spec.
+ public static final int T_BOOLEAN = 4;
+ public static final int T_CHAR = 5;
+ public static final int T_FLOAT = 6;
+ public static final int T_DOUBLE = 7;
+ public static final int T_BYTE = 8;
+ public static final int T_SHORT = 9;
+ public static final int T_INT = 10;
+ public static final int T_LONG = 11;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/HackJavaValue.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+/**
+ * This is used to represent values that the program doesn't really understand.
+ * This includes the null vlaue, and unresolved references (which shouldn't
+ * happen in well-formed hprof files).
+ *
+ *
+ * @author Bill Foote
+ */
+
+
+
+
+public class HackJavaValue extends JavaValue {
+
+ private String value;
+ private int size;
+
+ public HackJavaValue(String value, int size) {
+ this.value = value;
+ this.size = size;
+ }
+
+ public String toString() {
+ return value;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaBoolean.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+/**
+ * Represents a boolean (i.e. a boolean field in an instance).
+ *
+ * @author Bill Foote
+ */
+
+
+public class JavaBoolean extends JavaValue {
+
+ boolean value;
+
+ public JavaBoolean(boolean value) {
+ this.value = value;
+ }
+
+ public String toString() {
+ return "" + value;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaByte.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+/**
+ * Represents an byte (i.e. a byte field in an instance).
+ *
+ * @author Bill Foote
+ */
+
+
+public class JavaByte extends JavaValue {
+
+ byte value;
+
+ public JavaByte(byte value) {
+ this.value = value;
+ }
+
+ public String toString() {
+ return "0x" + Integer.toString(((int) value) & 0xff, 16);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaChar.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+/**
+ * Represents a char (i.e. a char field in an instance).
+ *
+ * @author Bill Foote
+ */
+
+
+public class JavaChar extends JavaValue {
+
+ char value;
+
+ public JavaChar(char value) {
+ this.value = value;
+ }
+
+ public String toString() {
+ return "" + value;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaClass.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,503 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+import java.util.Vector;
+import java.util.Enumeration;
+import jdk.test.lib.hprof.util.CompositeEnumeration;
+import jdk.test.lib.hprof.parser.ReadBuffer;
+
+/**
+ *
+ * @author Bill Foote
+ */
+
+
+public class JavaClass extends JavaHeapObject {
+ // my id
+ private long id;
+ // my name
+ private String name;
+
+ // These are JavaObjectRef before resolve
+ private JavaThing superclass;
+ private JavaThing loader;
+ private JavaThing signers;
+ private JavaThing protectionDomain;
+
+ // non-static fields
+ private JavaField[] fields;
+ // static fields
+ private JavaStatic[] statics;
+
+ private static final JavaClass[] EMPTY_CLASS_ARRAY = new JavaClass[0];
+ // my subclasses
+ private JavaClass[] subclasses = EMPTY_CLASS_ARRAY;
+
+ // my instances
+ private Vector<JavaHeapObject> instances = new Vector<JavaHeapObject>();
+
+ // Who I belong to. Set on resolve.
+ private Snapshot mySnapshot;
+
+ // Size of an instance, including VM overhead
+ private int instanceSize;
+ // Total number of fields including inherited ones
+ private int totalNumFields;
+
+
+ public JavaClass(long id, String name, long superclassId, long loaderId,
+ long signersId, long protDomainId,
+ JavaField[] fields, JavaStatic[] statics,
+ int instanceSize) {
+ this.id = id;
+ this.name = name;
+ this.superclass = new JavaObjectRef(superclassId);
+ this.loader = new JavaObjectRef(loaderId);
+ this.signers = new JavaObjectRef(signersId);
+ this.protectionDomain = new JavaObjectRef(protDomainId);
+ this.fields = fields;
+ this.statics = statics;
+ this.instanceSize = instanceSize;
+ }
+
+ public JavaClass(String name, long superclassId, long loaderId,
+ long signersId, long protDomainId,
+ JavaField[] fields, JavaStatic[] statics,
+ int instanceSize) {
+ this(-1L, name, superclassId, loaderId, signersId,
+ protDomainId, fields, statics, instanceSize);
+ }
+
+ public final JavaClass getClazz() {
+ return mySnapshot.getJavaLangClass();
+ }
+
+ public final int getIdentifierSize() {
+ return mySnapshot.getIdentifierSize();
+ }
+
+ public final int getMinimumObjectSize() {
+ return mySnapshot.getMinimumObjectSize();
+ }
+
+ public void resolve(Snapshot snapshot) {
+ if (mySnapshot != null) {
+ return;
+ }
+ mySnapshot = snapshot;
+ resolveSuperclass(snapshot);
+ if (superclass != null) {
+ ((JavaClass) superclass).addSubclass(this);
+ }
+
+ loader = loader.dereference(snapshot, null);
+ signers = signers.dereference(snapshot, null);
+ protectionDomain = protectionDomain.dereference(snapshot, null);
+
+ for (int i = 0; i < statics.length; i++) {
+ statics[i].resolve(this, snapshot);
+ }
+ snapshot.getJavaLangClass().addInstance(this);
+ super.resolve(snapshot);
+ return;
+ }
+
+ /**
+ * Resolve our superclass. This might be called well before
+ * all instances are available (like when reading deferred
+ * instances in a 1.2 dump file :-) Calling this is sufficient
+ * to be able to explore this class' fields.
+ */
+ public void resolveSuperclass(Snapshot snapshot) {
+ if (superclass == null) {
+ // We must be java.lang.Object, so we have no superclass.
+ } else {
+ totalNumFields = fields.length;
+ superclass = superclass.dereference(snapshot, null);
+ if (superclass == snapshot.getNullThing()) {
+ superclass = null;
+ } else {
+ try {
+ JavaClass sc = (JavaClass) superclass;
+ sc.resolveSuperclass(snapshot);
+ totalNumFields += sc.totalNumFields;
+ } catch (ClassCastException ex) {
+ System.out.println("Warning! Superclass of " + name + " is " + superclass);
+ superclass = null;
+ }
+ }
+ }
+ }
+
+ public boolean isString() {
+ return mySnapshot.getJavaLangString() == this;
+ }
+
+ public boolean isClassLoader() {
+ return mySnapshot.getJavaLangClassLoader().isAssignableFrom(this);
+ }
+
+ /**
+ * Get a numbered field from this class
+ */
+ public JavaField getField(int i) {
+ if (i < 0 || i >= fields.length) {
+ throw new Error("No field " + i + " for " + name);
+ }
+ return fields[i];
+ }
+
+ /**
+ * Get the total number of fields that are part of an instance of
+ * this class. That is, include superclasses.
+ */
+ public int getNumFieldsForInstance() {
+ return totalNumFields;
+ }
+
+ /**
+ * Get a numbered field from all the fields that are part of instance
+ * of this class. That is, include superclasses.
+ */
+ public JavaField getFieldForInstance(int i) {
+ if (superclass != null) {
+ JavaClass sc = (JavaClass) superclass;
+ if (i < sc.totalNumFields) {
+ return sc.getFieldForInstance(i);
+ }
+ i -= sc.totalNumFields;
+ }
+ return getField(i);
+ }
+
+ /**
+ * Get the class responsible for field i, where i is a field number that
+ * could be passed into getFieldForInstance.
+ *
+ * @see JavaClass.getFieldForInstance()
+ */
+ public JavaClass getClassForField(int i) {
+ if (superclass != null) {
+ JavaClass sc = (JavaClass) superclass;
+ if (i < sc.totalNumFields) {
+ return sc.getClassForField(i);
+ }
+ }
+ return this;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public boolean isArray() {
+ return name.indexOf('[') != -1;
+ }
+
+ public Enumeration<JavaHeapObject> getInstances(boolean includeSubclasses) {
+ if (includeSubclasses) {
+ Enumeration<JavaHeapObject> res = instances.elements();
+ for (int i = 0; i < subclasses.length; i++) {
+ res = new CompositeEnumeration(res,
+ subclasses[i].getInstances(true));
+ }
+ return res;
+ } else {
+ return instances.elements();
+ }
+ }
+
+ /**
+ * @return a count of the instances of this class
+ */
+ public int getInstancesCount(boolean includeSubclasses) {
+ int result = instances.size();
+ if (includeSubclasses) {
+ for (int i = 0; i < subclasses.length; i++) {
+ result += subclasses[i].getInstancesCount(includeSubclasses);
+ }
+ }
+ return result;
+ }
+
+ public JavaClass[] getSubclasses() {
+ return subclasses;
+ }
+
+ /**
+ * This can only safely be called after resolve()
+ */
+ public JavaClass getSuperclass() {
+ return (JavaClass) superclass;
+ }
+
+ /**
+ * This can only safely be called after resolve()
+ */
+ public JavaThing getLoader() {
+ return loader;
+ }
+
+ /**
+ * This can only safely be called after resolve()
+ */
+ public boolean isBootstrap() {
+ return loader == mySnapshot.getNullThing();
+ }
+
+ /**
+ * This can only safely be called after resolve()
+ */
+ public JavaThing getSigners() {
+ return signers;
+ }
+
+ /**
+ * This can only safely be called after resolve()
+ */
+ public JavaThing getProtectionDomain() {
+ return protectionDomain;
+ }
+
+ public JavaField[] getFields() {
+ return fields;
+ }
+
+ /**
+ * Includes superclass fields
+ */
+ public JavaField[] getFieldsForInstance() {
+ Vector<JavaField> v = new Vector<JavaField>();
+ addFields(v);
+ JavaField[] result = new JavaField[v.size()];
+ for (int i = 0; i < v.size(); i++) {
+ result[i] = v.elementAt(i);
+ }
+ return result;
+ }
+
+
+ public JavaStatic[] getStatics() {
+ return statics;
+ }
+
+ // returns value of static field of given name
+ public JavaThing getStaticField(String name) {
+ for (int i = 0; i < statics.length; i++) {
+ JavaStatic s = statics[i];
+ if (s.getField().getName().equals(name)) {
+ return s.getValue();
+ }
+ }
+ return null;
+ }
+
+ public String toString() {
+ return "class " + name;
+ }
+
+ public int compareTo(JavaThing other) {
+ if (other instanceof JavaClass) {
+ return name.compareTo(((JavaClass) other).name);
+ }
+ return super.compareTo(other);
+ }
+
+
+ /**
+ * @return true iff a variable of type this is assignable from an instance
+ * of other
+ */
+ public boolean isAssignableFrom(JavaClass other) {
+ if (this == other) {
+ return true;
+ } else if (other == null) {
+ return false;
+ } else {
+ return isAssignableFrom((JavaClass) other.superclass);
+ // Trivial tail recursion: I have faith in javac.
+ }
+ }
+
+ /**
+ * Describe the reference that this thing has to target. This will only
+ * be called if target is in the array returned by getChildrenForRootset.
+ */
+ public String describeReferenceTo(JavaThing target, Snapshot ss) {
+ for (int i = 0; i < statics.length; i++) {
+ JavaField f = statics[i].getField();
+ if (f.hasId()) {
+ JavaThing other = statics[i].getValue();
+ if (other == target) {
+ return "static field " + f.getName();
+ }
+ }
+ }
+ return super.describeReferenceTo(target, ss);
+ }
+
+ /**
+ * @return the size of an instance of this class. Gives 0 for an array
+ * type.
+ */
+ public int getInstanceSize() {
+ return instanceSize + mySnapshot.getMinimumObjectSize();
+ }
+
+
+ /**
+ * @return The size of all instances of this class. Correctly handles
+ * arrays.
+ */
+ public long getTotalInstanceSize() {
+ int count = instances.size();
+ if (count == 0 || !isArray()) {
+ return count * instanceSize;
+ }
+
+ // array class and non-zero count, we have to
+ // get the size of each instance and sum it
+ long result = 0;
+ for (int i = 0; i < count; i++) {
+ JavaThing t = (JavaThing) instances.elementAt(i);
+ result += t.getSize();
+ }
+ return result;
+ }
+
+ /**
+ * @return the size of this object
+ */
+ public int getSize() {
+ JavaClass cl = mySnapshot.getJavaLangClass();
+ if (cl == null) {
+ return 0;
+ } else {
+ return cl.getInstanceSize();
+ }
+ }
+
+ public void visitReferencedObjects(JavaHeapObjectVisitor v) {
+ super.visitReferencedObjects(v);
+ JavaHeapObject sc = getSuperclass();
+ if (sc != null) v.visit(getSuperclass());
+
+ JavaThing other;
+ other = getLoader();
+ if (other instanceof JavaHeapObject) {
+ v.visit((JavaHeapObject)other);
+ }
+ other = getSigners();
+ if (other instanceof JavaHeapObject) {
+ v.visit((JavaHeapObject)other);
+ }
+ other = getProtectionDomain();
+ if (other instanceof JavaHeapObject) {
+ v.visit((JavaHeapObject)other);
+ }
+
+ for (int i = 0; i < statics.length; i++) {
+ JavaField f = statics[i].getField();
+ if (!v.exclude(this, f) && f.hasId()) {
+ other = statics[i].getValue();
+ if (other instanceof JavaHeapObject) {
+ v.visit((JavaHeapObject) other);
+ }
+ }
+ }
+ }
+
+ // package-privates below this point
+ final ReadBuffer getReadBuffer() {
+ return mySnapshot.getReadBuffer();
+ }
+
+ final void setNew(JavaHeapObject obj, boolean flag) {
+ mySnapshot.setNew(obj, flag);
+ }
+
+ final boolean isNew(JavaHeapObject obj) {
+ return mySnapshot.isNew(obj);
+ }
+
+ final StackTrace getSiteTrace(JavaHeapObject obj) {
+ return mySnapshot.getSiteTrace(obj);
+ }
+
+ final void addReferenceFromRoot(Root root, JavaHeapObject obj) {
+ mySnapshot.addReferenceFromRoot(root, obj);
+ }
+
+ final Root getRoot(JavaHeapObject obj) {
+ return mySnapshot.getRoot(obj);
+ }
+
+ final Snapshot getSnapshot() {
+ return mySnapshot;
+ }
+
+ void addInstance(JavaHeapObject inst) {
+ instances.addElement(inst);
+ }
+
+ // Internals only below this point
+ private void addFields(Vector<JavaField> v) {
+ if (superclass != null) {
+ ((JavaClass) superclass).addFields(v);
+ }
+ for (int i = 0; i < fields.length; i++) {
+ v.addElement(fields[i]);
+ }
+ }
+
+ private void addSubclassInstances(Vector<JavaHeapObject> v) {
+ for (int i = 0; i < subclasses.length; i++) {
+ subclasses[i].addSubclassInstances(v);
+ }
+ for (int i = 0; i < instances.size(); i++) {
+ v.addElement(instances.elementAt(i));
+ }
+ }
+
+ private void addSubclass(JavaClass sub) {
+ JavaClass newValue[] = new JavaClass[subclasses.length + 1];
+ System.arraycopy(subclasses, 0, newValue, 0, subclasses.length);
+ newValue[subclasses.length] = sub;
+ subclasses = newValue;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaDouble.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+/**
+ * Represents a double (i.e. a double field in an instance).
+ *
+ * @author Bill Foote
+ */
+
+
+public class JavaDouble extends JavaValue {
+
+ double value;
+
+ public JavaDouble(double value) {
+ this.value = value;
+ }
+
+ public String toString() {
+ return Double.toString(value);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaField.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+
+/**
+ *
+ * @author Bill Foote
+ */
+
+public class JavaField {
+
+ private String name;
+ private String signature;
+
+ public JavaField(String name, String signature) {
+ this.name = name;
+ this.signature = signature;
+ }
+
+
+ /**
+ * @return true if the type of this field is something that has an ID.
+ * int fields, for exampe, don't.
+ */
+ public boolean hasId() {
+ char ch = signature.charAt(0);
+ return (ch == '[' || ch == 'L');
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getSignature() {
+ return signature;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaFloat.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+/**
+ * Represents a float (i.e. a float field in an instance).
+ *
+ * @author Bill Foote
+ */
+
+
+public class JavaFloat extends JavaValue {
+
+ float value;
+
+ public JavaFloat(float value) {
+ this.value = value;
+ }
+
+ public String toString() {
+ return Float.toString(value);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaHeapObject.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.test.lib.hprof.util.Misc;
+
+
+/**
+ *
+ * @author Bill Foote
+ */
+
+/**
+ * Represents an object that's allocated out of the Java heap. It occupies
+ * memory in the VM, and is the sort of thing that in a JDK 1.1 VM had
+ * a handle. It can be a
+ * JavaClass, a JavaObjectArray, a JavaValueArray or a JavaObject.
+ */
+
+public abstract class JavaHeapObject extends JavaThing {
+
+ //
+ // Who we refer to. This is heavily optimized for space, because it's
+ // well worth trading a bit of speed for less swapping.
+ // referers and referersLen go through two phases: Building and
+ // resolved. When building, referers might have duplicates, but can
+ // be appended to. When resolved, referers has no duplicates or
+ // empty slots.
+ //
+ private JavaThing[] referers = null;
+ private int referersLen = 0; // -1 when resolved
+
+ public abstract JavaClass getClazz();
+ public abstract int getSize();
+ public abstract long getId();
+
+ /**
+ * Do any initialization this thing needs after its data is read in.
+ * Subclasses that override this should call super.resolve().
+ */
+ public void resolve(Snapshot snapshot) {
+ StackTrace trace = snapshot.getSiteTrace(this);
+ if (trace != null) {
+ trace.resolve(snapshot);
+ }
+ }
+
+ //
+ // Eliminate duplicates from referers, and size the array exactly.
+ // This sets us up to answer queries. See the comments around the
+ // referers data member for details.
+ //
+ void setupReferers() {
+ if (referersLen > 1) {
+ // Copy referers to map, screening out duplicates
+ Map<JavaThing, JavaThing> map = new HashMap<JavaThing, JavaThing>();
+ for (int i = 0; i < referersLen; i++) {
+ if (map.get(referers[i]) == null) {
+ map.put(referers[i], referers[i]);
+ }
+ }
+
+ // Now copy into the array
+ referers = new JavaThing[map.size()];
+ map.keySet().toArray(referers);
+ }
+ referersLen = -1;
+ }
+
+
+ /**
+ * @return the id of this thing as hex string
+ */
+ public String getIdString() {
+ return Misc.toHex(getId());
+ }
+
+ public String toString() {
+ return getClazz().getName() + "@" + getIdString();
+ }
+
+ /**
+ * @return the StackTrace of the point of allocation of this object,
+ * or null if unknown
+ */
+ public StackTrace getAllocatedFrom() {
+ return getClazz().getSiteTrace(this);
+ }
+
+ public boolean isNew() {
+ return getClazz().isNew(this);
+ }
+
+ void setNew(boolean flag) {
+ getClazz().setNew(this, flag);
+ }
+
+ /**
+ * Tell the visitor about all of the objects we refer to
+ */
+ public void visitReferencedObjects(JavaHeapObjectVisitor v) {
+ v.visit(getClazz());
+ }
+
+ void addReferenceFrom(JavaHeapObject other) {
+ if (referersLen == 0) {
+ referers = new JavaThing[1]; // It was null
+ } else if (referersLen == referers.length) {
+ JavaThing[] copy = new JavaThing[(3 * (referersLen + 1)) / 2];
+ System.arraycopy(referers, 0, copy, 0, referersLen);
+ referers = copy;
+ }
+ referers[referersLen++] = other;
+ // We just append to referers here. Measurements have shown that
+ // around 10% to 30% are duplicates, so it's better to just append
+ // blindly and screen out all the duplicates at once.
+ }
+
+ void addReferenceFromRoot(Root r) {
+ getClazz().addReferenceFromRoot(r, this);
+ }
+
+ /**
+ * If the rootset includes this object, return a Root describing one
+ * of the reasons why.
+ */
+ public Root getRoot() {
+ return getClazz().getRoot(this);
+ }
+
+ /**
+ * Tell who refers to us.
+ *
+ * @return an Enumeration of JavaHeapObject instances
+ */
+ public Enumeration<JavaThing> getReferers() {
+ if (referersLen != -1) {
+ throw new RuntimeException("not resolved: " + getIdString());
+ }
+ return new Enumeration<JavaThing>() {
+
+ private int num = 0;
+
+ public boolean hasMoreElements() {
+ return referers != null && num < referers.length;
+ }
+
+ public JavaThing nextElement() {
+ return referers[num++];
+ }
+ };
+ }
+
+ /**
+ * Given other, which the caller promises is in referers, determines if
+ * the reference is only a weak reference.
+ */
+ public boolean refersOnlyWeaklyTo(Snapshot ss, JavaThing other) {
+ return false;
+ }
+
+ /**
+ * Describe the reference that this thing has to target. This will only
+ * be called if target is in the array returned by getChildrenForRootset.
+ */
+ public String describeReferenceTo(JavaThing target, Snapshot ss) {
+ return "??";
+ }
+
+ public boolean isHeapAllocated() {
+ return true;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaHeapObjectVisitor.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+/**
+ * A visitor for a JavaThing. @see JavaObject#visitReferencedObjects()
+ *
+ * @author Bill Foote
+ */
+
+
+public interface JavaHeapObjectVisitor {
+ public void visit(JavaHeapObject other);
+
+ /**
+ * Should the given field be excluded from the set of things visited?
+ * @return true if it should.
+ */
+ public boolean exclude(JavaClass clazz, JavaField f);
+
+ /**
+ * @return true iff exclude might ever return true
+ */
+ public boolean mightExclude();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaInt.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+/**
+ * Represents an integer (i.e. an int field in an instance).
+ *
+ * @author Bill Foote
+ */
+
+
+public class JavaInt extends JavaValue {
+
+ int value;
+
+ public JavaInt(int value) {
+ this.value = value;
+ }
+
+ public String toString() {
+ return "" + value;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaLazyReadObject.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+import java.io.IOException;
+import jdk.test.lib.hprof.parser.ReadBuffer;
+
+/*
+ * Base class for lazily read Java heap objects.
+ */
+public abstract class JavaLazyReadObject extends JavaHeapObject {
+
+ // file offset from which this object data starts
+ private final long offset;
+
+ protected JavaLazyReadObject(long offset) {
+ this.offset = offset;
+ }
+
+ public final int getSize() {
+ return getValueLength() + getClazz().getMinimumObjectSize();
+ }
+
+ protected final long getOffset() {
+ return offset;
+ }
+
+ // return the length of the data for this object
+ protected final int getValueLength() {
+ try {
+ return readValueLength();
+ } catch (IOException exp) {
+ System.err.println("lazy read failed at offset " + offset);
+ exp.printStackTrace();
+ return 0;
+ }
+ }
+
+ // get this object's content as byte array
+ protected final byte[] getValue() {
+ try {
+ return readValue();
+ } catch (IOException exp) {
+ System.err.println("lazy read failed at offset " + offset);
+ exp.printStackTrace();
+ return Snapshot.EMPTY_BYTE_ARRAY;
+ }
+ }
+
+ // get ID of this object
+ public final long getId() {
+ try {
+ ReadBuffer buf = getClazz().getReadBuffer();
+ int idSize = getClazz().getIdentifierSize();
+ if (idSize == 4) {
+ return ((long)buf.getInt(offset)) & Snapshot.SMALL_ID_MASK;
+ } else {
+ return buf.getLong(offset);
+ }
+ } catch (IOException exp) {
+ System.err.println("lazy read failed at offset " + offset);
+ exp.printStackTrace();
+ return -1;
+ }
+ }
+
+ protected abstract int readValueLength() throws IOException;
+ protected abstract byte[] readValue() throws IOException;
+
+ // make Integer or Long for given object ID
+ protected static Number makeId(long id) {
+ if ((id & ~Snapshot.SMALL_ID_MASK) == 0) {
+ return (int)id;
+ } else {
+ return id;
+ }
+ }
+
+ // get ID as long value from Number
+ protected static long getIdValue(Number num) {
+ long id = num.longValue();
+ if (num instanceof Integer) {
+ id &= Snapshot.SMALL_ID_MASK;
+ }
+ return id;
+ }
+
+ // read object ID from given index from given byte array
+ protected final long objectIdAt(int index, byte[] data) {
+ int idSize = getClazz().getIdentifierSize();
+ if (idSize == 4) {
+ return ((long)intAt(index, data)) & Snapshot.SMALL_ID_MASK;
+ } else {
+ return longAt(index, data);
+ }
+ }
+
+ // utility methods to read primitive types from byte array
+ protected static byte byteAt(int index, byte[] value) {
+ return value[index];
+ }
+
+ protected static boolean booleanAt(int index, byte[] value) {
+ return (value[index] & 0xff) == 0? false: true;
+ }
+
+ protected static char charAt(int index, byte[] value) {
+ int b1 = ((int) value[index++] & 0xff);
+ int b2 = ((int) value[index++] & 0xff);
+ return (char) ((b1 << 8) + b2);
+ }
+
+ protected static short shortAt(int index, byte[] value) {
+ int b1 = ((int) value[index++] & 0xff);
+ int b2 = ((int) value[index++] & 0xff);
+ return (short) ((b1 << 8) + b2);
+ }
+
+ protected static int intAt(int index, byte[] value) {
+ int b1 = ((int) value[index++] & 0xff);
+ int b2 = ((int) value[index++] & 0xff);
+ int b3 = ((int) value[index++] & 0xff);
+ int b4 = ((int) value[index++] & 0xff);
+ return ((b1 << 24) + (b2 << 16) + (b3 << 8) + b4);
+ }
+
+ protected static long longAt(int index, byte[] value) {
+ long val = 0;
+ for (int j = 0; j < 8; j++) {
+ val = val << 8;
+ int b = ((int)value[index++]) & 0xff;
+ val |= b;
+ }
+ return val;
+ }
+
+ protected static float floatAt(int index, byte[] value) {
+ int val = intAt(index, value);
+ return Float.intBitsToFloat(val);
+ }
+
+ protected static double doubleAt(int index, byte[] value) {
+ long val = longAt(index, value);
+ return Double.longBitsToDouble(val);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaLong.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+/**
+ * Represents a long (i.e. a long field in an instance).
+ *
+ * @author Bill Foote
+ */
+
+
+public class JavaLong extends JavaValue {
+
+ long value;
+
+ public JavaLong(long value) {
+ this.value = value;
+ }
+
+ public String toString() {
+ return Long.toString(value);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaObject.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+import java.io.IOException;
+import jdk.test.lib.hprof.parser.ReadBuffer;
+
+/**
+ * Represents Java instance
+ *
+ * @author Bill Foote
+ */
+public class JavaObject extends JavaLazyReadObject {
+
+ private Object clazz; // Number before resolve
+ // JavaClass after resolve
+ /**
+ * Construct a new JavaObject.
+ *
+ * @param classID id of the class object
+ * @param offset The offset of field data
+ */
+ public JavaObject(long classID, long offset) {
+ super(offset);
+ this.clazz = makeId(classID);
+ }
+
+ public void resolve(Snapshot snapshot) {
+ if (clazz instanceof JavaClass) {
+ return;
+ }
+ if (clazz instanceof Number) {
+ long classID = getIdValue((Number)clazz);
+ clazz = snapshot.findThing(classID);
+ if (! (clazz instanceof JavaClass)) {
+ warn("Class " + Long.toHexString(classID) + " not found, " +
+ "adding fake class!");
+ int length;
+ ReadBuffer buf = snapshot.getReadBuffer();
+ int idSize = snapshot.getIdentifierSize();
+ long lenOffset = getOffset() + 2*idSize + 4;
+ try {
+ length = buf.getInt(lenOffset);
+ } catch (IOException exp) {
+ throw new RuntimeException(exp);
+ }
+ clazz = snapshot.addFakeInstanceClass(classID, length);
+ }
+ } else {
+ throw new InternalError("should not reach here");
+ }
+
+ JavaClass cl = (JavaClass) clazz;
+ cl.resolve(snapshot);
+
+ // while resolving, parse fields in verbose mode.
+ // but, getFields calls parseFields in non-verbose mode
+ // to avoid printing warnings repeatedly.
+ parseFields(getValue(), true);
+
+ cl.addInstance(this);
+ super.resolve(snapshot);
+ }
+
+ /**
+ * Are we the same type as other? We are iff our clazz is the
+ * same type as other's.
+ */
+ public boolean isSameTypeAs(JavaThing other) {
+ if (!(other instanceof JavaObject)) {
+ return false;
+ }
+ JavaObject oo = (JavaObject) other;
+ return getClazz().equals(oo.getClazz());
+ }
+
+ /**
+ * Return our JavaClass object. This may only be called after resolve.
+ */
+ public JavaClass getClazz() {
+ return (JavaClass) clazz;
+ }
+
+ public JavaThing[] getFields() {
+ // pass false to verbose mode so that dereference
+ // warnings are not printed.
+ return parseFields(getValue(), false);
+ }
+
+ // returns the value of field of given name
+ public JavaThing getField(String name) {
+ JavaThing[] flds = getFields();
+ JavaField[] instFields = getClazz().getFieldsForInstance();
+ for (int i = 0; i < instFields.length; i++) {
+ if (instFields[i].getName().equals(name)) {
+ return flds[i];
+ }
+ }
+ return null;
+ }
+
+ public int compareTo(JavaThing other) {
+ if (other instanceof JavaObject) {
+ JavaObject oo = (JavaObject) other;
+ return getClazz().getName().compareTo(oo.getClazz().getName());
+ }
+ return super.compareTo(other);
+ }
+
+ public void visitReferencedObjects(JavaHeapObjectVisitor v) {
+ super.visitReferencedObjects(v);
+ JavaThing[] flds = getFields();
+ for (int i = 0; i < flds.length; i++) {
+ if (flds[i] != null) {
+ if (v.mightExclude()
+ && v.exclude(getClazz().getClassForField(i),
+ getClazz().getFieldForInstance(i)))
+ {
+ // skip it
+ } else if (flds[i] instanceof JavaHeapObject) {
+ v.visit((JavaHeapObject) flds[i]);
+ }
+ }
+ }
+ }
+
+ public boolean refersOnlyWeaklyTo(Snapshot ss, JavaThing other) {
+ if (ss.getWeakReferenceClass() != null) {
+ final int referentFieldIndex = ss.getReferentFieldIndex();
+ if (ss.getWeakReferenceClass().isAssignableFrom(getClazz())) {
+ //
+ // REMIND: This introduces a dependency on the JDK
+ // implementation that is undesirable.
+ JavaThing[] flds = getFields();
+ for (int i = 0; i < flds.length; i++) {
+ if (i != referentFieldIndex && flds[i] == other) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Describe the reference that this thing has to target. This will only
+ * be called if target is in the array returned by getChildrenForRootset.
+ */
+ public String describeReferenceTo(JavaThing target, Snapshot ss) {
+ JavaThing[] flds = getFields();
+ for (int i = 0; i < flds.length; i++) {
+ if (flds[i] == target) {
+ JavaField f = getClazz().getFieldForInstance(i);
+ return "field " + f.getName();
+ }
+ }
+ return super.describeReferenceTo(target, ss);
+ }
+
+ public String toString() {
+ if (getClazz().isString()) {
+ JavaThing value = getField("value");
+ if (value instanceof JavaValueArray) {
+ return ((JavaValueArray)value).valueString();
+ } else {
+ return "null";
+ }
+ } else {
+ return super.toString();
+ }
+ }
+
+ // Internals only below this point
+
+ /*
+ * Java instance record (HPROF_GC_INSTANCE_DUMP) looks as below:
+ *
+ * object ID
+ * stack trace serial number (int)
+ * class ID
+ * data length (int)
+ * byte[length]
+ */
+ protected final int readValueLength() throws IOException {
+ JavaClass cl = getClazz();
+ int idSize = cl.getIdentifierSize();
+ long lengthOffset = getOffset() + 2*idSize + 4;
+ return cl.getReadBuffer().getInt(lengthOffset);
+ }
+
+ protected final byte[] readValue() throws IOException {
+ JavaClass cl = getClazz();
+ int idSize = cl.getIdentifierSize();
+ ReadBuffer buf = cl.getReadBuffer();
+ long offset = getOffset() + 2*idSize + 4;
+ int length = buf.getInt(offset);
+ if (length == 0) {
+ return Snapshot.EMPTY_BYTE_ARRAY;
+ } else {
+ byte[] res = new byte[length];
+ buf.get(offset + 4, res);
+ return res;
+ }
+ }
+
+ private JavaThing[] parseFields(byte[] data, boolean verbose) {
+ JavaClass cl = getClazz();
+ int target = cl.getNumFieldsForInstance();
+ JavaField[] fields = cl.getFields();
+ JavaThing[] fieldValues = new JavaThing[target];
+ Snapshot snapshot = cl.getSnapshot();
+ int idSize = snapshot.getIdentifierSize();
+ int fieldNo = 0;
+ // In the dump file, the fields are stored in this order:
+ // fields of most derived class (immediate class) are stored
+ // first and then the super class and so on. In this object,
+ // fields are stored in the reverse ("natural") order. i.e.,
+ // fields of most super class are stored first.
+
+ // target variable is used to compensate for the fact that
+ // the dump file starts field values from the leaf working
+ // upwards in the inheritance hierarchy, whereas JavaObject
+ // starts with the top of the inheritance hierarchy and works down.
+ target -= fields.length;
+ JavaClass currClass = cl;
+ int index = 0;
+ for (int i = 0; i < fieldValues.length; i++, fieldNo++) {
+ while (fieldNo >= fields.length) {
+ currClass = currClass.getSuperclass();
+ fields = currClass.getFields();
+ fieldNo = 0;
+ target -= fields.length;
+ }
+ JavaField f = fields[fieldNo];
+ char sig = f.getSignature().charAt(0);
+ switch (sig) {
+ case 'L':
+ case '[': {
+ long id = objectIdAt(index, data);
+ index += idSize;
+ JavaObjectRef ref = new JavaObjectRef(id);
+ fieldValues[target+fieldNo] = ref.dereference(snapshot, f, verbose);
+ break;
+ }
+ case 'Z': {
+ byte value = byteAt(index, data);
+ index++;
+ fieldValues[target+fieldNo] = new JavaBoolean(value != 0);
+ break;
+ }
+ case 'B': {
+ byte value = byteAt(index, data);
+ index++;
+ fieldValues[target+fieldNo] = new JavaByte(value);
+ break;
+ }
+ case 'S': {
+ short value = shortAt(index, data);
+ index += 2;
+ fieldValues[target+fieldNo] = new JavaShort(value);
+ break;
+ }
+ case 'C': {
+ char value = charAt(index, data);
+ index += 2;
+ fieldValues[target+fieldNo] = new JavaChar(value);
+ break;
+ }
+ case 'I': {
+ int value = intAt(index, data);
+ index += 4;
+ fieldValues[target+fieldNo] = new JavaInt(value);
+ break;
+ }
+ case 'J': {
+ long value = longAt(index, data);
+ index += 8;
+ fieldValues[target+fieldNo] = new JavaLong(value);
+ break;
+ }
+ case 'F': {
+ float value = floatAt(index, data);
+ index += 4;
+ fieldValues[target+fieldNo] = new JavaFloat(value);
+ break;
+ }
+ case 'D': {
+ double value = doubleAt(index, data);
+ index += 8;
+ fieldValues[target+fieldNo] = new JavaDouble(value);
+ break;
+ }
+ default:
+ throw new RuntimeException("invalid signature: " + sig);
+ }
+ }
+ return fieldValues;
+ }
+
+ private void warn(String msg) {
+ System.out.println("WARNING: " + msg);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaObjectArray.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+import java.io.IOException;
+import jdk.test.lib.hprof.parser.ReadBuffer;
+
+/**
+ * @author Bill Foote
+ */
+public class JavaObjectArray extends JavaLazyReadObject {
+
+ private Object clazz; // Long before resolve, the class after resolve
+
+ public JavaObjectArray(long classID, long offset) {
+ super(offset);
+ this.clazz = makeId(classID);
+ }
+
+ public JavaClass getClazz() {
+ return (JavaClass) clazz;
+ }
+
+ public void resolve(Snapshot snapshot) {
+ if (clazz instanceof JavaClass) {
+ return;
+ }
+ long classID = getIdValue((Number)clazz);
+ if (snapshot.isNewStyleArrayClass()) {
+ // Modern heap dumps do this
+ JavaThing t = snapshot.findThing(classID);
+ if (t instanceof JavaClass) {
+ clazz = (JavaClass) t;
+ }
+ }
+ if (!(clazz instanceof JavaClass)) {
+ JavaThing t = snapshot.findThing(classID);
+ if (t != null && t instanceof JavaClass) {
+ JavaClass el = (JavaClass) t;
+ String nm = el.getName();
+ if (!nm.startsWith("[")) {
+ nm = "L" + el.getName() + ";";
+ }
+ clazz = snapshot.getArrayClass(nm);
+ }
+ }
+
+ if (!(clazz instanceof JavaClass)) {
+ clazz = snapshot.getOtherArrayType();
+ }
+ ((JavaClass)clazz).addInstance(this);
+ super.resolve(snapshot);
+ }
+
+ public JavaThing[] getValues() {
+ return getElements();
+ }
+
+ public JavaThing[] getElements() {
+ Snapshot snapshot = getClazz().getSnapshot();
+ byte[] data = getValue();
+ final int idSize = snapshot.getIdentifierSize();
+ final int numElements = data.length / idSize;
+ JavaThing[] elements = new JavaThing[numElements];
+ int index = 0;
+ for (int i = 0; i < elements.length; i++) {
+ long id = objectIdAt(index, data);
+ index += idSize;
+ elements[i] = snapshot.findThing(id);
+ }
+ return elements;
+ }
+
+ public int compareTo(JavaThing other) {
+ if (other instanceof JavaObjectArray) {
+ return 0;
+ }
+ return super.compareTo(other);
+ }
+
+ public int getLength() {
+ return getValueLength() / getClazz().getIdentifierSize();
+ }
+
+ public void visitReferencedObjects(JavaHeapObjectVisitor v) {
+ super.visitReferencedObjects(v);
+ JavaThing[] elements = getElements();
+ for (int i = 0; i < elements.length; i++) {
+ if (elements[i] != null && elements[i] instanceof JavaHeapObject) {
+ v.visit((JavaHeapObject) elements[i]);
+ }
+ }
+ }
+
+ /**
+ * Describe the reference that this thing has to target. This will only
+ * be called if target is in the array returned by getChildrenForRootset.
+ */
+ public String describeReferenceTo(JavaThing target, Snapshot ss) {
+ JavaThing[] elements = getElements();
+ for (int i = 0; i < elements.length; i++) {
+ if (elements[i] == target) {
+ return "Element " + i + " of " + this;
+ }
+ }
+ return super.describeReferenceTo(target, ss);
+ }
+
+ /*
+ * Java object array record (HPROF_GC_OBJ_ARRAY_DUMP)
+ * looks as below:
+ *
+ * object ID
+ * stack trace serial number (int)
+ * array length (int)
+ * array class ID
+ * array element IDs
+ */
+ protected final int readValueLength() throws IOException {
+ JavaClass cl = getClazz();
+ ReadBuffer buf = cl.getReadBuffer();
+ int idSize = cl.getIdentifierSize();
+ long offset = getOffset() + idSize + 4;
+ int len = buf.getInt(offset);
+ return len * cl.getIdentifierSize();
+ }
+
+ protected final byte[] readValue() throws IOException {
+ JavaClass cl = getClazz();
+ ReadBuffer buf = cl.getReadBuffer();
+ int idSize = cl.getIdentifierSize();
+ long offset = getOffset() + idSize + 4;
+ int len = buf.getInt(offset);
+ if (len == 0) {
+ return Snapshot.EMPTY_BYTE_ARRAY;
+ } else {
+ byte[] res = new byte[len * idSize];
+ buf.get(offset + 4 + idSize, res);
+ return res;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaObjectRef.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+import jdk.test.lib.hprof.util.Misc;
+
+/**
+ * A forward reference to an object. This is an intermediate representation
+ * for a JavaThing, when we have the thing's ID, but we might not have read
+ * the thing yet.
+ *
+ * @author Bill Foote
+ */
+public class JavaObjectRef extends JavaThing {
+ private long id;
+
+ public JavaObjectRef(long id) {
+ this.id = id;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public boolean isHeapAllocated() {
+ return true;
+ }
+
+ public JavaThing dereference(Snapshot snapshot, JavaField field) {
+ return dereference(snapshot, field, true);
+ }
+
+ public JavaThing dereference(Snapshot snapshot, JavaField field, boolean verbose) {
+ if (field != null && !field.hasId()) {
+ // If this happens, we must be a field that represents an int.
+ // (This only happens with .bod-style files)
+ return new JavaLong(id);
+ }
+ if (id == 0) {
+ return snapshot.getNullThing();
+ }
+ JavaThing result = snapshot.findThing(id);
+ if (result == null) {
+ if (!snapshot.getUnresolvedObjectsOK() && verbose) {
+ String msg = "WARNING: Failed to resolve object id "
+ + Misc.toHex(id);
+ if (field != null) {
+ msg += " for field " + field.getName()
+ + " (signature " + field.getSignature() + ")";
+ }
+ System.out.println(msg);
+ // Thread.dumpStack();
+ }
+ result = new HackJavaValue("Unresolved object "
+ + Misc.toHex(id), 0);
+ }
+ return result;
+ }
+
+ public int getSize() {
+ return 0;
+ }
+
+ public String toString() {
+ return "Unresolved object " + Misc.toHex(id);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaShort.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+/**
+ * Represents a short (i.e. a short field in an instance).
+ *
+ * @author Bill Foote
+ */
+
+
+public class JavaShort extends JavaValue {
+
+ short value;
+
+ public JavaShort(short value) {
+ this.value = value;
+ }
+
+ public String toString() {
+ return "" + value;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaStatic.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+/**
+ *
+ * @author Bill Foote
+ */
+
+/**
+ * Represents the value of a static field of a JavaClass
+ */
+
+public class JavaStatic {
+
+ private JavaField field;
+ private JavaThing value;
+
+ public JavaStatic(JavaField field, JavaThing value) {
+ this.field = field;
+ this.value = value;
+ }
+
+ public void resolve(JavaClass clazz, Snapshot snapshot) {
+ long id = -1;
+ if (value instanceof JavaObjectRef) {
+ id = ((JavaObjectRef)value).getId();
+ }
+ value = value.dereference(snapshot, field);
+ if (value.isHeapAllocated() &&
+ clazz.getLoader() == snapshot.getNullThing()) {
+ // static fields are only roots if they are in classes
+ // loaded by the root classloader.
+ JavaHeapObject ho = (JavaHeapObject) value;
+ String s = "Static reference from " + clazz.getName()
+ + "." + field.getName();
+ snapshot.addRoot(new Root(id, clazz.getId(),
+ Root.JAVA_STATIC, s));
+ }
+ }
+
+ public JavaField getField() {
+ return field;
+ }
+
+ public JavaThing getValue() {
+ return value;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaThing.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+
+/**
+ *
+ * @author Bill Foote
+ */
+
+
+/**
+ * Represents a java "Thing". A thing is anything that can be the value of
+ * a field. This includes JavaHeapObject, JavaObjectRef, and JavaValue.
+ */
+
+public abstract class JavaThing {
+
+ protected JavaThing() {
+ }
+
+ /**
+ * If this is a forward reference, figure out what it really
+ * refers to.
+ *
+ * @param snapshot The snapshot this is for
+ * @param field The field this thing represents. If null, it is
+ * assumed this thing is an object (and never a value).
+ */
+ public JavaThing dereference(Snapshot shapshot, JavaField field) {
+ return this;
+ }
+
+
+ /**
+ * Are we the same type as other?
+ *
+ * @see JavaObject.isSameTypeAs()
+ */
+ public boolean isSameTypeAs(JavaThing other) {
+ return getClass() == other.getClass();
+ }
+ /**
+ * @return true iff this represents a heap-allocated object
+ */
+ abstract public boolean isHeapAllocated();
+
+ /**
+ * @return the size of this object, in bytes, including VM overhead
+ */
+ abstract public int getSize();
+
+ /**
+ * @return a human-readable string representation of this thing
+ */
+ abstract public String toString();
+
+ /**
+ * Compare our string representation to other's
+ * @see java.lang.String.compareTo()
+ */
+ public int compareTo(JavaThing other) {
+ return toString().compareTo(other.toString());
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaValue.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+/**
+ * Abstract base class for all value types (ints, longs, floats, etc.)
+ *
+ * @author Bill Foote
+ */
+
+
+
+
+public abstract class JavaValue extends JavaThing {
+
+ protected JavaValue() {
+ }
+
+ public boolean isHeapAllocated() {
+ return false;
+ }
+
+ abstract public String toString();
+
+ public int getSize() {
+ // The size of a value is already accounted for in the class
+ // that has the data member.
+ return 0;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/JavaValueArray.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+import jdk.test.lib.hprof.parser.ReadBuffer;
+import java.io.IOException;
+
+/**
+ * An array of values, that is, an array of ints, boolean, floats or the like.
+ *
+ * @author Bill Foote
+ */
+public class JavaValueArray extends JavaLazyReadObject
+ /*imports*/ implements ArrayTypeCodes {
+
+ private static String arrayTypeName(byte sig) {
+ switch (sig) {
+ case 'B':
+ return "byte[]";
+ case 'Z':
+ return "boolean[]";
+ case 'C':
+ return "char[]";
+ case 'S':
+ return "short[]";
+ case 'I':
+ return "int[]";
+ case 'F':
+ return "float[]";
+ case 'J':
+ return "long[]";
+ case 'D':
+ return "double[]";
+ default:
+ throw new RuntimeException("invalid array element sig: " + sig);
+ }
+ }
+
+ private static int elementSize(byte type) {
+ switch (type) {
+ case T_BYTE:
+ case T_BOOLEAN:
+ return 1;
+ case T_CHAR:
+ case T_SHORT:
+ return 2;
+ case T_INT:
+ case T_FLOAT:
+ return 4;
+ case T_LONG:
+ case T_DOUBLE:
+ return 8;
+ default:
+ throw new RuntimeException("invalid array element type: " + type);
+ }
+ }
+
+ /*
+ * Java primitive array record (HPROF_GC_PRIM_ARRAY_DUMP) looks
+ * as below:
+ *
+ * object ID
+ * stack trace serial number (int)
+ * length of the instance data (int)
+ * element type (byte)
+ * array data
+ */
+ protected final int readValueLength() throws IOException {
+ JavaClass cl = getClazz();
+ ReadBuffer buf = cl.getReadBuffer();
+ int idSize = cl.getIdentifierSize();
+ long offset = getOffset() + idSize + 4;
+ // length of the array
+ int len = buf.getInt(offset);
+ // typecode of array element type
+ byte type = buf.getByte(offset + 4);
+ return len * elementSize(type);
+ }
+
+ protected final byte[] readValue() throws IOException {
+ JavaClass cl = getClazz();
+ ReadBuffer buf = cl.getReadBuffer();
+ int idSize = cl.getIdentifierSize();
+ long offset = getOffset() + idSize + 4;
+ // length of the array
+ int length = buf.getInt(offset);
+ // typecode of array element type
+ byte type = buf.getByte(offset + 4);
+ if (length == 0) {
+ return Snapshot.EMPTY_BYTE_ARRAY;
+ } else {
+ length *= elementSize(type);
+ byte[] res = new byte[length];
+ buf.get(offset + 5, res);
+ return res;
+ }
+ }
+
+ // JavaClass set only after resolve.
+ private JavaClass clazz;
+
+ // This field contains elementSignature byte and
+ // divider to be used to calculate length. Note that
+ // length of content byte[] is not same as array length.
+ // Actual array length is (byte[].length / divider)
+ private int data;
+
+ // First 8 bits of data is used for element signature
+ private static final int SIGNATURE_MASK = 0x0FF;
+
+ // Next 8 bits of data is used for length divider
+ private static final int LENGTH_DIVIDER_MASK = 0x0FF00;
+
+ // Number of bits to shift to get length divider
+ private static final int LENGTH_DIVIDER_SHIFT = 8;
+
+ public JavaValueArray(byte elementSignature, long offset) {
+ super(offset);
+ this.data = (elementSignature & SIGNATURE_MASK);
+ }
+
+ public JavaClass getClazz() {
+ return clazz;
+ }
+
+ public void visitReferencedObjects(JavaHeapObjectVisitor v) {
+ super.visitReferencedObjects(v);
+ }
+
+ public void resolve(Snapshot snapshot) {
+ if (clazz instanceof JavaClass) {
+ return;
+ }
+ byte elementSig = getElementType();
+ clazz = snapshot.findClass(arrayTypeName(elementSig));
+ if (clazz == null) {
+ clazz = snapshot.getArrayClass("" + ((char) elementSig));
+ }
+ getClazz().addInstance(this);
+ super.resolve(snapshot);
+ }
+
+ public int getLength() {
+ int divider = (data & LENGTH_DIVIDER_MASK) >>> LENGTH_DIVIDER_SHIFT;
+ if (divider == 0) {
+ byte elementSignature = getElementType();
+ switch (elementSignature) {
+ case 'B':
+ case 'Z':
+ divider = 1;
+ break;
+ case 'C':
+ case 'S':
+ divider = 2;
+ break;
+ case 'I':
+ case 'F':
+ divider = 4;
+ break;
+ case 'J':
+ case 'D':
+ divider = 8;
+ break;
+ default:
+ throw new RuntimeException("unknown primitive type: " +
+ elementSignature);
+ }
+ data |= (divider << LENGTH_DIVIDER_SHIFT);
+ }
+ return (getValueLength() / divider);
+ }
+
+ public Object getElements() {
+ final int len = getLength();
+ final byte et = getElementType();
+ byte[] data = getValue();
+ int index = 0;
+ switch (et) {
+ case 'Z': {
+ boolean[] res = new boolean[len];
+ for (int i = 0; i < len; i++) {
+ res[i] = booleanAt(index, data);
+ index++;
+ }
+ return res;
+ }
+ case 'B': {
+ byte[] res = new byte[len];
+ for (int i = 0; i < len; i++) {
+ res[i] = byteAt(index, data);
+ index++;
+ }
+ return res;
+ }
+ case 'C': {
+ char[] res = new char[len];
+ for (int i = 0; i < len; i++) {
+ res[i] = charAt(index, data);
+ index += 2;
+ }
+ return res;
+ }
+ case 'S': {
+ short[] res = new short[len];
+ for (int i = 0; i < len; i++) {
+ res[i] = shortAt(index, data);
+ index += 2;
+ }
+ return res;
+ }
+ case 'I': {
+ int[] res = new int[len];
+ for (int i = 0; i < len; i++) {
+ res[i] = intAt(index, data);
+ index += 4;
+ }
+ return res;
+ }
+ case 'J': {
+ long[] res = new long[len];
+ for (int i = 0; i < len; i++) {
+ res[i] = longAt(index, data);
+ index += 8;
+ }
+ return res;
+ }
+ case 'F': {
+ float[] res = new float[len];
+ for (int i = 0; i < len; i++) {
+ res[i] = floatAt(index, data);
+ index += 4;
+ }
+ return res;
+ }
+ case 'D': {
+ double[] res = new double[len];
+ for (int i = 0; i < len; i++) {
+ res[i] = doubleAt(index, data);
+ index += 8;
+ }
+ return res;
+ }
+ default: {
+ throw new RuntimeException("unknown primitive type?");
+ }
+ }
+ }
+
+ public byte getElementType() {
+ return (byte) (data & SIGNATURE_MASK);
+ }
+
+ private void checkIndex(int index) {
+ if (index < 0 || index >= getLength()) {
+ throw new ArrayIndexOutOfBoundsException(index);
+ }
+ }
+
+ private void requireType(char type) {
+ if (getElementType() != type) {
+ throw new RuntimeException("not of type : " + type);
+ }
+ }
+
+ public boolean getBooleanAt(int index) {
+ checkIndex(index);
+ requireType('Z');
+ return booleanAt(index, getValue());
+ }
+
+ public byte getByteAt(int index) {
+ checkIndex(index);
+ requireType('B');
+ return byteAt(index, getValue());
+ }
+
+ public char getCharAt(int index) {
+ checkIndex(index);
+ requireType('C');
+ return charAt(index << 1, getValue());
+ }
+
+ public short getShortAt(int index) {
+ checkIndex(index);
+ requireType('S');
+ return shortAt(index << 1, getValue());
+ }
+
+ public int getIntAt(int index) {
+ checkIndex(index);
+ requireType('I');
+ return intAt(index << 2, getValue());
+ }
+
+ public long getLongAt(int index) {
+ checkIndex(index);
+ requireType('J');
+ return longAt(index << 3, getValue());
+ }
+
+ public float getFloatAt(int index) {
+ checkIndex(index);
+ requireType('F');
+ return floatAt(index << 2, getValue());
+ }
+
+ public double getDoubleAt(int index) {
+ checkIndex(index);
+ requireType('D');
+ return doubleAt(index << 3, getValue());
+ }
+
+ public String valueString() {
+ return valueString(true);
+ }
+
+ public String valueString(boolean bigLimit) {
+ // Char arrays deserve special treatment
+ StringBuilder result;
+ byte[] value = getValue();
+ int max = value.length;
+ byte elementSignature = getElementType();
+ if (elementSignature == 'C') {
+ result = new StringBuilder();
+ for (int i = 0; i < value.length; ) {
+ char val = charAt(i, value);
+ result.append(val);
+ i += 2;
+ }
+ } else {
+ int limit = 8;
+ if (bigLimit) {
+ limit = 1000;
+ }
+ result = new StringBuilder("{");
+ int num = 0;
+ for (int i = 0; i < value.length; ) {
+ if (num > 0) {
+ result.append(", ");
+ }
+ if (num >= limit) {
+ result.append("... ");
+ break;
+ }
+ num++;
+ switch (elementSignature) {
+ case 'Z': {
+ boolean val = booleanAt(i, value);
+ if (val) {
+ result.append("true");
+ } else {
+ result.append("false");
+ }
+ i++;
+ break;
+ }
+ case 'B': {
+ int val = 0xFF & byteAt(i, value);
+ result.append("0x").append(Integer.toString(val, 16));
+ i++;
+ break;
+ }
+ case 'S': {
+ short val = shortAt(i, value);
+ i += 2;
+ result.append(val);
+ break;
+ }
+ case 'I': {
+ int val = intAt(i, value);
+ i += 4;
+ result.append(val);
+ break;
+ }
+ case 'J': { // long
+ long val = longAt(i, value);
+ result.append(val);
+ i += 8;
+ break;
+ }
+ case 'F': {
+ float val = floatAt(i, value);
+ result.append(val);
+ i += 4;
+ break;
+ }
+ case 'D': { // double
+ double val = doubleAt(i, value);
+ result.append(val);
+ i += 8;
+ break;
+ }
+ default: {
+ throw new RuntimeException("unknown primitive type?");
+ }
+ }
+ }
+ result.append('}');
+ }
+ return result.toString();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/ReachableExcludes.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+
+/**
+ * This represents a set of data members that should be excluded from the
+ * reachable objects query. This is useful to exclude observers from the
+ * transitive closure of objects reachable from a given object, allowing
+ * some kind of real determination of the "size" of that object.
+ *
+ */
+
+public interface ReachableExcludes {
+ /**
+ * @return true iff the given field is on the hitlist of excluded
+ * fields.
+ */
+ public boolean isExcluded(String fieldName);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/ReachableExcludesImpl.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.BufferedReader;
+import java.io.IOException;
+
+import java.util.Hashtable;
+
+/**
+ * This represents a set of data members that should be excluded from the
+ * reachable objects query.
+ * This is useful to exclude observers from the
+ * transitive closure of objects reachable from a given object, allowing
+ * some kind of real determination of the "size" of that object.
+ *
+ * @author Bill Foote
+ */
+public class ReachableExcludesImpl implements ReachableExcludes {
+
+ private File excludesFile;
+ private long lastModified;
+ private Hashtable<String, String> methods; // Used as a bag
+
+ /**
+ * Create a new ReachableExcludesImpl over the given file. The file will be
+ * re-read whenever the timestamp changes.
+ */
+ public ReachableExcludesImpl(File excludesFile) {
+ this.excludesFile = excludesFile;
+ readFile();
+ }
+
+ private void readFileIfNeeded() {
+ if (excludesFile.lastModified() != lastModified) {
+ synchronized(this) {
+ if (excludesFile.lastModified() != lastModified) {
+ readFile();
+ }
+ }
+ }
+ }
+
+ private void readFile() {
+ long lm = excludesFile.lastModified();
+ Hashtable<String, String> m = new Hashtable<String, String>();
+
+ try (BufferedReader r = new BufferedReader(new InputStreamReader(
+ new FileInputStream(excludesFile)))) {
+ String method;
+ while ((method = r.readLine()) != null) {
+ m.put(method, method);
+ }
+ lastModified = lm;
+ methods = m; // We want this to be atomic
+ } catch (IOException ex) {
+ System.out.println("Error reading " + excludesFile + ": " + ex);
+ }
+ }
+
+ /**
+ * @return true iff the given field is on the histlist of excluded
+ * fields.
+ */
+ public boolean isExcluded(String fieldName) {
+ readFileIfNeeded();
+ return methods.get(fieldName) != null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/ReachableObjects.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+import java.util.Vector;
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+import jdk.test.lib.hprof.util.ArraySorter;
+import jdk.test.lib.hprof.util.Comparer;
+
+/**
+ * @author A. Sundararajan
+ */
+
+public class ReachableObjects {
+ public ReachableObjects(JavaHeapObject root,
+ final ReachableExcludes excludes) {
+ this.root = root;
+
+ final Hashtable<JavaHeapObject, JavaHeapObject> bag = new Hashtable<JavaHeapObject, JavaHeapObject>();
+ final Hashtable<String, String> fieldsExcluded = new Hashtable<String, String>(); //Bag<String>
+ final Hashtable<String, String> fieldsUsed = new Hashtable<String, String>(); // Bag<String>
+ JavaHeapObjectVisitor visitor = new AbstractJavaHeapObjectVisitor() {
+ public void visit(JavaHeapObject t) {
+ // Size is zero for things like integer fields
+ if (t != null && t.getSize() > 0 && bag.get(t) == null) {
+ bag.put(t, t);
+ t.visitReferencedObjects(this);
+ }
+ }
+
+ public boolean mightExclude() {
+ return excludes != null;
+ }
+
+ public boolean exclude(JavaClass clazz, JavaField f) {
+ if (excludes == null) {
+ return false;
+ }
+ String nm = clazz.getName() + "." + f.getName();
+ if (excludes.isExcluded(nm)) {
+ fieldsExcluded.put(nm, nm);
+ return true;
+ } else {
+ fieldsUsed.put(nm, nm);
+ return false;
+ }
+ }
+ };
+ // Put the closure of root and all objects reachable from root into
+ // bag (depth first), but don't include root:
+ visitor.visit(root);
+ bag.remove(root);
+
+ // Now grab the elements into a vector, and sort it in decreasing size
+ JavaThing[] things = new JavaThing[bag.size()];
+ int i = 0;
+ for (Enumeration<JavaHeapObject> e = bag.elements(); e.hasMoreElements(); ) {
+ things[i++] = (JavaThing) e.nextElement();
+ }
+ ArraySorter.sort(things, new Comparer() {
+ public int compare(Object lhs, Object rhs) {
+ JavaThing left = (JavaThing) lhs;
+ JavaThing right = (JavaThing) rhs;
+ int diff = right.getSize() - left.getSize();
+ if (diff != 0) {
+ return diff;
+ }
+ return left.compareTo(right);
+ }
+ });
+ this.reachables = things;
+
+ this.totalSize = root.getSize();
+ for (i = 0; i < things.length; i++) {
+ this.totalSize += things[i].getSize();
+ }
+
+ excludedFields = getElements(fieldsExcluded);
+ usedFields = getElements(fieldsUsed);
+ }
+
+ public JavaHeapObject getRoot() {
+ return root;
+ }
+
+ public JavaThing[] getReachables() {
+ return reachables;
+ }
+
+ public long getTotalSize() {
+ return totalSize;
+ }
+
+ public String[] getExcludedFields() {
+ return excludedFields;
+ }
+
+ public String[] getUsedFields() {
+ return usedFields;
+ }
+
+ private String[] getElements(Hashtable<?, ?> ht) {
+ Object[] keys = ht.keySet().toArray();
+ int len = keys.length;
+ String[] res = new String[len];
+ System.arraycopy(keys, 0, res, 0, len);
+ ArraySorter.sortArrayOfStrings(res);
+ return res;
+ }
+
+ private JavaHeapObject root;
+ private JavaThing[] reachables;
+ private String[] excludedFields;
+ private String[] usedFields;
+ private long totalSize;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/ReferenceChain.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+/**
+ * Represents a chain of references to some target object
+ *
+ * @author Bill Foote
+ */
+
+public class ReferenceChain {
+
+ JavaHeapObject obj; // Object referred to
+ ReferenceChain next; // Next in chain
+
+ public ReferenceChain(JavaHeapObject obj, ReferenceChain next) {
+ this.obj = obj;
+ this.next = next;
+ }
+
+ public JavaHeapObject getObj() {
+ return obj;
+ }
+
+ public ReferenceChain getNext() {
+ return next;
+ }
+
+ public int getDepth() {
+ int count = 1;
+ ReferenceChain tmp = next;
+ while (tmp != null) {
+ count++;
+ tmp = tmp.next;
+ }
+ return count;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/Root.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+import jdk.test.lib.hprof.util.Misc;
+
+/**
+ *
+ * @author Bill Foote
+ */
+
+
+/**
+ * Represents a member of the rootset, that is, one of the objects that
+ * the GC starts from when marking reachable objects.
+ */
+
+public class Root {
+
+ private long id; // ID of the JavaThing we refer to
+ private long refererId; // Thread or Class responsible for this, or 0
+ private int index = -1; // Index in Snapshot.roots
+ private int type;
+ private String description;
+ private JavaHeapObject referer = null;
+ private StackTrace stackTrace = null;
+
+ // Values for type. Higher values are more interesting -- see getType().
+ // See also getTypeName()
+ public final static int INVALID_TYPE = 0;
+ public final static int UNKNOWN = 1;
+ public final static int SYSTEM_CLASS = 2;
+
+ public final static int NATIVE_LOCAL = 3;
+ public final static int NATIVE_STATIC = 4;
+ public final static int THREAD_BLOCK = 5;
+ public final static int BUSY_MONITOR = 6;
+ public final static int JAVA_LOCAL = 7;
+ public final static int NATIVE_STACK = 8;
+ public final static int JAVA_STATIC = 9;
+
+
+ public Root(long id, long refererId, int type, String description) {
+ this(id, refererId, type, description, null);
+ }
+
+
+ public Root(long id, long refererId, int type, String description,
+ StackTrace stackTrace) {
+ this.id = id;
+ this.refererId = refererId;
+ this.type = type;
+ this.description = description;
+ this.stackTrace = stackTrace;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public String getIdString() {
+ return Misc.toHex(id);
+ }
+
+ public String getDescription() {
+ if ("".equals(description)) {
+ return getTypeName() + " Reference";
+ } else {
+ return description;
+ }
+ }
+
+ /**
+ * Return type. We guarantee that more interesting roots will have
+ * a type that is numerically higher.
+ */
+ public int getType() {
+ return type;
+ }
+
+ public String getTypeName() {
+ switch(type) {
+ case INVALID_TYPE: return "Invalid (?!?)";
+ case UNKNOWN: return "Unknown";
+ case SYSTEM_CLASS: return "System Class";
+ case NATIVE_LOCAL: return "JNI Local";
+ case NATIVE_STATIC: return "JNI Global";
+ case THREAD_BLOCK: return "Thread Block";
+ case BUSY_MONITOR: return "Busy Monitor";
+ case JAVA_LOCAL: return "Java Local";
+ case NATIVE_STACK: return "Native Stack (possibly Java local)";
+ case JAVA_STATIC: return "Java Static";
+ default: return "??";
+ }
+ }
+
+ /**
+ * Given two Root instances, return the one that is most interesting.
+ */
+ public Root mostInteresting(Root other) {
+ if (other.type > this.type) {
+ return other;
+ } else {
+ return this;
+ }
+ }
+
+ /**
+ * Get the object that's responsible for this root, if there is one.
+ * This will be null, a Thread object, or a Class object.
+ */
+ public JavaHeapObject getReferer() {
+ return referer;
+ }
+
+ /**
+ * @return the stack trace responsible for this root, or null if there
+ * is none.
+ */
+ public StackTrace getStackTrace() {
+ return stackTrace;
+ }
+
+ /**
+ * @return The index of this root in Snapshot.roots
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ void resolve(Snapshot ss) {
+ if (refererId != 0) {
+ referer = ss.findThing(refererId);
+ }
+ if (stackTrace != null) {
+ stackTrace.resolve(ss);
+ }
+ }
+
+ void setIndex(int i) {
+ index = i;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/Snapshot.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,635 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+import java.lang.ref.SoftReference;
+import java.util.*;
+
+import jdk.test.lib.hprof.parser.ReadBuffer;
+import jdk.test.lib.hprof.util.Misc;
+
+/**
+ *
+ * @author Bill Foote
+ */
+
+/**
+ * Represents a snapshot of the Java objects in the VM at one instant.
+ * This is the top-level "model" object read out of a single .hprof or .bod
+ * file.
+ */
+
+public class Snapshot implements AutoCloseable {
+
+ public static final long SMALL_ID_MASK = 0x0FFFFFFFFL;
+ public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+
+ private static final JavaField[] EMPTY_FIELD_ARRAY = new JavaField[0];
+ private static final JavaStatic[] EMPTY_STATIC_ARRAY = new JavaStatic[0];
+
+ // all heap objects
+ private Hashtable<Number, JavaHeapObject> heapObjects =
+ new Hashtable<Number, JavaHeapObject>();
+
+ private Hashtable<Number, JavaClass> fakeClasses =
+ new Hashtable<Number, JavaClass>();
+
+ // all Roots in this Snapshot
+ private Vector<Root> roots = new Vector<Root>();
+
+ // name-to-class map
+ private Map<String, JavaClass> classes =
+ new TreeMap<String, JavaClass>();
+
+ // new objects relative to a baseline - lazily initialized
+ private volatile Map<JavaHeapObject, Boolean> newObjects;
+
+ // allocation site traces for all objects - lazily initialized
+ private volatile Map<JavaHeapObject, StackTrace> siteTraces;
+
+ // object-to-Root map for all objects
+ private Map<JavaHeapObject, Root> rootsMap =
+ new HashMap<JavaHeapObject, Root>();
+
+ // soft cache of finalizeable objects - lazily initialized
+ private SoftReference<Vector<?>> finalizablesCache;
+
+ // represents null reference
+ private JavaThing nullThing;
+
+ // java.lang.ref.Reference class
+ private JavaClass weakReferenceClass;
+ // index of 'referent' field in java.lang.ref.Reference class
+ private int referentFieldIndex;
+
+ // java.lang.Class class
+ private JavaClass javaLangClass;
+ // java.lang.String class
+ private JavaClass javaLangString;
+ // java.lang.ClassLoader class
+ private JavaClass javaLangClassLoader;
+
+ // unknown "other" array class
+ private volatile JavaClass otherArrayType;
+ // Stuff to exclude from reachable query
+ private ReachableExcludes reachableExcludes;
+ // the underlying heap dump buffer
+ private ReadBuffer readBuf;
+
+ // True iff some heap objects have isNew set
+ private boolean hasNewSet;
+ private boolean unresolvedObjectsOK;
+
+ // whether object array instances have new style class or
+ // old style (element) class.
+ private boolean newStyleArrayClass;
+
+ // object id size in the heap dump
+ private int identifierSize = 4;
+
+ // minimum object size - accounts for object header in
+ // most Java virtual machines - we assume 2 identifierSize
+ // (which is true for Sun's hotspot JVM).
+ private int minimumObjectSize;
+
+ public Snapshot(ReadBuffer buf) {
+ nullThing = new HackJavaValue("<null>", 0);
+ readBuf = buf;
+ }
+
+ public void setSiteTrace(JavaHeapObject obj, StackTrace trace) {
+ if (trace != null && trace.getFrames().length != 0) {
+ initSiteTraces();
+ siteTraces.put(obj, trace);
+ }
+ }
+
+ public StackTrace getSiteTrace(JavaHeapObject obj) {
+ if (siteTraces != null) {
+ return siteTraces.get(obj);
+ } else {
+ return null;
+ }
+ }
+
+ public void setNewStyleArrayClass(boolean value) {
+ newStyleArrayClass = value;
+ }
+
+ public boolean isNewStyleArrayClass() {
+ return newStyleArrayClass;
+ }
+
+ public void setIdentifierSize(int size) {
+ identifierSize = size;
+ minimumObjectSize = 2 * size;
+ }
+
+ public int getIdentifierSize() {
+ return identifierSize;
+ }
+
+ public int getMinimumObjectSize() {
+ return minimumObjectSize;
+ }
+
+ public void addHeapObject(long id, JavaHeapObject ho) {
+ heapObjects.put(makeId(id), ho);
+ }
+
+ public void addRoot(Root r) {
+ r.setIndex(roots.size());
+ roots.addElement(r);
+ }
+
+ public void addClass(long id, JavaClass c) {
+ addHeapObject(id, c);
+ putInClassesMap(c);
+ }
+
+ JavaClass addFakeInstanceClass(long classID, int instSize) {
+ // Create a fake class name based on ID.
+ String name = "unknown-class<@" + Misc.toHex(classID) + ">";
+
+ // Create fake fields convering the given instance size.
+ // Create as many as int type fields and for the left over
+ // size create byte type fields.
+ int numInts = instSize / 4;
+ int numBytes = instSize % 4;
+ JavaField[] fields = new JavaField[numInts + numBytes];
+ int i;
+ for (i = 0; i < numInts; i++) {
+ fields[i] = new JavaField("unknown-field-" + i, "I");
+ }
+ for (i = 0; i < numBytes; i++) {
+ fields[i + numInts] = new JavaField("unknown-field-" +
+ i + numInts, "B");
+ }
+
+ // Create fake instance class
+ JavaClass c = new JavaClass(name, 0, 0, 0, 0, fields,
+ EMPTY_STATIC_ARRAY, instSize);
+ // Add the class
+ addFakeClass(makeId(classID), c);
+ return c;
+ }
+
+
+ /**
+ * @return true iff it's possible that some JavaThing instances might
+ * isNew set
+ *
+ * @see JavaThing.isNew()
+ */
+ public boolean getHasNewSet() {
+ return hasNewSet;
+ }
+
+ //
+ // Used in the body of resolve()
+ //
+ private static class MyVisitor extends AbstractJavaHeapObjectVisitor {
+ JavaHeapObject t;
+ public void visit(JavaHeapObject other) {
+ other.addReferenceFrom(t);
+ }
+ }
+
+ // To show heap parsing progress, we print a '.' after this limit
+ private static final int DOT_LIMIT = 5000;
+
+ /**
+ * Called after reading complete, to initialize the structure
+ */
+ public void resolve(boolean calculateRefs) {
+ System.out.println("Resolving " + heapObjects.size() + " objects...");
+
+ // First, resolve the classes. All classes must be resolved before
+ // we try any objects, because the objects use classes in their
+ // resolution.
+ javaLangClass = findClass("java.lang.Class");
+ if (javaLangClass == null) {
+ System.out.println("WARNING: hprof file does not include java.lang.Class!");
+ javaLangClass = new JavaClass("java.lang.Class", 0, 0, 0, 0,
+ EMPTY_FIELD_ARRAY, EMPTY_STATIC_ARRAY, 0);
+ addFakeClass(javaLangClass);
+ }
+ javaLangString = findClass("java.lang.String");
+ if (javaLangString == null) {
+ System.out.println("WARNING: hprof file does not include java.lang.String!");
+ javaLangString = new JavaClass("java.lang.String", 0, 0, 0, 0,
+ EMPTY_FIELD_ARRAY, EMPTY_STATIC_ARRAY, 0);
+ addFakeClass(javaLangString);
+ }
+ javaLangClassLoader = findClass("java.lang.ClassLoader");
+ if (javaLangClassLoader == null) {
+ System.out.println("WARNING: hprof file does not include java.lang.ClassLoader!");
+ javaLangClassLoader = new JavaClass("java.lang.ClassLoader", 0, 0, 0, 0,
+ EMPTY_FIELD_ARRAY, EMPTY_STATIC_ARRAY, 0);
+ addFakeClass(javaLangClassLoader);
+ }
+
+ for (JavaHeapObject t : heapObjects.values()) {
+ if (t instanceof JavaClass) {
+ t.resolve(this);
+ }
+ }
+
+ // Now, resolve everything else.
+ for (JavaHeapObject t : heapObjects.values()) {
+ if (!(t instanceof JavaClass)) {
+ t.resolve(this);
+ }
+ }
+
+ heapObjects.putAll(fakeClasses);
+ fakeClasses.clear();
+
+ weakReferenceClass = findClass("java.lang.ref.Reference");
+ referentFieldIndex = 0;
+ if (weakReferenceClass != null) {
+ JavaField[] fields = weakReferenceClass.getFieldsForInstance();
+ for (int i = 0; i < fields.length; i++) {
+ if ("referent".equals(fields[i].getName())) {
+ referentFieldIndex = i;
+ break;
+ }
+ }
+ }
+
+ if (calculateRefs) {
+ calculateReferencesToObjects();
+ System.out.print("Eliminating duplicate references");
+ System.out.flush();
+ // This println refers to the *next* step
+ }
+ int count = 0;
+ for (JavaHeapObject t : heapObjects.values()) {
+ t.setupReferers();
+ ++count;
+ if (calculateRefs && count % DOT_LIMIT == 0) {
+ System.out.print(".");
+ System.out.flush();
+ }
+ }
+ if (calculateRefs) {
+ System.out.println("");
+ }
+
+ // to ensure that Iterator.remove() on getClasses()
+ // result will throw exception..
+ classes = Collections.unmodifiableMap(classes);
+ }
+
+ private void calculateReferencesToObjects() {
+ System.out.print("Chasing references, expect "
+ + (heapObjects.size() / DOT_LIMIT) + " dots");
+ System.out.flush();
+ int count = 0;
+ MyVisitor visitor = new MyVisitor();
+ for (JavaHeapObject t : heapObjects.values()) {
+ visitor.t = t;
+ // call addReferenceFrom(t) on all objects t references:
+ t.visitReferencedObjects(visitor);
+ ++count;
+ if (count % DOT_LIMIT == 0) {
+ System.out.print(".");
+ System.out.flush();
+ }
+ }
+ System.out.println();
+ for (Root r : roots) {
+ r.resolve(this);
+ JavaHeapObject t = findThing(r.getId());
+ if (t != null) {
+ t.addReferenceFromRoot(r);
+ }
+ }
+ }
+
+ public void markNewRelativeTo(Snapshot baseline) {
+ hasNewSet = true;
+ for (JavaHeapObject t : heapObjects.values()) {
+ boolean isNew;
+ long thingID = t.getId();
+ if (thingID == 0L || thingID == -1L) {
+ isNew = false;
+ } else {
+ JavaThing other = baseline.findThing(t.getId());
+ if (other == null) {
+ isNew = true;
+ } else {
+ isNew = !t.isSameTypeAs(other);
+ }
+ }
+ t.setNew(isNew);
+ }
+ }
+
+ public Enumeration<JavaHeapObject> getThings() {
+ return heapObjects.elements();
+ }
+
+
+ public JavaHeapObject findThing(long id) {
+ Number idObj = makeId(id);
+ JavaHeapObject jho = heapObjects.get(idObj);
+ return jho != null? jho : fakeClasses.get(idObj);
+ }
+
+ public JavaHeapObject findThing(String id) {
+ return findThing(Misc.parseHex(id));
+ }
+
+ public JavaClass findClass(String name) {
+ if (name.startsWith("0x")) {
+ return (JavaClass) findThing(name);
+ } else {
+ return classes.get(name);
+ }
+ }
+
+ /**
+ * Return an Iterator of all of the classes in this snapshot.
+ **/
+ public Iterator<JavaClass> getClasses() {
+ // note that because classes is a TreeMap
+ // classes are already sorted by name
+ return classes.values().iterator();
+ }
+
+ public JavaClass[] getClassesArray() {
+ JavaClass[] res = new JavaClass[classes.size()];
+ classes.values().toArray(res);
+ return res;
+ }
+
+ public synchronized Enumeration<?> getFinalizerObjects() {
+ Vector<?> obj;
+ if (finalizablesCache != null &&
+ (obj = finalizablesCache.get()) != null) {
+ return obj.elements();
+ }
+
+ JavaClass clazz = findClass("java.lang.ref.Finalizer");
+ JavaObject queue = (JavaObject) clazz.getStaticField("queue");
+ JavaThing tmp = queue.getField("head");
+ Vector<JavaHeapObject> finalizables = new Vector<JavaHeapObject>();
+ if (tmp != getNullThing()) {
+ JavaObject head = (JavaObject) tmp;
+ while (true) {
+ JavaHeapObject referent = (JavaHeapObject) head.getField("referent");
+ JavaThing next = head.getField("next");
+ if (next == getNullThing() || next.equals(head)) {
+ break;
+ }
+ head = (JavaObject) next;
+ finalizables.add(referent);
+ }
+ }
+ finalizablesCache = new SoftReference<Vector<?>>(finalizables);
+ return finalizables.elements();
+ }
+
+ public Enumeration<Root> getRoots() {
+ return roots.elements();
+ }
+
+ public Root[] getRootsArray() {
+ Root[] res = new Root[roots.size()];
+ roots.toArray(res);
+ return res;
+ }
+
+ public Root getRootAt(int i) {
+ return roots.elementAt(i);
+ }
+
+ public ReferenceChain[]
+ rootsetReferencesTo(JavaHeapObject target, boolean includeWeak) {
+ Vector<ReferenceChain> fifo = new Vector<ReferenceChain>(); // This is slow... A real fifo would help
+ // Must be a fifo to go breadth-first
+ Hashtable<JavaHeapObject, JavaHeapObject> visited = new Hashtable<JavaHeapObject, JavaHeapObject>();
+ // Objects are added here right after being added to fifo.
+ Vector<ReferenceChain> result = new Vector<ReferenceChain>();
+ visited.put(target, target);
+ fifo.addElement(new ReferenceChain(target, null));
+
+ while (fifo.size() > 0) {
+ ReferenceChain chain = fifo.elementAt(0);
+ fifo.removeElementAt(0);
+ JavaHeapObject curr = chain.getObj();
+ if (curr.getRoot() != null) {
+ result.addElement(chain);
+ // Even though curr is in the rootset, we want to explore its
+ // referers, because they might be more interesting.
+ }
+ Enumeration<JavaThing> referers = curr.getReferers();
+ while (referers.hasMoreElements()) {
+ JavaHeapObject t = (JavaHeapObject) referers.nextElement();
+ if (t != null && !visited.containsKey(t)) {
+ if (includeWeak || !t.refersOnlyWeaklyTo(this, curr)) {
+ visited.put(t, t);
+ fifo.addElement(new ReferenceChain(t, chain));
+ }
+ }
+ }
+ }
+
+ ReferenceChain[] realResult = new ReferenceChain[result.size()];
+ for (int i = 0; i < result.size(); i++) {
+ realResult[i] = result.elementAt(i);
+ }
+ return realResult;
+ }
+
+ public boolean getUnresolvedObjectsOK() {
+ return unresolvedObjectsOK;
+ }
+
+ public void setUnresolvedObjectsOK(boolean v) {
+ unresolvedObjectsOK = v;
+ }
+
+ public JavaClass getWeakReferenceClass() {
+ return weakReferenceClass;
+ }
+
+ public int getReferentFieldIndex() {
+ return referentFieldIndex;
+ }
+
+ public JavaThing getNullThing() {
+ return nullThing;
+ }
+
+ public void setReachableExcludes(ReachableExcludes e) {
+ reachableExcludes = e;
+ }
+
+ public ReachableExcludes getReachableExcludes() {
+ return reachableExcludes;
+ }
+
+ // package privates
+ void addReferenceFromRoot(Root r, JavaHeapObject obj) {
+ Root root = rootsMap.get(obj);
+ if (root == null) {
+ rootsMap.put(obj, r);
+ } else {
+ rootsMap.put(obj, root.mostInteresting(r));
+ }
+ }
+
+ Root getRoot(JavaHeapObject obj) {
+ return rootsMap.get(obj);
+ }
+
+ JavaClass getJavaLangClass() {
+ return javaLangClass;
+ }
+
+ JavaClass getJavaLangString() {
+ return javaLangString;
+ }
+
+ JavaClass getJavaLangClassLoader() {
+ return javaLangClassLoader;
+ }
+
+ JavaClass getOtherArrayType() {
+ if (otherArrayType == null) {
+ synchronized(this) {
+ if (otherArrayType == null) {
+ addFakeClass(new JavaClass("[<other>", 0, 0, 0, 0,
+ EMPTY_FIELD_ARRAY, EMPTY_STATIC_ARRAY,
+ 0));
+ otherArrayType = findClass("[<other>");
+ }
+ }
+ }
+ return otherArrayType;
+ }
+
+ JavaClass getArrayClass(String elementSignature) {
+ JavaClass clazz;
+ synchronized(classes) {
+ clazz = findClass("[" + elementSignature);
+ if (clazz == null) {
+ clazz = new JavaClass("[" + elementSignature, 0, 0, 0, 0,
+ EMPTY_FIELD_ARRAY, EMPTY_STATIC_ARRAY, 0);
+ addFakeClass(clazz);
+ // This is needed because the JDK only creates Class structures
+ // for array element types, not the arrays themselves. For
+ // analysis, though, we need to pretend that there's a
+ // JavaClass for the array type, too.
+ }
+ }
+ return clazz;
+ }
+
+ ReadBuffer getReadBuffer() {
+ return readBuf;
+ }
+
+ void setNew(JavaHeapObject obj, boolean isNew) {
+ initNewObjects();
+ if (isNew) {
+ newObjects.put(obj, Boolean.TRUE);
+ }
+ }
+
+ boolean isNew(JavaHeapObject obj) {
+ if (newObjects != null) {
+ return newObjects.get(obj) != null;
+ } else {
+ return false;
+ }
+ }
+
+ // Internals only below this point
+ private Number makeId(long id) {
+ if (identifierSize == 4) {
+ return (int)id;
+ } else {
+ return id;
+ }
+ }
+
+ private void putInClassesMap(JavaClass c) {
+ String name = c.getName();
+ if (classes.containsKey(name)) {
+ // more than one class can have the same name
+ // if so, create a unique name by appending
+ // - and id string to it.
+ name += "-" + c.getIdString();
+ }
+ classes.put(c.getName(), c);
+ }
+
+ private void addFakeClass(JavaClass c) {
+ putInClassesMap(c);
+ c.resolve(this);
+ }
+
+ private void addFakeClass(Number id, JavaClass c) {
+ fakeClasses.put(id, c);
+ addFakeClass(c);
+ }
+
+ private synchronized void initNewObjects() {
+ if (newObjects == null) {
+ synchronized (this) {
+ if (newObjects == null) {
+ newObjects = new HashMap<JavaHeapObject, Boolean>();
+ }
+ }
+ }
+ }
+
+ private synchronized void initSiteTraces() {
+ if (siteTraces == null) {
+ synchronized (this) {
+ if (siteTraces == null) {
+ siteTraces = new HashMap<JavaHeapObject, StackTrace>();
+ }
+ }
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ readBuf.close();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/StackFrame.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+/**
+ *
+ * @author Bill Foote
+ */
+
+
+/**
+ * Represents a stack frame.
+ */
+
+public class StackFrame {
+
+ //
+ // Values for the lineNumber data member. These are the same
+ // as the values used in the JDK 1.2 heap dump file.
+ //
+ public final static int LINE_NUMBER_UNKNOWN = -1;
+ public final static int LINE_NUMBER_COMPILED = -2;
+ public final static int LINE_NUMBER_NATIVE = -3;
+
+ private String methodName;
+ private String methodSignature;
+ private String className;
+ private String sourceFileName;
+ private int lineNumber;
+
+ public StackFrame(String methodName, String methodSignature,
+ String className, String sourceFileName, int lineNumber) {
+ this.methodName = methodName;
+ this.methodSignature = methodSignature;
+ this.className = className;
+ this.sourceFileName = sourceFileName;
+ this.lineNumber = lineNumber;
+ }
+
+ public void resolve(Snapshot snapshot) {
+ }
+
+ public String getMethodName() {
+ return methodName;
+ }
+
+ public String getMethodSignature() {
+ return methodSignature;
+ }
+
+ public String getClassName() {
+ return className;
+ }
+
+ public String getSourceFileName() {
+ return sourceFileName;
+ }
+
+ public String getLineNumber() {
+ switch(lineNumber) {
+ case LINE_NUMBER_UNKNOWN:
+ return "(unknown)";
+ case LINE_NUMBER_COMPILED:
+ return "(compiled method)";
+ case LINE_NUMBER_NATIVE:
+ return "(native method)";
+ default:
+ return Integer.toString(lineNumber, 10);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/model/StackTrace.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.model;
+
+/**
+ *
+ * @author Bill Foote
+ */
+
+
+/**
+ * Represents a stack trace, that is, an ordered collection of stack frames.
+ */
+
+public class StackTrace {
+
+ private StackFrame[] frames;
+
+ public StackTrace(StackFrame[] frames) {
+ this.frames = frames;
+ }
+
+ /**
+ * @param depth. The minimum reasonable depth is 1.
+ *
+ * @return a (possibly new) StackTrace that is limited to depth.
+ */
+ public StackTrace traceForDepth(int depth) {
+ if (depth >= frames.length) {
+ return this;
+ } else {
+ StackFrame[] f = new StackFrame[depth];
+ System.arraycopy(frames, 0, f, 0, depth);
+ return new StackTrace(f);
+ }
+ }
+
+ public void resolve(Snapshot snapshot) {
+ for (int i = 0; i < frames.length; i++) {
+ frames[i].resolve(snapshot);
+ }
+ }
+
+ public StackFrame[] getFrames() {
+ return frames;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/parser/FileReadBuffer.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.parser;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+/**
+ * Implementation of ReadBuffer using a RandomAccessFile
+ *
+ * @author A. Sundararajan
+ */
+class FileReadBuffer implements ReadBuffer {
+ // underlying file to read
+ private RandomAccessFile file;
+
+ FileReadBuffer(RandomAccessFile file) {
+ this.file = file;
+ }
+
+ private void seek(long pos) throws IOException {
+ file.getChannel().position(pos);
+ }
+
+ public synchronized void get(long pos, byte[] buf) throws IOException {
+ seek(pos);
+ file.read(buf);
+ }
+
+ public synchronized char getChar(long pos) throws IOException {
+ seek(pos);
+ return file.readChar();
+ }
+
+ public synchronized byte getByte(long pos) throws IOException {
+ seek(pos);
+ return (byte) file.read();
+ }
+
+ public synchronized short getShort(long pos) throws IOException {
+ seek(pos);
+ return file.readShort();
+ }
+
+ public synchronized int getInt(long pos) throws IOException {
+ seek(pos);
+ return file.readInt();
+ }
+
+ public synchronized long getLong(long pos) throws IOException {
+ seek(pos);
+ return file.readLong();
+ }
+
+ @Override
+ public void close() throws Exception {
+ file.close();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/parser/HprofReader.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,899 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.parser;
+
+import java.io.*;
+import java.util.Date;
+import java.util.Hashtable;
+import jdk.test.lib.hprof.model.ArrayTypeCodes;
+import jdk.test.lib.hprof.model.*;
+
+/**
+ * Object that's used to read a hprof file.
+ *
+ * @author Bill Foote
+ */
+
+public class HprofReader extends Reader /* imports */ implements ArrayTypeCodes {
+
+ final static int MAGIC_NUMBER = 0x4a415641;
+ // That's "JAVA", the first part of "JAVA PROFILE ..."
+ private final static String[] VERSIONS = {
+ " PROFILE 1.0\0",
+ " PROFILE 1.0.1\0",
+ " PROFILE 1.0.2\0",
+ };
+
+ private final static int VERSION_JDK12BETA3 = 0;
+ private final static int VERSION_JDK12BETA4 = 1;
+ private final static int VERSION_JDK6 = 2;
+ // These version numbers are indices into VERSIONS. The instance data
+ // member version is set to one of these, and it drives decisions when
+ // reading the file.
+ //
+ // Version 1.0.1 added HPROF_GC_PRIM_ARRAY_DUMP, which requires no
+ // version-sensitive parsing.
+ //
+ // Version 1.0.1 changed the type of a constant pool entry from a signature
+ // to a typecode.
+ //
+ // Version 1.0.2 added HPROF_HEAP_DUMP_SEGMENT and HPROF_HEAP_DUMP_END
+ // to allow a large heap to be dumped as a sequence of heap dump segments.
+ //
+ // The HPROF agent in J2SE 1.2 through to 5.0 generate a version 1.0.1
+ // file. In Java SE 6.0 the version is either 1.0.1 or 1.0.2 depending on
+ // the size of the heap (normally it will be 1.0.1 but for multi-GB
+ // heaps the heap dump will not fit in a HPROF_HEAP_DUMP record so the
+ // dump is generated as version 1.0.2).
+
+ //
+ // Record types:
+ //
+ static final int HPROF_UTF8 = 0x01;
+ static final int HPROF_LOAD_CLASS = 0x02;
+ static final int HPROF_UNLOAD_CLASS = 0x03;
+ static final int HPROF_FRAME = 0x04;
+ static final int HPROF_TRACE = 0x05;
+ static final int HPROF_ALLOC_SITES = 0x06;
+ static final int HPROF_HEAP_SUMMARY = 0x07;
+
+ static final int HPROF_START_THREAD = 0x0a;
+ static final int HPROF_END_THREAD = 0x0b;
+
+ static final int HPROF_HEAP_DUMP = 0x0c;
+
+ static final int HPROF_CPU_SAMPLES = 0x0d;
+ static final int HPROF_CONTROL_SETTINGS = 0x0e;
+ static final int HPROF_LOCKSTATS_WAIT_TIME = 0x10;
+ static final int HPROF_LOCKSTATS_HOLD_TIME = 0x11;
+
+ static final int HPROF_GC_ROOT_UNKNOWN = 0xff;
+ static final int HPROF_GC_ROOT_JNI_GLOBAL = 0x01;
+ static final int HPROF_GC_ROOT_JNI_LOCAL = 0x02;
+ static final int HPROF_GC_ROOT_JAVA_FRAME = 0x03;
+ static final int HPROF_GC_ROOT_NATIVE_STACK = 0x04;
+ static final int HPROF_GC_ROOT_STICKY_CLASS = 0x05;
+ static final int HPROF_GC_ROOT_THREAD_BLOCK = 0x06;
+ static final int HPROF_GC_ROOT_MONITOR_USED = 0x07;
+ static final int HPROF_GC_ROOT_THREAD_OBJ = 0x08;
+
+ static final int HPROF_GC_CLASS_DUMP = 0x20;
+ static final int HPROF_GC_INSTANCE_DUMP = 0x21;
+ static final int HPROF_GC_OBJ_ARRAY_DUMP = 0x22;
+ static final int HPROF_GC_PRIM_ARRAY_DUMP = 0x23;
+
+ static final int HPROF_HEAP_DUMP_SEGMENT = 0x1c;
+ static final int HPROF_HEAP_DUMP_END = 0x2c;
+
+ private final static int T_CLASS = 2;
+
+ private int version; // The version of .hprof being read
+
+ private int debugLevel;
+ private long currPos; // Current position in the file
+
+ private int dumpsToSkip;
+ private boolean callStack; // If true, read the call stack of objects
+
+ private int identifierSize; // Size, in bytes, of identifiers.
+ private Hashtable<Long, String> names;
+
+ // Hashtable<Integer, ThreadObject>, used to map the thread sequence number
+ // (aka "serial number") to the thread object ID for
+ // HPROF_GC_ROOT_THREAD_OBJ. ThreadObject is a trivial inner class,
+ // at the end of this file.
+ private Hashtable<Integer, ThreadObject> threadObjects;
+
+ // Hashtable<Long, String>, maps class object ID to class name
+ // (with / converted to .)
+ private Hashtable<Long, String> classNameFromObjectID;
+
+ // Hashtable<Integer, Integer>, maps class serial # to class object ID
+ private Hashtable<Integer, String> classNameFromSerialNo;
+
+ // Hashtable<Long, StackFrame> maps stack frame ID to StackFrame.
+ // Null if we're not tracking them.
+ private Hashtable<Long, StackFrame> stackFrames;
+
+ // Hashtable<Integer, StackTrace> maps stack frame ID to StackTrace
+ // Null if we're not tracking them.
+ private Hashtable<Integer, StackTrace> stackTraces;
+
+ private Snapshot snapshot;
+
+ public HprofReader(String fileName, PositionDataInputStream in,
+ int dumpNumber, boolean callStack, int debugLevel)
+ throws IOException {
+ super(in);
+ RandomAccessFile file = new RandomAccessFile(fileName, "r");
+ this.snapshot = new Snapshot(MappedReadBuffer.create(file));
+ this.dumpsToSkip = dumpNumber - 1;
+ this.callStack = callStack;
+ this.debugLevel = debugLevel;
+ names = new Hashtable<Long, String>();
+ threadObjects = new Hashtable<Integer, ThreadObject>(43);
+ classNameFromObjectID = new Hashtable<Long, String>();
+ if (callStack) {
+ stackFrames = new Hashtable<Long, StackFrame>(43);
+ stackTraces = new Hashtable<Integer, StackTrace>(43);
+ classNameFromSerialNo = new Hashtable<Integer, String>();
+ }
+ }
+
+ public Snapshot read() throws IOException {
+ currPos = 4; // 4 because of the magic number
+ version = readVersionHeader();
+ identifierSize = in.readInt();
+ snapshot.setIdentifierSize(identifierSize);
+ if (version >= VERSION_JDK12BETA4) {
+ snapshot.setNewStyleArrayClass(true);
+ } else {
+ snapshot.setNewStyleArrayClass(false);
+ }
+
+ currPos += 4;
+ if (identifierSize != 4 && identifierSize != 8) {
+ throw new IOException("I'm sorry, but I can't deal with an identifier size of " + identifierSize + ". I can only deal with 4 or 8.");
+ }
+ System.out.println("Dump file created " + (new Date(in.readLong())));
+ currPos += 8;
+
+ for (;;) {
+ int type;
+ try {
+ type = in.readUnsignedByte();
+ } catch (EOFException ignored) {
+ break;
+ }
+ in.readInt(); // Timestamp of this record
+ // Length of record: readInt() will return negative value for record
+ // length >2GB. so store 32bit value in long to keep it unsigned.
+ long length = in.readInt() & 0xffffffffL;
+ if (debugLevel > 0) {
+ System.out.println("Read record type " + type
+ + ", length " + length
+ + " at position " + toHex(currPos));
+ }
+ if (length < 0) {
+ throw new IOException("Bad record length of " + length
+ + " at byte " + toHex(currPos+5)
+ + " of file.");
+ }
+ currPos += 9 + length;
+ switch (type) {
+ case HPROF_UTF8: {
+ long id = readID();
+ byte[] chars = new byte[(int)length - identifierSize];
+ in.readFully(chars);
+ names.put(id, new String(chars));
+ break;
+ }
+ case HPROF_LOAD_CLASS: {
+ int serialNo = in.readInt(); // Not used
+ long classID = readID();
+ int stackTraceSerialNo = in.readInt();
+ long classNameID = readID();
+ Long classIdI = classID;
+ String nm = getNameFromID(classNameID).replace('/', '.');
+ classNameFromObjectID.put(classIdI, nm);
+ if (classNameFromSerialNo != null) {
+ classNameFromSerialNo.put(serialNo, nm);
+ }
+ break;
+ }
+
+ case HPROF_HEAP_DUMP: {
+ if (dumpsToSkip <= 0) {
+ try {
+ readHeapDump(length, currPos);
+ } catch (EOFException exp) {
+ handleEOF(exp, snapshot);
+ }
+ if (debugLevel > 0) {
+ System.out.println(" Finished processing instances in heap dump.");
+ }
+ return snapshot;
+ } else {
+ dumpsToSkip--;
+ skipBytes(length);
+ }
+ break;
+ }
+
+ case HPROF_HEAP_DUMP_END: {
+ if (version >= VERSION_JDK6) {
+ if (dumpsToSkip <= 0) {
+ skipBytes(length); // should be no-op
+ return snapshot;
+ } else {
+ // skip this dump (of the end record for a sequence of dump segments)
+ dumpsToSkip--;
+ }
+ } else {
+ // HPROF_HEAP_DUMP_END only recognized in >= 1.0.2
+ warn("Ignoring unrecognized record type " + type);
+ }
+ skipBytes(length); // should be no-op
+ break;
+ }
+
+ case HPROF_HEAP_DUMP_SEGMENT: {
+ if (version >= VERSION_JDK6) {
+ if (dumpsToSkip <= 0) {
+ try {
+ // read the dump segment
+ readHeapDump(length, currPos);
+ } catch (EOFException exp) {
+ handleEOF(exp, snapshot);
+ }
+ } else {
+ // all segments comprising the heap dump will be skipped
+ skipBytes(length);
+ }
+ } else {
+ // HPROF_HEAP_DUMP_SEGMENT only recognized in >= 1.0.2
+ warn("Ignoring unrecognized record type " + type);
+ skipBytes(length);
+ }
+ break;
+ }
+
+ case HPROF_FRAME: {
+ if (stackFrames == null) {
+ skipBytes(length);
+ } else {
+ long id = readID();
+ String methodName = getNameFromID(readID());
+ String methodSig = getNameFromID(readID());
+ String sourceFile = getNameFromID(readID());
+ int classSer = in.readInt();
+ String className = classNameFromSerialNo.get(classSer);
+ int lineNumber = in.readInt();
+ if (lineNumber < StackFrame.LINE_NUMBER_NATIVE) {
+ warn("Weird stack frame line number: " + lineNumber);
+ lineNumber = StackFrame.LINE_NUMBER_UNKNOWN;
+ }
+ stackFrames.put(id,
+ new StackFrame(methodName, methodSig,
+ className, sourceFile,
+ lineNumber));
+ }
+ break;
+ }
+ case HPROF_TRACE: {
+ if (stackTraces == null) {
+ skipBytes(length);
+ } else {
+ int serialNo = in.readInt();
+ int threadSeq = in.readInt(); // Not used
+ StackFrame[] frames = new StackFrame[in.readInt()];
+ for (int i = 0; i < frames.length; i++) {
+ long fid = readID();
+ frames[i] = stackFrames.get(fid);
+ if (frames[i] == null) {
+ throw new IOException("Stack frame " + toHex(fid) + " not found");
+ }
+ }
+ stackTraces.put(serialNo,
+ new StackTrace(frames));
+ }
+ break;
+ }
+ case HPROF_UNLOAD_CLASS:
+ case HPROF_ALLOC_SITES:
+ case HPROF_START_THREAD:
+ case HPROF_END_THREAD:
+ case HPROF_HEAP_SUMMARY:
+ case HPROF_CPU_SAMPLES:
+ case HPROF_CONTROL_SETTINGS:
+ case HPROF_LOCKSTATS_WAIT_TIME:
+ case HPROF_LOCKSTATS_HOLD_TIME:
+ {
+ // Ignore these record types
+ skipBytes(length);
+ break;
+ }
+ default: {
+ skipBytes(length);
+ warn("Ignoring unrecognized record type " + type);
+ }
+ }
+ }
+
+ return snapshot;
+ }
+
+ private void skipBytes(long length) throws IOException {
+ while (length > 0) {
+ long skipped = in.skip(length);
+ if (skipped == 0) {
+ // EOF or other problem, throw exception
+ throw new EOFException("Couldn't skip enough bytes");
+ }
+ length -= skipped;
+ }
+ }
+
+ private int readVersionHeader() throws IOException {
+ int candidatesLeft = VERSIONS.length;
+ boolean[] matched = new boolean[VERSIONS.length];
+ for (int i = 0; i < candidatesLeft; i++) {
+ matched[i] = true;
+ }
+
+ int pos = 0;
+ while (candidatesLeft > 0) {
+ char c = (char) in.readByte();
+ currPos++;
+ for (int i = 0; i < VERSIONS.length; i++) {
+ if (matched[i]) {
+ if (c != VERSIONS[i].charAt(pos)) { // Not matched
+ matched[i] = false;
+ --candidatesLeft;
+ } else if (pos == VERSIONS[i].length() - 1) { // Full match
+ return i;
+ }
+ }
+ }
+ ++pos;
+ }
+ throw new IOException("Version string not recognized at byte " + (pos+3));
+ }
+
+ private void readHeapDump(long bytesLeft, long posAtEnd) throws IOException {
+ while (bytesLeft > 0) {
+ int type = in.readUnsignedByte();
+ if (debugLevel > 0) {
+ System.out.println(" Read heap sub-record type " + type
+ + " at position "
+ + toHex(posAtEnd - bytesLeft));
+ }
+ bytesLeft--;
+ switch(type) {
+ case HPROF_GC_ROOT_UNKNOWN: {
+ long id = readID();
+ bytesLeft -= identifierSize;
+ snapshot.addRoot(new Root(id, 0, Root.UNKNOWN, ""));
+ break;
+ }
+ case HPROF_GC_ROOT_THREAD_OBJ: {
+ long id = readID();
+ int threadSeq = in.readInt();
+ int stackSeq = in.readInt();
+ bytesLeft -= identifierSize + 8;
+ threadObjects.put(threadSeq,
+ new ThreadObject(id, stackSeq));
+ break;
+ }
+ case HPROF_GC_ROOT_JNI_GLOBAL: {
+ long id = readID();
+ long globalRefId = readID(); // Ignored, for now
+ bytesLeft -= 2*identifierSize;
+ snapshot.addRoot(new Root(id, 0, Root.NATIVE_STATIC, ""));
+ break;
+ }
+ case HPROF_GC_ROOT_JNI_LOCAL: {
+ long id = readID();
+ int threadSeq = in.readInt();
+ int depth = in.readInt();
+ bytesLeft -= identifierSize + 8;
+ ThreadObject to = getThreadObjectFromSequence(threadSeq);
+ StackTrace st = getStackTraceFromSerial(to.stackSeq);
+ if (st != null) {
+ st = st.traceForDepth(depth+1);
+ }
+ snapshot.addRoot(new Root(id, to.threadId,
+ Root.NATIVE_LOCAL, "", st));
+ break;
+ }
+ case HPROF_GC_ROOT_JAVA_FRAME: {
+ long id = readID();
+ int threadSeq = in.readInt();
+ int depth = in.readInt();
+ bytesLeft -= identifierSize + 8;
+ ThreadObject to = getThreadObjectFromSequence(threadSeq);
+ StackTrace st = getStackTraceFromSerial(to.stackSeq);
+ if (st != null) {
+ st = st.traceForDepth(depth+1);
+ }
+ snapshot.addRoot(new Root(id, to.threadId,
+ Root.JAVA_LOCAL, "", st));
+ break;
+ }
+ case HPROF_GC_ROOT_NATIVE_STACK: {
+ long id = readID();
+ int threadSeq = in.readInt();
+ bytesLeft -= identifierSize + 4;
+ ThreadObject to = getThreadObjectFromSequence(threadSeq);
+ StackTrace st = getStackTraceFromSerial(to.stackSeq);
+ snapshot.addRoot(new Root(id, to.threadId,
+ Root.NATIVE_STACK, "", st));
+ break;
+ }
+ case HPROF_GC_ROOT_STICKY_CLASS: {
+ long id = readID();
+ bytesLeft -= identifierSize;
+ snapshot.addRoot(new Root(id, 0, Root.SYSTEM_CLASS, ""));
+ break;
+ }
+ case HPROF_GC_ROOT_THREAD_BLOCK: {
+ long id = readID();
+ int threadSeq = in.readInt();
+ bytesLeft -= identifierSize + 4;
+ ThreadObject to = getThreadObjectFromSequence(threadSeq);
+ StackTrace st = getStackTraceFromSerial(to.stackSeq);
+ snapshot.addRoot(new Root(id, to.threadId,
+ Root.THREAD_BLOCK, "", st));
+ break;
+ }
+ case HPROF_GC_ROOT_MONITOR_USED: {
+ long id = readID();
+ bytesLeft -= identifierSize;
+ snapshot.addRoot(new Root(id, 0, Root.BUSY_MONITOR, ""));
+ break;
+ }
+ case HPROF_GC_CLASS_DUMP: {
+ int bytesRead = readClass();
+ bytesLeft -= bytesRead;
+ break;
+ }
+ case HPROF_GC_INSTANCE_DUMP: {
+ int bytesRead = readInstance();
+ bytesLeft -= bytesRead;
+ break;
+ }
+ case HPROF_GC_OBJ_ARRAY_DUMP: {
+ long bytesRead = readArray(false);
+ bytesLeft -= bytesRead;
+ break;
+ }
+ case HPROF_GC_PRIM_ARRAY_DUMP: {
+ long bytesRead = readArray(true);
+ bytesLeft -= bytesRead;
+ break;
+ }
+ default: {
+ throw new IOException("Unrecognized heap dump sub-record type: " + type);
+ }
+ }
+ }
+ if (bytesLeft != 0) {
+ warn("Error reading heap dump or heap dump segment: Byte count is " + bytesLeft + " instead of 0");
+ skipBytes(bytesLeft);
+ }
+ if (debugLevel > 0) {
+ System.out.println(" Finished heap sub-records.");
+ }
+ }
+
+ private long readID() throws IOException {
+ return (identifierSize == 4)?
+ (Snapshot.SMALL_ID_MASK & (long)in.readInt()) : in.readLong();
+ }
+
+ //
+ // Read a java value. If result is non-null, it's expected to be an
+ // array of one element. We use it to fake multiple return values.
+ // @returns the number of bytes read
+ //
+ private int readValue(JavaThing[] resultArr) throws IOException {
+ byte type = in.readByte();
+ return 1 + readValueForType(type, resultArr);
+ }
+
+ private int readValueForType(byte type, JavaThing[] resultArr)
+ throws IOException {
+ if (version >= VERSION_JDK12BETA4) {
+ type = signatureFromTypeId(type);
+ }
+ return readValueForTypeSignature(type, resultArr);
+ }
+
+ private int readValueForTypeSignature(byte type, JavaThing[] resultArr)
+ throws IOException {
+ switch (type) {
+ case '[':
+ case 'L': {
+ long id = readID();
+ if (resultArr != null) {
+ resultArr[0] = new JavaObjectRef(id);
+ }
+ return identifierSize;
+ }
+ case 'Z': {
+ int b = in.readByte();
+ if (b != 0 && b != 1) {
+ warn("Illegal boolean value read");
+ }
+ if (resultArr != null) {
+ resultArr[0] = new JavaBoolean(b != 0);
+ }
+ return 1;
+ }
+ case 'B': {
+ byte b = in.readByte();
+ if (resultArr != null) {
+ resultArr[0] = new JavaByte(b);
+ }
+ return 1;
+ }
+ case 'S': {
+ short s = in.readShort();
+ if (resultArr != null) {
+ resultArr[0] = new JavaShort(s);
+ }
+ return 2;
+ }
+ case 'C': {
+ char ch = in.readChar();
+ if (resultArr != null) {
+ resultArr[0] = new JavaChar(ch);
+ }
+ return 2;
+ }
+ case 'I': {
+ int val = in.readInt();
+ if (resultArr != null) {
+ resultArr[0] = new JavaInt(val);
+ }
+ return 4;
+ }
+ case 'J': {
+ long val = in.readLong();
+ if (resultArr != null) {
+ resultArr[0] = new JavaLong(val);
+ }
+ return 8;
+ }
+ case 'F': {
+ float val = in.readFloat();
+ if (resultArr != null) {
+ resultArr[0] = new JavaFloat(val);
+ }
+ return 4;
+ }
+ case 'D': {
+ double val = in.readDouble();
+ if (resultArr != null) {
+ resultArr[0] = new JavaDouble(val);
+ }
+ return 8;
+ }
+ default: {
+ throw new IOException("Bad value signature: " + type);
+ }
+ }
+ }
+
+ private ThreadObject getThreadObjectFromSequence(int threadSeq)
+ throws IOException {
+ ThreadObject to = threadObjects.get(threadSeq);
+ if (to == null) {
+ throw new IOException("Thread " + threadSeq +
+ " not found for JNI local ref");
+ }
+ return to;
+ }
+
+ private String getNameFromID(long id) throws IOException {
+ return getNameFromID(Long.valueOf(id));
+ }
+
+ private String getNameFromID(Long id) throws IOException {
+ if (id.longValue() == 0L) {
+ return "";
+ }
+ String result = names.get(id);
+ if (result == null) {
+ warn("Name not found at " + toHex(id.longValue()));
+ return "unresolved name " + toHex(id.longValue());
+ }
+ return result;
+ }
+
+ private StackTrace getStackTraceFromSerial(int ser) throws IOException {
+ if (stackTraces == null) {
+ return null;
+ }
+ StackTrace result = stackTraces.get(ser);
+ if (result == null) {
+ warn("Stack trace not found for serial # " + ser);
+ }
+ return result;
+ }
+
+ //
+ // Handle a HPROF_GC_CLASS_DUMP
+ // Return number of bytes read
+ //
+ private int readClass() throws IOException {
+ long id = readID();
+ StackTrace stackTrace = getStackTraceFromSerial(in.readInt());
+ long superId = readID();
+ long classLoaderId = readID();
+ long signersId = readID();
+ long protDomainId = readID();
+ long reserved1 = readID();
+ long reserved2 = readID();
+ int instanceSize = in.readInt();
+ int bytesRead = 7 * identifierSize + 8;
+
+ int numConstPoolEntries = in.readUnsignedShort();
+ bytesRead += 2;
+ for (int i = 0; i < numConstPoolEntries; i++) {
+ int index = in.readUnsignedShort(); // unused
+ bytesRead += 2;
+ bytesRead += readValue(null); // We ignore the values
+ }
+
+ int numStatics = in.readUnsignedShort();
+ bytesRead += 2;
+ JavaThing[] valueBin = new JavaThing[1];
+ JavaStatic[] statics = new JavaStatic[numStatics];
+ for (int i = 0; i < numStatics; i++) {
+ long nameId = readID();
+ bytesRead += identifierSize;
+ byte type = in.readByte();
+ bytesRead++;
+ bytesRead += readValueForType(type, valueBin);
+ String fieldName = getNameFromID(nameId);
+ if (version >= VERSION_JDK12BETA4) {
+ type = signatureFromTypeId(type);
+ }
+ String signature = "" + ((char) type);
+ JavaField f = new JavaField(fieldName, signature);
+ statics[i] = new JavaStatic(f, valueBin[0]);
+ }
+
+ int numFields = in.readUnsignedShort();
+ bytesRead += 2;
+ JavaField[] fields = new JavaField[numFields];
+ for (int i = 0; i < numFields; i++) {
+ long nameId = readID();
+ bytesRead += identifierSize;
+ byte type = in.readByte();
+ bytesRead++;
+ String fieldName = getNameFromID(nameId);
+ if (version >= VERSION_JDK12BETA4) {
+ type = signatureFromTypeId(type);
+ }
+ String signature = "" + ((char) type);
+ fields[i] = new JavaField(fieldName, signature);
+ }
+ String name = classNameFromObjectID.get(id);
+ if (name == null) {
+ warn("Class name not found for " + toHex(id));
+ name = "unknown-name@" + toHex(id);
+ }
+ JavaClass c = new JavaClass(id, name, superId, classLoaderId, signersId,
+ protDomainId, fields, statics,
+ instanceSize);
+ snapshot.addClass(id, c);
+ snapshot.setSiteTrace(c, stackTrace);
+
+ return bytesRead;
+ }
+
+ private String toHex(long addr) {
+ return jdk.test.lib.hprof.util.Misc.toHex(addr);
+ }
+
+ //
+ // Handle a HPROF_GC_INSTANCE_DUMP
+ // Return number of bytes read
+ //
+ private int readInstance() throws IOException {
+ long start = in.position();
+ long id = readID();
+ StackTrace stackTrace = getStackTraceFromSerial(in.readInt());
+ long classID = readID();
+ int bytesFollowing = in.readInt();
+ int bytesRead = (2 * identifierSize) + 8 + bytesFollowing;
+ JavaObject jobj = new JavaObject(classID, start);
+ skipBytes(bytesFollowing);
+ snapshot.addHeapObject(id, jobj);
+ snapshot.setSiteTrace(jobj, stackTrace);
+ return bytesRead;
+ }
+
+ //
+ // Handle a HPROF_GC_OBJ_ARRAY_DUMP or HPROF_GC_PRIM_ARRAY_DUMP
+ // Return number of bytes read
+ //
+ private long readArray(boolean isPrimitive) throws IOException {
+ long start = in.position();
+ long id = readID();
+ StackTrace stackTrace = getStackTraceFromSerial(in.readInt());
+ int num = in.readInt();
+ long bytesRead = identifierSize + 8;
+ long elementClassID;
+ if (isPrimitive) {
+ elementClassID = in.readByte();
+ bytesRead++;
+ } else {
+ elementClassID = readID();
+ bytesRead += identifierSize;
+ }
+
+ // Check for primitive arrays:
+ byte primitiveSignature = 0x00;
+ int elSize = 0;
+ if (isPrimitive || version < VERSION_JDK12BETA4) {
+ switch ((int)elementClassID) {
+ case T_BOOLEAN: {
+ primitiveSignature = (byte) 'Z';
+ elSize = 1;
+ break;
+ }
+ case T_CHAR: {
+ primitiveSignature = (byte) 'C';
+ elSize = 2;
+ break;
+ }
+ case T_FLOAT: {
+ primitiveSignature = (byte) 'F';
+ elSize = 4;
+ break;
+ }
+ case T_DOUBLE: {
+ primitiveSignature = (byte) 'D';
+ elSize = 8;
+ break;
+ }
+ case T_BYTE: {
+ primitiveSignature = (byte) 'B';
+ elSize = 1;
+ break;
+ }
+ case T_SHORT: {
+ primitiveSignature = (byte) 'S';
+ elSize = 2;
+ break;
+ }
+ case T_INT: {
+ primitiveSignature = (byte) 'I';
+ elSize = 4;
+ break;
+ }
+ case T_LONG: {
+ primitiveSignature = (byte) 'J';
+ elSize = 8;
+ break;
+ }
+ }
+ if (version >= VERSION_JDK12BETA4 && primitiveSignature == 0x00) {
+ throw new IOException("Unrecognized typecode: "
+ + elementClassID);
+ }
+ }
+ if (primitiveSignature != 0x00) {
+ long size = elSize * (long)num;
+ bytesRead += size;
+ JavaValueArray va = new JavaValueArray(primitiveSignature, start);
+ skipBytes(size);
+ snapshot.addHeapObject(id, va);
+ snapshot.setSiteTrace(va, stackTrace);
+ } else {
+ long sz = (long)num * identifierSize;
+ bytesRead += sz;
+ JavaObjectArray arr = new JavaObjectArray(elementClassID, start);
+ skipBytes(sz);
+ snapshot.addHeapObject(id, arr);
+ snapshot.setSiteTrace(arr, stackTrace);
+ }
+ return bytesRead;
+ }
+
+ private byte signatureFromTypeId(byte typeId) throws IOException {
+ switch (typeId) {
+ case T_CLASS: {
+ return (byte) 'L';
+ }
+ case T_BOOLEAN: {
+ return (byte) 'Z';
+ }
+ case T_CHAR: {
+ return (byte) 'C';
+ }
+ case T_FLOAT: {
+ return (byte) 'F';
+ }
+ case T_DOUBLE: {
+ return (byte) 'D';
+ }
+ case T_BYTE: {
+ return (byte) 'B';
+ }
+ case T_SHORT: {
+ return (byte) 'S';
+ }
+ case T_INT: {
+ return (byte) 'I';
+ }
+ case T_LONG: {
+ return (byte) 'J';
+ }
+ default: {
+ throw new IOException("Invalid type id of " + typeId);
+ }
+ }
+ }
+
+ private void handleEOF(EOFException exp, Snapshot snapshot) {
+ if (debugLevel > 0) {
+ exp.printStackTrace();
+ }
+ warn("Unexpected EOF. Will miss information...");
+ // we have EOF, we have to tolerate missing references
+ snapshot.setUnresolvedObjectsOK(true);
+ }
+
+ private void warn(String msg) {
+ System.out.println("WARNING: " + msg);
+ }
+
+ //
+ // A trivial data-holder class for HPROF_GC_ROOT_THREAD_OBJ.
+ //
+ private class ThreadObject {
+
+ long threadId;
+ int stackSeq;
+
+ ThreadObject(long threadId, int stackSeq) {
+ this.threadId = threadId;
+ this.stackSeq = stackSeq;
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/parser/MappedReadBuffer.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.parser;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+
+/**
+ * Implementation of ReadBuffer using mapped file buffer
+ *
+ * @author A. Sundararajan
+ */
+class MappedReadBuffer implements ReadBuffer {
+ private MappedByteBuffer buf;
+ private RandomAccessFile file;
+
+ MappedReadBuffer(RandomAccessFile file, MappedByteBuffer buf) {
+ this.file = file;
+ this.buf = buf;
+ }
+
+ /**
+ * Factory method to create correct ReadBuffer for a given file.
+ *
+ * The initial purpose of this method was to choose how to read hprof file for parsing
+ * depending on the size of the file and the system property 'jhat.disableFileMap':
+ * "If file size is more than 2 GB and when file mapping is configured (default),
+ * use mapped file reader".
+ *
+ * However, it has been discovered a problem with this approach.
+ * Creating java.nio.MappedByteBuffer from inside the test leads to hprof file
+ * is locked on Windows until test process dies since there is no good way to
+ * release this resource.
+ *
+ * java.nio.MappedByteBuffer will be used only if 'jhat.enableFileMap' is set to true.
+ * Per default 'jhat.enableFileMap' is not set.
+ */
+ static ReadBuffer create(RandomAccessFile file) throws IOException {
+ if (canUseFileMap()) {
+ MappedByteBuffer buf;
+ try {
+ FileChannel ch = file.getChannel();
+ long size = ch.size();
+ buf = ch.map(FileChannel.MapMode.READ_ONLY, 0, size);
+ ch.close();
+ return new MappedReadBuffer(file, buf);
+ } catch (IOException exp) {
+ exp.printStackTrace();
+ System.err.println("File mapping failed, will use direct read");
+ // fall through
+ }
+ } // else fall through
+ return new FileReadBuffer(file);
+ }
+
+ /**
+ * Set system property 'jhat.enableFileMap' to 'true' to enable file mapping.
+ */
+ private static boolean canUseFileMap() {
+ String prop = System.getProperty("jhat.enableFileMap");
+ return prop != null && prop.equals("true");
+ }
+
+ private void seek(long pos) throws IOException {
+ assert pos <= Integer.MAX_VALUE : "position overflow";
+ buf.position((int)pos);
+ }
+
+ public synchronized void get(long pos, byte[] res) throws IOException {
+ seek(pos);
+ buf.get(res);
+ }
+
+ public synchronized char getChar(long pos) throws IOException {
+ seek(pos);
+ return buf.getChar();
+ }
+
+ public synchronized byte getByte(long pos) throws IOException {
+ seek(pos);
+ return buf.get();
+ }
+
+ public synchronized short getShort(long pos) throws IOException {
+ seek(pos);
+ return buf.getShort();
+ }
+
+ public synchronized int getInt(long pos) throws IOException {
+ seek(pos);
+ return buf.getInt();
+ }
+
+ public synchronized long getLong(long pos) throws IOException {
+ seek(pos);
+ return buf.getLong();
+ }
+
+ @Override
+ public void close() throws Exception {
+ file.close();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/parser/PositionDataInputStream.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.parser;
+
+import java.io.DataInputStream;
+import java.io.InputStream;
+
+/**
+ * A DataInputStream that keeps track of total bytes read
+ * (in effect 'position' in stream) so far.
+ *
+ */
+public class PositionDataInputStream extends DataInputStream {
+ public PositionDataInputStream(InputStream in) {
+ super(in instanceof PositionInputStream?
+ in : new PositionInputStream(in));
+ }
+
+ public boolean markSupported() {
+ return false;
+ }
+
+ public void mark(int readLimit) {
+ throw new UnsupportedOperationException("mark");
+ }
+
+ public void reset() {
+ throw new UnsupportedOperationException("reset");
+ }
+
+ public long position() {
+ return ((PositionInputStream)in).position();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/parser/PositionInputStream.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.parser;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * InputStream that keeps track of total bytes read (in effect
+ * 'position' in stream) from the input stream.
+ *
+ */
+public class PositionInputStream extends FilterInputStream {
+ private long position = 0L;
+
+ public PositionInputStream(InputStream in) {
+ super(in);
+ }
+
+ public int read() throws IOException {
+ int res = super.read();
+ if (res != -1) position++;
+ return res;
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException {
+ int res = super.read(b, off, len);
+ if (res != -1) position += res;
+ return res;
+ }
+
+ public long skip(long n) throws IOException {
+ long res = super.skip(n);
+ position += res;
+ return res;
+ }
+
+ public boolean markSupported() {
+ return false;
+ }
+
+ public void mark(int readLimit) {
+ throw new UnsupportedOperationException("mark");
+ }
+
+ public void reset() {
+ throw new UnsupportedOperationException("reset");
+ }
+
+ public long position() {
+ return position;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/parser/ReadBuffer.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.parser;
+
+import java.io.IOException;
+
+/**
+ * Positionable read only buffer
+ *
+ * @author A. Sundararajan
+ */
+public interface ReadBuffer extends AutoCloseable {
+ // read methods - only byte array and int primitive types.
+ // read position has to be specified always.
+ public void get(long pos, byte[] buf) throws IOException;
+ public char getChar(long pos) throws IOException;
+ public byte getByte(long pos) throws IOException;
+ public short getShort(long pos) throws IOException;
+ public int getInt(long pos) throws IOException;
+ public long getLong(long pos) throws IOException;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/parser/Reader.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.parser;
+
+import java.io.*;
+import jdk.test.lib.hprof.model.*;
+
+/**
+ * Abstract base class for reading object dump files. A reader need not be
+ * thread-safe.
+ *
+ * @author Bill Foote
+ */
+
+
+public abstract class Reader {
+ protected PositionDataInputStream in;
+
+ protected Reader(PositionDataInputStream in) {
+ this.in = in;
+ }
+
+ /**
+ * Read a snapshot from a data input stream. It is assumed that the magic
+ * number has already been read.
+ */
+ abstract public Snapshot read() throws IOException;
+
+ /**
+ * Read a snapshot from a file.
+ *
+ * @param heapFile The name of a file containing a heap dump
+ * @param callStack If true, read the call stack of allocaation sites
+ */
+ public static Snapshot readFile(String heapFile, boolean callStack,
+ int debugLevel)
+ throws IOException {
+ int dumpNumber = 1;
+ int pos = heapFile.lastIndexOf('#');
+ if (pos > -1) {
+ String num = heapFile.substring(pos+1, heapFile.length());
+ try {
+ dumpNumber = Integer.parseInt(num, 10);
+ } catch (java.lang.NumberFormatException ex) {
+ String msg = "In file name \"" + heapFile
+ + "\", a dump number was "
+ + "expected after the :, but \""
+ + num + "\" was found instead.";
+ System.err.println(msg);
+ throw new IOException(msg);
+ }
+ heapFile = heapFile.substring(0, pos);
+ }
+ try (PositionDataInputStream in = new PositionDataInputStream(
+ new BufferedInputStream(new FileInputStream(heapFile)))) {
+ int i = in.readInt();
+ if (i == HprofReader.MAGIC_NUMBER) {
+ Reader r
+ = new HprofReader(heapFile, in, dumpNumber,
+ callStack, debugLevel);
+ return r.read();
+ } else {
+ throw new IOException("Unrecognized magic number: " + i);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/util/ArraySorter.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.util;
+import java.util.*;
+
+/**
+ * A singleton utility class that sorts an array of objects.
+ * <p>
+ * Use:
+ * <pre>
+ *
+ * Stuff[] arr = ...;
+ * ArraySorter.sort(arr, new Comparer() {
+ * public int compare(Object lhs, Object rhs) {
+ * return ((String) lhs).compareTo((String) rhs);
+ * }
+ * });
+ * </pre>
+ *
+ * @author Bill Foote
+ */
+
+public class ArraySorter {
+
+ /**
+ * Sort the given array, using c for comparison
+ **/
+ static public void sort(Object[] arr, Comparer c) {
+ quickSort(arr, c, 0, arr.length-1);
+ }
+
+
+ /**
+ * Sort an array of strings, using String.compareTo()
+ **/
+ static public void sortArrayOfStrings(Object[] arr) {
+ sort(arr, new Comparer() {
+ public int compare(Object lhs, Object rhs) {
+ return ((String) lhs).compareTo((String) rhs);
+ }
+ });
+ }
+
+
+ static private void swap(Object[] arr, int a, int b) {
+ Object tmp = arr[a];
+ arr[a] = arr[b];
+ arr[b] = tmp;
+ }
+
+ //
+ // Sorts arr between from and to, inclusive. This is a quick, off-the-top-
+ // of-my-head quicksort: I haven't put any thought into optimizing it.
+ // I _did_ put thought into making sure it's safe (it will always
+ // terminate). Worst-case it's O(n^2), but it will usually run in
+ // in O(n log n). It's well-behaved if the list is already sorted,
+ // or nearly so.
+ //
+ static private void quickSort(Object[] arr, Comparer c, int from, int to) {
+ if (to <= from)
+ return;
+ int mid = (from + to) / 2;
+ if (mid != from)
+ swap(arr, mid, from);
+ Object pivot = arr[from]; // Simple-minded, but reasonable
+ int highestBelowPivot = from - 1;
+ int low = from+1;
+ int high = to;
+ // We now move low and high toward each other, maintaining the
+ // invariants:
+ // arr[i] <= pivot for all i < low
+ // arr[i] > pivot for all i > high
+ // As long as these invariants hold, and every iteration makes
+ // progress, we are safe.
+ while (low <= high) {
+ int cmp = c.compare(arr[low], pivot);
+ if (cmp <= 0) { // arr[low] <= pivot
+ if (cmp < 0) {
+ highestBelowPivot = low;
+ }
+ low++;
+ } else {
+ int c2;
+ for (;;) {
+ // arr[high] > pivot:
+ c2 = c.compare(arr[high], pivot);
+ if (c2 > 0) {
+ high--;
+ if (low > high) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ // At this point, low is never == high, BTW
+ if (low <= high) {
+ swap(arr, low, high);
+ if (c2 < 0) {
+ highestBelowPivot = low;
+ }
+ low++;
+ high--;
+ }
+ }
+ }
+ // At this point, low == high+1
+ // Now we just need to sort from from..highestBelowPivot
+ // and from high+1..to
+ if (highestBelowPivot > from) {
+ // pivot == pivot, so ensure algorithm terminates
+ swap(arr, from, highestBelowPivot);
+ quickSort(arr, c, from, highestBelowPivot-1);
+ }
+ quickSort(arr, c, high+1, to);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/util/Comparer.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.util;
+
+/**
+ * Base class for comparison of two objects.
+ * @see VectorSorter
+ *
+ * @author Bill Foote
+ */
+
+abstract public class Comparer {
+
+ /**
+ * @return a number <, == or > 0 depending on lhs compared to rhs
+ * @see java.lang.String.compareTo
+ **/
+ abstract public int compare(Object lhs, Object rhs);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/util/CompositeEnumeration.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.util;
+
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+import jdk.test.lib.hprof.model.JavaHeapObject;
+
+public class CompositeEnumeration implements Enumeration<JavaHeapObject> {
+ Enumeration<JavaHeapObject> e1;
+ Enumeration<JavaHeapObject> e2;
+
+ public CompositeEnumeration(Enumeration<JavaHeapObject> e1, Enumeration<JavaHeapObject> e2) {
+ this.e1 = e1;
+ this.e2 = e2;
+ }
+
+ public boolean hasMoreElements() {
+ return e1.hasMoreElements() || e2.hasMoreElements();
+ }
+
+ public JavaHeapObject nextElement() {
+ if (e1.hasMoreElements()) {
+ return e1.nextElement();
+ }
+
+ if (e2.hasMoreElements()) {
+ return e2.nextElement();
+ }
+
+ throw new NoSuchElementException();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/util/Misc.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.util;
+import java.util.*;
+
+/**
+ * Miscellaneous functions I couldn't think of a good place to put.
+ *
+ * @author Bill Foote
+ */
+
+
+public class Misc {
+
+ private static char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+ public final static String toHex(int addr) {
+ char[] buf = new char[8];
+ int i = 0;
+ for (int s = 28; s >= 0; s -= 4) {
+ buf[i++] = digits[(addr >> s) & 0xf];
+ }
+ return "0x" + new String(buf);
+ }
+
+ public final static String toHex(long addr) {
+ return "0x" + Long.toHexString(addr);
+ }
+
+ public final static long parseHex(String value) {
+ long result = 0;
+ if (value.length() < 2 || value.charAt(0) != '0' ||
+ value.charAt(1) != 'x') {
+ return -1L;
+ }
+ for(int i = 2; i < value.length(); i++) {
+ result *= 16;
+ char ch = value.charAt(i);
+ if (ch >= '0' && ch <= '9') {
+ result += (ch - '0');
+ } else if (ch >= 'a' && ch <= 'f') {
+ result += (ch - 'a') + 10;
+ } else if (ch >= 'A' && ch <= 'F') {
+ result += (ch - 'A') + 10;
+ } else {
+ throw new NumberFormatException("" + ch
+ + " is not a valid hex digit");
+ }
+ }
+ return result;
+ }
+
+ public static String encodeHtml(String str) {
+ final int len = str.length();
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < len; i++) {
+ char ch = str.charAt(i);
+ if (ch == '<') {
+ sb.append("<");
+ } else if (ch == '>') {
+ sb.append(">");
+ } else if (ch == '"') {
+ sb.append(""");
+ } else if (ch == '\'') {
+ sb.append("'");
+ } else if (ch == '&') {
+ sb.append("&");
+ } else if (ch < ' ') {
+ sb.append("&#").append((int)ch).append(';');
+ } else {
+ int c = (ch & 0xFFFF);
+ if (c > 127) {
+ sb.append("&#").append(c).append(';');
+ } else {
+ sb.append(ch);
+ }
+ }
+ }
+ return sb.toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/hprof/util/VectorSorter.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.util;
+import java.util.*;
+
+/**
+ * A singleton utility class that sorts a vector.
+ * <p>
+ * Use:
+ * <pre>
+ *
+ * Vector v = <a vector of, say, String objects>;
+ * VectorSorter.sort(v, new Comparer() {
+ * public int compare(Object lhs, Object rhs) {
+ * return ((String) lhs).compareTo((String) rhs);
+ * }
+ * });
+ * </pre>
+ *
+ * @author Bill Foote
+ */
+
+
+public class VectorSorter {
+
+ /**
+ * Sort the given vector, using c for comparison
+ **/
+ static public void sort(Vector<Object> v, Comparer c) {
+ quickSort(v, c, 0, v.size()-1);
+ }
+
+
+ /**
+ * Sort a vector of strings, using String.compareTo()
+ **/
+ static public void sortVectorOfStrings(Vector<Object> v) {
+ sort(v, new Comparer() {
+ public int compare(Object lhs, Object rhs) {
+ return ((String) lhs).compareTo((String) rhs);
+ }
+ });
+ }
+
+
+ static private void swap(Vector<Object> v, int a, int b) {
+ Object tmp = v.elementAt(a);
+ v.setElementAt(v.elementAt(b), a);
+ v.setElementAt(tmp, b);
+ }
+
+ //
+ // Sorts v between from and to, inclusive. This is a quick, off-the-top-
+ // of-my-head quicksort: I haven't put any thought into optimizing it.
+ // I _did_ put thought into making sure it's safe (it will always
+ // terminate). Worst-case it's O(n^2), but it will usually run in
+ // in O(n log n). It's well-behaved if the list is already sorted,
+ // or nearly so.
+ //
+ static private void quickSort(Vector<Object> v, Comparer c, int from, int to) {
+ if (to <= from)
+ return;
+ int mid = (from + to) / 2;
+ if (mid != from)
+ swap(v, mid, from);
+ Object pivot = v.elementAt(from);
+ // Simple-minded, but reasonable
+ int highestBelowPivot = from - 1;
+ int low = from+1;
+ int high = to;
+ // We now move low and high toward eachother, maintaining the
+ // invariants:
+ // v[i] <= pivot for all i < low
+ // v[i] > pivot for all i > high
+ // As long as these invariants hold, and every iteration makes
+ // progress, we are safe.
+ while (low <= high) {
+ int cmp = c.compare(v.elementAt(low), pivot);
+ if (cmp <= 0) { // v[low] <= pivot
+ if (cmp < 0) {
+ highestBelowPivot = low;
+ }
+ low++;
+ } else {
+ int c2;
+ for (;;) {
+ c2 = c.compare(v.elementAt(high), pivot);
+ // v[high] > pivot:
+ if (c2 > 0) {
+ high--;
+ if (low > high) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ // At this point, low is never == high
+ if (low <= high) {
+ swap(v, low, high);
+ if (c2 < 0) {
+ highestBelowPivot = low;
+ }
+ low++;
+ high--;
+ }
+ }
+ }
+ // Now we just need to sort from from..highestBelowPivot
+ // and from high+1..to
+ if (highestBelowPivot > from) {
+ // pivot == pivot, so ensure algorithm terminates
+ swap(v, from, highestBelowPivot);
+ quickSort(v, c, from, highestBelowPivot-1);
+ }
+ quickSort(v, c, high+1, to);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/process/ExitCode.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.process;
+
+/**
+ * Exit code values that could be returned by the JVM.
+ */
+public enum ExitCode {
+ OK(0),
+ FAIL(1),
+ CRASH(134);
+
+ public final int value;
+
+ ExitCode(int value) {
+ this.value = value;
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/process/OutputAnalyzer.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.process;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public final class OutputAnalyzer {
+
+ private final String stdout;
+ private final String stderr;
+ private final int exitValue;
+
+ /**
+ * Create an OutputAnalyzer, a utility class for verifying output and exit
+ * value from a Process
+ *
+ * @param process Process to analyze
+ * @throws IOException If an I/O error occurs.
+ */
+ public OutputAnalyzer(Process process) throws IOException {
+ OutputBuffer output = ProcessTools.getOutput(process);
+ exitValue = process.exitValue();
+ this.stdout = output.getStdout();
+ this.stderr = output.getStderr();
+ }
+
+ /**
+ * Create an OutputAnalyzer, a utility class for verifying output
+ *
+ * @param buf String buffer to analyze
+ */
+ public OutputAnalyzer(String buf) {
+ this(buf, buf);
+ }
+
+ /**
+ * Create an OutputAnalyzer, a utility class for verifying output
+ *
+ * @param stdout stdout buffer to analyze
+ * @param stderr stderr buffer to analyze
+ */
+ public OutputAnalyzer(String stdout, String stderr) {
+ this.stdout = stdout;
+ this.stderr = stderr;
+ exitValue = -1;
+ }
+
+ /**
+ * Verify that the stdout contents of output buffer is empty
+ *
+ * @throws RuntimeException
+ * If stdout was not empty
+ */
+ public void stdoutShouldBeEmpty() {
+ if (!getStdout().isEmpty()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("stdout was not empty");
+ }
+ }
+
+ /**
+ * Verify that the stderr contents of output buffer is empty
+ *
+ * @throws RuntimeException
+ * If stderr was not empty
+ */
+ public void stderrShouldBeEmpty() {
+ if (!getStderr().isEmpty()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("stderr was not empty");
+ }
+ }
+
+ /**
+ * Verify that the stdout contents of output buffer is not empty
+ *
+ * @throws RuntimeException
+ * If stdout was empty
+ */
+ public void stdoutShouldNotBeEmpty() {
+ if (getStdout().isEmpty()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("stdout was empty");
+ }
+ }
+
+ /**
+ * Verify that the stderr contents of output buffer is not empty
+ *
+ * @throws RuntimeException
+ * If stderr was empty
+ */
+ public void stderrShouldNotBeEmpty() {
+ if (getStderr().isEmpty()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("stderr was empty");
+ }
+ }
+
+ /**
+ * Verify that the stdout and stderr contents of output buffer contains the string
+ *
+ * @param expectedString String that buffer should contain
+ * @throws RuntimeException If the string was not found
+ */
+ public OutputAnalyzer shouldContain(String expectedString) {
+ if (!stdout.contains(expectedString) && !stderr.contains(expectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stdout contents of output buffer contains the string
+ *
+ * @param expectedString String that buffer should contain
+ * @throws RuntimeException If the string was not found
+ */
+ public OutputAnalyzer stdoutShouldContain(String expectedString) {
+ if (!stdout.contains(expectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + expectedString + "' missing from stdout \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stderr contents of output buffer contains the string
+ *
+ * @param expectedString String that buffer should contain
+ * @throws RuntimeException If the string was not found
+ */
+ public OutputAnalyzer stderrShouldContain(String expectedString) {
+ if (!stderr.contains(expectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + expectedString + "' missing from stderr \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stdout and stderr contents of output buffer does not contain the string
+ *
+ * @param expectedString String that the buffer should not contain
+ * @throws RuntimeException If the string was found
+ */
+ public OutputAnalyzer shouldNotContain(String notExpectedString) {
+ if (stdout.contains(notExpectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
+ }
+ if (stderr.contains(notExpectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stdout contents of output buffer does not contain the string
+ *
+ * @param expectedString String that the buffer should not contain
+ * @throws RuntimeException If the string was found
+ */
+ public OutputAnalyzer stdoutShouldNotContain(String notExpectedString) {
+ if (stdout.contains(notExpectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stderr contents of output buffer does not contain the string
+ *
+ * @param expectedString String that the buffer should not contain
+ * @throws RuntimeException If the string was found
+ */
+ public OutputAnalyzer stderrShouldNotContain(String notExpectedString) {
+ if (stderr.contains(notExpectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stdout and stderr contents of output buffer matches
+ * the pattern
+ *
+ * @param pattern
+ * @throws RuntimeException If the pattern was not found
+ */
+ public OutputAnalyzer shouldMatch(String pattern) {
+ Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+ Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+ if (!stdoutMatcher.find() && !stderrMatcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' missing from stdout/stderr \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stdout contents of output buffer matches the
+ * pattern
+ *
+ * @param pattern
+ * @throws RuntimeException If the pattern was not found
+ */
+ public OutputAnalyzer stdoutShouldMatch(String pattern) {
+ Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+ if (!matcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' missing from stdout \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stderr contents of output buffer matches the
+ * pattern
+ *
+ * @param pattern
+ * @throws RuntimeException If the pattern was not found
+ */
+ public OutputAnalyzer stderrShouldMatch(String pattern) {
+ Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+ if (!matcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' missing from stderr \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stdout and stderr contents of output buffer does not
+ * match the pattern
+ *
+ * @param pattern
+ * @throws RuntimeException If the pattern was found
+ */
+ public OutputAnalyzer shouldNotMatch(String pattern) {
+ Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+ if (matcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' found in stdout: '" + matcher.group() + "' \n");
+ }
+ matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+ if (matcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' found in stderr: '" + matcher.group() + "' \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stdout contents of output buffer does not match the
+ * pattern
+ *
+ * @param pattern
+ * @throws RuntimeException If the pattern was found
+ */
+ public OutputAnalyzer stdoutShouldNotMatch(String pattern) {
+ Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+ if (matcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' found in stdout \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stderr contents of output buffer does not match the
+ * pattern
+ *
+ * @param pattern
+ * @throws RuntimeException If the pattern was found
+ */
+ public OutputAnalyzer stderrShouldNotMatch(String pattern) {
+ Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+ if (matcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' found in stderr \n");
+ }
+ return this;
+ }
+
+ /**
+ * Get the captured group of the first string matching the pattern.
+ * stderr is searched before stdout.
+ *
+ * @param pattern The multi-line pattern to match
+ * @param group The group to capture
+ * @return The matched string or null if no match was found
+ */
+ public String firstMatch(String pattern, int group) {
+ Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+ Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+ if (stderrMatcher.find()) {
+ return stderrMatcher.group(group);
+ }
+ if (stdoutMatcher.find()) {
+ return stdoutMatcher.group(group);
+ }
+ return null;
+ }
+
+ /**
+ * Get the first string matching the pattern.
+ * stderr is searched before stdout.
+ *
+ * @param pattern The multi-line pattern to match
+ * @return The matched string or null if no match was found
+ */
+ public String firstMatch(String pattern) {
+ return firstMatch(pattern, 0);
+ }
+
+ /**
+ * Verify the exit value of the process
+ *
+ * @param expectedExitValue Expected exit value from process
+ * @throws RuntimeException If the exit value from the process did not match the expected value
+ */
+ public OutputAnalyzer shouldHaveExitValue(int expectedExitValue) {
+ if (getExitValue() != expectedExitValue) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("Expected to get exit value of ["
+ + expectedExitValue + "]\n");
+ }
+ return this;
+ }
+
+
+ /**
+ * Report summary that will help to diagnose the problem
+ * Currently includes:
+ * - standard input produced by the process under test
+ * - standard output
+ * - exit code
+ * Note: the command line is printed by the ProcessTools
+ */
+ public void reportDiagnosticSummary() {
+ String msg =
+ " stdout: [" + stdout + "];\n" +
+ " stderr: [" + stderr + "]\n" +
+ " exitValue = " + getExitValue() + "\n";
+
+ System.err.println(msg);
+ }
+
+
+ /**
+ * Get the contents of the output buffer (stdout and stderr)
+ *
+ * @return Content of the output buffer
+ */
+ public String getOutput() {
+ return stdout + stderr;
+ }
+
+ /**
+ * Get the contents of the stdout buffer
+ *
+ * @return Content of the stdout buffer
+ */
+ public String getStdout() {
+ return stdout;
+ }
+
+ /**
+ * Get the contents of the stderr buffer
+ *
+ * @return Content of the stderr buffer
+ */
+ public String getStderr() {
+ return stderr;
+ }
+
+ /**
+ * Get the process exit value
+ *
+ * @return Process exit value
+ */
+ public int getExitValue() {
+ return exitValue;
+ }
+
+ /**
+ * Get the contents of the output buffer (stdout and stderr) as list of strings.
+ * Output will be split by newlines.
+ *
+ * @return Contents of the output buffer as list of strings
+ */
+ public List<String> asLines() {
+ return asLines(getOutput());
+ }
+
+ private List<String> asLines(String buffer) {
+ return Arrays.asList(buffer.split("(\\r\\n|\\n|\\r)"));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/process/OutputBuffer.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.process;
+
+public class OutputBuffer {
+ private final String stdout;
+ private final String stderr;
+
+ /**
+ * Create an OutputBuffer, a class for storing and managing stdout and stderr
+ * results separately
+ *
+ * @param stdout stdout result
+ * @param stderr stderr result
+ */
+ public OutputBuffer(String stdout, String stderr) {
+ this.stdout = stdout;
+ this.stderr = stderr;
+ }
+
+ /**
+ * Returns the stdout result
+ *
+ * @return stdout result
+ */
+ public String getStdout() {
+ return stdout;
+ }
+
+ /**
+ * Returns the stderr result
+ *
+ * @return stderr result
+ */
+ public String getStderr() {
+ return stderr;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/process/ProcessTools.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,617 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.process;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.concurrent.CountDownLatch;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.function.Predicate;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.Platform;
+import jdk.test.lib.Utils;
+
+public final class ProcessTools {
+ private static final class LineForwarder extends StreamPumper.LinePump {
+ private final PrintStream ps;
+ private final String prefix;
+ LineForwarder(String prefix, PrintStream os) {
+ this.ps = os;
+ this.prefix = prefix;
+ }
+ @Override
+ protected void processLine(String line) {
+ ps.println("[" + prefix + "] " + line);
+ }
+ }
+
+ private ProcessTools() {
+ }
+
+ /**
+ * Pumps stdout and stderr from running the process into a String.
+ *
+ * @param processHandler ProcessHandler to run.
+ * @return Output from process.
+ * @throws IOException If an I/O error occurs.
+ */
+ public static OutputBuffer getOutput(ProcessBuilder processBuilder) throws IOException {
+ return getOutput(processBuilder.start());
+ }
+
+ /**
+ * Pumps stdout and stderr the running process into a String.
+ *
+ * @param process Process to pump.
+ * @return Output from process.
+ * @throws IOException If an I/O error occurs.
+ */
+ public static OutputBuffer getOutput(Process process) throws IOException {
+ ByteArrayOutputStream stderrBuffer = new ByteArrayOutputStream();
+ ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream();
+ StreamPumper outPumper = new StreamPumper(process.getInputStream(), stdoutBuffer);
+ StreamPumper errPumper = new StreamPumper(process.getErrorStream(), stderrBuffer);
+ Thread outPumperThread = new Thread(outPumper);
+ Thread errPumperThread = new Thread(errPumper);
+
+ outPumperThread.setDaemon(true);
+ errPumperThread.setDaemon(true);
+
+ outPumperThread.start();
+ errPumperThread.start();
+
+ try {
+ process.waitFor();
+ outPumperThread.join();
+ errPumperThread.join();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ return null;
+ }
+
+ return new OutputBuffer(stdoutBuffer.toString(), stderrBuffer.toString());
+ }
+
+ /**
+ * <p>Starts a process from its builder.</p>
+ * <span>The default redirects of STDOUT and STDERR are started</span>
+ * @param name The process name
+ * @param processBuilder The process builder
+ * @return Returns the initialized process
+ * @throws IOException
+ */
+ public static Process startProcess(String name,
+ ProcessBuilder processBuilder)
+ throws IOException {
+ return startProcess(name, processBuilder, (Consumer<String>)null);
+ }
+
+ /**
+ * <p>Starts a process from its builder.</p>
+ * <span>The default redirects of STDOUT and STDERR are started</span>
+ * <p>It is possible to monitor the in-streams via the provided {@code consumer}
+ * @param name The process name
+ * @param consumer {@linkplain Consumer} instance to process the in-streams
+ * @param processBuilder The process builder
+ * @return Returns the initialized process
+ * @throws IOException
+ */
+ @SuppressWarnings("overloads")
+ public static Process startProcess(String name,
+ ProcessBuilder processBuilder,
+ Consumer<String> consumer)
+ throws IOException {
+ try {
+ return startProcess(name, processBuilder, consumer, null, -1, TimeUnit.NANOSECONDS);
+ } catch (InterruptedException | TimeoutException e) {
+ // will never happen
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * <p>Starts a process from its builder.</p>
+ * <span>The default redirects of STDOUT and STDERR are started</span>
+ * <p>
+ * It is possible to wait for the process to get to a warmed-up state
+ * via {@linkplain Predicate} condition on the STDOUT
+ * </p>
+ * @param name The process name
+ * @param processBuilder The process builder
+ * @param linePredicate The {@linkplain Predicate} to use on the STDOUT
+ * Used to determine the moment the target app is
+ * properly warmed-up.
+ * It can be null - in that case the warmup is skipped.
+ * @param timeout The timeout for the warmup waiting; -1 = no wait; 0 = wait forever
+ * @param unit The timeout {@linkplain TimeUnit}
+ * @return Returns the initialized {@linkplain Process}
+ * @throws IOException
+ * @throws InterruptedException
+ * @throws TimeoutException
+ */
+ public static Process startProcess(String name,
+ ProcessBuilder processBuilder,
+ final Predicate<String> linePredicate,
+ long timeout,
+ TimeUnit unit)
+ throws IOException, InterruptedException, TimeoutException {
+ return startProcess(name, processBuilder, null, linePredicate, timeout, unit);
+ }
+
+ /**
+ * <p>Starts a process from its builder.</p>
+ * <span>The default redirects of STDOUT and STDERR are started</span>
+ * <p>
+ * It is possible to wait for the process to get to a warmed-up state
+ * via {@linkplain Predicate} condition on the STDOUT and monitor the
+ * in-streams via the provided {@linkplain Consumer}
+ * </p>
+ * @param name The process name
+ * @param processBuilder The process builder
+ * @param lineConsumer The {@linkplain Consumer} the lines will be forwarded to
+ * @param linePredicate The {@linkplain Predicate} to use on the STDOUT
+ * Used to determine the moment the target app is
+ * properly warmed-up.
+ * It can be null - in that case the warmup is skipped.
+ * @param timeout The timeout for the warmup waiting; -1 = no wait; 0 = wait forever
+ * @param unit The timeout {@linkplain TimeUnit}
+ * @return Returns the initialized {@linkplain Process}
+ * @throws IOException
+ * @throws InterruptedException
+ * @throws TimeoutException
+ */
+ public static Process startProcess(String name,
+ ProcessBuilder processBuilder,
+ final Consumer<String> lineConsumer,
+ final Predicate<String> linePredicate,
+ long timeout,
+ TimeUnit unit)
+ throws IOException, InterruptedException, TimeoutException {
+ System.out.println("["+name+"]:" + processBuilder.command().stream().collect(Collectors.joining(" ")));
+ Process p = processBuilder.start();
+ StreamPumper stdout = new StreamPumper(p.getInputStream());
+ StreamPumper stderr = new StreamPumper(p.getErrorStream());
+
+ stdout.addPump(new LineForwarder(name, System.out));
+ stderr.addPump(new LineForwarder(name, System.err));
+ if (lineConsumer != null) {
+ StreamPumper.LinePump pump = new StreamPumper.LinePump() {
+ @Override
+ protected void processLine(String line) {
+ lineConsumer.accept(line);
+ }
+ };
+ stdout.addPump(pump);
+ stderr.addPump(pump);
+ }
+
+
+ CountDownLatch latch = new CountDownLatch(1);
+ if (linePredicate != null) {
+ StreamPumper.LinePump pump = new StreamPumper.LinePump() {
+ @Override
+ protected void processLine(String line) {
+ if (latch.getCount() > 0 && linePredicate.test(line)) {
+ latch.countDown();
+ }
+ }
+ };
+ stdout.addPump(pump);
+ stderr.addPump(pump);
+ } else {
+ latch.countDown();
+ }
+ final Future<Void> stdoutTask = stdout.process();
+ final Future<Void> stderrTask = stderr.process();
+
+ try {
+ if (timeout > -1) {
+ if (timeout == 0) {
+ latch.await();
+ } else {
+ if (!latch.await(Utils.adjustTimeout(timeout), unit)) {
+ throw new TimeoutException();
+ }
+ }
+ }
+ } catch (TimeoutException | InterruptedException e) {
+ System.err.println("Failed to start a process (thread dump follows)");
+ for(Map.Entry<Thread, StackTraceElement[]> s : Thread.getAllStackTraces().entrySet()) {
+ printStack(s.getKey(), s.getValue());
+ }
+
+ if (p.isAlive()) {
+ p.destroyForcibly();
+ }
+
+ stdoutTask.cancel(true);
+ stderrTask.cancel(true);
+ throw e;
+ }
+
+ return new ProcessImpl(p, stdoutTask, stderrTask);
+ }
+
+ /**
+ * <p>Starts a process from its builder.</p>
+ * <span>The default redirects of STDOUT and STDERR are started</span>
+ * <p>
+ * It is possible to wait for the process to get to a warmed-up state
+ * via {@linkplain Predicate} condition on the STDOUT. The warm-up will
+ * wait indefinitely.
+ * </p>
+ * @param name The process name
+ * @param processBuilder The process builder
+ * @param linePredicate The {@linkplain Predicate} to use on the STDOUT
+ * Used to determine the moment the target app is
+ * properly warmed-up.
+ * It can be null - in that case the warmup is skipped.
+ * @return Returns the initialized {@linkplain Process}
+ * @throws IOException
+ * @throws InterruptedException
+ * @throws TimeoutException
+ */
+ @SuppressWarnings("overloads")
+ public static Process startProcess(String name,
+ ProcessBuilder processBuilder,
+ final Predicate<String> linePredicate)
+ throws IOException, InterruptedException, TimeoutException {
+ return startProcess(name, processBuilder, linePredicate, 0, TimeUnit.SECONDS);
+ }
+
+ /**
+ * Get the process id of the current running Java process
+ *
+ * @return Process id
+ */
+ public static long getProcessId() throws Exception {
+ return ProcessHandle.current().getPid();
+ }
+ /**
+ * Gets the array of strings containing input arguments passed to the VM
+ *
+ * @return arguments
+ */
+ public static String[] getVmInputArgs() {
+ RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
+ List<String> args = runtime.getInputArguments();
+ return args.toArray(new String[args.size()]);
+ }
+
+ /**
+ * Get platform specific VM arguments (e.g. -d64 on 64bit Solaris)
+ *
+ * @return String[] with platform specific arguments, empty if there are
+ * none
+ */
+ public static String[] getPlatformSpecificVMArgs() {
+
+ if (Platform.is64bit() && Platform.isSolaris()) {
+ return new String[] { "-d64" };
+ }
+
+ return new String[] {};
+ }
+
+
+ /**
+ * Create ProcessBuilder using the java launcher from the jdk to be tested and
+ * with any platform specific arguments prepended
+ */
+ public static ProcessBuilder createJavaProcessBuilder(String... command) throws Exception {
+ return createJavaProcessBuilder(false, command);
+ }
+
+ /**
+ * Create ProcessBuilder using the java launcher from the jdk to be tested,
+ * and with any platform specific arguments prepended.
+ *
+ * @param addTestVmAndJavaOptions If true, adds test.vm.opts and test.java.opts
+ * to the java arguments.
+ * @param command Arguments to pass to the java command.
+ * @return The ProcessBuilder instance representing the java command.
+ */
+ public static ProcessBuilder createJavaProcessBuilder(boolean addTestVmAndJavaOptions, String... command) throws Exception {
+ String javapath = JDKToolFinder.getJDKTool("java");
+
+ ArrayList<String> args = new ArrayList<>();
+ args.add(javapath);
+ Collections.addAll(args, getPlatformSpecificVMArgs());
+
+ args.add("-cp");
+ args.add(System.getProperty("java.class.path"));
+
+ if (addTestVmAndJavaOptions) {
+ Collections.addAll(args, Utils.getTestJavaOpts());
+ }
+
+ Collections.addAll(args, command);
+
+ // Reporting
+ StringBuilder cmdLine = new StringBuilder();
+ for (String cmd : args)
+ cmdLine.append(cmd).append(' ');
+ System.out.println("Command line: [" + cmdLine.toString() + "]");
+
+ return new ProcessBuilder(args.toArray(new String[args.size()]));
+ }
+
+ private static void printStack(Thread t, StackTraceElement[] stack) {
+ System.out.println("\t" + t +
+ " stack: (length = " + stack.length + ")");
+ if (t != null) {
+ for (StackTraceElement stack1 : stack) {
+ System.out.println("\t" + stack1);
+ }
+ System.out.println();
+ }
+ }
+
+ /**
+ * Executes a test jvm process, waits for it to finish and returns the process output.
+ * The default jvm options from the test's run command, jtreg, test.vm.opts and test.java.opts, are added.
+ * The java from the test.jdk is used to execute the command.
+ *
+ * The command line will be like:
+ * {test.jdk}/bin/java {test.fromRun.opts} {test.vm.opts} {test.java.opts} cmds
+ *
+ * @param cmds User specifed arguments.
+ * @return The output from the process.
+ */
+ public static OutputAnalyzer executeTestJvmAllArgs(String... cmds) throws Throwable {
+ List<String> argsList = new ArrayList<>();
+ String[] testArgs = getVmInputArgs();
+ Collections.addAll(argsList, testArgs);
+ Collections.addAll(argsList, Utils.addTestJavaOpts(cmds));
+ ProcessBuilder pb = createJavaProcessBuilder(argsList.toArray(new String[argsList.size()]));
+ return executeProcess(pb);
+ }
+
+ /**
+ * Executes a test jvm process, waits for it to finish and returns the process output.
+ * The default jvm options from jtreg, test.vm.opts and test.java.opts, are added.
+ * The java from the test.jdk is used to execute the command.
+ *
+ * The command line will be like:
+ * {test.jdk}/bin/java {test.vm.opts} {test.java.opts} cmds
+ *
+ * The jvm process will have exited before this method returns.
+ *
+ * @param cmds User specifed arguments.
+ * @return The output from the process.
+ */
+ public static OutputAnalyzer executeTestJvm(String... cmds) throws Exception {
+ ProcessBuilder pb = createJavaProcessBuilder(Utils.addTestJavaOpts(cmds));
+ return executeProcess(pb);
+ }
+
+ /**
+ * Executes a process, waits for it to finish and returns the process output.
+ * The process will have exited before this method returns.
+ * @param pb The ProcessBuilder to execute.
+ * @return The {@linkplain OutputAnalyzer} instance wrapping the process.
+ */
+ public static OutputAnalyzer executeProcess(ProcessBuilder pb) throws Exception {
+ OutputAnalyzer output = null;
+ Process p = null;
+ boolean failed = false;
+ try {
+ p = pb.start();
+ output = new OutputAnalyzer(p);
+ p.waitFor();
+
+ return output;
+ } catch (Throwable t) {
+ if (p != null) {
+ p.destroyForcibly().waitFor();
+ }
+
+ failed = true;
+ System.out.println("executeProcess() failed: " + t);
+ throw t;
+ } finally {
+ if (failed) {
+ System.err.println(getProcessLog(pb, output));
+ }
+ }
+ }
+
+ /**
+ * Executes a process, waits for it to finish and returns the process output.
+ *
+ * The process will have exited before this method returns.
+ *
+ * @param cmds The command line to execute.
+ * @return The output from the process.
+ */
+ public static OutputAnalyzer executeProcess(String... cmds) throws Throwable {
+ return executeProcess(new ProcessBuilder(cmds));
+ }
+
+ /**
+ * Used to log command line, stdout, stderr and exit code from an executed process.
+ * @param pb The executed process.
+ * @param output The output from the process.
+ */
+ public static String getProcessLog(ProcessBuilder pb, OutputAnalyzer output) {
+ String stderr = output == null ? "null" : output.getStderr();
+ String stdout = output == null ? "null" : output.getStdout();
+ String exitValue = output == null ? "null": Integer.toString(output.getExitValue());
+ StringBuilder logMsg = new StringBuilder();
+ final String nl = System.getProperty("line.separator");
+ logMsg.append("--- ProcessLog ---" + nl);
+ logMsg.append("cmd: " + getCommandLine(pb) + nl);
+ logMsg.append("exitvalue: " + exitValue + nl);
+ logMsg.append("stderr: " + stderr + nl);
+ logMsg.append("stdout: " + stdout + nl);
+
+ return logMsg.toString();
+ }
+
+ /**
+ * @return The full command line for the ProcessBuilder.
+ */
+ public static String getCommandLine(ProcessBuilder pb) {
+ if (pb == null) {
+ return "null";
+ }
+ StringBuilder cmd = new StringBuilder();
+ for (String s : pb.command()) {
+ cmd.append(s).append(" ");
+ }
+ return cmd.toString().trim();
+ }
+
+ /**
+ * Executes a process, waits for it to finish, prints the process output
+ * to stdout, and returns the process output.
+ *
+ * The process will have exited before this method returns.
+ *
+ * @param cmds The command line to execute.
+ * @return The {@linkplain OutputAnalyzer} instance wrapping the process.
+ */
+ public static OutputAnalyzer executeCommand(String... cmds)
+ throws Throwable {
+ String cmdLine = Arrays.stream(cmds).collect(Collectors.joining(" "));
+ System.out.println("Command line: [" + cmdLine + "]");
+ OutputAnalyzer analyzer = ProcessTools.executeProcess(cmds);
+ System.out.println(analyzer.getOutput());
+ return analyzer;
+ }
+
+ /**
+ * Executes a process, waits for it to finish, prints the process output
+ * to stdout and returns the process output.
+ *
+ * The process will have exited before this method returns.
+ *
+ * @param pb The ProcessBuilder to execute.
+ * @return The {@linkplain OutputAnalyzer} instance wrapping the process.
+ */
+ public static OutputAnalyzer executeCommand(ProcessBuilder pb)
+ throws Throwable {
+ String cmdLine = pb.command().stream().collect(Collectors.joining(" "));
+ System.out.println("Command line: [" + cmdLine + "]");
+ OutputAnalyzer analyzer = ProcessTools.executeProcess(pb);
+ System.out.println(analyzer.getOutput());
+ return analyzer;
+ }
+
+ private static class ProcessImpl extends Process {
+
+ private final Process p;
+ private final Future<Void> stdoutTask;
+ private final Future<Void> stderrTask;
+
+ public ProcessImpl(Process p, Future<Void> stdoutTask, Future<Void> stderrTask) {
+ this.p = p;
+ this.stdoutTask = stdoutTask;
+ this.stderrTask = stderrTask;
+ }
+
+ @Override
+ public OutputStream getOutputStream() {
+ return p.getOutputStream();
+ }
+
+ @Override
+ public InputStream getInputStream() {
+ return p.getInputStream();
+ }
+
+ @Override
+ public InputStream getErrorStream() {
+ return p.getErrorStream();
+ }
+
+ @Override
+ public int waitFor() throws InterruptedException {
+ int rslt = p.waitFor();
+ waitForStreams();
+ return rslt;
+ }
+
+ @Override
+ public int exitValue() {
+ return p.exitValue();
+ }
+
+ @Override
+ public void destroy() {
+ p.destroy();
+ }
+
+ @Override
+ public long getPid() {
+ return p.getPid();
+ }
+
+ @Override
+ public boolean isAlive() {
+ return p.isAlive();
+ }
+
+ @Override
+ public Process destroyForcibly() {
+ return p.destroyForcibly();
+ }
+
+ @Override
+ public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException {
+ boolean rslt = p.waitFor(timeout, unit);
+ if (rslt) {
+ waitForStreams();
+ }
+ return rslt;
+ }
+
+ private void waitForStreams() throws InterruptedException {
+ try {
+ stdoutTask.get();
+ } catch (ExecutionException e) {
+ }
+ try {
+ stderrTask.get();
+ } catch (ExecutionException e) {
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/process/StreamPumper.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.process;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public final class StreamPumper implements Runnable {
+
+ private static final int BUF_SIZE = 256;
+
+ /**
+ * Pump will be called by the StreamPumper to process the incoming data
+ */
+ abstract public static class Pump {
+ abstract void register(StreamPumper d);
+ }
+
+ /**
+ * OutputStream -> Pump adapter
+ */
+ final public static class StreamPump extends Pump {
+ private final OutputStream out;
+ public StreamPump(OutputStream out) {
+ this.out = out;
+ }
+
+ @Override
+ void register(StreamPumper sp) {
+ sp.addOutputStream(out);
+ }
+ }
+
+ /**
+ * Used to process the incoming data line-by-line
+ */
+ abstract public static class LinePump extends Pump {
+ @Override
+ final void register(StreamPumper sp) {
+ sp.addLineProcessor(this);
+ }
+
+ abstract protected void processLine(String line);
+ }
+
+ private final InputStream in;
+ private final Set<OutputStream> outStreams = new HashSet<>();
+ private final Set<LinePump> linePumps = new HashSet<>();
+
+ private final AtomicBoolean processing = new AtomicBoolean(false);
+ private final FutureTask<Void> processingTask = new FutureTask<>(this, null);
+
+ public StreamPumper(InputStream in) {
+ this.in = in;
+ }
+
+ /**
+ * Create a StreamPumper that reads from in and writes to out.
+ *
+ * @param in The stream to read from.
+ * @param out The stream to write to.
+ */
+ public StreamPumper(InputStream in, OutputStream out) {
+ this(in);
+ this.addOutputStream(out);
+ }
+
+ /**
+ * Implements Thread.run(). Continuously read from {@code in} and write to
+ * {@code out} until {@code in} has reached end of stream. Abort on
+ * interruption. Abort on IOExceptions.
+ */
+ @Override
+ public void run() {
+ try (BufferedInputStream is = new BufferedInputStream(in)) {
+ ByteArrayOutputStream lineBos = new ByteArrayOutputStream();
+ byte[] buf = new byte[BUF_SIZE];
+ int len = 0;
+ int linelen = 0;
+
+ while ((len = is.read(buf)) > 0 && !Thread.interrupted()) {
+ for(OutputStream out : outStreams) {
+ out.write(buf, 0, len);
+ }
+ if (!linePumps.isEmpty()) {
+ int i = 0;
+ int lastcrlf = -1;
+ while (i < len) {
+ if (buf[i] == '\n' || buf[i] == '\r') {
+ int bufLinelen = i - lastcrlf - 1;
+ if (bufLinelen > 0) {
+ lineBos.write(buf, lastcrlf + 1, bufLinelen);
+ }
+ linelen += bufLinelen;
+
+ if (linelen > 0) {
+ lineBos.flush();
+ final String line = lineBos.toString();
+ linePumps.stream().forEach((lp) -> {
+ lp.processLine(line);
+ });
+ lineBos.reset();
+ linelen = 0;
+ }
+ lastcrlf = i;
+ }
+
+ i++;
+ }
+ if (lastcrlf == -1) {
+ lineBos.write(buf, 0, len);
+ linelen += len;
+ } else if (lastcrlf < len - 1) {
+ lineBos.write(buf, lastcrlf + 1, len - lastcrlf - 1);
+ linelen += len - lastcrlf - 1;
+ }
+ }
+ }
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ for(OutputStream out : outStreams) {
+ try {
+ out.flush();
+ } catch (IOException e) {}
+ }
+ try {
+ in.close();
+ } catch (IOException e) {}
+ }
+ }
+
+ final void addOutputStream(OutputStream out) {
+ outStreams.add(out);
+ }
+
+ final void addLineProcessor(LinePump lp) {
+ linePumps.add(lp);
+ }
+
+ final public StreamPumper addPump(Pump ... pump) {
+ if (processing.get()) {
+ throw new IllegalStateException("Can not modify pumper while " +
+ "processing is in progress");
+ }
+ for(Pump p : pump) {
+ p.register(this);
+ }
+ return this;
+ }
+
+ final public Future<Void> process() {
+ if (!processing.compareAndSet(false, true)) {
+ throw new IllegalStateException("Can not re-run the processing");
+ }
+ Thread t = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ processingTask.run();
+ }
+ });
+ t.setDaemon(true);
+ t.start();
+
+ return processingTask;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/util/Pair.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.util;
+
+import java.util.Objects;
+
+/**
+ * Pair - a two element tuple
+ *
+ * @param <F> first type
+ * @param <S> second type
+ */
+public class Pair<F, S> {
+ public final F first;
+ public final S second;
+
+ public Pair(F first, S second) {
+ this.first = first;
+ this.second = second;
+ }
+
+ @Override
+ public String toString() {
+ return "(" + first + ":" + second + ")";
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof Pair<?, ?>) {
+ Pair<?, ?> otherPair = (Pair<?, ?>) other;
+ return Objects.equals(first, otherPair.first) &&
+ Objects.equals(second, otherPair.second);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ if (first == null) {
+ return (second == null) ? 0 : second.hashCode();
+ } else if (second == null) {
+ return first.hashCode();
+ } else {
+ return first.hashCode() * 17 + second.hashCode();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/util/Triple.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.util;
+
+import java.util.Objects;
+
+/**
+ * Triple - a three element tuple
+ *
+ * @param <F> first element type
+ * @param <S> second element type
+ * @param <T> third element type
+ */
+public class Triple<F, S, T> {
+ private final Pair<F, Pair<S, T>> container;
+
+ /**
+ * Constructor
+ *
+ * @param first first element of the triple
+ * @param second second element of the triple
+ * @param third third element of the triple
+ */
+ public Triple(F first, S second, T third) {
+ container = new Pair<>(first, new Pair<>(second, third));
+ }
+
+ /**
+ * Gets first element of the triple
+ */
+ public F getFirst() {
+ return container.first;
+ }
+
+ /**
+ * Gets second element of the triple
+ */
+ public S getSecond() {
+ return container.second.first;
+ }
+
+ /**
+ * Gets third element of the triple
+ */
+ public T getThird() {
+ return container.second.second;
+ }
+
+ @Override
+ public int hashCode() {
+ return container.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Triple<?, ?, ?>) {
+ Triple<?, ?, ?> objTriple = (Triple<?, ?, ?>) obj;
+ return Objects.equals(container.first, objTriple.container.first)
+ && Objects.equals(container.second,
+ objTriple.container.second);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "(" + getFirst() + " : " + getSecond() + " : " + getThird() + ")";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/wrappers/InfiniteLoop.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.wrappers;
+
+import java.util.Objects;
+
+/**
+ * Class which runs another Runnable in infinite loop with certain pauses
+ * between cycles.
+ */
+public class InfiniteLoop implements Runnable {
+ private final Runnable target;
+ private final long mills;
+
+
+ /**
+ * @param target a target to run in a loop
+ * @param mills the length of pause time in milliseconds
+ * @throws NullPointerException if target is null
+ * @throws IllegalArgumentException if the value of millis is negative
+ */
+ public InfiniteLoop(Runnable target, long mills) {
+ Objects.requireNonNull(target);
+ if (mills < 0) {
+ throw new IllegalArgumentException("mills < 0");
+ }
+ this.target = target;
+ this.mills = mills;
+ }
+
+ @Override
+ public void run() {
+ try {
+ while (true) {
+ target.run();
+ if (mills > 0) {
+ Thread.sleep(mills);
+ }
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new Error(e);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/wrappers/TimeLimitedRunner.java Fri Aug 26 10:02:44 2016 -0700
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.wrappers;
+
+import java.util.Objects;
+import java.util.concurrent.Callable;
+
+/**
+ * Auxiliary class to run target w/ given timeout.
+ */
+public class TimeLimitedRunner implements Callable<Void> {
+ private final long stoptime;
+ private final long timeout;
+ private final double factor;
+ private final Callable<Boolean> target;
+
+ /**
+ * @param timeout a timeout. zero means no time limitation
+ * @param factor a multiplier used to estimate next iteration time
+ * @param target a target to run
+ * @throws NullPointerException if target is null
+ * @throws IllegalArgumentException if timeout is negative or
+ factor isn't positive
+ */
+ public TimeLimitedRunner(long timeout, double factor,
+ Callable<Boolean> target) {
+ Objects.requireNonNull(target, "target must not be null");
+ if (timeout < 0) {
+ throw new IllegalArgumentException("timeout[" + timeout + "] < 0");
+ }
+ if (factor <= 0d) {
+ throw new IllegalArgumentException("factor[" + factor + "] <= 0");
+ }
+ this.stoptime = System.currentTimeMillis() + timeout;
+ this.timeout = timeout;
+ this.factor = factor;
+ this.target = target;
+ }
+
+ /**
+ * Runs @{linkplan target} while it returns true and timeout isn't exceeded
+ */
+ @Override
+ public Void call() throws Exception {
+ long maxDuration = 0L;
+ long iterStart = System.currentTimeMillis();
+ if (timeout != 0 && iterStart > stoptime) {
+ return null;
+ }
+ while (target.call()) {
+ if (timeout != 0) {
+ long iterDuration = System.currentTimeMillis() - iterStart;
+ maxDuration = Math.max(maxDuration, iterDuration);
+ iterStart = System.currentTimeMillis();
+ if (iterStart + (maxDuration * factor) > stoptime) {
+ System.out.println("Not enough time to continue execution. "
+ + "Interrupted.");
+ break;
+ }
+ }
+ }
+ return null;
+ }
+
+}
--- a/test/lib/share/classes/jdk/test/lib/Asserts.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,620 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 jdk.test.lib;
-
-import java.util.Objects;
-
-/**
- * Asserts that can be used for verifying assumptions in tests.
- *
- * An assertion will throw a {@link RuntimeException} if the assertion isn't true.
- * All the asserts can be imported into a test by using a static import:
- *
- * <pre>
- * {@code
- * import static jdk.testlibrary.Asserts.*;
- * }
- *
- * Always provide a message describing the assumption if the line number of the
- * failing assertion isn't enough to understand why the assumption failed. For
- * example, if the assertion is in a loop or in a method that is called
- * multiple times, then the line number won't provide enough context to
- * understand the failure.
- * </pre>
- */
-public class Asserts {
-
- /**
- * Shorthand for {@link #assertLessThan(Comparable, Comparable)}.
- *
- * @param <T> a type
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @see #assertLessThan(Comparable, Comparable)
- */
- public static <T extends Comparable<T>> void assertLT(T lhs, T rhs) {
- assertLessThan(lhs, rhs);
- }
-
- /**
- * Shorthand for {@link #assertLessThan(Comparable, Comparable, String)}.
- *
- * @param <T> a type
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @param msg A description of the assumption; {@code null} for a default message.
- * @see #assertLessThan(Comparable, Comparable, String)
- */
- public static <T extends Comparable<T>> void assertLT(T lhs, T rhs, String msg) {
- assertLessThan(lhs, rhs, msg);
- }
-
- /**
- * Calls {@link #assertLessThan(Comparable, Comparable, String)} with a default message.
- *
- * @param <T> a type
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @see #assertLessThan(Comparable, Comparable, String)
- */
- public static <T extends Comparable<T>> void assertLessThan(T lhs, T rhs) {
- assertLessThan(lhs, rhs, null);
- }
-
- /**
- * Asserts that {@code lhs} is less than {@code rhs}.
- *
- * @param <T> a type
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @param msg A description of the assumption; {@code null} for a default message.
- * @throws RuntimeException if the assertion is not true.
- */
- public static <T extends Comparable<T>>void assertLessThan(T lhs, T rhs, String msg) {
- if (!(compare(lhs, rhs, msg) < 0)) {
- msg = Objects.toString(msg, "assertLessThan")
- + ": expected that " + Objects.toString(lhs)
- + " < " + Objects.toString(rhs);
- fail(msg);
- }
- }
-
- /**
- * Shorthand for {@link #assertLessThanOrEqual(Comparable, Comparable)}.
- *
- * @param <T> a type
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @see #assertLessThanOrEqual(Comparable, Comparable)
- */
- public static <T extends Comparable<T>> void assertLTE(T lhs, T rhs) {
- assertLessThanOrEqual(lhs, rhs);
- }
-
- /**
- * Shorthand for {@link #assertLessThanOrEqual(Comparable, Comparable, String)}.
- *
- * @param <T> a type
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @param msg A description of the assumption; {@code null} for a default message.
- * @see #assertLessThanOrEqual(Comparable, Comparable, String)
- */
- public static <T extends Comparable<T>> void assertLTE(T lhs, T rhs, String msg) {
- assertLessThanOrEqual(lhs, rhs, msg);
- }
-
- /**
- * Calls {@link #assertLessThanOrEqual(Comparable, Comparable, String)} with a default message.
- *
- * @param <T> a type
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @see #assertLessThanOrEqual(Comparable, Comparable, String)
- */
- public static <T extends Comparable<T>> void assertLessThanOrEqual(T lhs, T rhs) {
- assertLessThanOrEqual(lhs, rhs, null);
- }
-
- /**
- * Asserts that {@code lhs} is less than or equal to {@code rhs}.
- *
- * @param <T> a type
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @param msg A description of the assumption; {@code null} for a default message.
- * @throws RuntimeException if the assertion is not true.
- */
- public static <T extends Comparable<T>> void assertLessThanOrEqual(T lhs, T rhs, String msg) {
- if (!(compare(lhs, rhs, msg) <= 0)) {
- msg = Objects.toString(msg, "assertLessThanOrEqual")
- + ": expected that " + Objects.toString(lhs)
- + " <= " + Objects.toString(rhs);
- fail(msg);
- }
- }
-
- /**
- * Shorthand for {@link #assertEquals(Object, Object)}.
- *
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @see #assertEquals(Object, Object)
- */
- public static void assertEQ(Object lhs, Object rhs) {
- assertEquals(lhs, rhs);
- }
-
- /**
- * Shorthand for {@link #assertEquals(Object, Object, String)}.
- *
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @param msg A description of the assumption; {@code null} for a default message.
- * @see #assertEquals(Object, Object, String)
- */
- public static void assertEQ(Object lhs, Object rhs, String msg) {
- assertEquals(lhs, rhs, msg);
- }
-
- /**
- * Calls {@link #assertEquals(java.lang.Object, java.lang.Object, java.lang.String)} with a default message.
- *
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @see #assertEquals(Object, Object, String)
- */
- public static void assertEquals(Object lhs, Object rhs) {
- assertEquals(lhs, rhs, null);
- }
-
- /**
- * Asserts that {@code lhs} is equal to {@code rhs}.
- *
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @param msg A description of the assumption; {@code null} for a default message.
- * @throws RuntimeException if the assertion is not true.
- */
- public static void assertEquals(Object lhs, Object rhs, String msg) {
- if ((lhs != rhs) && ((lhs == null) || !(lhs.equals(rhs)))) {
- msg = Objects.toString(msg, "assertEquals")
- + ": expected " + Objects.toString(lhs)
- + " to equal " + Objects.toString(rhs);
- fail(msg);
- }
- }
-
- /**
- * Calls {@link #assertSame(java.lang.Object, java.lang.Object, java.lang.String)} with a default message.
- *
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @see #assertSame(Object, Object, String)
- */
- public static void assertSame(Object lhs, Object rhs) {
- assertSame(lhs, rhs, null);
- }
-
- /**
- * Asserts that {@code lhs} is the same as {@code rhs}.
- *
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @param msg A description of the assumption; {@code null} for a default message.
- * @throws RuntimeException if the assertion is not true.
- */
- public static void assertSame(Object lhs, Object rhs, String msg) {
- if (lhs != rhs) {
- msg = Objects.toString(msg, "assertSame")
- + ": expected " + Objects.toString(lhs)
- + " to equal " + Objects.toString(rhs);
- fail(msg);
- }
- }
-
- /**
- * Shorthand for {@link #assertGreaterThanOrEqual(Comparable, Comparable)}.
- *
- * @param <T> a type
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @see #assertGreaterThanOrEqual(Comparable, Comparable)
- */
- public static <T extends Comparable<T>> void assertGTE(T lhs, T rhs) {
- assertGreaterThanOrEqual(lhs, rhs);
- }
-
- /**
- * Shorthand for {@link #assertGreaterThanOrEqual(Comparable, Comparable, String)}.
- *
- * @param <T> a type
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @param msg A description of the assumption; {@code null} for a default message.
- * @see #assertGreaterThanOrEqual(Comparable, Comparable, String)
- */
- public static <T extends Comparable<T>> void assertGTE(T lhs, T rhs, String msg) {
- assertGreaterThanOrEqual(lhs, rhs, msg);
- }
-
- /**
- * Calls {@link #assertGreaterThanOrEqual(Comparable, Comparable, String)} with a default message.
- *
- * @param <T> a type
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @see #assertGreaterThanOrEqual(Comparable, Comparable, String)
- */
- public static <T extends Comparable<T>> void assertGreaterThanOrEqual(T lhs, T rhs) {
- assertGreaterThanOrEqual(lhs, rhs, null);
- }
-
- /**
- * Asserts that {@code lhs} is greater than or equal to {@code rhs}.
- *
- * @param <T> a type
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @param msg A description of the assumption; {@code null} for a default message.
- * @throws RuntimeException if the assertion is not true.
- */
- public static <T extends Comparable<T>> void assertGreaterThanOrEqual(T lhs, T rhs, String msg) {
- if (!(compare(lhs, rhs, msg) >= 0)) {
- msg = Objects.toString(msg, "assertGreaterThanOrEqual")
- + ": expected " + Objects.toString(lhs)
- + " >= " + Objects.toString(rhs);
- fail(msg);
- }
- }
-
- /**
- * Shorthand for {@link #assertGreaterThan(Comparable, Comparable)}.
- *
- * @param <T> a type
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @see #assertGreaterThan(Comparable, Comparable)
- */
- public static <T extends Comparable<T>> void assertGT(T lhs, T rhs) {
- assertGreaterThan(lhs, rhs);
- }
-
- /**
- * Shorthand for {@link #assertGreaterThan(Comparable, Comparable, String)}.
- *
- * @param <T> a type
- * @param lhs the left hand value
- * @param rhs the right hand value
- * @param msg A description of the assumption; {@code null} for a default message.
- * @see #assertGreaterThan(Comparable, Comparable, String)
- */
- public static <T extends Comparable<T>> void assertGT(T lhs, T rhs, String msg) {
- assertGreaterThan(lhs, rhs, msg);
- }
-
- /**
- * Calls {@link #assertGreaterThan(Comparable, Comparable, String)} with a default message.
- *
- * @param <T> a type
- * @param lhs the left hand value
- * @param rhs the right hand value
- * @see #assertGreaterThan(Comparable, Comparable, String)
- */
- public static <T extends Comparable<T>> void assertGreaterThan(T lhs, T rhs) {
- assertGreaterThan(lhs, rhs, null);
- }
-
- /**
- * Asserts that {@code lhs} is greater than {@code rhs}.
- *
- * @param <T> a type
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @param msg A description of the assumption; {@code null} for a default message.
- * @throws RuntimeException if the assertion is not true.
- */
- public static <T extends Comparable<T>> void assertGreaterThan(T lhs, T rhs, String msg) {
- if (!(compare(lhs, rhs, msg) > 0)) {
- msg = Objects.toString(msg, "assertGreaterThan")
- + ": expected " + Objects.toString(lhs)
- + " > " + Objects.toString(rhs);
- fail(msg);
- }
- }
-
- /**
- * Shorthand for {@link #assertNotEquals(Object, Object)}.
- *
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @see #assertNotEquals(Object, Object)
- */
- public static void assertNE(Object lhs, Object rhs) {
- assertNotEquals(lhs, rhs);
- }
-
- /**
- * Shorthand for {@link #assertNotEquals(Object, Object, String)}.
- *
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @param msg A description of the assumption; {@code null} for a default message.
- * @see #assertNotEquals(Object, Object, String)
- */
- public static void assertNE(Object lhs, Object rhs, String msg) {
- assertNotEquals(lhs, rhs, msg);
- }
-
- /**
- * Calls {@link #assertNotEquals(Object, Object, String)} with a default message.
- *
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @see #assertNotEquals(Object, Object, String)
- */
- public static void assertNotEquals(Object lhs, Object rhs) {
- assertNotEquals(lhs, rhs, null);
- }
-
- /**
- * Asserts that {@code lhs} is not equal to {@code rhs}.
- *
- * @param lhs The left hand side of the comparison.
- * @param rhs The right hand side of the comparison.
- * @param msg A description of the assumption; {@code null} for a default message.
- * @throws RuntimeException if the assertion is not true.
- */
- public static void assertNotEquals(Object lhs, Object rhs, String msg) {
- if ((lhs == rhs) || (lhs != null && lhs.equals(rhs))) {
- msg = Objects.toString(msg, "assertNotEquals")
- + ": expected " + Objects.toString(lhs)
- + " to not equal " + Objects.toString(rhs);
- fail(msg);
- }
- }
-
- /**
- * Calls {@link #assertNull(Object, String)} with a default message.
- *
- * @param o The reference assumed to be null.
- * @see #assertNull(Object, String)
- */
- public static void assertNull(Object o) {
- assertNull(o, null);
- }
-
- /**
- * Asserts that {@code o} is null.
- *
- * @param o The reference assumed to be null.
- * @param msg A description of the assumption; {@code null} for a default message.
- * @throws RuntimeException if the assertion is not true.
- */
- public static void assertNull(Object o, String msg) {
- assertEquals(o, null, msg);
- }
-
- /**
- * Calls {@link #assertNotNull(Object, String)} with a default message.
- *
- * @param o The reference assumed <i>not</i> to be null,
- * @see #assertNotNull(Object, String)
- */
- public static void assertNotNull(Object o) {
- assertNotNull(o, null);
- }
-
- /**
- * Asserts that {@code o} is <i>not</i> null.
- *
- * @param o The reference assumed <i>not</i> to be null,
- * @param msg A description of the assumption; {@code null} for a default message.
- * @throws RuntimeException if the assertion is not true.
- */
- public static void assertNotNull(Object o, String msg) {
- assertNotEquals(o, null, msg);
- }
-
- /**
- * Calls {@link #assertFalse(boolean, String)} with a default message.
- *
- * @param value The value assumed to be false.
- * @see #assertFalse(boolean, String)
- */
- public static void assertFalse(boolean value) {
- assertFalse(value, null);
- }
-
- /**
- * Asserts that {@code value} is {@code false}.
- *
- * @param value The value assumed to be false.
- * @param msg A description of the assumption; {@code null} for a default message.
- * @throws RuntimeException if the assertion is not true.
- */
- public static void assertFalse(boolean value, String msg) {
- if (value) {
- msg = Objects.toString(msg, "assertFalse")
- + ": expected false, was true";
- fail(msg);
- }
- }
-
- /**
- * Calls {@link #assertTrue(boolean, String)} with a default message.
- *
- * @param value The value assumed to be true.
- * @see #assertTrue(boolean, String)
- */
- public static void assertTrue(boolean value) {
- assertTrue(value, null);
- }
-
- /**
- * Asserts that {@code value} is {@code true}.
- *
- * @param value The value assumed to be true.
- * @param msg A description of the assumption; {@code null} for a default message.
- * @throws RuntimeException if the assertion is not true.
- */
- public static void assertTrue(boolean value, String msg) {
- if (!value) {
- msg = Objects.toString(msg, "assertTrue")
- + ": expected true, was false";
- fail(msg);
- }
- }
-
- private static <T extends Comparable<T>> int compare(T lhs, T rhs, String msg) {
- if (lhs == null || rhs == null) {
- fail(lhs, rhs, msg + ": values must be non-null:", ",");
- }
- return lhs.compareTo(rhs);
- }
-
-/**
- * Asserts that two strings are equal.
- *
- * If strings are not equals, then exception message
- * will contain {@code msg} followed by list of mismatched lines.
- *
- * @param str1 First string to compare.
- * @param str2 Second string to compare.
- * @param msg A description of the assumption.
- * @throws RuntimeException if strings are not equal.
- */
- public static void assertStringsEqual(String str1, String str2,
- String msg) {
- String lineSeparator = System.getProperty("line.separator");
- String str1Lines[] = str1.split(lineSeparator);
- String str2Lines[] = str2.split(lineSeparator);
-
- int minLength = Math.min(str1Lines.length, str2Lines.length);
- String longestStringLines[] = ((str1Lines.length == minLength) ?
- str2Lines : str1Lines);
-
- boolean stringsAreDifferent = false;
-
- StringBuilder messageBuilder = new StringBuilder(msg);
-
- messageBuilder.append("\n");
-
- for (int line = 0; line < minLength; line++) {
- if (!str1Lines[line].equals(str2Lines[line])) {
- messageBuilder.append(String.
- format("[line %d] '%s' differs " +
- "from '%s'\n",
- line,
- str1Lines[line],
- str2Lines[line]));
- stringsAreDifferent = true;
- }
- }
-
- if (minLength < longestStringLines.length) {
- String stringName = ((longestStringLines == str1Lines) ?
- "first" : "second");
- messageBuilder.append(String.format("Only %s string contains " +
- "following lines:\n",
- stringName));
- stringsAreDifferent = true;
- for(int line = minLength; line < longestStringLines.length; line++) {
- messageBuilder.append(String.
- format("[line %d] '%s'", line,
- longestStringLines[line]));
- }
- }
-
- if (stringsAreDifferent) {
- fail(messageBuilder.toString());
- }
- }
-
- /**
- * Returns a string formatted with a message and expected and actual values.
- * @param lhs the actual value
- * @param rhs the expected value
- * @param message the actual value
- * @param relation the asserted relationship between lhs and rhs
- * @return a formatted string
- */
- public static String format(Object lhs, Object rhs, String message, String relation) {
- StringBuilder sb = new StringBuilder(80);
- if (message != null) {
- sb.append(message);
- sb.append(' ');
- }
- sb.append("<");
- sb.append(Objects.toString(lhs));
- sb.append("> ");
- sb.append(Objects.toString(relation, ","));
- sb.append(" <");
- sb.append(Objects.toString(rhs));
- sb.append(">");
- return sb.toString();
- }
-
- /**
- * Fail reports a failure with message fail.
- *
- * @throws RuntimeException always
- */
- public static void fail() {
- fail("fail");
- }
-
- /**
- * Fail reports a failure with a message.
- * @param message for the failure
- * @throws RuntimeException always
- */
- public static void fail(String message) {
- throw new RuntimeException(message);
- }
-
- /**
- * Fail reports a failure with a formatted message.
- *
- * @param lhs the actual value
- * @param rhs the expected value
- * @param message to be format before the expected and actual values
- * @param relation the asserted relationship between lhs and rhs
- * @throws RuntimeException always
- */
- public static void fail(Object lhs, Object rhs, String message, String relation) {
- throw new RuntimeException(format(lhs, rhs, message, relation));
- }
-
- /**
- * Fail reports a failure with a message and a cause.
- * @param message to be format before the expected and actual values
- * @param cause the exception that caused this failure
- * @throws RuntimeException always
- */
- public static void fail(String message, Throwable cause) {
- throw new RuntimeException(message, cause);
- }
-
-}
--- a/test/lib/share/classes/jdk/test/lib/JDKToolFinder.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 jdk.test.lib;
-
-import java.io.FileNotFoundException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-public final class JDKToolFinder {
-
- private JDKToolFinder() {
- }
-
- /**
- * Returns the full path to an executable in jdk/bin based on System
- * property {@code test.jdk} or {@code compile.jdk} (both are set by the jtreg test suite)
- *
- * @return Full path to an executable in jdk/bin
- */
- public static String getJDKTool(String tool) {
-
- // First try to find the executable in test.jdk
- try {
- return getTool(tool, "test.jdk");
- } catch (FileNotFoundException e) {
-
- }
-
- // Now see if it's available in compile.jdk
- try {
- return getTool(tool, "compile.jdk");
- } catch (FileNotFoundException e) {
- throw new RuntimeException("Failed to find " + tool +
- ", looked in test.jdk (" + System.getProperty("test.jdk") +
- ") and compile.jdk (" + System.getProperty("compile.jdk") + ")");
- }
- }
-
- /**
- * Returns the full path to an executable in jdk/bin based on System
- * property {@code compile.jdk}
- *
- * @return Full path to an executable in jdk/bin
- */
- public static String getCompileJDKTool(String tool) {
- try {
- return getTool(tool, "compile.jdk");
- } catch (FileNotFoundException e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Returns the full path to an executable in jdk/bin based on System
- * property {@code test.jdk}
- *
- * @return Full path to an executable in jdk/bin
- */
- public static String getTestJDKTool(String tool) {
- try {
- return getTool(tool, "test.jdk");
- } catch (FileNotFoundException e) {
- throw new RuntimeException(e);
- }
- }
-
- private static String getTool(String tool, String property) throws FileNotFoundException {
- String jdkPath = System.getProperty(property);
-
- if (jdkPath == null) {
- throw new RuntimeException(
- "System property '" + property + "' not set. This property is normally set by jtreg. "
- + "When running test separately, set this property using '-D" + property + "=/path/to/jdk'.");
- }
-
- Path toolName = Paths.get("bin", tool + (Platform.isWindows() ? ".exe" : ""));
-
- Path jdkTool = Paths.get(jdkPath, toolName.toString());
- if (!jdkTool.toFile().exists()) {
- throw new FileNotFoundException("Could not find file " + jdkTool.toAbsolutePath());
- }
-
- return jdkTool.toAbsolutePath().toString();
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/JDKToolLauncher.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 jdk.test.lib;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import jdk.test.lib.process.*;
-
-/**
- * A utility for constructing command lines for starting JDK tool processes.
- *
- * The JDKToolLauncher can in particular be combined with a
- * java.lang.ProcessBuilder to easily run a JDK tool. For example, the following
- * code run {@code jmap -heap} against a process with GC logging turned on for
- * the {@code jmap} process:
- *
- * <pre>
- * {@code
- * JDKToolLauncher jmap = JDKToolLauncher.create("jmap")
- * .addVMArg("-XX:+PrintGC");
- * .addVMArg("-XX:+PrintGCDetails")
- * .addToolArg("-heap")
- * .addToolArg(pid);
- * ProcessBuilder pb = new ProcessBuilder(jmap.getCommand());
- * Process p = pb.start();
- * }
- * </pre>
- */
-public class JDKToolLauncher {
- private final String executable;
- private final List<String> vmArgs = new ArrayList<String>();
- private final List<String> toolArgs = new ArrayList<String>();
-
- private JDKToolLauncher(String tool, boolean useCompilerJDK) {
- if (useCompilerJDK) {
- executable = JDKToolFinder.getJDKTool(tool);
- } else {
- executable = JDKToolFinder.getTestJDKTool(tool);
- }
- vmArgs.addAll(Arrays.asList(ProcessTools.getPlatformSpecificVMArgs()));
- }
-
- /**
- * Creates a new JDKToolLauncher for the specified tool. Using tools path
- * from the compiler JDK.
- *
- * @param tool
- * The name of the tool
- * @return A new JDKToolLauncher
- */
- public static JDKToolLauncher create(String tool) {
- return new JDKToolLauncher(tool, true);
- }
-
- /**
- * Creates a new JDKToolLauncher for the specified tool in the Tested JDK.
- *
- * @param tool
- * The name of the tool
- *
- * @return A new JDKToolLauncher
- */
- public static JDKToolLauncher createUsingTestJDK(String tool) {
- return new JDKToolLauncher(tool, false);
- }
-
- /**
- * Adds an argument to the JVM running the tool.
- *
- * The JVM arguments are passed to the underlying JVM running the tool.
- * Arguments will automatically be prepended with "-J".
- *
- * Any platform specific arguments required for running the tool are
- * automatically added.
- *
- *
- * @param arg
- * The argument to VM running the tool
- * @return The JDKToolLauncher instance
- */
- public JDKToolLauncher addVMArg(String arg) {
- vmArgs.add(arg);
- return this;
- }
-
- /**
- * Adds an argument to the tool.
- *
- * @param arg
- * The argument to the tool
- * @return The JDKToolLauncher instance
- */
- public JDKToolLauncher addToolArg(String arg) {
- toolArgs.add(arg);
- return this;
- }
-
- /**
- * Returns the command that can be used for running the tool.
- *
- * @return An array whose elements are the arguments of the command.
- */
- public String[] getCommand() {
- List<String> command = new ArrayList<String>();
- command.add(executable);
- // Add -J in front of all vmArgs
- for (String arg : vmArgs) {
- command.add("-J" + arg);
- }
- command.addAll(toolArgs);
- return command.toArray(new String[command.size()]);
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/Platform.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 jdk.test.lib;
-
-import java.util.regex.Pattern;
-
-public class Platform {
- public static final String vmName = System.getProperty("java.vm.name");
- public static final String vmInfo = System.getProperty("java.vm.info");
- private static final String osName = System.getProperty("os.name");
- private static final String dataModel = System.getProperty("sun.arch.data.model");
- private static final String vmVersion = System.getProperty("java.vm.version");
- private static final String javaVersion = System.getProperty("java.version");
- private static final String osArch = System.getProperty("os.arch");
- private static final String userName = System.getProperty("user.name");
- private static final String compiler = System.getProperty("sun.management.compiler");
-
- public static boolean isClient() {
- return vmName.endsWith(" Client VM");
- }
-
- public static boolean isServer() {
- return vmName.endsWith(" Server VM");
- }
-
- public static boolean isGraal() {
- return vmName.endsWith(" Graal VM");
- }
-
- public static boolean isZero() {
- return vmName.endsWith(" Zero VM");
- }
-
- public static boolean isMinimal() {
- return vmName.endsWith(" Minimal VM");
- }
-
- public static boolean isEmbedded() {
- return vmName.contains("Embedded");
- }
-
- public static boolean isTieredSupported() {
- return compiler.contains("Tiered Compilers");
- }
-
- public static boolean isInt() {
- return vmInfo.contains("interpreted");
- }
-
- public static boolean isMixed() {
- return vmInfo.contains("mixed");
- }
-
- public static boolean isComp() {
- return vmInfo.contains("compiled");
- }
-
- public static boolean is32bit() {
- return dataModel.equals("32");
- }
-
- public static boolean is64bit() {
- return dataModel.equals("64");
- }
-
- public static boolean isAix() {
- return isOs("aix");
- }
-
- public static boolean isLinux() {
- return isOs("linux");
- }
-
- public static boolean isOSX() {
- return isOs("mac");
- }
-
- public static boolean isSolaris() {
- return isOs("sunos");
- }
-
- public static boolean isWindows() {
- return isOs("win");
- }
-
- private static boolean isOs(String osname) {
- return osName.toLowerCase().startsWith(osname.toLowerCase());
- }
-
- public static String getOsName() {
- return osName;
- }
-
- public static boolean isDebugBuild() {
- return (vmVersion.toLowerCase().contains("debug") ||
- javaVersion.toLowerCase().contains("debug"));
- }
-
- public static String getVMVersion() {
- return vmVersion;
- }
-
- // Returns true for sparc and sparcv9.
- public static boolean isSparc() {
- return isArch("sparc.*");
- }
-
- public static boolean isARM() {
- return isArch("arm.*");
- }
-
- public static boolean isPPC() {
- return isArch("ppc.*");
- }
-
- public static boolean isX86() {
- // On Linux it's 'i386', Windows 'x86' without '_64' suffix.
- return isArch("(i386)|(x86(?!_64))");
- }
-
- public static boolean isX64() {
- // On OSX it's 'x86_64' and on other (Linux, Windows and Solaris) platforms it's 'amd64'
- return isArch("(amd64)|(x86_64)");
- }
-
- public static boolean isAArch64() {
- return isArch("aarch64");
- }
-
- public static String getOsArch() {
- return osArch;
- }
-
- /**
- * Return a boolean for whether we expect to be able to attach
- * the SA to our own processes on this system.
- */
- public static boolean shouldSAAttach() throws Exception {
-
- if (isAix()) {
- return false; // SA not implemented.
- } else if (isLinux()) {
- return canPtraceAttachLinux();
- } else if (isOSX()) {
- return canAttachOSX();
- } else {
- // Other platforms expected to work:
- return true;
- }
- }
-
- /**
- * On Linux, first check the SELinux boolean "deny_ptrace" and return false
- * as we expect to be denied if that is "1". Then expect permission to attach
- * if we are root, so return true. Then return false for an expected denial
- * if "ptrace_scope" is 1, and true otherwise.
- */
- public static boolean canPtraceAttachLinux() throws Exception {
-
- // SELinux deny_ptrace:
- String deny_ptrace = Utils.fileAsString("/sys/fs/selinux/booleans/deny_ptrace");
- if (deny_ptrace != null && deny_ptrace.contains("1")) {
- // ptrace will be denied:
- return false;
- }
-
- // YAMA enhanced security ptrace_scope:
- // 0 - a process can PTRACE_ATTACH to any other process running under the same uid
- // 1 - restricted ptrace: a process must be a children of the inferior or user is root
- // 2 - only processes with CAP_SYS_PTRACE may use ptrace or user is root
- // 3 - no attach: no processes may use ptrace with PTRACE_ATTACH
- String ptrace_scope = Utils.fileAsString("/proc/sys/kernel/yama/ptrace_scope");
- if (ptrace_scope != null) {
- if (ptrace_scope.startsWith("3")) {
- return false;
- }
- if (!userName.equals("root") && !ptrace_scope.startsWith("0")) {
- // ptrace will be denied:
- return false;
- }
- }
- // Otherwise expect to be permitted:
- return true;
- }
-
- /**
- * On OSX, expect permission to attach only if we are root.
- */
- public static boolean canAttachOSX() throws Exception {
- return userName.equals("root");
- }
-
- private static boolean isArch(String archnameRE) {
- return Pattern.compile(archnameRE, Pattern.CASE_INSENSITIVE)
- .matcher(osArch)
- .matches();
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/Utils.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,640 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 jdk.test.lib;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.net.InetAddress;
-import java.net.MalformedURLException;
-import java.net.ServerSocket;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.net.UnknownHostException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Random;
-import java.util.function.BooleanSupplier;
-import java.util.concurrent.TimeUnit;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import jdk.internal.misc.Unsafe;
-
-import jdk.test.lib.process.*;
-import static jdk.test.lib.Asserts.assertTrue;
-
-/**
- * Common library for various test helper functions.
- */
-public final class Utils {
-
- /**
- * Returns the value of 'test.class.path' system property.
- */
- public static final String TEST_CLASS_PATH = System.getProperty("test.class.path", ".");
-
- /**
- * Returns the sequence used by operating system to separate lines.
- */
- public static final String NEW_LINE = System.getProperty("line.separator");
-
- /**
- * Returns the value of 'test.vm.opts' system property.
- */
- public static final String VM_OPTIONS = System.getProperty("test.vm.opts", "").trim();
-
- /**
- * Returns the value of 'test.java.opts' system property.
- */
- public static final String JAVA_OPTIONS = System.getProperty("test.java.opts", "").trim();
-
- /**
- * Returns the value of 'test.src' system property.
- */
- public static final String TEST_SRC = System.getProperty("test.src", "").trim();
-
- private static Unsafe unsafe = null;
-
- /**
- * Defines property name for seed value.
- */
- public static final String SEED_PROPERTY_NAME = "jdk.test.lib.random.seed";
-
- /* (non-javadoc)
- * Random generator with (or without) predefined seed. Depends on
- * "jdk.test.lib.random.seed" property value.
- */
- private static volatile Random RANDOM_GENERATOR;
-
- /**
- * Contains the seed value used for {@link java.util.Random} creation.
- */
- public static final long SEED = Long.getLong(SEED_PROPERTY_NAME, new Random().nextLong());
- /**
- * Returns the value of 'test.timeout.factor' system property
- * converted to {@code double}.
- */
- public static final double TIMEOUT_FACTOR;
- static {
- String toFactor = System.getProperty("test.timeout.factor", "1.0");
- TIMEOUT_FACTOR = Double.parseDouble(toFactor);
- }
-
- /**
- * Returns the value of JTREG default test timeout in milliseconds
- * converted to {@code long}.
- */
- public static final long DEFAULT_TEST_TIMEOUT = TimeUnit.SECONDS.toMillis(120);
-
- private Utils() {
- // Private constructor to prevent class instantiation
- }
-
- /**
- * Returns the list of VM options.
- *
- * @return List of VM options
- */
- public static List<String> getVmOptions() {
- return Arrays.asList(safeSplitString(VM_OPTIONS));
- }
-
- /**
- * Returns the list of VM options with -J prefix.
- *
- * @return The list of VM options with -J prefix
- */
- public static List<String> getForwardVmOptions() {
- String[] opts = safeSplitString(VM_OPTIONS);
- for (int i = 0; i < opts.length; i++) {
- opts[i] = "-J" + opts[i];
- }
- return Arrays.asList(opts);
- }
-
- /**
- * Returns the default JTReg arguments for a jvm running a test.
- * This is the combination of JTReg arguments test.vm.opts and test.java.opts.
- * @return An array of options, or an empty array if no options.
- */
- public static String[] getTestJavaOpts() {
- List<String> opts = new ArrayList<String>();
- Collections.addAll(opts, safeSplitString(VM_OPTIONS));
- Collections.addAll(opts, safeSplitString(JAVA_OPTIONS));
- return opts.toArray(new String[0]);
- }
-
- /**
- * Combines given arguments with default JTReg arguments for a jvm running a test.
- * This is the combination of JTReg arguments test.vm.opts and test.java.opts
- * @return The combination of JTReg test java options and user args.
- */
- public static String[] addTestJavaOpts(String... userArgs) {
- List<String> opts = new ArrayList<String>();
- Collections.addAll(opts, getTestJavaOpts());
- Collections.addAll(opts, userArgs);
- return opts.toArray(new String[0]);
- }
-
- /**
- * Removes any options specifying which GC to use, for example "-XX:+UseG1GC".
- * Removes any options matching: -XX:(+/-)Use*GC
- * Used when a test need to set its own GC version. Then any
- * GC specified by the framework must first be removed.
- * @return A copy of given opts with all GC options removed.
- */
- private static final Pattern useGcPattern = Pattern.compile(
- "(?:\\-XX\\:[\\+\\-]Use.+GC)"
- + "|(?:\\-Xconcgc)");
- public static List<String> removeGcOpts(List<String> opts) {
- List<String> optsWithoutGC = new ArrayList<String>();
- for (String opt : opts) {
- if (useGcPattern.matcher(opt).matches()) {
- System.out.println("removeGcOpts: removed " + opt);
- } else {
- optsWithoutGC.add(opt);
- }
- }
- return optsWithoutGC;
- }
-
- /**
- * Returns the default JTReg arguments for a jvm running a test without
- * options that matches regular expressions in {@code filters}.
- * This is the combination of JTReg arguments test.vm.opts and test.java.opts.
- * @param filters Regular expressions used to filter out options.
- * @return An array of options, or an empty array if no options.
- */
- public static String[] getFilteredTestJavaOpts(String... filters) {
- String options[] = getTestJavaOpts();
-
- if (filters.length == 0) {
- return options;
- }
-
- List<String> filteredOptions = new ArrayList<String>(options.length);
- Pattern patterns[] = new Pattern[filters.length];
- for (int i = 0; i < filters.length; i++) {
- patterns[i] = Pattern.compile(filters[i]);
- }
-
- for (String option : options) {
- boolean matched = false;
- for (int i = 0; i < patterns.length && !matched; i++) {
- Matcher matcher = patterns[i].matcher(option);
- matched = matcher.find();
- }
- if (!matched) {
- filteredOptions.add(option);
- }
- }
-
- return filteredOptions.toArray(new String[filteredOptions.size()]);
- }
-
- /**
- * Splits a string by white space.
- * Works like String.split(), but returns an empty array
- * if the string is null or empty.
- */
- private static String[] safeSplitString(String s) {
- if (s == null || s.trim().isEmpty()) {
- return new String[] {};
- }
- return s.trim().split("\\s+");
- }
-
- /**
- * @return The full command line for the ProcessBuilder.
- */
- public static String getCommandLine(ProcessBuilder pb) {
- StringBuilder cmd = new StringBuilder();
- for (String s : pb.command()) {
- cmd.append(s).append(" ");
- }
- return cmd.toString();
- }
-
- /**
- * Returns the free port on the local host.
- * The function will spin until a valid port number is found.
- *
- * @return The port number
- * @throws InterruptedException if any thread has interrupted the current thread
- * @throws IOException if an I/O error occurs when opening the socket
- */
- public static int getFreePort() throws InterruptedException, IOException {
- int port = -1;
-
- while (port <= 0) {
- Thread.sleep(100);
-
- ServerSocket serverSocket = null;
- try {
- serverSocket = new ServerSocket(0);
- port = serverSocket.getLocalPort();
- } finally {
- serverSocket.close();
- }
- }
-
- return port;
- }
-
- /**
- * Returns the name of the local host.
- *
- * @return The host name
- * @throws UnknownHostException if IP address of a host could not be determined
- */
- public static String getHostname() throws UnknownHostException {
- InetAddress inetAddress = InetAddress.getLocalHost();
- String hostName = inetAddress.getHostName();
-
- assertTrue((hostName != null && !hostName.isEmpty()),
- "Cannot get hostname");
-
- return hostName;
- }
-
- /**
- * Uses "jcmd -l" to search for a jvm pid. This function will wait
- * forever (until jtreg timeout) for the pid to be found.
- * @param key Regular expression to search for
- * @return The found pid.
- */
- public static int waitForJvmPid(String key) throws Throwable {
- final long iterationSleepMillis = 250;
- System.out.println("waitForJvmPid: Waiting for key '" + key + "'");
- System.out.flush();
- while (true) {
- int pid = tryFindJvmPid(key);
- if (pid >= 0) {
- return pid;
- }
- Thread.sleep(iterationSleepMillis);
- }
- }
-
- /**
- * Searches for a jvm pid in the output from "jcmd -l".
- *
- * Example output from jcmd is:
- * 12498 sun.tools.jcmd.JCmd -l
- * 12254 /tmp/jdk8/tl/jdk/JTwork/classes/com/sun/tools/attach/Application.jar
- *
- * @param key A regular expression to search for.
- * @return The found pid, or -1 if not found.
- * @throws Exception If multiple matching jvms are found.
- */
- public static int tryFindJvmPid(String key) throws Throwable {
- OutputAnalyzer output = null;
- try {
- JDKToolLauncher jcmdLauncher = JDKToolLauncher.create("jcmd");
- jcmdLauncher.addToolArg("-l");
- output = ProcessTools.executeProcess(jcmdLauncher.getCommand());
- output.shouldHaveExitValue(0);
-
- // Search for a line starting with numbers (pid), follwed by the key.
- Pattern pattern = Pattern.compile("([0-9]+)\\s.*(" + key + ").*\\r?\\n");
- Matcher matcher = pattern.matcher(output.getStdout());
-
- int pid = -1;
- if (matcher.find()) {
- pid = Integer.parseInt(matcher.group(1));
- System.out.println("findJvmPid.pid: " + pid);
- if (matcher.find()) {
- throw new Exception("Found multiple JVM pids for key: " + key);
- }
- }
- return pid;
- } catch (Throwable t) {
- System.out.println(String.format("Utils.findJvmPid(%s) failed: %s", key, t));
- throw t;
- }
- }
-
- /**
- * Adjusts the provided timeout value for the TIMEOUT_FACTOR
- * @param tOut the timeout value to be adjusted
- * @return The timeout value adjusted for the value of "test.timeout.factor"
- * system property
- */
- public static long adjustTimeout(long tOut) {
- return Math.round(tOut * Utils.TIMEOUT_FACTOR);
- }
-
- /**
- * Return the contents of the named file as a single String,
- * or null if not found.
- * @param filename name of the file to read
- * @return String contents of file, or null if file not found.
- * @throws IOException
- * if an I/O error occurs reading from the file or a malformed or
- * unmappable byte sequence is read
- */
- public static String fileAsString(String filename) throws IOException {
- Path filePath = Paths.get(filename);
- if (!Files.exists(filePath)) return null;
- return new String(Files.readAllBytes(filePath));
- }
-
- /**
- * @return Unsafe instance.
- */
- public static synchronized Unsafe getUnsafe() {
- if (unsafe == null) {
- try {
- Field f = Unsafe.class.getDeclaredField("theUnsafe");
- f.setAccessible(true);
- unsafe = (Unsafe) f.get(null);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- throw new RuntimeException("Unable to get Unsafe instance.", e);
- }
- }
- return unsafe;
- }
- private static final char[] hexArray = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
-
- /**
- * Returns hex view of byte array
- *
- * @param bytes byte array to process
- * @return Space separated hexadecimal string representation of bytes
- */
-
- public static String toHexString(byte[] bytes) {
- char[] hexView = new char[bytes.length * 3];
- int i = 0;
- for (byte b : bytes) {
- hexView[i++] = hexArray[(b >> 4) & 0x0F];
- hexView[i++] = hexArray[b & 0x0F];
- hexView[i++] = ' ';
- }
- return new String(hexView);
- }
-
- /**
- * Returns {@link java.util.Random} generator initialized with particular seed.
- * The seed could be provided via system property {@link Utils#SEED_PROPERTY_NAME}
- * In case no seed is provided, the method uses a random number.
- * The used seed printed to stdout.
- * @return {@link java.util.Random} generator with particular seed.
- */
- public static Random getRandomInstance() {
- if (RANDOM_GENERATOR == null) {
- synchronized (Utils.class) {
- if (RANDOM_GENERATOR == null) {
- RANDOM_GENERATOR = new Random(SEED);
- System.out.printf("For random generator using seed: %d%n", SEED);
- System.out.printf("To re-run test with same seed value please add \"-D%s=%d\" to command line.%n", SEED_PROPERTY_NAME, SEED);
- }
- }
- }
- return RANDOM_GENERATOR;
- }
-
- /**
- * Returns random element of non empty collection
- *
- * @param <T> a type of collection element
- * @param collection collection of elements
- * @return random element of collection
- * @throws IllegalArgumentException if collection is empty
- */
- public static <T> T getRandomElement(Collection<T> collection)
- throws IllegalArgumentException {
- if (collection.isEmpty()) {
- throw new IllegalArgumentException("Empty collection");
- }
- Random random = getRandomInstance();
- int elementIndex = 1 + random.nextInt(collection.size() - 1);
- Iterator<T> iterator = collection.iterator();
- while (--elementIndex != 0) {
- iterator.next();
- }
- return iterator.next();
- }
-
- /**
- * Wait for condition to be true
- *
- * @param condition, a condition to wait for
- */
- public static final void waitForCondition(BooleanSupplier condition) {
- waitForCondition(condition, -1L, 100L);
- }
-
- /**
- * Wait until timeout for condition to be true
- *
- * @param condition, a condition to wait for
- * @param timeout a time in milliseconds to wait for condition to be true
- * specifying -1 will wait forever
- * @return condition value, to determine if wait was successful
- */
- public static final boolean waitForCondition(BooleanSupplier condition,
- long timeout) {
- return waitForCondition(condition, timeout, 100L);
- }
-
- /**
- * Wait until timeout for condition to be true for specified time
- *
- * @param condition, a condition to wait for
- * @param timeout a time in milliseconds to wait for condition to be true,
- * specifying -1 will wait forever
- * @param sleepTime a time to sleep value in milliseconds
- * @return condition value, to determine if wait was successful
- */
- public static final boolean waitForCondition(BooleanSupplier condition,
- long timeout, long sleepTime) {
- long startTime = System.currentTimeMillis();
- while (!(condition.getAsBoolean() || (timeout != -1L
- && ((System.currentTimeMillis() - startTime) > timeout)))) {
- try {
- Thread.sleep(sleepTime);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- throw new Error(e);
- }
- }
- return condition.getAsBoolean();
- }
-
- /**
- * Interface same as java.lang.Runnable but with
- * method {@code run()} able to throw any Throwable.
- */
- public static interface ThrowingRunnable {
- void run() throws Throwable;
- }
-
- /**
- * Filters out an exception that may be thrown by the given
- * test according to the given filter.
- *
- * @param test - method that is invoked and checked for exception.
- * @param filter - function that checks if the thrown exception matches
- * criteria given in the filter's implementation.
- * @return - exception that matches the filter if it has been thrown or
- * {@code null} otherwise.
- * @throws Throwable - if test has thrown an exception that does not
- * match the filter.
- */
- public static Throwable filterException(ThrowingRunnable test,
- Function<Throwable, Boolean> filter) throws Throwable {
- try {
- test.run();
- } catch (Throwable t) {
- if (filter.apply(t)) {
- return t;
- } else {
- throw t;
- }
- }
- return null;
- }
-
- /**
- * Ensures a requested class is loaded
- * @param aClass class to load
- */
- public static void ensureClassIsLoaded(Class<?> aClass) {
- if (aClass == null) {
- throw new Error("Requested null class");
- }
- try {
- Class.forName(aClass.getName(), /* initialize = */ true,
- ClassLoader.getSystemClassLoader());
- } catch (ClassNotFoundException e) {
- throw new Error("Class not found", e);
- }
- }
- /**
- * @param parent a class loader to be the parent for the returned one
- * @return an UrlClassLoader with urls made of the 'test.class.path' jtreg
- * property and with the given parent
- */
- public static URLClassLoader getTestClassPathURLClassLoader(ClassLoader parent) {
- URL[] urls = Arrays.stream(TEST_CLASS_PATH.split(File.pathSeparator))
- .map(Paths::get)
- .map(Path::toUri)
- .map(x -> {
- try {
- return x.toURL();
- } catch (MalformedURLException ex) {
- throw new Error("Test issue. JTREG property"
- + " 'test.class.path'"
- + " is not defined correctly", ex);
- }
- }).toArray(URL[]::new);
- return new URLClassLoader(urls, parent);
- }
-
- /**
- * Runs runnable and checks that it throws expected exception. If exceptionException is null it means
- * that we expect no exception to be thrown.
- * @param runnable what we run
- * @param expectedException expected exception
- */
- public static void runAndCheckException(Runnable runnable, Class<? extends Throwable> expectedException) {
- runAndCheckException(runnable, t -> {
- if (t == null) {
- if (expectedException != null) {
- throw new AssertionError("Didn't get expected exception " + expectedException.getSimpleName());
- }
- } else {
- String message = "Got unexpected exception " + t.getClass().getSimpleName();
- if (expectedException == null) {
- throw new AssertionError(message, t);
- } else if (!expectedException.isAssignableFrom(t.getClass())) {
- message += " instead of " + expectedException.getSimpleName();
- throw new AssertionError(message, t);
- }
- }
- });
- }
-
- /**
- * Runs runnable and makes some checks to ensure that it throws expected exception.
- * @param runnable what we run
- * @param checkException a consumer which checks that we got expected exception and raises a new exception otherwise
- */
- public static void runAndCheckException(Runnable runnable, Consumer<Throwable> checkException) {
- try {
- runnable.run();
- checkException.accept(null);
- } catch (Throwable t) {
- checkException.accept(t);
- }
- }
-
- /**
- * Converts to VM type signature
- *
- * @param type Java type to convert
- * @return string representation of VM type
- */
- public static String toJVMTypeSignature(Class<?> type) {
- if (type.isPrimitive()) {
- if (type == boolean.class) {
- return "Z";
- } else if (type == byte.class) {
- return "B";
- } else if (type == char.class) {
- return "C";
- } else if (type == double.class) {
- return "D";
- } else if (type == float.class) {
- return "F";
- } else if (type == int.class) {
- return "I";
- } else if (type == long.class) {
- return "J";
- } else if (type == short.class) {
- return "S";
- } else if (type == void.class) {
- return "V";
- } else {
- throw new Error("Unsupported type: " + type);
- }
- }
- String result = type.getName().replaceAll("\\.", "/");
- if (!type.isArray()) {
- return "L" + result + ";";
- }
- return result;
- }
-}
-
--- a/test/lib/share/classes/jdk/test/lib/apps/LingeredApp.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,466 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 jdk.test.lib.apps;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.nio.file.Files;
-import java.nio.file.NoSuchFileException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.nio.file.attribute.FileTime;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-/**
- * This is a framework to launch an app that could be synchronized with caller
- * to make further attach actions reliable across supported platforms
-
- * Caller example:
- * SmartTestApp a = SmartTestApp.startApp(cmd);
- * // do something
- * a.stopApp();
- *
- * or fine grained control
- *
- * a = new SmartTestApp("MyLock.lck");
- * a.createLock();
- * a.runApp();
- * a.waitAppReady();
- * // do something
- * a.deleteLock();
- * a.waitAppTerminate();
- *
- * Then you can work with app output and process object
- *
- * output = a.getAppOutput();
- * process = a.getProcess();
- *
- */
-public class LingeredApp {
-
- private static final long spinDelay = 1000;
- private static final int appWaitTime = 100;
-
- private final String lockFileName;
- private long lockCreationTime;
- private Process appProcess;
- private final ArrayList<String> storedAppOutput;
-
- /*
- * Drain child process output, store it into string array
- */
- class InputGobbler extends Thread {
-
- InputStream is;
- List<String> astr;
-
- InputGobbler(InputStream is, List<String> astr) {
- this.is = is;
- this.astr = astr;
- }
-
- public void run() {
- try {
- InputStreamReader isr = new InputStreamReader(is);
- BufferedReader br = new BufferedReader(isr);
- String line = null;
- while ((line = br.readLine()) != null) {
- astr.add(line);
- }
- } catch (IOException ex) {
- // pass
- }
- }
- }
-
- /**
- * Create LingeredApp object on caller side. Lock file have be a valid filename
- * at writable location
- *
- * @param lockFileName - the name of lock file
- */
- public LingeredApp(String lockFileName) {
- this.lockFileName = lockFileName;
- this.storedAppOutput = new ArrayList<String>();
- }
-
- public LingeredApp() {
- final String lockName = UUID.randomUUID().toString() + ".lck";
- this.lockFileName = lockName;
- this.storedAppOutput = new ArrayList<String>();
- }
-
- /**
- *
- * @return name of lock file
- */
- public String getLockFileName() {
- return this.lockFileName;
- }
-
- /**
- *
- * @return name of testapp
- */
- public String getAppName() {
- return this.getClass().getName();
- }
-
- /**
- *
- * @return pid of java process running testapp
- */
- public long getPid() {
- if (appProcess == null) {
- throw new RuntimeException("Process is not alive");
- }
- return appProcess.getPid();
- }
-
- /**
- *
- * @return process object
- */
- public Process getProcess() {
- return appProcess;
- }
-
- /**
- *
- * @return application output as string array. Empty array if application produced no output
- */
- public List<String> getAppOutput() {
- if (appProcess.isAlive()) {
- throw new RuntimeException("Process is still alive. Can't get its output.");
- }
- return storedAppOutput;
- }
-
- /* Make sure all part of the app use the same method to get dates,
- as different methods could produce different results
- */
- private static long epoch() {
- return new Date().getTime();
- }
-
- private static long lastModified(String fileName) throws IOException {
- Path path = Paths.get(fileName);
- BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class);
- return attr.lastModifiedTime().toMillis();
- }
-
- private static void setLastModified(String fileName, long newTime) throws IOException {
- Path path = Paths.get(fileName);
- FileTime fileTime = FileTime.fromMillis(newTime);
- Files.setLastModifiedTime(path, fileTime);
- }
-
- /**
- * create lock
- *
- * @throws IOException
- */
- public void createLock() throws IOException {
- Path path = Paths.get(lockFileName);
- // Files.deleteIfExists(path);
- Files.createFile(path);
- lockCreationTime = lastModified(lockFileName);
- }
-
- /**
- * Delete lock
- *
- * @throws IOException
- */
- public void deleteLock() throws IOException {
- try {
- Path path = Paths.get(lockFileName);
- Files.delete(path);
- } catch (NoSuchFileException ex) {
- // Lock already deleted. Ignore error
- }
- }
-
- public void waitAppTerminate() {
- while (true) {
- try {
- appProcess.waitFor();
- break;
- } catch (InterruptedException ex) {
- // pass
- }
- }
- }
-
- /**
- * The app touches the lock file when it's started
- * wait while it happens. Caller have to delete lock on wait error.
- *
- * @param timeout
- * @throws java.io.IOException
- */
- public void waitAppReady(long timeout) throws IOException {
- long here = epoch();
- while (true) {
- long epoch = epoch();
- if (epoch - here > (timeout * 1000)) {
- throw new IOException("App waiting timeout");
- }
-
- // Live process should touch lock file every second
- long lm = lastModified(lockFileName);
- if (lm > lockCreationTime) {
- break;
- }
-
- // Make sure process didn't already exit
- if (!appProcess.isAlive()) {
- throw new IOException("App exited unexpectedly with " + appProcess.exitValue());
- }
-
- try {
- Thread.sleep(spinDelay);
- } catch (InterruptedException ex) {
- // pass
- }
- }
- }
-
- /**
- * Run the app
- *
- * @param vmArguments
- * @throws IOException
- */
- public void runApp(List<String> vmArguments)
- throws IOException {
-
- // We should always use testjava or throw an exception,
- // so we can't use JDKToolFinder.getJDKTool("java");
- // that falls back to compile java on error
- String jdkPath = System.getProperty("test.jdk");
- if (jdkPath == null) {
- // we are not under jtreg, try env
- Map<String, String> env = System.getenv();
- jdkPath = env.get("TESTJAVA");
- }
-
- if (jdkPath == null) {
- throw new RuntimeException("Can't determine jdk path neither test.jdk property no TESTJAVA env are set");
- }
-
- String osname = System.getProperty("os.name");
- String javapath = jdkPath + ((osname.startsWith("window")) ? "/bin/java.exe" : "/bin/java");
-
- List<String> cmd = new ArrayList<String>();
- cmd.add(javapath);
-
-
- if (vmArguments == null) {
- // Propagate test.vm.options to LingeredApp, filter out possible empty options
- String testVmOpts[] = System.getProperty("test.vm.opts","").split("\\s+");
- for (String s : testVmOpts) {
- if (!s.equals("")) {
- cmd.add(s);
- }
- }
- }
- else{
- // Lets user manage LingeredApp options
- cmd.addAll(vmArguments);
- }
-
- // Make sure we set correct classpath to run the app
- cmd.add("-cp");
- String classpath = System.getProperty("test.class.path");
- cmd.add((classpath == null) ? "." : classpath);
-
- cmd.add(this.getAppName());
- cmd.add(lockFileName);
-
- // Reporting
- StringBuilder cmdLine = new StringBuilder();
- for (String strCmd : cmd) {
- cmdLine.append("'").append(strCmd).append("' ");
- }
-
- // A bit of verbosity
- System.out.println("Command line: [" + cmdLine.toString() + "]");
-
- ProcessBuilder pb = new ProcessBuilder(cmd);
- // we don't expect any error output but make sure we are not stuck on pipe
- // pb.redirectErrorStream(false);
- pb.redirectError(ProcessBuilder.Redirect.INHERIT);
-
- appProcess = pb.start();
-
- // Create pipe reader for process, and read stdin and stderr to array of strings
- InputGobbler gb = new InputGobbler(appProcess.getInputStream(), storedAppOutput);
- gb.start();
- }
-
- /**
- * Delete lock file that signals app to terminate, then
- * wait until app is actually terminated.
- * @throws IOException
- */
- public void stopApp() throws IOException {
- deleteLock();
- waitAppTerminate();
- int exitcode = appProcess.exitValue();
- if (exitcode != 0) {
- throw new IOException("LingeredApp terminated with non-zero exit code " + exitcode);
- }
- }
-
- /**
- * High level interface for test writers
- */
- /**
- * Factory method that creates LingeredApp object with ready to use application
- * lock name is autogenerated
- * @param cmd - vm options, could be null to auto add testvm.options
- * @return LingeredApp object
- * @throws IOException
- */
- public static LingeredApp startApp(List<String> cmd) throws IOException {
- LingeredApp a = new LingeredApp();
- a.createLock();
- try {
- a.runApp(cmd);
- a.waitAppReady(appWaitTime);
- } catch (Exception ex) {
- a.deleteLock();
- throw ex;
- }
-
- return a;
- }
-
- /**
- * Factory method that starts pre-created LingeredApp
- * lock name is autogenerated
- * @param cmd - vm options, could be null to auto add testvm.options
- * @param theApp - app to start
- * @return LingeredApp object
- * @throws IOException
- */
-
- public static void startApp(List<String> cmd, LingeredApp theApp) throws IOException {
- theApp.createLock();
- try {
- theApp.runApp(cmd);
- theApp.waitAppReady(appWaitTime);
- } catch (Exception ex) {
- theApp.deleteLock();
- throw ex;
- }
- }
-
- public static LingeredApp startApp() throws IOException {
- return startApp(null);
- }
-
- public static void stopApp(LingeredApp app) throws IOException {
- if (app != null) {
- // LingeredApp can throw an exception during the intialization,
- // make sure we don't have cascade NPE
- app.stopApp();
- }
- }
-
- /**
- * LastModified time might not work correctly in some cases it might
- * cause later failures
- */
-
- public static boolean isLastModifiedWorking() {
- boolean sane = true;
- try {
- long lm = lastModified(".");
- if (lm == 0) {
- System.err.println("SANITY Warning! The lastModifiedTime() doesn't work on this system, it returns 0");
- sane = false;
- }
-
- long now = epoch();
- if (lm > now) {
- System.err.println("SANITY Warning! The Clock is wrong on this system lastModifiedTime() > getTime()");
- sane = false;
- }
-
- setLastModified(".", epoch());
- long lm1 = lastModified(".");
- if (lm1 <= lm) {
- System.err.println("SANITY Warning! The setLastModified doesn't work on this system");
- sane = false;
- }
- }
- catch(IOException e) {
- System.err.println("SANITY Warning! IOException during sanity check " + e);
- sane = false;
- }
-
- return sane;
- }
-
- /**
- * This part is the application it self
- */
- public static void main(String args[]) {
-
- if (args.length != 1) {
- System.err.println("Lock file name is not specified");
- System.exit(7);
- }
-
- String theLockFileName = args[0];
-
- try {
- Path path = Paths.get(theLockFileName);
-
- while (Files.exists(path)) {
- // Touch the lock to indicate our readiness
- setLastModified(theLockFileName, epoch());
- Thread.sleep(spinDelay);
- }
- } catch (NoSuchFileException ex) {
- // Lock deleted while we are setting last modified time.
- // Ignore error and lets the app exits
- } catch (Exception ex) {
- System.err.println("LingeredApp ERROR: " + ex);
- // Leave exit_code = 1 to Java launcher
- System.exit(3);
- }
-
- System.exit(0);
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/apps/LingeredAppWithDeadlock.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 jdk.test.lib.apps;
-
-import java.util.concurrent.Phaser;
-
-public class LingeredAppWithDeadlock extends LingeredApp {
-
- private static final Object Lock1 = new Object();
- private static final Object Lock2 = new Object();
-
- private static volatile int reachCount = 0;
-
- private static final Phaser p = new Phaser(2);
-
- private static class ThreadOne extends Thread {
- public void run() {
- // wait Lock2 is locked
- p.arriveAndAwaitAdvance();
- synchronized (Lock1) {
- // signal Lock1 is locked
- p.arriveAndAwaitAdvance();
- synchronized (Lock2) {
- reachCount += 1;
- }
- }
- }
- }
-
- private static class ThreadTwo extends Thread {
- public void run() {
- synchronized (Lock2) {
- // signal Lock2 is locked
- p.arriveAndAwaitAdvance();
- // wait Lock1 is locked
- p.arriveAndAwaitAdvance();
- synchronized (Lock1) {
- reachCount += 1;
- }
- }
- }
- }
-
- public static void main(String args[]) {
- if (args.length != 1) {
- System.err.println("Lock file name is not specified");
- System.exit(7);
- }
-
- // Run two theads that should come to deadlock
- new ThreadOne().start();
- new ThreadTwo().start();
-
- if (reachCount > 0) {
- // Not able to deadlock, exiting
- System.exit(3);
- }
-
- LingeredApp.main(args);
- }
- }
--- a/test/lib/share/classes/jdk/test/lib/hprof/HprofParser.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 jdk.test.lib.hprof;
-
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-
-import jdk.test.lib.hprof.model.Snapshot;
-import jdk.test.lib.hprof.parser.Reader;
-
-/**
- * Helper class to parse a java heap dump file.
- */
-public class HprofParser {
-
- public static void main(String[] args) throws Exception {
- if (args.length < 1) {
- System.out.println("No arguments supplied");
- }
- File dump = new File(args[0]);
- if (!dump.exists() || !dump.isFile()) {
- throw new RuntimeException("The dump file does not exist or not a file");
- }
- parse(dump);
- }
-
- /**
- * @see #parse(File, boolean, boolean, boolean)
- */
- public static File parse(File dump) throws Exception {
- return parse(dump, false, true, true);
- }
-
- /**
- * @see #parse(File, boolean, boolean, boolean)
- */
- public static File parseWithDebugInfo(File dump) throws Exception {
- return parse(dump, true, true, true);
- }
-
- /**
- * Parse a java heap dump file
- *
- * @param dump Heap dump file to parse
- * @param debug Turn on/off debug file parsing
- * @param callStack Turn on/off tracking of object allocation call stack
- * @param calculateRefs Turn on/off tracking object allocation call stack
- * @throws Exception
- * @return File containing output from the parser
- */
- public static File parse(File dump, boolean debug, boolean callStack, boolean calculateRefs) throws Exception {
- File out = new File("hprof." + System.currentTimeMillis() + ".out");
- if (out.exists()) {
- out.delete();
- }
-
- PrintStream psSystemOut = System.out;
- try (PrintStream psHprof = new PrintStream(new BufferedOutputStream(new FileOutputStream(out.getAbsolutePath())))) {
- System.setOut(psHprof);
-
- int debugLevel = debug ? 2 : 0;
- try (Snapshot snapshot = Reader.readFile(dump.getAbsolutePath(), callStack, debugLevel)) {
- System.out.println("Snapshot read, resolving...");
- snapshot.resolve(calculateRefs);
- System.out.println("Snapshot resolved.");
- }
- } finally {
- System.setOut(psSystemOut);
- }
-
- return out;
- }
-
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/README Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-The jhat tool has been removed. jhat hprof file parser/validator
-are needed for tests. The old packages for jhat were moved here:
-com.sun.tools.hat.internal.model -> jdk.test.lib.hprof.model
-com.sun.tools.hat.internal.parser -> jdk.test.lib.hprof.parser
-com.sun.tools.hat.internal.util -> jdk.test.lib.hprof.util
-
-jhat was added in JDK 6 and its original implementation was from
-java.net HAT project [1]. jhat is an experimental, unsupported tool.
-There hasn't been much update to jhat tool in the JDK. In addition,
-there are several better heap dump visualizer/analyzer emerged since
-JDK 5/6 serviceability support.
-
-[1] https://java.net/projects/hat
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/AbstractJavaHeapObjectVisitor.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-/**
- * A visitor for a JavaThing. @see JavaObject#visitReferencedObjects()
- *
- */
-
-
-abstract public class AbstractJavaHeapObjectVisitor
- implements JavaHeapObjectVisitor {
- abstract public void visit(JavaHeapObject other);
-
- /**
- * Should the given field be excluded from the set of things visited?
- * @return true if it should.
- */
- public boolean exclude(JavaClass clazz, JavaField f) {
- return false;
- }
-
- /**
- * @return true iff exclude might ever return true
- */
- public boolean mightExclude() {
- return false;
- }
-
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/ArrayTypeCodes.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-/**
- * Primitive array type codes as defined by VM specification.
- *
- */
-public interface ArrayTypeCodes {
- // Typecodes for array elements.
- // Refer to newarray instruction in VM Spec.
- public static final int T_BOOLEAN = 4;
- public static final int T_CHAR = 5;
- public static final int T_FLOAT = 6;
- public static final int T_DOUBLE = 7;
- public static final int T_BYTE = 8;
- public static final int T_SHORT = 9;
- public static final int T_INT = 10;
- public static final int T_LONG = 11;
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/HackJavaValue.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-/**
- * This is used to represent values that the program doesn't really understand.
- * This includes the null vlaue, and unresolved references (which shouldn't
- * happen in well-formed hprof files).
- *
- *
- * @author Bill Foote
- */
-
-
-
-
-public class HackJavaValue extends JavaValue {
-
- private String value;
- private int size;
-
- public HackJavaValue(String value, int size) {
- this.value = value;
- this.size = size;
- }
-
- public String toString() {
- return value;
- }
-
- public int getSize() {
- return size;
- }
-
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaBoolean.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-/**
- * Represents a boolean (i.e. a boolean field in an instance).
- *
- * @author Bill Foote
- */
-
-
-public class JavaBoolean extends JavaValue {
-
- boolean value;
-
- public JavaBoolean(boolean value) {
- this.value = value;
- }
-
- public String toString() {
- return "" + value;
- }
-
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaByte.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-/**
- * Represents an byte (i.e. a byte field in an instance).
- *
- * @author Bill Foote
- */
-
-
-public class JavaByte extends JavaValue {
-
- byte value;
-
- public JavaByte(byte value) {
- this.value = value;
- }
-
- public String toString() {
- return "0x" + Integer.toString(((int) value) & 0xff, 16);
- }
-
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaChar.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-/**
- * Represents a char (i.e. a char field in an instance).
- *
- * @author Bill Foote
- */
-
-
-public class JavaChar extends JavaValue {
-
- char value;
-
- public JavaChar(char value) {
- this.value = value;
- }
-
- public String toString() {
- return "" + value;
- }
-
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaClass.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,503 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-import java.util.Vector;
-import java.util.Enumeration;
-import jdk.test.lib.hprof.util.CompositeEnumeration;
-import jdk.test.lib.hprof.parser.ReadBuffer;
-
-/**
- *
- * @author Bill Foote
- */
-
-
-public class JavaClass extends JavaHeapObject {
- // my id
- private long id;
- // my name
- private String name;
-
- // These are JavaObjectRef before resolve
- private JavaThing superclass;
- private JavaThing loader;
- private JavaThing signers;
- private JavaThing protectionDomain;
-
- // non-static fields
- private JavaField[] fields;
- // static fields
- private JavaStatic[] statics;
-
- private static final JavaClass[] EMPTY_CLASS_ARRAY = new JavaClass[0];
- // my subclasses
- private JavaClass[] subclasses = EMPTY_CLASS_ARRAY;
-
- // my instances
- private Vector<JavaHeapObject> instances = new Vector<JavaHeapObject>();
-
- // Who I belong to. Set on resolve.
- private Snapshot mySnapshot;
-
- // Size of an instance, including VM overhead
- private int instanceSize;
- // Total number of fields including inherited ones
- private int totalNumFields;
-
-
- public JavaClass(long id, String name, long superclassId, long loaderId,
- long signersId, long protDomainId,
- JavaField[] fields, JavaStatic[] statics,
- int instanceSize) {
- this.id = id;
- this.name = name;
- this.superclass = new JavaObjectRef(superclassId);
- this.loader = new JavaObjectRef(loaderId);
- this.signers = new JavaObjectRef(signersId);
- this.protectionDomain = new JavaObjectRef(protDomainId);
- this.fields = fields;
- this.statics = statics;
- this.instanceSize = instanceSize;
- }
-
- public JavaClass(String name, long superclassId, long loaderId,
- long signersId, long protDomainId,
- JavaField[] fields, JavaStatic[] statics,
- int instanceSize) {
- this(-1L, name, superclassId, loaderId, signersId,
- protDomainId, fields, statics, instanceSize);
- }
-
- public final JavaClass getClazz() {
- return mySnapshot.getJavaLangClass();
- }
-
- public final int getIdentifierSize() {
- return mySnapshot.getIdentifierSize();
- }
-
- public final int getMinimumObjectSize() {
- return mySnapshot.getMinimumObjectSize();
- }
-
- public void resolve(Snapshot snapshot) {
- if (mySnapshot != null) {
- return;
- }
- mySnapshot = snapshot;
- resolveSuperclass(snapshot);
- if (superclass != null) {
- ((JavaClass) superclass).addSubclass(this);
- }
-
- loader = loader.dereference(snapshot, null);
- signers = signers.dereference(snapshot, null);
- protectionDomain = protectionDomain.dereference(snapshot, null);
-
- for (int i = 0; i < statics.length; i++) {
- statics[i].resolve(this, snapshot);
- }
- snapshot.getJavaLangClass().addInstance(this);
- super.resolve(snapshot);
- return;
- }
-
- /**
- * Resolve our superclass. This might be called well before
- * all instances are available (like when reading deferred
- * instances in a 1.2 dump file :-) Calling this is sufficient
- * to be able to explore this class' fields.
- */
- public void resolveSuperclass(Snapshot snapshot) {
- if (superclass == null) {
- // We must be java.lang.Object, so we have no superclass.
- } else {
- totalNumFields = fields.length;
- superclass = superclass.dereference(snapshot, null);
- if (superclass == snapshot.getNullThing()) {
- superclass = null;
- } else {
- try {
- JavaClass sc = (JavaClass) superclass;
- sc.resolveSuperclass(snapshot);
- totalNumFields += sc.totalNumFields;
- } catch (ClassCastException ex) {
- System.out.println("Warning! Superclass of " + name + " is " + superclass);
- superclass = null;
- }
- }
- }
- }
-
- public boolean isString() {
- return mySnapshot.getJavaLangString() == this;
- }
-
- public boolean isClassLoader() {
- return mySnapshot.getJavaLangClassLoader().isAssignableFrom(this);
- }
-
- /**
- * Get a numbered field from this class
- */
- public JavaField getField(int i) {
- if (i < 0 || i >= fields.length) {
- throw new Error("No field " + i + " for " + name);
- }
- return fields[i];
- }
-
- /**
- * Get the total number of fields that are part of an instance of
- * this class. That is, include superclasses.
- */
- public int getNumFieldsForInstance() {
- return totalNumFields;
- }
-
- /**
- * Get a numbered field from all the fields that are part of instance
- * of this class. That is, include superclasses.
- */
- public JavaField getFieldForInstance(int i) {
- if (superclass != null) {
- JavaClass sc = (JavaClass) superclass;
- if (i < sc.totalNumFields) {
- return sc.getFieldForInstance(i);
- }
- i -= sc.totalNumFields;
- }
- return getField(i);
- }
-
- /**
- * Get the class responsible for field i, where i is a field number that
- * could be passed into getFieldForInstance.
- *
- * @see JavaClass.getFieldForInstance()
- */
- public JavaClass getClassForField(int i) {
- if (superclass != null) {
- JavaClass sc = (JavaClass) superclass;
- if (i < sc.totalNumFields) {
- return sc.getClassForField(i);
- }
- }
- return this;
- }
-
- public long getId() {
- return id;
- }
-
- public String getName() {
- return name;
- }
-
- public boolean isArray() {
- return name.indexOf('[') != -1;
- }
-
- public Enumeration<JavaHeapObject> getInstances(boolean includeSubclasses) {
- if (includeSubclasses) {
- Enumeration<JavaHeapObject> res = instances.elements();
- for (int i = 0; i < subclasses.length; i++) {
- res = new CompositeEnumeration(res,
- subclasses[i].getInstances(true));
- }
- return res;
- } else {
- return instances.elements();
- }
- }
-
- /**
- * @return a count of the instances of this class
- */
- public int getInstancesCount(boolean includeSubclasses) {
- int result = instances.size();
- if (includeSubclasses) {
- for (int i = 0; i < subclasses.length; i++) {
- result += subclasses[i].getInstancesCount(includeSubclasses);
- }
- }
- return result;
- }
-
- public JavaClass[] getSubclasses() {
- return subclasses;
- }
-
- /**
- * This can only safely be called after resolve()
- */
- public JavaClass getSuperclass() {
- return (JavaClass) superclass;
- }
-
- /**
- * This can only safely be called after resolve()
- */
- public JavaThing getLoader() {
- return loader;
- }
-
- /**
- * This can only safely be called after resolve()
- */
- public boolean isBootstrap() {
- return loader == mySnapshot.getNullThing();
- }
-
- /**
- * This can only safely be called after resolve()
- */
- public JavaThing getSigners() {
- return signers;
- }
-
- /**
- * This can only safely be called after resolve()
- */
- public JavaThing getProtectionDomain() {
- return protectionDomain;
- }
-
- public JavaField[] getFields() {
- return fields;
- }
-
- /**
- * Includes superclass fields
- */
- public JavaField[] getFieldsForInstance() {
- Vector<JavaField> v = new Vector<JavaField>();
- addFields(v);
- JavaField[] result = new JavaField[v.size()];
- for (int i = 0; i < v.size(); i++) {
- result[i] = v.elementAt(i);
- }
- return result;
- }
-
-
- public JavaStatic[] getStatics() {
- return statics;
- }
-
- // returns value of static field of given name
- public JavaThing getStaticField(String name) {
- for (int i = 0; i < statics.length; i++) {
- JavaStatic s = statics[i];
- if (s.getField().getName().equals(name)) {
- return s.getValue();
- }
- }
- return null;
- }
-
- public String toString() {
- return "class " + name;
- }
-
- public int compareTo(JavaThing other) {
- if (other instanceof JavaClass) {
- return name.compareTo(((JavaClass) other).name);
- }
- return super.compareTo(other);
- }
-
-
- /**
- * @return true iff a variable of type this is assignable from an instance
- * of other
- */
- public boolean isAssignableFrom(JavaClass other) {
- if (this == other) {
- return true;
- } else if (other == null) {
- return false;
- } else {
- return isAssignableFrom((JavaClass) other.superclass);
- // Trivial tail recursion: I have faith in javac.
- }
- }
-
- /**
- * Describe the reference that this thing has to target. This will only
- * be called if target is in the array returned by getChildrenForRootset.
- */
- public String describeReferenceTo(JavaThing target, Snapshot ss) {
- for (int i = 0; i < statics.length; i++) {
- JavaField f = statics[i].getField();
- if (f.hasId()) {
- JavaThing other = statics[i].getValue();
- if (other == target) {
- return "static field " + f.getName();
- }
- }
- }
- return super.describeReferenceTo(target, ss);
- }
-
- /**
- * @return the size of an instance of this class. Gives 0 for an array
- * type.
- */
- public int getInstanceSize() {
- return instanceSize + mySnapshot.getMinimumObjectSize();
- }
-
-
- /**
- * @return The size of all instances of this class. Correctly handles
- * arrays.
- */
- public long getTotalInstanceSize() {
- int count = instances.size();
- if (count == 0 || !isArray()) {
- return count * instanceSize;
- }
-
- // array class and non-zero count, we have to
- // get the size of each instance and sum it
- long result = 0;
- for (int i = 0; i < count; i++) {
- JavaThing t = (JavaThing) instances.elementAt(i);
- result += t.getSize();
- }
- return result;
- }
-
- /**
- * @return the size of this object
- */
- public int getSize() {
- JavaClass cl = mySnapshot.getJavaLangClass();
- if (cl == null) {
- return 0;
- } else {
- return cl.getInstanceSize();
- }
- }
-
- public void visitReferencedObjects(JavaHeapObjectVisitor v) {
- super.visitReferencedObjects(v);
- JavaHeapObject sc = getSuperclass();
- if (sc != null) v.visit(getSuperclass());
-
- JavaThing other;
- other = getLoader();
- if (other instanceof JavaHeapObject) {
- v.visit((JavaHeapObject)other);
- }
- other = getSigners();
- if (other instanceof JavaHeapObject) {
- v.visit((JavaHeapObject)other);
- }
- other = getProtectionDomain();
- if (other instanceof JavaHeapObject) {
- v.visit((JavaHeapObject)other);
- }
-
- for (int i = 0; i < statics.length; i++) {
- JavaField f = statics[i].getField();
- if (!v.exclude(this, f) && f.hasId()) {
- other = statics[i].getValue();
- if (other instanceof JavaHeapObject) {
- v.visit((JavaHeapObject) other);
- }
- }
- }
- }
-
- // package-privates below this point
- final ReadBuffer getReadBuffer() {
- return mySnapshot.getReadBuffer();
- }
-
- final void setNew(JavaHeapObject obj, boolean flag) {
- mySnapshot.setNew(obj, flag);
- }
-
- final boolean isNew(JavaHeapObject obj) {
- return mySnapshot.isNew(obj);
- }
-
- final StackTrace getSiteTrace(JavaHeapObject obj) {
- return mySnapshot.getSiteTrace(obj);
- }
-
- final void addReferenceFromRoot(Root root, JavaHeapObject obj) {
- mySnapshot.addReferenceFromRoot(root, obj);
- }
-
- final Root getRoot(JavaHeapObject obj) {
- return mySnapshot.getRoot(obj);
- }
-
- final Snapshot getSnapshot() {
- return mySnapshot;
- }
-
- void addInstance(JavaHeapObject inst) {
- instances.addElement(inst);
- }
-
- // Internals only below this point
- private void addFields(Vector<JavaField> v) {
- if (superclass != null) {
- ((JavaClass) superclass).addFields(v);
- }
- for (int i = 0; i < fields.length; i++) {
- v.addElement(fields[i]);
- }
- }
-
- private void addSubclassInstances(Vector<JavaHeapObject> v) {
- for (int i = 0; i < subclasses.length; i++) {
- subclasses[i].addSubclassInstances(v);
- }
- for (int i = 0; i < instances.size(); i++) {
- v.addElement(instances.elementAt(i));
- }
- }
-
- private void addSubclass(JavaClass sub) {
- JavaClass newValue[] = new JavaClass[subclasses.length + 1];
- System.arraycopy(subclasses, 0, newValue, 0, subclasses.length);
- newValue[subclasses.length] = sub;
- subclasses = newValue;
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaDouble.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-/**
- * Represents a double (i.e. a double field in an instance).
- *
- * @author Bill Foote
- */
-
-
-public class JavaDouble extends JavaValue {
-
- double value;
-
- public JavaDouble(double value) {
- this.value = value;
- }
-
- public String toString() {
- return Double.toString(value);
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaField.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-
-/**
- *
- * @author Bill Foote
- */
-
-public class JavaField {
-
- private String name;
- private String signature;
-
- public JavaField(String name, String signature) {
- this.name = name;
- this.signature = signature;
- }
-
-
- /**
- * @return true if the type of this field is something that has an ID.
- * int fields, for exampe, don't.
- */
- public boolean hasId() {
- char ch = signature.charAt(0);
- return (ch == '[' || ch == 'L');
- }
-
- public String getName() {
- return name;
- }
-
- public String getSignature() {
- return signature;
- }
-
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaFloat.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-/**
- * Represents a float (i.e. a float field in an instance).
- *
- * @author Bill Foote
- */
-
-
-public class JavaFloat extends JavaValue {
-
- float value;
-
- public JavaFloat(float value) {
- this.value = value;
- }
-
- public String toString() {
- return Float.toString(value);
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaHeapObject.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,207 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
-import jdk.test.lib.hprof.util.Misc;
-
-
-/**
- *
- * @author Bill Foote
- */
-
-/**
- * Represents an object that's allocated out of the Java heap. It occupies
- * memory in the VM, and is the sort of thing that in a JDK 1.1 VM had
- * a handle. It can be a
- * JavaClass, a JavaObjectArray, a JavaValueArray or a JavaObject.
- */
-
-public abstract class JavaHeapObject extends JavaThing {
-
- //
- // Who we refer to. This is heavily optimized for space, because it's
- // well worth trading a bit of speed for less swapping.
- // referers and referersLen go through two phases: Building and
- // resolved. When building, referers might have duplicates, but can
- // be appended to. When resolved, referers has no duplicates or
- // empty slots.
- //
- private JavaThing[] referers = null;
- private int referersLen = 0; // -1 when resolved
-
- public abstract JavaClass getClazz();
- public abstract int getSize();
- public abstract long getId();
-
- /**
- * Do any initialization this thing needs after its data is read in.
- * Subclasses that override this should call super.resolve().
- */
- public void resolve(Snapshot snapshot) {
- StackTrace trace = snapshot.getSiteTrace(this);
- if (trace != null) {
- trace.resolve(snapshot);
- }
- }
-
- //
- // Eliminate duplicates from referers, and size the array exactly.
- // This sets us up to answer queries. See the comments around the
- // referers data member for details.
- //
- void setupReferers() {
- if (referersLen > 1) {
- // Copy referers to map, screening out duplicates
- Map<JavaThing, JavaThing> map = new HashMap<JavaThing, JavaThing>();
- for (int i = 0; i < referersLen; i++) {
- if (map.get(referers[i]) == null) {
- map.put(referers[i], referers[i]);
- }
- }
-
- // Now copy into the array
- referers = new JavaThing[map.size()];
- map.keySet().toArray(referers);
- }
- referersLen = -1;
- }
-
-
- /**
- * @return the id of this thing as hex string
- */
- public String getIdString() {
- return Misc.toHex(getId());
- }
-
- public String toString() {
- return getClazz().getName() + "@" + getIdString();
- }
-
- /**
- * @return the StackTrace of the point of allocation of this object,
- * or null if unknown
- */
- public StackTrace getAllocatedFrom() {
- return getClazz().getSiteTrace(this);
- }
-
- public boolean isNew() {
- return getClazz().isNew(this);
- }
-
- void setNew(boolean flag) {
- getClazz().setNew(this, flag);
- }
-
- /**
- * Tell the visitor about all of the objects we refer to
- */
- public void visitReferencedObjects(JavaHeapObjectVisitor v) {
- v.visit(getClazz());
- }
-
- void addReferenceFrom(JavaHeapObject other) {
- if (referersLen == 0) {
- referers = new JavaThing[1]; // It was null
- } else if (referersLen == referers.length) {
- JavaThing[] copy = new JavaThing[(3 * (referersLen + 1)) / 2];
- System.arraycopy(referers, 0, copy, 0, referersLen);
- referers = copy;
- }
- referers[referersLen++] = other;
- // We just append to referers here. Measurements have shown that
- // around 10% to 30% are duplicates, so it's better to just append
- // blindly and screen out all the duplicates at once.
- }
-
- void addReferenceFromRoot(Root r) {
- getClazz().addReferenceFromRoot(r, this);
- }
-
- /**
- * If the rootset includes this object, return a Root describing one
- * of the reasons why.
- */
- public Root getRoot() {
- return getClazz().getRoot(this);
- }
-
- /**
- * Tell who refers to us.
- *
- * @return an Enumeration of JavaHeapObject instances
- */
- public Enumeration<JavaThing> getReferers() {
- if (referersLen != -1) {
- throw new RuntimeException("not resolved: " + getIdString());
- }
- return new Enumeration<JavaThing>() {
-
- private int num = 0;
-
- public boolean hasMoreElements() {
- return referers != null && num < referers.length;
- }
-
- public JavaThing nextElement() {
- return referers[num++];
- }
- };
- }
-
- /**
- * Given other, which the caller promises is in referers, determines if
- * the reference is only a weak reference.
- */
- public boolean refersOnlyWeaklyTo(Snapshot ss, JavaThing other) {
- return false;
- }
-
- /**
- * Describe the reference that this thing has to target. This will only
- * be called if target is in the array returned by getChildrenForRootset.
- */
- public String describeReferenceTo(JavaThing target, Snapshot ss) {
- return "??";
- }
-
- public boolean isHeapAllocated() {
- return true;
- }
-
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaHeapObjectVisitor.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-/**
- * A visitor for a JavaThing. @see JavaObject#visitReferencedObjects()
- *
- * @author Bill Foote
- */
-
-
-public interface JavaHeapObjectVisitor {
- public void visit(JavaHeapObject other);
-
- /**
- * Should the given field be excluded from the set of things visited?
- * @return true if it should.
- */
- public boolean exclude(JavaClass clazz, JavaField f);
-
- /**
- * @return true iff exclude might ever return true
- */
- public boolean mightExclude();
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaInt.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-/**
- * Represents an integer (i.e. an int field in an instance).
- *
- * @author Bill Foote
- */
-
-
-public class JavaInt extends JavaValue {
-
- int value;
-
- public JavaInt(int value) {
- this.value = value;
- }
-
- public String toString() {
- return "" + value;
- }
-
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaLazyReadObject.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-import java.io.IOException;
-import jdk.test.lib.hprof.parser.ReadBuffer;
-
-/*
- * Base class for lazily read Java heap objects.
- */
-public abstract class JavaLazyReadObject extends JavaHeapObject {
-
- // file offset from which this object data starts
- private final long offset;
-
- protected JavaLazyReadObject(long offset) {
- this.offset = offset;
- }
-
- public final int getSize() {
- return getValueLength() + getClazz().getMinimumObjectSize();
- }
-
- protected final long getOffset() {
- return offset;
- }
-
- // return the length of the data for this object
- protected final int getValueLength() {
- try {
- return readValueLength();
- } catch (IOException exp) {
- System.err.println("lazy read failed at offset " + offset);
- exp.printStackTrace();
- return 0;
- }
- }
-
- // get this object's content as byte array
- protected final byte[] getValue() {
- try {
- return readValue();
- } catch (IOException exp) {
- System.err.println("lazy read failed at offset " + offset);
- exp.printStackTrace();
- return Snapshot.EMPTY_BYTE_ARRAY;
- }
- }
-
- // get ID of this object
- public final long getId() {
- try {
- ReadBuffer buf = getClazz().getReadBuffer();
- int idSize = getClazz().getIdentifierSize();
- if (idSize == 4) {
- return ((long)buf.getInt(offset)) & Snapshot.SMALL_ID_MASK;
- } else {
- return buf.getLong(offset);
- }
- } catch (IOException exp) {
- System.err.println("lazy read failed at offset " + offset);
- exp.printStackTrace();
- return -1;
- }
- }
-
- protected abstract int readValueLength() throws IOException;
- protected abstract byte[] readValue() throws IOException;
-
- // make Integer or Long for given object ID
- protected static Number makeId(long id) {
- if ((id & ~Snapshot.SMALL_ID_MASK) == 0) {
- return (int)id;
- } else {
- return id;
- }
- }
-
- // get ID as long value from Number
- protected static long getIdValue(Number num) {
- long id = num.longValue();
- if (num instanceof Integer) {
- id &= Snapshot.SMALL_ID_MASK;
- }
- return id;
- }
-
- // read object ID from given index from given byte array
- protected final long objectIdAt(int index, byte[] data) {
- int idSize = getClazz().getIdentifierSize();
- if (idSize == 4) {
- return ((long)intAt(index, data)) & Snapshot.SMALL_ID_MASK;
- } else {
- return longAt(index, data);
- }
- }
-
- // utility methods to read primitive types from byte array
- protected static byte byteAt(int index, byte[] value) {
- return value[index];
- }
-
- protected static boolean booleanAt(int index, byte[] value) {
- return (value[index] & 0xff) == 0? false: true;
- }
-
- protected static char charAt(int index, byte[] value) {
- int b1 = ((int) value[index++] & 0xff);
- int b2 = ((int) value[index++] & 0xff);
- return (char) ((b1 << 8) + b2);
- }
-
- protected static short shortAt(int index, byte[] value) {
- int b1 = ((int) value[index++] & 0xff);
- int b2 = ((int) value[index++] & 0xff);
- return (short) ((b1 << 8) + b2);
- }
-
- protected static int intAt(int index, byte[] value) {
- int b1 = ((int) value[index++] & 0xff);
- int b2 = ((int) value[index++] & 0xff);
- int b3 = ((int) value[index++] & 0xff);
- int b4 = ((int) value[index++] & 0xff);
- return ((b1 << 24) + (b2 << 16) + (b3 << 8) + b4);
- }
-
- protected static long longAt(int index, byte[] value) {
- long val = 0;
- for (int j = 0; j < 8; j++) {
- val = val << 8;
- int b = ((int)value[index++]) & 0xff;
- val |= b;
- }
- return val;
- }
-
- protected static float floatAt(int index, byte[] value) {
- int val = intAt(index, value);
- return Float.intBitsToFloat(val);
- }
-
- protected static double doubleAt(int index, byte[] value) {
- long val = longAt(index, value);
- return Double.longBitsToDouble(val);
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaLong.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-/**
- * Represents a long (i.e. a long field in an instance).
- *
- * @author Bill Foote
- */
-
-
-public class JavaLong extends JavaValue {
-
- long value;
-
- public JavaLong(long value) {
- this.value = value;
- }
-
- public String toString() {
- return Long.toString(value);
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaObject.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,334 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-import java.io.IOException;
-import jdk.test.lib.hprof.parser.ReadBuffer;
-
-/**
- * Represents Java instance
- *
- * @author Bill Foote
- */
-public class JavaObject extends JavaLazyReadObject {
-
- private Object clazz; // Number before resolve
- // JavaClass after resolve
- /**
- * Construct a new JavaObject.
- *
- * @param classID id of the class object
- * @param offset The offset of field data
- */
- public JavaObject(long classID, long offset) {
- super(offset);
- this.clazz = makeId(classID);
- }
-
- public void resolve(Snapshot snapshot) {
- if (clazz instanceof JavaClass) {
- return;
- }
- if (clazz instanceof Number) {
- long classID = getIdValue((Number)clazz);
- clazz = snapshot.findThing(classID);
- if (! (clazz instanceof JavaClass)) {
- warn("Class " + Long.toHexString(classID) + " not found, " +
- "adding fake class!");
- int length;
- ReadBuffer buf = snapshot.getReadBuffer();
- int idSize = snapshot.getIdentifierSize();
- long lenOffset = getOffset() + 2*idSize + 4;
- try {
- length = buf.getInt(lenOffset);
- } catch (IOException exp) {
- throw new RuntimeException(exp);
- }
- clazz = snapshot.addFakeInstanceClass(classID, length);
- }
- } else {
- throw new InternalError("should not reach here");
- }
-
- JavaClass cl = (JavaClass) clazz;
- cl.resolve(snapshot);
-
- // while resolving, parse fields in verbose mode.
- // but, getFields calls parseFields in non-verbose mode
- // to avoid printing warnings repeatedly.
- parseFields(getValue(), true);
-
- cl.addInstance(this);
- super.resolve(snapshot);
- }
-
- /**
- * Are we the same type as other? We are iff our clazz is the
- * same type as other's.
- */
- public boolean isSameTypeAs(JavaThing other) {
- if (!(other instanceof JavaObject)) {
- return false;
- }
- JavaObject oo = (JavaObject) other;
- return getClazz().equals(oo.getClazz());
- }
-
- /**
- * Return our JavaClass object. This may only be called after resolve.
- */
- public JavaClass getClazz() {
- return (JavaClass) clazz;
- }
-
- public JavaThing[] getFields() {
- // pass false to verbose mode so that dereference
- // warnings are not printed.
- return parseFields(getValue(), false);
- }
-
- // returns the value of field of given name
- public JavaThing getField(String name) {
- JavaThing[] flds = getFields();
- JavaField[] instFields = getClazz().getFieldsForInstance();
- for (int i = 0; i < instFields.length; i++) {
- if (instFields[i].getName().equals(name)) {
- return flds[i];
- }
- }
- return null;
- }
-
- public int compareTo(JavaThing other) {
- if (other instanceof JavaObject) {
- JavaObject oo = (JavaObject) other;
- return getClazz().getName().compareTo(oo.getClazz().getName());
- }
- return super.compareTo(other);
- }
-
- public void visitReferencedObjects(JavaHeapObjectVisitor v) {
- super.visitReferencedObjects(v);
- JavaThing[] flds = getFields();
- for (int i = 0; i < flds.length; i++) {
- if (flds[i] != null) {
- if (v.mightExclude()
- && v.exclude(getClazz().getClassForField(i),
- getClazz().getFieldForInstance(i)))
- {
- // skip it
- } else if (flds[i] instanceof JavaHeapObject) {
- v.visit((JavaHeapObject) flds[i]);
- }
- }
- }
- }
-
- public boolean refersOnlyWeaklyTo(Snapshot ss, JavaThing other) {
- if (ss.getWeakReferenceClass() != null) {
- final int referentFieldIndex = ss.getReferentFieldIndex();
- if (ss.getWeakReferenceClass().isAssignableFrom(getClazz())) {
- //
- // REMIND: This introduces a dependency on the JDK
- // implementation that is undesirable.
- JavaThing[] flds = getFields();
- for (int i = 0; i < flds.length; i++) {
- if (i != referentFieldIndex && flds[i] == other) {
- return false;
- }
- }
- return true;
- }
- }
- return false;
- }
-
- /**
- * Describe the reference that this thing has to target. This will only
- * be called if target is in the array returned by getChildrenForRootset.
- */
- public String describeReferenceTo(JavaThing target, Snapshot ss) {
- JavaThing[] flds = getFields();
- for (int i = 0; i < flds.length; i++) {
- if (flds[i] == target) {
- JavaField f = getClazz().getFieldForInstance(i);
- return "field " + f.getName();
- }
- }
- return super.describeReferenceTo(target, ss);
- }
-
- public String toString() {
- if (getClazz().isString()) {
- JavaThing value = getField("value");
- if (value instanceof JavaValueArray) {
- return ((JavaValueArray)value).valueString();
- } else {
- return "null";
- }
- } else {
- return super.toString();
- }
- }
-
- // Internals only below this point
-
- /*
- * Java instance record (HPROF_GC_INSTANCE_DUMP) looks as below:
- *
- * object ID
- * stack trace serial number (int)
- * class ID
- * data length (int)
- * byte[length]
- */
- protected final int readValueLength() throws IOException {
- JavaClass cl = getClazz();
- int idSize = cl.getIdentifierSize();
- long lengthOffset = getOffset() + 2*idSize + 4;
- return cl.getReadBuffer().getInt(lengthOffset);
- }
-
- protected final byte[] readValue() throws IOException {
- JavaClass cl = getClazz();
- int idSize = cl.getIdentifierSize();
- ReadBuffer buf = cl.getReadBuffer();
- long offset = getOffset() + 2*idSize + 4;
- int length = buf.getInt(offset);
- if (length == 0) {
- return Snapshot.EMPTY_BYTE_ARRAY;
- } else {
- byte[] res = new byte[length];
- buf.get(offset + 4, res);
- return res;
- }
- }
-
- private JavaThing[] parseFields(byte[] data, boolean verbose) {
- JavaClass cl = getClazz();
- int target = cl.getNumFieldsForInstance();
- JavaField[] fields = cl.getFields();
- JavaThing[] fieldValues = new JavaThing[target];
- Snapshot snapshot = cl.getSnapshot();
- int idSize = snapshot.getIdentifierSize();
- int fieldNo = 0;
- // In the dump file, the fields are stored in this order:
- // fields of most derived class (immediate class) are stored
- // first and then the super class and so on. In this object,
- // fields are stored in the reverse ("natural") order. i.e.,
- // fields of most super class are stored first.
-
- // target variable is used to compensate for the fact that
- // the dump file starts field values from the leaf working
- // upwards in the inheritance hierarchy, whereas JavaObject
- // starts with the top of the inheritance hierarchy and works down.
- target -= fields.length;
- JavaClass currClass = cl;
- int index = 0;
- for (int i = 0; i < fieldValues.length; i++, fieldNo++) {
- while (fieldNo >= fields.length) {
- currClass = currClass.getSuperclass();
- fields = currClass.getFields();
- fieldNo = 0;
- target -= fields.length;
- }
- JavaField f = fields[fieldNo];
- char sig = f.getSignature().charAt(0);
- switch (sig) {
- case 'L':
- case '[': {
- long id = objectIdAt(index, data);
- index += idSize;
- JavaObjectRef ref = new JavaObjectRef(id);
- fieldValues[target+fieldNo] = ref.dereference(snapshot, f, verbose);
- break;
- }
- case 'Z': {
- byte value = byteAt(index, data);
- index++;
- fieldValues[target+fieldNo] = new JavaBoolean(value != 0);
- break;
- }
- case 'B': {
- byte value = byteAt(index, data);
- index++;
- fieldValues[target+fieldNo] = new JavaByte(value);
- break;
- }
- case 'S': {
- short value = shortAt(index, data);
- index += 2;
- fieldValues[target+fieldNo] = new JavaShort(value);
- break;
- }
- case 'C': {
- char value = charAt(index, data);
- index += 2;
- fieldValues[target+fieldNo] = new JavaChar(value);
- break;
- }
- case 'I': {
- int value = intAt(index, data);
- index += 4;
- fieldValues[target+fieldNo] = new JavaInt(value);
- break;
- }
- case 'J': {
- long value = longAt(index, data);
- index += 8;
- fieldValues[target+fieldNo] = new JavaLong(value);
- break;
- }
- case 'F': {
- float value = floatAt(index, data);
- index += 4;
- fieldValues[target+fieldNo] = new JavaFloat(value);
- break;
- }
- case 'D': {
- double value = doubleAt(index, data);
- index += 8;
- fieldValues[target+fieldNo] = new JavaDouble(value);
- break;
- }
- default:
- throw new RuntimeException("invalid signature: " + sig);
- }
- }
- return fieldValues;
- }
-
- private void warn(String msg) {
- System.out.println("WARNING: " + msg);
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaObjectArray.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,172 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-import java.io.IOException;
-import jdk.test.lib.hprof.parser.ReadBuffer;
-
-/**
- * @author Bill Foote
- */
-public class JavaObjectArray extends JavaLazyReadObject {
-
- private Object clazz; // Long before resolve, the class after resolve
-
- public JavaObjectArray(long classID, long offset) {
- super(offset);
- this.clazz = makeId(classID);
- }
-
- public JavaClass getClazz() {
- return (JavaClass) clazz;
- }
-
- public void resolve(Snapshot snapshot) {
- if (clazz instanceof JavaClass) {
- return;
- }
- long classID = getIdValue((Number)clazz);
- if (snapshot.isNewStyleArrayClass()) {
- // Modern heap dumps do this
- JavaThing t = snapshot.findThing(classID);
- if (t instanceof JavaClass) {
- clazz = (JavaClass) t;
- }
- }
- if (!(clazz instanceof JavaClass)) {
- JavaThing t = snapshot.findThing(classID);
- if (t != null && t instanceof JavaClass) {
- JavaClass el = (JavaClass) t;
- String nm = el.getName();
- if (!nm.startsWith("[")) {
- nm = "L" + el.getName() + ";";
- }
- clazz = snapshot.getArrayClass(nm);
- }
- }
-
- if (!(clazz instanceof JavaClass)) {
- clazz = snapshot.getOtherArrayType();
- }
- ((JavaClass)clazz).addInstance(this);
- super.resolve(snapshot);
- }
-
- public JavaThing[] getValues() {
- return getElements();
- }
-
- public JavaThing[] getElements() {
- Snapshot snapshot = getClazz().getSnapshot();
- byte[] data = getValue();
- final int idSize = snapshot.getIdentifierSize();
- final int numElements = data.length / idSize;
- JavaThing[] elements = new JavaThing[numElements];
- int index = 0;
- for (int i = 0; i < elements.length; i++) {
- long id = objectIdAt(index, data);
- index += idSize;
- elements[i] = snapshot.findThing(id);
- }
- return elements;
- }
-
- public int compareTo(JavaThing other) {
- if (other instanceof JavaObjectArray) {
- return 0;
- }
- return super.compareTo(other);
- }
-
- public int getLength() {
- return getValueLength() / getClazz().getIdentifierSize();
- }
-
- public void visitReferencedObjects(JavaHeapObjectVisitor v) {
- super.visitReferencedObjects(v);
- JavaThing[] elements = getElements();
- for (int i = 0; i < elements.length; i++) {
- if (elements[i] != null && elements[i] instanceof JavaHeapObject) {
- v.visit((JavaHeapObject) elements[i]);
- }
- }
- }
-
- /**
- * Describe the reference that this thing has to target. This will only
- * be called if target is in the array returned by getChildrenForRootset.
- */
- public String describeReferenceTo(JavaThing target, Snapshot ss) {
- JavaThing[] elements = getElements();
- for (int i = 0; i < elements.length; i++) {
- if (elements[i] == target) {
- return "Element " + i + " of " + this;
- }
- }
- return super.describeReferenceTo(target, ss);
- }
-
- /*
- * Java object array record (HPROF_GC_OBJ_ARRAY_DUMP)
- * looks as below:
- *
- * object ID
- * stack trace serial number (int)
- * array length (int)
- * array class ID
- * array element IDs
- */
- protected final int readValueLength() throws IOException {
- JavaClass cl = getClazz();
- ReadBuffer buf = cl.getReadBuffer();
- int idSize = cl.getIdentifierSize();
- long offset = getOffset() + idSize + 4;
- int len = buf.getInt(offset);
- return len * cl.getIdentifierSize();
- }
-
- protected final byte[] readValue() throws IOException {
- JavaClass cl = getClazz();
- ReadBuffer buf = cl.getReadBuffer();
- int idSize = cl.getIdentifierSize();
- long offset = getOffset() + idSize + 4;
- int len = buf.getInt(offset);
- if (len == 0) {
- return Snapshot.EMPTY_BYTE_ARRAY;
- } else {
- byte[] res = new byte[len * idSize];
- buf.get(offset + 4 + idSize, res);
- return res;
- }
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaObjectRef.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-import jdk.test.lib.hprof.util.Misc;
-
-/**
- * A forward reference to an object. This is an intermediate representation
- * for a JavaThing, when we have the thing's ID, but we might not have read
- * the thing yet.
- *
- * @author Bill Foote
- */
-public class JavaObjectRef extends JavaThing {
- private long id;
-
- public JavaObjectRef(long id) {
- this.id = id;
- }
-
- public long getId() {
- return id;
- }
-
- public boolean isHeapAllocated() {
- return true;
- }
-
- public JavaThing dereference(Snapshot snapshot, JavaField field) {
- return dereference(snapshot, field, true);
- }
-
- public JavaThing dereference(Snapshot snapshot, JavaField field, boolean verbose) {
- if (field != null && !field.hasId()) {
- // If this happens, we must be a field that represents an int.
- // (This only happens with .bod-style files)
- return new JavaLong(id);
- }
- if (id == 0) {
- return snapshot.getNullThing();
- }
- JavaThing result = snapshot.findThing(id);
- if (result == null) {
- if (!snapshot.getUnresolvedObjectsOK() && verbose) {
- String msg = "WARNING: Failed to resolve object id "
- + Misc.toHex(id);
- if (field != null) {
- msg += " for field " + field.getName()
- + " (signature " + field.getSignature() + ")";
- }
- System.out.println(msg);
- // Thread.dumpStack();
- }
- result = new HackJavaValue("Unresolved object "
- + Misc.toHex(id), 0);
- }
- return result;
- }
-
- public int getSize() {
- return 0;
- }
-
- public String toString() {
- return "Unresolved object " + Misc.toHex(id);
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaShort.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-/**
- * Represents a short (i.e. a short field in an instance).
- *
- * @author Bill Foote
- */
-
-
-public class JavaShort extends JavaValue {
-
- short value;
-
- public JavaShort(short value) {
- this.value = value;
- }
-
- public String toString() {
- return "" + value;
- }
-
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaStatic.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-/**
- *
- * @author Bill Foote
- */
-
-/**
- * Represents the value of a static field of a JavaClass
- */
-
-public class JavaStatic {
-
- private JavaField field;
- private JavaThing value;
-
- public JavaStatic(JavaField field, JavaThing value) {
- this.field = field;
- this.value = value;
- }
-
- public void resolve(JavaClass clazz, Snapshot snapshot) {
- long id = -1;
- if (value instanceof JavaObjectRef) {
- id = ((JavaObjectRef)value).getId();
- }
- value = value.dereference(snapshot, field);
- if (value.isHeapAllocated() &&
- clazz.getLoader() == snapshot.getNullThing()) {
- // static fields are only roots if they are in classes
- // loaded by the root classloader.
- JavaHeapObject ho = (JavaHeapObject) value;
- String s = "Static reference from " + clazz.getName()
- + "." + field.getName();
- snapshot.addRoot(new Root(id, clazz.getId(),
- Root.JAVA_STATIC, s));
- }
- }
-
- public JavaField getField() {
- return field;
- }
-
- public JavaThing getValue() {
- return value;
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaThing.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-
-/**
- *
- * @author Bill Foote
- */
-
-
-/**
- * Represents a java "Thing". A thing is anything that can be the value of
- * a field. This includes JavaHeapObject, JavaObjectRef, and JavaValue.
- */
-
-public abstract class JavaThing {
-
- protected JavaThing() {
- }
-
- /**
- * If this is a forward reference, figure out what it really
- * refers to.
- *
- * @param snapshot The snapshot this is for
- * @param field The field this thing represents. If null, it is
- * assumed this thing is an object (and never a value).
- */
- public JavaThing dereference(Snapshot shapshot, JavaField field) {
- return this;
- }
-
-
- /**
- * Are we the same type as other?
- *
- * @see JavaObject.isSameTypeAs()
- */
- public boolean isSameTypeAs(JavaThing other) {
- return getClass() == other.getClass();
- }
- /**
- * @return true iff this represents a heap-allocated object
- */
- abstract public boolean isHeapAllocated();
-
- /**
- * @return the size of this object, in bytes, including VM overhead
- */
- abstract public int getSize();
-
- /**
- * @return a human-readable string representation of this thing
- */
- abstract public String toString();
-
- /**
- * Compare our string representation to other's
- * @see java.lang.String.compareTo()
- */
- public int compareTo(JavaThing other) {
- return toString().compareTo(other.toString());
- }
-
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaValue.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-/**
- * Abstract base class for all value types (ints, longs, floats, etc.)
- *
- * @author Bill Foote
- */
-
-
-
-
-public abstract class JavaValue extends JavaThing {
-
- protected JavaValue() {
- }
-
- public boolean isHeapAllocated() {
- return false;
- }
-
- abstract public String toString();
-
- public int getSize() {
- // The size of a value is already accounted for in the class
- // that has the data member.
- return 0;
- }
-
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/JavaValueArray.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,433 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-import jdk.test.lib.hprof.parser.ReadBuffer;
-import java.io.IOException;
-
-/**
- * An array of values, that is, an array of ints, boolean, floats or the like.
- *
- * @author Bill Foote
- */
-public class JavaValueArray extends JavaLazyReadObject
- /*imports*/ implements ArrayTypeCodes {
-
- private static String arrayTypeName(byte sig) {
- switch (sig) {
- case 'B':
- return "byte[]";
- case 'Z':
- return "boolean[]";
- case 'C':
- return "char[]";
- case 'S':
- return "short[]";
- case 'I':
- return "int[]";
- case 'F':
- return "float[]";
- case 'J':
- return "long[]";
- case 'D':
- return "double[]";
- default:
- throw new RuntimeException("invalid array element sig: " + sig);
- }
- }
-
- private static int elementSize(byte type) {
- switch (type) {
- case T_BYTE:
- case T_BOOLEAN:
- return 1;
- case T_CHAR:
- case T_SHORT:
- return 2;
- case T_INT:
- case T_FLOAT:
- return 4;
- case T_LONG:
- case T_DOUBLE:
- return 8;
- default:
- throw new RuntimeException("invalid array element type: " + type);
- }
- }
-
- /*
- * Java primitive array record (HPROF_GC_PRIM_ARRAY_DUMP) looks
- * as below:
- *
- * object ID
- * stack trace serial number (int)
- * length of the instance data (int)
- * element type (byte)
- * array data
- */
- protected final int readValueLength() throws IOException {
- JavaClass cl = getClazz();
- ReadBuffer buf = cl.getReadBuffer();
- int idSize = cl.getIdentifierSize();
- long offset = getOffset() + idSize + 4;
- // length of the array
- int len = buf.getInt(offset);
- // typecode of array element type
- byte type = buf.getByte(offset + 4);
- return len * elementSize(type);
- }
-
- protected final byte[] readValue() throws IOException {
- JavaClass cl = getClazz();
- ReadBuffer buf = cl.getReadBuffer();
- int idSize = cl.getIdentifierSize();
- long offset = getOffset() + idSize + 4;
- // length of the array
- int length = buf.getInt(offset);
- // typecode of array element type
- byte type = buf.getByte(offset + 4);
- if (length == 0) {
- return Snapshot.EMPTY_BYTE_ARRAY;
- } else {
- length *= elementSize(type);
- byte[] res = new byte[length];
- buf.get(offset + 5, res);
- return res;
- }
- }
-
- // JavaClass set only after resolve.
- private JavaClass clazz;
-
- // This field contains elementSignature byte and
- // divider to be used to calculate length. Note that
- // length of content byte[] is not same as array length.
- // Actual array length is (byte[].length / divider)
- private int data;
-
- // First 8 bits of data is used for element signature
- private static final int SIGNATURE_MASK = 0x0FF;
-
- // Next 8 bits of data is used for length divider
- private static final int LENGTH_DIVIDER_MASK = 0x0FF00;
-
- // Number of bits to shift to get length divider
- private static final int LENGTH_DIVIDER_SHIFT = 8;
-
- public JavaValueArray(byte elementSignature, long offset) {
- super(offset);
- this.data = (elementSignature & SIGNATURE_MASK);
- }
-
- public JavaClass getClazz() {
- return clazz;
- }
-
- public void visitReferencedObjects(JavaHeapObjectVisitor v) {
- super.visitReferencedObjects(v);
- }
-
- public void resolve(Snapshot snapshot) {
- if (clazz instanceof JavaClass) {
- return;
- }
- byte elementSig = getElementType();
- clazz = snapshot.findClass(arrayTypeName(elementSig));
- if (clazz == null) {
- clazz = snapshot.getArrayClass("" + ((char) elementSig));
- }
- getClazz().addInstance(this);
- super.resolve(snapshot);
- }
-
- public int getLength() {
- int divider = (data & LENGTH_DIVIDER_MASK) >>> LENGTH_DIVIDER_SHIFT;
- if (divider == 0) {
- byte elementSignature = getElementType();
- switch (elementSignature) {
- case 'B':
- case 'Z':
- divider = 1;
- break;
- case 'C':
- case 'S':
- divider = 2;
- break;
- case 'I':
- case 'F':
- divider = 4;
- break;
- case 'J':
- case 'D':
- divider = 8;
- break;
- default:
- throw new RuntimeException("unknown primitive type: " +
- elementSignature);
- }
- data |= (divider << LENGTH_DIVIDER_SHIFT);
- }
- return (getValueLength() / divider);
- }
-
- public Object getElements() {
- final int len = getLength();
- final byte et = getElementType();
- byte[] data = getValue();
- int index = 0;
- switch (et) {
- case 'Z': {
- boolean[] res = new boolean[len];
- for (int i = 0; i < len; i++) {
- res[i] = booleanAt(index, data);
- index++;
- }
- return res;
- }
- case 'B': {
- byte[] res = new byte[len];
- for (int i = 0; i < len; i++) {
- res[i] = byteAt(index, data);
- index++;
- }
- return res;
- }
- case 'C': {
- char[] res = new char[len];
- for (int i = 0; i < len; i++) {
- res[i] = charAt(index, data);
- index += 2;
- }
- return res;
- }
- case 'S': {
- short[] res = new short[len];
- for (int i = 0; i < len; i++) {
- res[i] = shortAt(index, data);
- index += 2;
- }
- return res;
- }
- case 'I': {
- int[] res = new int[len];
- for (int i = 0; i < len; i++) {
- res[i] = intAt(index, data);
- index += 4;
- }
- return res;
- }
- case 'J': {
- long[] res = new long[len];
- for (int i = 0; i < len; i++) {
- res[i] = longAt(index, data);
- index += 8;
- }
- return res;
- }
- case 'F': {
- float[] res = new float[len];
- for (int i = 0; i < len; i++) {
- res[i] = floatAt(index, data);
- index += 4;
- }
- return res;
- }
- case 'D': {
- double[] res = new double[len];
- for (int i = 0; i < len; i++) {
- res[i] = doubleAt(index, data);
- index += 8;
- }
- return res;
- }
- default: {
- throw new RuntimeException("unknown primitive type?");
- }
- }
- }
-
- public byte getElementType() {
- return (byte) (data & SIGNATURE_MASK);
- }
-
- private void checkIndex(int index) {
- if (index < 0 || index >= getLength()) {
- throw new ArrayIndexOutOfBoundsException(index);
- }
- }
-
- private void requireType(char type) {
- if (getElementType() != type) {
- throw new RuntimeException("not of type : " + type);
- }
- }
-
- public boolean getBooleanAt(int index) {
- checkIndex(index);
- requireType('Z');
- return booleanAt(index, getValue());
- }
-
- public byte getByteAt(int index) {
- checkIndex(index);
- requireType('B');
- return byteAt(index, getValue());
- }
-
- public char getCharAt(int index) {
- checkIndex(index);
- requireType('C');
- return charAt(index << 1, getValue());
- }
-
- public short getShortAt(int index) {
- checkIndex(index);
- requireType('S');
- return shortAt(index << 1, getValue());
- }
-
- public int getIntAt(int index) {
- checkIndex(index);
- requireType('I');
- return intAt(index << 2, getValue());
- }
-
- public long getLongAt(int index) {
- checkIndex(index);
- requireType('J');
- return longAt(index << 3, getValue());
- }
-
- public float getFloatAt(int index) {
- checkIndex(index);
- requireType('F');
- return floatAt(index << 2, getValue());
- }
-
- public double getDoubleAt(int index) {
- checkIndex(index);
- requireType('D');
- return doubleAt(index << 3, getValue());
- }
-
- public String valueString() {
- return valueString(true);
- }
-
- public String valueString(boolean bigLimit) {
- // Char arrays deserve special treatment
- StringBuilder result;
- byte[] value = getValue();
- int max = value.length;
- byte elementSignature = getElementType();
- if (elementSignature == 'C') {
- result = new StringBuilder();
- for (int i = 0; i < value.length; ) {
- char val = charAt(i, value);
- result.append(val);
- i += 2;
- }
- } else {
- int limit = 8;
- if (bigLimit) {
- limit = 1000;
- }
- result = new StringBuilder("{");
- int num = 0;
- for (int i = 0; i < value.length; ) {
- if (num > 0) {
- result.append(", ");
- }
- if (num >= limit) {
- result.append("... ");
- break;
- }
- num++;
- switch (elementSignature) {
- case 'Z': {
- boolean val = booleanAt(i, value);
- if (val) {
- result.append("true");
- } else {
- result.append("false");
- }
- i++;
- break;
- }
- case 'B': {
- int val = 0xFF & byteAt(i, value);
- result.append("0x").append(Integer.toString(val, 16));
- i++;
- break;
- }
- case 'S': {
- short val = shortAt(i, value);
- i += 2;
- result.append(val);
- break;
- }
- case 'I': {
- int val = intAt(i, value);
- i += 4;
- result.append(val);
- break;
- }
- case 'J': { // long
- long val = longAt(i, value);
- result.append(val);
- i += 8;
- break;
- }
- case 'F': {
- float val = floatAt(i, value);
- result.append(val);
- i += 4;
- break;
- }
- case 'D': { // double
- double val = doubleAt(i, value);
- result.append(val);
- i += 8;
- break;
- }
- default: {
- throw new RuntimeException("unknown primitive type?");
- }
- }
- }
- result.append('}');
- }
- return result.toString();
- }
-
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/ReachableExcludes.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-
-/**
- * This represents a set of data members that should be excluded from the
- * reachable objects query. This is useful to exclude observers from the
- * transitive closure of objects reachable from a given object, allowing
- * some kind of real determination of the "size" of that object.
- *
- */
-
-public interface ReachableExcludes {
- /**
- * @return true iff the given field is on the hitlist of excluded
- * fields.
- */
- public boolean isExcluded(String fieldName);
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/ReachableExcludesImpl.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.BufferedReader;
-import java.io.IOException;
-
-import java.util.Hashtable;
-
-/**
- * This represents a set of data members that should be excluded from the
- * reachable objects query.
- * This is useful to exclude observers from the
- * transitive closure of objects reachable from a given object, allowing
- * some kind of real determination of the "size" of that object.
- *
- * @author Bill Foote
- */
-public class ReachableExcludesImpl implements ReachableExcludes {
-
- private File excludesFile;
- private long lastModified;
- private Hashtable<String, String> methods; // Used as a bag
-
- /**
- * Create a new ReachableExcludesImpl over the given file. The file will be
- * re-read whenever the timestamp changes.
- */
- public ReachableExcludesImpl(File excludesFile) {
- this.excludesFile = excludesFile;
- readFile();
- }
-
- private void readFileIfNeeded() {
- if (excludesFile.lastModified() != lastModified) {
- synchronized(this) {
- if (excludesFile.lastModified() != lastModified) {
- readFile();
- }
- }
- }
- }
-
- private void readFile() {
- long lm = excludesFile.lastModified();
- Hashtable<String, String> m = new Hashtable<String, String>();
-
- try (BufferedReader r = new BufferedReader(new InputStreamReader(
- new FileInputStream(excludesFile)))) {
- String method;
- while ((method = r.readLine()) != null) {
- m.put(method, method);
- }
- lastModified = lm;
- methods = m; // We want this to be atomic
- } catch (IOException ex) {
- System.out.println("Error reading " + excludesFile + ": " + ex);
- }
- }
-
- /**
- * @return true iff the given field is on the histlist of excluded
- * fields.
- */
- public boolean isExcluded(String fieldName) {
- readFileIfNeeded();
- return methods.get(fieldName) != null;
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/ReachableObjects.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-import java.util.Vector;
-import java.util.Hashtable;
-import java.util.Enumeration;
-
-import jdk.test.lib.hprof.util.ArraySorter;
-import jdk.test.lib.hprof.util.Comparer;
-
-/**
- * @author A. Sundararajan
- */
-
-public class ReachableObjects {
- public ReachableObjects(JavaHeapObject root,
- final ReachableExcludes excludes) {
- this.root = root;
-
- final Hashtable<JavaHeapObject, JavaHeapObject> bag = new Hashtable<JavaHeapObject, JavaHeapObject>();
- final Hashtable<String, String> fieldsExcluded = new Hashtable<String, String>(); //Bag<String>
- final Hashtable<String, String> fieldsUsed = new Hashtable<String, String>(); // Bag<String>
- JavaHeapObjectVisitor visitor = new AbstractJavaHeapObjectVisitor() {
- public void visit(JavaHeapObject t) {
- // Size is zero for things like integer fields
- if (t != null && t.getSize() > 0 && bag.get(t) == null) {
- bag.put(t, t);
- t.visitReferencedObjects(this);
- }
- }
-
- public boolean mightExclude() {
- return excludes != null;
- }
-
- public boolean exclude(JavaClass clazz, JavaField f) {
- if (excludes == null) {
- return false;
- }
- String nm = clazz.getName() + "." + f.getName();
- if (excludes.isExcluded(nm)) {
- fieldsExcluded.put(nm, nm);
- return true;
- } else {
- fieldsUsed.put(nm, nm);
- return false;
- }
- }
- };
- // Put the closure of root and all objects reachable from root into
- // bag (depth first), but don't include root:
- visitor.visit(root);
- bag.remove(root);
-
- // Now grab the elements into a vector, and sort it in decreasing size
- JavaThing[] things = new JavaThing[bag.size()];
- int i = 0;
- for (Enumeration<JavaHeapObject> e = bag.elements(); e.hasMoreElements(); ) {
- things[i++] = (JavaThing) e.nextElement();
- }
- ArraySorter.sort(things, new Comparer() {
- public int compare(Object lhs, Object rhs) {
- JavaThing left = (JavaThing) lhs;
- JavaThing right = (JavaThing) rhs;
- int diff = right.getSize() - left.getSize();
- if (diff != 0) {
- return diff;
- }
- return left.compareTo(right);
- }
- });
- this.reachables = things;
-
- this.totalSize = root.getSize();
- for (i = 0; i < things.length; i++) {
- this.totalSize += things[i].getSize();
- }
-
- excludedFields = getElements(fieldsExcluded);
- usedFields = getElements(fieldsUsed);
- }
-
- public JavaHeapObject getRoot() {
- return root;
- }
-
- public JavaThing[] getReachables() {
- return reachables;
- }
-
- public long getTotalSize() {
- return totalSize;
- }
-
- public String[] getExcludedFields() {
- return excludedFields;
- }
-
- public String[] getUsedFields() {
- return usedFields;
- }
-
- private String[] getElements(Hashtable<?, ?> ht) {
- Object[] keys = ht.keySet().toArray();
- int len = keys.length;
- String[] res = new String[len];
- System.arraycopy(keys, 0, res, 0, len);
- ArraySorter.sortArrayOfStrings(res);
- return res;
- }
-
- private JavaHeapObject root;
- private JavaThing[] reachables;
- private String[] excludedFields;
- private String[] usedFields;
- private long totalSize;
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/ReferenceChain.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-/**
- * Represents a chain of references to some target object
- *
- * @author Bill Foote
- */
-
-public class ReferenceChain {
-
- JavaHeapObject obj; // Object referred to
- ReferenceChain next; // Next in chain
-
- public ReferenceChain(JavaHeapObject obj, ReferenceChain next) {
- this.obj = obj;
- this.next = next;
- }
-
- public JavaHeapObject getObj() {
- return obj;
- }
-
- public ReferenceChain getNext() {
- return next;
- }
-
- public int getDepth() {
- int count = 1;
- ReferenceChain tmp = next;
- while (tmp != null) {
- count++;
- tmp = tmp.next;
- }
- return count;
- }
-
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/Root.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-import jdk.test.lib.hprof.util.Misc;
-
-/**
- *
- * @author Bill Foote
- */
-
-
-/**
- * Represents a member of the rootset, that is, one of the objects that
- * the GC starts from when marking reachable objects.
- */
-
-public class Root {
-
- private long id; // ID of the JavaThing we refer to
- private long refererId; // Thread or Class responsible for this, or 0
- private int index = -1; // Index in Snapshot.roots
- private int type;
- private String description;
- private JavaHeapObject referer = null;
- private StackTrace stackTrace = null;
-
- // Values for type. Higher values are more interesting -- see getType().
- // See also getTypeName()
- public final static int INVALID_TYPE = 0;
- public final static int UNKNOWN = 1;
- public final static int SYSTEM_CLASS = 2;
-
- public final static int NATIVE_LOCAL = 3;
- public final static int NATIVE_STATIC = 4;
- public final static int THREAD_BLOCK = 5;
- public final static int BUSY_MONITOR = 6;
- public final static int JAVA_LOCAL = 7;
- public final static int NATIVE_STACK = 8;
- public final static int JAVA_STATIC = 9;
-
-
- public Root(long id, long refererId, int type, String description) {
- this(id, refererId, type, description, null);
- }
-
-
- public Root(long id, long refererId, int type, String description,
- StackTrace stackTrace) {
- this.id = id;
- this.refererId = refererId;
- this.type = type;
- this.description = description;
- this.stackTrace = stackTrace;
- }
-
- public long getId() {
- return id;
- }
-
- public String getIdString() {
- return Misc.toHex(id);
- }
-
- public String getDescription() {
- if ("".equals(description)) {
- return getTypeName() + " Reference";
- } else {
- return description;
- }
- }
-
- /**
- * Return type. We guarantee that more interesting roots will have
- * a type that is numerically higher.
- */
- public int getType() {
- return type;
- }
-
- public String getTypeName() {
- switch(type) {
- case INVALID_TYPE: return "Invalid (?!?)";
- case UNKNOWN: return "Unknown";
- case SYSTEM_CLASS: return "System Class";
- case NATIVE_LOCAL: return "JNI Local";
- case NATIVE_STATIC: return "JNI Global";
- case THREAD_BLOCK: return "Thread Block";
- case BUSY_MONITOR: return "Busy Monitor";
- case JAVA_LOCAL: return "Java Local";
- case NATIVE_STACK: return "Native Stack (possibly Java local)";
- case JAVA_STATIC: return "Java Static";
- default: return "??";
- }
- }
-
- /**
- * Given two Root instances, return the one that is most interesting.
- */
- public Root mostInteresting(Root other) {
- if (other.type > this.type) {
- return other;
- } else {
- return this;
- }
- }
-
- /**
- * Get the object that's responsible for this root, if there is one.
- * This will be null, a Thread object, or a Class object.
- */
- public JavaHeapObject getReferer() {
- return referer;
- }
-
- /**
- * @return the stack trace responsible for this root, or null if there
- * is none.
- */
- public StackTrace getStackTrace() {
- return stackTrace;
- }
-
- /**
- * @return The index of this root in Snapshot.roots
- */
- public int getIndex() {
- return index;
- }
-
- void resolve(Snapshot ss) {
- if (refererId != 0) {
- referer = ss.findThing(refererId);
- }
- if (stackTrace != null) {
- stackTrace.resolve(ss);
- }
- }
-
- void setIndex(int i) {
- index = i;
- }
-
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/Snapshot.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,635 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-import java.lang.ref.SoftReference;
-import java.util.*;
-
-import jdk.test.lib.hprof.parser.ReadBuffer;
-import jdk.test.lib.hprof.util.Misc;
-
-/**
- *
- * @author Bill Foote
- */
-
-/**
- * Represents a snapshot of the Java objects in the VM at one instant.
- * This is the top-level "model" object read out of a single .hprof or .bod
- * file.
- */
-
-public class Snapshot implements AutoCloseable {
-
- public static final long SMALL_ID_MASK = 0x0FFFFFFFFL;
- public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
-
- private static final JavaField[] EMPTY_FIELD_ARRAY = new JavaField[0];
- private static final JavaStatic[] EMPTY_STATIC_ARRAY = new JavaStatic[0];
-
- // all heap objects
- private Hashtable<Number, JavaHeapObject> heapObjects =
- new Hashtable<Number, JavaHeapObject>();
-
- private Hashtable<Number, JavaClass> fakeClasses =
- new Hashtable<Number, JavaClass>();
-
- // all Roots in this Snapshot
- private Vector<Root> roots = new Vector<Root>();
-
- // name-to-class map
- private Map<String, JavaClass> classes =
- new TreeMap<String, JavaClass>();
-
- // new objects relative to a baseline - lazily initialized
- private volatile Map<JavaHeapObject, Boolean> newObjects;
-
- // allocation site traces for all objects - lazily initialized
- private volatile Map<JavaHeapObject, StackTrace> siteTraces;
-
- // object-to-Root map for all objects
- private Map<JavaHeapObject, Root> rootsMap =
- new HashMap<JavaHeapObject, Root>();
-
- // soft cache of finalizeable objects - lazily initialized
- private SoftReference<Vector<?>> finalizablesCache;
-
- // represents null reference
- private JavaThing nullThing;
-
- // java.lang.ref.Reference class
- private JavaClass weakReferenceClass;
- // index of 'referent' field in java.lang.ref.Reference class
- private int referentFieldIndex;
-
- // java.lang.Class class
- private JavaClass javaLangClass;
- // java.lang.String class
- private JavaClass javaLangString;
- // java.lang.ClassLoader class
- private JavaClass javaLangClassLoader;
-
- // unknown "other" array class
- private volatile JavaClass otherArrayType;
- // Stuff to exclude from reachable query
- private ReachableExcludes reachableExcludes;
- // the underlying heap dump buffer
- private ReadBuffer readBuf;
-
- // True iff some heap objects have isNew set
- private boolean hasNewSet;
- private boolean unresolvedObjectsOK;
-
- // whether object array instances have new style class or
- // old style (element) class.
- private boolean newStyleArrayClass;
-
- // object id size in the heap dump
- private int identifierSize = 4;
-
- // minimum object size - accounts for object header in
- // most Java virtual machines - we assume 2 identifierSize
- // (which is true for Sun's hotspot JVM).
- private int minimumObjectSize;
-
- public Snapshot(ReadBuffer buf) {
- nullThing = new HackJavaValue("<null>", 0);
- readBuf = buf;
- }
-
- public void setSiteTrace(JavaHeapObject obj, StackTrace trace) {
- if (trace != null && trace.getFrames().length != 0) {
- initSiteTraces();
- siteTraces.put(obj, trace);
- }
- }
-
- public StackTrace getSiteTrace(JavaHeapObject obj) {
- if (siteTraces != null) {
- return siteTraces.get(obj);
- } else {
- return null;
- }
- }
-
- public void setNewStyleArrayClass(boolean value) {
- newStyleArrayClass = value;
- }
-
- public boolean isNewStyleArrayClass() {
- return newStyleArrayClass;
- }
-
- public void setIdentifierSize(int size) {
- identifierSize = size;
- minimumObjectSize = 2 * size;
- }
-
- public int getIdentifierSize() {
- return identifierSize;
- }
-
- public int getMinimumObjectSize() {
- return minimumObjectSize;
- }
-
- public void addHeapObject(long id, JavaHeapObject ho) {
- heapObjects.put(makeId(id), ho);
- }
-
- public void addRoot(Root r) {
- r.setIndex(roots.size());
- roots.addElement(r);
- }
-
- public void addClass(long id, JavaClass c) {
- addHeapObject(id, c);
- putInClassesMap(c);
- }
-
- JavaClass addFakeInstanceClass(long classID, int instSize) {
- // Create a fake class name based on ID.
- String name = "unknown-class<@" + Misc.toHex(classID) + ">";
-
- // Create fake fields convering the given instance size.
- // Create as many as int type fields and for the left over
- // size create byte type fields.
- int numInts = instSize / 4;
- int numBytes = instSize % 4;
- JavaField[] fields = new JavaField[numInts + numBytes];
- int i;
- for (i = 0; i < numInts; i++) {
- fields[i] = new JavaField("unknown-field-" + i, "I");
- }
- for (i = 0; i < numBytes; i++) {
- fields[i + numInts] = new JavaField("unknown-field-" +
- i + numInts, "B");
- }
-
- // Create fake instance class
- JavaClass c = new JavaClass(name, 0, 0, 0, 0, fields,
- EMPTY_STATIC_ARRAY, instSize);
- // Add the class
- addFakeClass(makeId(classID), c);
- return c;
- }
-
-
- /**
- * @return true iff it's possible that some JavaThing instances might
- * isNew set
- *
- * @see JavaThing.isNew()
- */
- public boolean getHasNewSet() {
- return hasNewSet;
- }
-
- //
- // Used in the body of resolve()
- //
- private static class MyVisitor extends AbstractJavaHeapObjectVisitor {
- JavaHeapObject t;
- public void visit(JavaHeapObject other) {
- other.addReferenceFrom(t);
- }
- }
-
- // To show heap parsing progress, we print a '.' after this limit
- private static final int DOT_LIMIT = 5000;
-
- /**
- * Called after reading complete, to initialize the structure
- */
- public void resolve(boolean calculateRefs) {
- System.out.println("Resolving " + heapObjects.size() + " objects...");
-
- // First, resolve the classes. All classes must be resolved before
- // we try any objects, because the objects use classes in their
- // resolution.
- javaLangClass = findClass("java.lang.Class");
- if (javaLangClass == null) {
- System.out.println("WARNING: hprof file does not include java.lang.Class!");
- javaLangClass = new JavaClass("java.lang.Class", 0, 0, 0, 0,
- EMPTY_FIELD_ARRAY, EMPTY_STATIC_ARRAY, 0);
- addFakeClass(javaLangClass);
- }
- javaLangString = findClass("java.lang.String");
- if (javaLangString == null) {
- System.out.println("WARNING: hprof file does not include java.lang.String!");
- javaLangString = new JavaClass("java.lang.String", 0, 0, 0, 0,
- EMPTY_FIELD_ARRAY, EMPTY_STATIC_ARRAY, 0);
- addFakeClass(javaLangString);
- }
- javaLangClassLoader = findClass("java.lang.ClassLoader");
- if (javaLangClassLoader == null) {
- System.out.println("WARNING: hprof file does not include java.lang.ClassLoader!");
- javaLangClassLoader = new JavaClass("java.lang.ClassLoader", 0, 0, 0, 0,
- EMPTY_FIELD_ARRAY, EMPTY_STATIC_ARRAY, 0);
- addFakeClass(javaLangClassLoader);
- }
-
- for (JavaHeapObject t : heapObjects.values()) {
- if (t instanceof JavaClass) {
- t.resolve(this);
- }
- }
-
- // Now, resolve everything else.
- for (JavaHeapObject t : heapObjects.values()) {
- if (!(t instanceof JavaClass)) {
- t.resolve(this);
- }
- }
-
- heapObjects.putAll(fakeClasses);
- fakeClasses.clear();
-
- weakReferenceClass = findClass("java.lang.ref.Reference");
- referentFieldIndex = 0;
- if (weakReferenceClass != null) {
- JavaField[] fields = weakReferenceClass.getFieldsForInstance();
- for (int i = 0; i < fields.length; i++) {
- if ("referent".equals(fields[i].getName())) {
- referentFieldIndex = i;
- break;
- }
- }
- }
-
- if (calculateRefs) {
- calculateReferencesToObjects();
- System.out.print("Eliminating duplicate references");
- System.out.flush();
- // This println refers to the *next* step
- }
- int count = 0;
- for (JavaHeapObject t : heapObjects.values()) {
- t.setupReferers();
- ++count;
- if (calculateRefs && count % DOT_LIMIT == 0) {
- System.out.print(".");
- System.out.flush();
- }
- }
- if (calculateRefs) {
- System.out.println("");
- }
-
- // to ensure that Iterator.remove() on getClasses()
- // result will throw exception..
- classes = Collections.unmodifiableMap(classes);
- }
-
- private void calculateReferencesToObjects() {
- System.out.print("Chasing references, expect "
- + (heapObjects.size() / DOT_LIMIT) + " dots");
- System.out.flush();
- int count = 0;
- MyVisitor visitor = new MyVisitor();
- for (JavaHeapObject t : heapObjects.values()) {
- visitor.t = t;
- // call addReferenceFrom(t) on all objects t references:
- t.visitReferencedObjects(visitor);
- ++count;
- if (count % DOT_LIMIT == 0) {
- System.out.print(".");
- System.out.flush();
- }
- }
- System.out.println();
- for (Root r : roots) {
- r.resolve(this);
- JavaHeapObject t = findThing(r.getId());
- if (t != null) {
- t.addReferenceFromRoot(r);
- }
- }
- }
-
- public void markNewRelativeTo(Snapshot baseline) {
- hasNewSet = true;
- for (JavaHeapObject t : heapObjects.values()) {
- boolean isNew;
- long thingID = t.getId();
- if (thingID == 0L || thingID == -1L) {
- isNew = false;
- } else {
- JavaThing other = baseline.findThing(t.getId());
- if (other == null) {
- isNew = true;
- } else {
- isNew = !t.isSameTypeAs(other);
- }
- }
- t.setNew(isNew);
- }
- }
-
- public Enumeration<JavaHeapObject> getThings() {
- return heapObjects.elements();
- }
-
-
- public JavaHeapObject findThing(long id) {
- Number idObj = makeId(id);
- JavaHeapObject jho = heapObjects.get(idObj);
- return jho != null? jho : fakeClasses.get(idObj);
- }
-
- public JavaHeapObject findThing(String id) {
- return findThing(Misc.parseHex(id));
- }
-
- public JavaClass findClass(String name) {
- if (name.startsWith("0x")) {
- return (JavaClass) findThing(name);
- } else {
- return classes.get(name);
- }
- }
-
- /**
- * Return an Iterator of all of the classes in this snapshot.
- **/
- public Iterator<JavaClass> getClasses() {
- // note that because classes is a TreeMap
- // classes are already sorted by name
- return classes.values().iterator();
- }
-
- public JavaClass[] getClassesArray() {
- JavaClass[] res = new JavaClass[classes.size()];
- classes.values().toArray(res);
- return res;
- }
-
- public synchronized Enumeration<?> getFinalizerObjects() {
- Vector<?> obj;
- if (finalizablesCache != null &&
- (obj = finalizablesCache.get()) != null) {
- return obj.elements();
- }
-
- JavaClass clazz = findClass("java.lang.ref.Finalizer");
- JavaObject queue = (JavaObject) clazz.getStaticField("queue");
- JavaThing tmp = queue.getField("head");
- Vector<JavaHeapObject> finalizables = new Vector<JavaHeapObject>();
- if (tmp != getNullThing()) {
- JavaObject head = (JavaObject) tmp;
- while (true) {
- JavaHeapObject referent = (JavaHeapObject) head.getField("referent");
- JavaThing next = head.getField("next");
- if (next == getNullThing() || next.equals(head)) {
- break;
- }
- head = (JavaObject) next;
- finalizables.add(referent);
- }
- }
- finalizablesCache = new SoftReference<Vector<?>>(finalizables);
- return finalizables.elements();
- }
-
- public Enumeration<Root> getRoots() {
- return roots.elements();
- }
-
- public Root[] getRootsArray() {
- Root[] res = new Root[roots.size()];
- roots.toArray(res);
- return res;
- }
-
- public Root getRootAt(int i) {
- return roots.elementAt(i);
- }
-
- public ReferenceChain[]
- rootsetReferencesTo(JavaHeapObject target, boolean includeWeak) {
- Vector<ReferenceChain> fifo = new Vector<ReferenceChain>(); // This is slow... A real fifo would help
- // Must be a fifo to go breadth-first
- Hashtable<JavaHeapObject, JavaHeapObject> visited = new Hashtable<JavaHeapObject, JavaHeapObject>();
- // Objects are added here right after being added to fifo.
- Vector<ReferenceChain> result = new Vector<ReferenceChain>();
- visited.put(target, target);
- fifo.addElement(new ReferenceChain(target, null));
-
- while (fifo.size() > 0) {
- ReferenceChain chain = fifo.elementAt(0);
- fifo.removeElementAt(0);
- JavaHeapObject curr = chain.getObj();
- if (curr.getRoot() != null) {
- result.addElement(chain);
- // Even though curr is in the rootset, we want to explore its
- // referers, because they might be more interesting.
- }
- Enumeration<JavaThing> referers = curr.getReferers();
- while (referers.hasMoreElements()) {
- JavaHeapObject t = (JavaHeapObject) referers.nextElement();
- if (t != null && !visited.containsKey(t)) {
- if (includeWeak || !t.refersOnlyWeaklyTo(this, curr)) {
- visited.put(t, t);
- fifo.addElement(new ReferenceChain(t, chain));
- }
- }
- }
- }
-
- ReferenceChain[] realResult = new ReferenceChain[result.size()];
- for (int i = 0; i < result.size(); i++) {
- realResult[i] = result.elementAt(i);
- }
- return realResult;
- }
-
- public boolean getUnresolvedObjectsOK() {
- return unresolvedObjectsOK;
- }
-
- public void setUnresolvedObjectsOK(boolean v) {
- unresolvedObjectsOK = v;
- }
-
- public JavaClass getWeakReferenceClass() {
- return weakReferenceClass;
- }
-
- public int getReferentFieldIndex() {
- return referentFieldIndex;
- }
-
- public JavaThing getNullThing() {
- return nullThing;
- }
-
- public void setReachableExcludes(ReachableExcludes e) {
- reachableExcludes = e;
- }
-
- public ReachableExcludes getReachableExcludes() {
- return reachableExcludes;
- }
-
- // package privates
- void addReferenceFromRoot(Root r, JavaHeapObject obj) {
- Root root = rootsMap.get(obj);
- if (root == null) {
- rootsMap.put(obj, r);
- } else {
- rootsMap.put(obj, root.mostInteresting(r));
- }
- }
-
- Root getRoot(JavaHeapObject obj) {
- return rootsMap.get(obj);
- }
-
- JavaClass getJavaLangClass() {
- return javaLangClass;
- }
-
- JavaClass getJavaLangString() {
- return javaLangString;
- }
-
- JavaClass getJavaLangClassLoader() {
- return javaLangClassLoader;
- }
-
- JavaClass getOtherArrayType() {
- if (otherArrayType == null) {
- synchronized(this) {
- if (otherArrayType == null) {
- addFakeClass(new JavaClass("[<other>", 0, 0, 0, 0,
- EMPTY_FIELD_ARRAY, EMPTY_STATIC_ARRAY,
- 0));
- otherArrayType = findClass("[<other>");
- }
- }
- }
- return otherArrayType;
- }
-
- JavaClass getArrayClass(String elementSignature) {
- JavaClass clazz;
- synchronized(classes) {
- clazz = findClass("[" + elementSignature);
- if (clazz == null) {
- clazz = new JavaClass("[" + elementSignature, 0, 0, 0, 0,
- EMPTY_FIELD_ARRAY, EMPTY_STATIC_ARRAY, 0);
- addFakeClass(clazz);
- // This is needed because the JDK only creates Class structures
- // for array element types, not the arrays themselves. For
- // analysis, though, we need to pretend that there's a
- // JavaClass for the array type, too.
- }
- }
- return clazz;
- }
-
- ReadBuffer getReadBuffer() {
- return readBuf;
- }
-
- void setNew(JavaHeapObject obj, boolean isNew) {
- initNewObjects();
- if (isNew) {
- newObjects.put(obj, Boolean.TRUE);
- }
- }
-
- boolean isNew(JavaHeapObject obj) {
- if (newObjects != null) {
- return newObjects.get(obj) != null;
- } else {
- return false;
- }
- }
-
- // Internals only below this point
- private Number makeId(long id) {
- if (identifierSize == 4) {
- return (int)id;
- } else {
- return id;
- }
- }
-
- private void putInClassesMap(JavaClass c) {
- String name = c.getName();
- if (classes.containsKey(name)) {
- // more than one class can have the same name
- // if so, create a unique name by appending
- // - and id string to it.
- name += "-" + c.getIdString();
- }
- classes.put(c.getName(), c);
- }
-
- private void addFakeClass(JavaClass c) {
- putInClassesMap(c);
- c.resolve(this);
- }
-
- private void addFakeClass(Number id, JavaClass c) {
- fakeClasses.put(id, c);
- addFakeClass(c);
- }
-
- private synchronized void initNewObjects() {
- if (newObjects == null) {
- synchronized (this) {
- if (newObjects == null) {
- newObjects = new HashMap<JavaHeapObject, Boolean>();
- }
- }
- }
- }
-
- private synchronized void initSiteTraces() {
- if (siteTraces == null) {
- synchronized (this) {
- if (siteTraces == null) {
- siteTraces = new HashMap<JavaHeapObject, StackTrace>();
- }
- }
- }
- }
-
- @Override
- public void close() throws Exception {
- readBuf.close();
- }
-
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/StackFrame.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-/**
- *
- * @author Bill Foote
- */
-
-
-/**
- * Represents a stack frame.
- */
-
-public class StackFrame {
-
- //
- // Values for the lineNumber data member. These are the same
- // as the values used in the JDK 1.2 heap dump file.
- //
- public final static int LINE_NUMBER_UNKNOWN = -1;
- public final static int LINE_NUMBER_COMPILED = -2;
- public final static int LINE_NUMBER_NATIVE = -3;
-
- private String methodName;
- private String methodSignature;
- private String className;
- private String sourceFileName;
- private int lineNumber;
-
- public StackFrame(String methodName, String methodSignature,
- String className, String sourceFileName, int lineNumber) {
- this.methodName = methodName;
- this.methodSignature = methodSignature;
- this.className = className;
- this.sourceFileName = sourceFileName;
- this.lineNumber = lineNumber;
- }
-
- public void resolve(Snapshot snapshot) {
- }
-
- public String getMethodName() {
- return methodName;
- }
-
- public String getMethodSignature() {
- return methodSignature;
- }
-
- public String getClassName() {
- return className;
- }
-
- public String getSourceFileName() {
- return sourceFileName;
- }
-
- public String getLineNumber() {
- switch(lineNumber) {
- case LINE_NUMBER_UNKNOWN:
- return "(unknown)";
- case LINE_NUMBER_COMPILED:
- return "(compiled method)";
- case LINE_NUMBER_NATIVE:
- return "(native method)";
- default:
- return Integer.toString(lineNumber, 10);
- }
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/model/StackTrace.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.model;
-
-/**
- *
- * @author Bill Foote
- */
-
-
-/**
- * Represents a stack trace, that is, an ordered collection of stack frames.
- */
-
-public class StackTrace {
-
- private StackFrame[] frames;
-
- public StackTrace(StackFrame[] frames) {
- this.frames = frames;
- }
-
- /**
- * @param depth. The minimum reasonable depth is 1.
- *
- * @return a (possibly new) StackTrace that is limited to depth.
- */
- public StackTrace traceForDepth(int depth) {
- if (depth >= frames.length) {
- return this;
- } else {
- StackFrame[] f = new StackFrame[depth];
- System.arraycopy(frames, 0, f, 0, depth);
- return new StackTrace(f);
- }
- }
-
- public void resolve(Snapshot snapshot) {
- for (int i = 0; i < frames.length; i++) {
- frames[i].resolve(snapshot);
- }
- }
-
- public StackFrame[] getFrames() {
- return frames;
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/parser/FileReadBuffer.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.parser;
-
-import java.io.IOException;
-import java.io.RandomAccessFile;
-
-/**
- * Implementation of ReadBuffer using a RandomAccessFile
- *
- * @author A. Sundararajan
- */
-class FileReadBuffer implements ReadBuffer {
- // underlying file to read
- private RandomAccessFile file;
-
- FileReadBuffer(RandomAccessFile file) {
- this.file = file;
- }
-
- private void seek(long pos) throws IOException {
- file.getChannel().position(pos);
- }
-
- public synchronized void get(long pos, byte[] buf) throws IOException {
- seek(pos);
- file.read(buf);
- }
-
- public synchronized char getChar(long pos) throws IOException {
- seek(pos);
- return file.readChar();
- }
-
- public synchronized byte getByte(long pos) throws IOException {
- seek(pos);
- return (byte) file.read();
- }
-
- public synchronized short getShort(long pos) throws IOException {
- seek(pos);
- return file.readShort();
- }
-
- public synchronized int getInt(long pos) throws IOException {
- seek(pos);
- return file.readInt();
- }
-
- public synchronized long getLong(long pos) throws IOException {
- seek(pos);
- return file.readLong();
- }
-
- @Override
- public void close() throws Exception {
- file.close();
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/parser/HprofReader.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,899 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.parser;
-
-import java.io.*;
-import java.util.Date;
-import java.util.Hashtable;
-import jdk.test.lib.hprof.model.ArrayTypeCodes;
-import jdk.test.lib.hprof.model.*;
-
-/**
- * Object that's used to read a hprof file.
- *
- * @author Bill Foote
- */
-
-public class HprofReader extends Reader /* imports */ implements ArrayTypeCodes {
-
- final static int MAGIC_NUMBER = 0x4a415641;
- // That's "JAVA", the first part of "JAVA PROFILE ..."
- private final static String[] VERSIONS = {
- " PROFILE 1.0\0",
- " PROFILE 1.0.1\0",
- " PROFILE 1.0.2\0",
- };
-
- private final static int VERSION_JDK12BETA3 = 0;
- private final static int VERSION_JDK12BETA4 = 1;
- private final static int VERSION_JDK6 = 2;
- // These version numbers are indices into VERSIONS. The instance data
- // member version is set to one of these, and it drives decisions when
- // reading the file.
- //
- // Version 1.0.1 added HPROF_GC_PRIM_ARRAY_DUMP, which requires no
- // version-sensitive parsing.
- //
- // Version 1.0.1 changed the type of a constant pool entry from a signature
- // to a typecode.
- //
- // Version 1.0.2 added HPROF_HEAP_DUMP_SEGMENT and HPROF_HEAP_DUMP_END
- // to allow a large heap to be dumped as a sequence of heap dump segments.
- //
- // The HPROF agent in J2SE 1.2 through to 5.0 generate a version 1.0.1
- // file. In Java SE 6.0 the version is either 1.0.1 or 1.0.2 depending on
- // the size of the heap (normally it will be 1.0.1 but for multi-GB
- // heaps the heap dump will not fit in a HPROF_HEAP_DUMP record so the
- // dump is generated as version 1.0.2).
-
- //
- // Record types:
- //
- static final int HPROF_UTF8 = 0x01;
- static final int HPROF_LOAD_CLASS = 0x02;
- static final int HPROF_UNLOAD_CLASS = 0x03;
- static final int HPROF_FRAME = 0x04;
- static final int HPROF_TRACE = 0x05;
- static final int HPROF_ALLOC_SITES = 0x06;
- static final int HPROF_HEAP_SUMMARY = 0x07;
-
- static final int HPROF_START_THREAD = 0x0a;
- static final int HPROF_END_THREAD = 0x0b;
-
- static final int HPROF_HEAP_DUMP = 0x0c;
-
- static final int HPROF_CPU_SAMPLES = 0x0d;
- static final int HPROF_CONTROL_SETTINGS = 0x0e;
- static final int HPROF_LOCKSTATS_WAIT_TIME = 0x10;
- static final int HPROF_LOCKSTATS_HOLD_TIME = 0x11;
-
- static final int HPROF_GC_ROOT_UNKNOWN = 0xff;
- static final int HPROF_GC_ROOT_JNI_GLOBAL = 0x01;
- static final int HPROF_GC_ROOT_JNI_LOCAL = 0x02;
- static final int HPROF_GC_ROOT_JAVA_FRAME = 0x03;
- static final int HPROF_GC_ROOT_NATIVE_STACK = 0x04;
- static final int HPROF_GC_ROOT_STICKY_CLASS = 0x05;
- static final int HPROF_GC_ROOT_THREAD_BLOCK = 0x06;
- static final int HPROF_GC_ROOT_MONITOR_USED = 0x07;
- static final int HPROF_GC_ROOT_THREAD_OBJ = 0x08;
-
- static final int HPROF_GC_CLASS_DUMP = 0x20;
- static final int HPROF_GC_INSTANCE_DUMP = 0x21;
- static final int HPROF_GC_OBJ_ARRAY_DUMP = 0x22;
- static final int HPROF_GC_PRIM_ARRAY_DUMP = 0x23;
-
- static final int HPROF_HEAP_DUMP_SEGMENT = 0x1c;
- static final int HPROF_HEAP_DUMP_END = 0x2c;
-
- private final static int T_CLASS = 2;
-
- private int version; // The version of .hprof being read
-
- private int debugLevel;
- private long currPos; // Current position in the file
-
- private int dumpsToSkip;
- private boolean callStack; // If true, read the call stack of objects
-
- private int identifierSize; // Size, in bytes, of identifiers.
- private Hashtable<Long, String> names;
-
- // Hashtable<Integer, ThreadObject>, used to map the thread sequence number
- // (aka "serial number") to the thread object ID for
- // HPROF_GC_ROOT_THREAD_OBJ. ThreadObject is a trivial inner class,
- // at the end of this file.
- private Hashtable<Integer, ThreadObject> threadObjects;
-
- // Hashtable<Long, String>, maps class object ID to class name
- // (with / converted to .)
- private Hashtable<Long, String> classNameFromObjectID;
-
- // Hashtable<Integer, Integer>, maps class serial # to class object ID
- private Hashtable<Integer, String> classNameFromSerialNo;
-
- // Hashtable<Long, StackFrame> maps stack frame ID to StackFrame.
- // Null if we're not tracking them.
- private Hashtable<Long, StackFrame> stackFrames;
-
- // Hashtable<Integer, StackTrace> maps stack frame ID to StackTrace
- // Null if we're not tracking them.
- private Hashtable<Integer, StackTrace> stackTraces;
-
- private Snapshot snapshot;
-
- public HprofReader(String fileName, PositionDataInputStream in,
- int dumpNumber, boolean callStack, int debugLevel)
- throws IOException {
- super(in);
- RandomAccessFile file = new RandomAccessFile(fileName, "r");
- this.snapshot = new Snapshot(MappedReadBuffer.create(file));
- this.dumpsToSkip = dumpNumber - 1;
- this.callStack = callStack;
- this.debugLevel = debugLevel;
- names = new Hashtable<Long, String>();
- threadObjects = new Hashtable<Integer, ThreadObject>(43);
- classNameFromObjectID = new Hashtable<Long, String>();
- if (callStack) {
- stackFrames = new Hashtable<Long, StackFrame>(43);
- stackTraces = new Hashtable<Integer, StackTrace>(43);
- classNameFromSerialNo = new Hashtable<Integer, String>();
- }
- }
-
- public Snapshot read() throws IOException {
- currPos = 4; // 4 because of the magic number
- version = readVersionHeader();
- identifierSize = in.readInt();
- snapshot.setIdentifierSize(identifierSize);
- if (version >= VERSION_JDK12BETA4) {
- snapshot.setNewStyleArrayClass(true);
- } else {
- snapshot.setNewStyleArrayClass(false);
- }
-
- currPos += 4;
- if (identifierSize != 4 && identifierSize != 8) {
- throw new IOException("I'm sorry, but I can't deal with an identifier size of " + identifierSize + ". I can only deal with 4 or 8.");
- }
- System.out.println("Dump file created " + (new Date(in.readLong())));
- currPos += 8;
-
- for (;;) {
- int type;
- try {
- type = in.readUnsignedByte();
- } catch (EOFException ignored) {
- break;
- }
- in.readInt(); // Timestamp of this record
- // Length of record: readInt() will return negative value for record
- // length >2GB. so store 32bit value in long to keep it unsigned.
- long length = in.readInt() & 0xffffffffL;
- if (debugLevel > 0) {
- System.out.println("Read record type " + type
- + ", length " + length
- + " at position " + toHex(currPos));
- }
- if (length < 0) {
- throw new IOException("Bad record length of " + length
- + " at byte " + toHex(currPos+5)
- + " of file.");
- }
- currPos += 9 + length;
- switch (type) {
- case HPROF_UTF8: {
- long id = readID();
- byte[] chars = new byte[(int)length - identifierSize];
- in.readFully(chars);
- names.put(id, new String(chars));
- break;
- }
- case HPROF_LOAD_CLASS: {
- int serialNo = in.readInt(); // Not used
- long classID = readID();
- int stackTraceSerialNo = in.readInt();
- long classNameID = readID();
- Long classIdI = classID;
- String nm = getNameFromID(classNameID).replace('/', '.');
- classNameFromObjectID.put(classIdI, nm);
- if (classNameFromSerialNo != null) {
- classNameFromSerialNo.put(serialNo, nm);
- }
- break;
- }
-
- case HPROF_HEAP_DUMP: {
- if (dumpsToSkip <= 0) {
- try {
- readHeapDump(length, currPos);
- } catch (EOFException exp) {
- handleEOF(exp, snapshot);
- }
- if (debugLevel > 0) {
- System.out.println(" Finished processing instances in heap dump.");
- }
- return snapshot;
- } else {
- dumpsToSkip--;
- skipBytes(length);
- }
- break;
- }
-
- case HPROF_HEAP_DUMP_END: {
- if (version >= VERSION_JDK6) {
- if (dumpsToSkip <= 0) {
- skipBytes(length); // should be no-op
- return snapshot;
- } else {
- // skip this dump (of the end record for a sequence of dump segments)
- dumpsToSkip--;
- }
- } else {
- // HPROF_HEAP_DUMP_END only recognized in >= 1.0.2
- warn("Ignoring unrecognized record type " + type);
- }
- skipBytes(length); // should be no-op
- break;
- }
-
- case HPROF_HEAP_DUMP_SEGMENT: {
- if (version >= VERSION_JDK6) {
- if (dumpsToSkip <= 0) {
- try {
- // read the dump segment
- readHeapDump(length, currPos);
- } catch (EOFException exp) {
- handleEOF(exp, snapshot);
- }
- } else {
- // all segments comprising the heap dump will be skipped
- skipBytes(length);
- }
- } else {
- // HPROF_HEAP_DUMP_SEGMENT only recognized in >= 1.0.2
- warn("Ignoring unrecognized record type " + type);
- skipBytes(length);
- }
- break;
- }
-
- case HPROF_FRAME: {
- if (stackFrames == null) {
- skipBytes(length);
- } else {
- long id = readID();
- String methodName = getNameFromID(readID());
- String methodSig = getNameFromID(readID());
- String sourceFile = getNameFromID(readID());
- int classSer = in.readInt();
- String className = classNameFromSerialNo.get(classSer);
- int lineNumber = in.readInt();
- if (lineNumber < StackFrame.LINE_NUMBER_NATIVE) {
- warn("Weird stack frame line number: " + lineNumber);
- lineNumber = StackFrame.LINE_NUMBER_UNKNOWN;
- }
- stackFrames.put(id,
- new StackFrame(methodName, methodSig,
- className, sourceFile,
- lineNumber));
- }
- break;
- }
- case HPROF_TRACE: {
- if (stackTraces == null) {
- skipBytes(length);
- } else {
- int serialNo = in.readInt();
- int threadSeq = in.readInt(); // Not used
- StackFrame[] frames = new StackFrame[in.readInt()];
- for (int i = 0; i < frames.length; i++) {
- long fid = readID();
- frames[i] = stackFrames.get(fid);
- if (frames[i] == null) {
- throw new IOException("Stack frame " + toHex(fid) + " not found");
- }
- }
- stackTraces.put(serialNo,
- new StackTrace(frames));
- }
- break;
- }
- case HPROF_UNLOAD_CLASS:
- case HPROF_ALLOC_SITES:
- case HPROF_START_THREAD:
- case HPROF_END_THREAD:
- case HPROF_HEAP_SUMMARY:
- case HPROF_CPU_SAMPLES:
- case HPROF_CONTROL_SETTINGS:
- case HPROF_LOCKSTATS_WAIT_TIME:
- case HPROF_LOCKSTATS_HOLD_TIME:
- {
- // Ignore these record types
- skipBytes(length);
- break;
- }
- default: {
- skipBytes(length);
- warn("Ignoring unrecognized record type " + type);
- }
- }
- }
-
- return snapshot;
- }
-
- private void skipBytes(long length) throws IOException {
- while (length > 0) {
- long skipped = in.skip(length);
- if (skipped == 0) {
- // EOF or other problem, throw exception
- throw new EOFException("Couldn't skip enough bytes");
- }
- length -= skipped;
- }
- }
-
- private int readVersionHeader() throws IOException {
- int candidatesLeft = VERSIONS.length;
- boolean[] matched = new boolean[VERSIONS.length];
- for (int i = 0; i < candidatesLeft; i++) {
- matched[i] = true;
- }
-
- int pos = 0;
- while (candidatesLeft > 0) {
- char c = (char) in.readByte();
- currPos++;
- for (int i = 0; i < VERSIONS.length; i++) {
- if (matched[i]) {
- if (c != VERSIONS[i].charAt(pos)) { // Not matched
- matched[i] = false;
- --candidatesLeft;
- } else if (pos == VERSIONS[i].length() - 1) { // Full match
- return i;
- }
- }
- }
- ++pos;
- }
- throw new IOException("Version string not recognized at byte " + (pos+3));
- }
-
- private void readHeapDump(long bytesLeft, long posAtEnd) throws IOException {
- while (bytesLeft > 0) {
- int type = in.readUnsignedByte();
- if (debugLevel > 0) {
- System.out.println(" Read heap sub-record type " + type
- + " at position "
- + toHex(posAtEnd - bytesLeft));
- }
- bytesLeft--;
- switch(type) {
- case HPROF_GC_ROOT_UNKNOWN: {
- long id = readID();
- bytesLeft -= identifierSize;
- snapshot.addRoot(new Root(id, 0, Root.UNKNOWN, ""));
- break;
- }
- case HPROF_GC_ROOT_THREAD_OBJ: {
- long id = readID();
- int threadSeq = in.readInt();
- int stackSeq = in.readInt();
- bytesLeft -= identifierSize + 8;
- threadObjects.put(threadSeq,
- new ThreadObject(id, stackSeq));
- break;
- }
- case HPROF_GC_ROOT_JNI_GLOBAL: {
- long id = readID();
- long globalRefId = readID(); // Ignored, for now
- bytesLeft -= 2*identifierSize;
- snapshot.addRoot(new Root(id, 0, Root.NATIVE_STATIC, ""));
- break;
- }
- case HPROF_GC_ROOT_JNI_LOCAL: {
- long id = readID();
- int threadSeq = in.readInt();
- int depth = in.readInt();
- bytesLeft -= identifierSize + 8;
- ThreadObject to = getThreadObjectFromSequence(threadSeq);
- StackTrace st = getStackTraceFromSerial(to.stackSeq);
- if (st != null) {
- st = st.traceForDepth(depth+1);
- }
- snapshot.addRoot(new Root(id, to.threadId,
- Root.NATIVE_LOCAL, "", st));
- break;
- }
- case HPROF_GC_ROOT_JAVA_FRAME: {
- long id = readID();
- int threadSeq = in.readInt();
- int depth = in.readInt();
- bytesLeft -= identifierSize + 8;
- ThreadObject to = getThreadObjectFromSequence(threadSeq);
- StackTrace st = getStackTraceFromSerial(to.stackSeq);
- if (st != null) {
- st = st.traceForDepth(depth+1);
- }
- snapshot.addRoot(new Root(id, to.threadId,
- Root.JAVA_LOCAL, "", st));
- break;
- }
- case HPROF_GC_ROOT_NATIVE_STACK: {
- long id = readID();
- int threadSeq = in.readInt();
- bytesLeft -= identifierSize + 4;
- ThreadObject to = getThreadObjectFromSequence(threadSeq);
- StackTrace st = getStackTraceFromSerial(to.stackSeq);
- snapshot.addRoot(new Root(id, to.threadId,
- Root.NATIVE_STACK, "", st));
- break;
- }
- case HPROF_GC_ROOT_STICKY_CLASS: {
- long id = readID();
- bytesLeft -= identifierSize;
- snapshot.addRoot(new Root(id, 0, Root.SYSTEM_CLASS, ""));
- break;
- }
- case HPROF_GC_ROOT_THREAD_BLOCK: {
- long id = readID();
- int threadSeq = in.readInt();
- bytesLeft -= identifierSize + 4;
- ThreadObject to = getThreadObjectFromSequence(threadSeq);
- StackTrace st = getStackTraceFromSerial(to.stackSeq);
- snapshot.addRoot(new Root(id, to.threadId,
- Root.THREAD_BLOCK, "", st));
- break;
- }
- case HPROF_GC_ROOT_MONITOR_USED: {
- long id = readID();
- bytesLeft -= identifierSize;
- snapshot.addRoot(new Root(id, 0, Root.BUSY_MONITOR, ""));
- break;
- }
- case HPROF_GC_CLASS_DUMP: {
- int bytesRead = readClass();
- bytesLeft -= bytesRead;
- break;
- }
- case HPROF_GC_INSTANCE_DUMP: {
- int bytesRead = readInstance();
- bytesLeft -= bytesRead;
- break;
- }
- case HPROF_GC_OBJ_ARRAY_DUMP: {
- long bytesRead = readArray(false);
- bytesLeft -= bytesRead;
- break;
- }
- case HPROF_GC_PRIM_ARRAY_DUMP: {
- long bytesRead = readArray(true);
- bytesLeft -= bytesRead;
- break;
- }
- default: {
- throw new IOException("Unrecognized heap dump sub-record type: " + type);
- }
- }
- }
- if (bytesLeft != 0) {
- warn("Error reading heap dump or heap dump segment: Byte count is " + bytesLeft + " instead of 0");
- skipBytes(bytesLeft);
- }
- if (debugLevel > 0) {
- System.out.println(" Finished heap sub-records.");
- }
- }
-
- private long readID() throws IOException {
- return (identifierSize == 4)?
- (Snapshot.SMALL_ID_MASK & (long)in.readInt()) : in.readLong();
- }
-
- //
- // Read a java value. If result is non-null, it's expected to be an
- // array of one element. We use it to fake multiple return values.
- // @returns the number of bytes read
- //
- private int readValue(JavaThing[] resultArr) throws IOException {
- byte type = in.readByte();
- return 1 + readValueForType(type, resultArr);
- }
-
- private int readValueForType(byte type, JavaThing[] resultArr)
- throws IOException {
- if (version >= VERSION_JDK12BETA4) {
- type = signatureFromTypeId(type);
- }
- return readValueForTypeSignature(type, resultArr);
- }
-
- private int readValueForTypeSignature(byte type, JavaThing[] resultArr)
- throws IOException {
- switch (type) {
- case '[':
- case 'L': {
- long id = readID();
- if (resultArr != null) {
- resultArr[0] = new JavaObjectRef(id);
- }
- return identifierSize;
- }
- case 'Z': {
- int b = in.readByte();
- if (b != 0 && b != 1) {
- warn("Illegal boolean value read");
- }
- if (resultArr != null) {
- resultArr[0] = new JavaBoolean(b != 0);
- }
- return 1;
- }
- case 'B': {
- byte b = in.readByte();
- if (resultArr != null) {
- resultArr[0] = new JavaByte(b);
- }
- return 1;
- }
- case 'S': {
- short s = in.readShort();
- if (resultArr != null) {
- resultArr[0] = new JavaShort(s);
- }
- return 2;
- }
- case 'C': {
- char ch = in.readChar();
- if (resultArr != null) {
- resultArr[0] = new JavaChar(ch);
- }
- return 2;
- }
- case 'I': {
- int val = in.readInt();
- if (resultArr != null) {
- resultArr[0] = new JavaInt(val);
- }
- return 4;
- }
- case 'J': {
- long val = in.readLong();
- if (resultArr != null) {
- resultArr[0] = new JavaLong(val);
- }
- return 8;
- }
- case 'F': {
- float val = in.readFloat();
- if (resultArr != null) {
- resultArr[0] = new JavaFloat(val);
- }
- return 4;
- }
- case 'D': {
- double val = in.readDouble();
- if (resultArr != null) {
- resultArr[0] = new JavaDouble(val);
- }
- return 8;
- }
- default: {
- throw new IOException("Bad value signature: " + type);
- }
- }
- }
-
- private ThreadObject getThreadObjectFromSequence(int threadSeq)
- throws IOException {
- ThreadObject to = threadObjects.get(threadSeq);
- if (to == null) {
- throw new IOException("Thread " + threadSeq +
- " not found for JNI local ref");
- }
- return to;
- }
-
- private String getNameFromID(long id) throws IOException {
- return getNameFromID(Long.valueOf(id));
- }
-
- private String getNameFromID(Long id) throws IOException {
- if (id.longValue() == 0L) {
- return "";
- }
- String result = names.get(id);
- if (result == null) {
- warn("Name not found at " + toHex(id.longValue()));
- return "unresolved name " + toHex(id.longValue());
- }
- return result;
- }
-
- private StackTrace getStackTraceFromSerial(int ser) throws IOException {
- if (stackTraces == null) {
- return null;
- }
- StackTrace result = stackTraces.get(ser);
- if (result == null) {
- warn("Stack trace not found for serial # " + ser);
- }
- return result;
- }
-
- //
- // Handle a HPROF_GC_CLASS_DUMP
- // Return number of bytes read
- //
- private int readClass() throws IOException {
- long id = readID();
- StackTrace stackTrace = getStackTraceFromSerial(in.readInt());
- long superId = readID();
- long classLoaderId = readID();
- long signersId = readID();
- long protDomainId = readID();
- long reserved1 = readID();
- long reserved2 = readID();
- int instanceSize = in.readInt();
- int bytesRead = 7 * identifierSize + 8;
-
- int numConstPoolEntries = in.readUnsignedShort();
- bytesRead += 2;
- for (int i = 0; i < numConstPoolEntries; i++) {
- int index = in.readUnsignedShort(); // unused
- bytesRead += 2;
- bytesRead += readValue(null); // We ignore the values
- }
-
- int numStatics = in.readUnsignedShort();
- bytesRead += 2;
- JavaThing[] valueBin = new JavaThing[1];
- JavaStatic[] statics = new JavaStatic[numStatics];
- for (int i = 0; i < numStatics; i++) {
- long nameId = readID();
- bytesRead += identifierSize;
- byte type = in.readByte();
- bytesRead++;
- bytesRead += readValueForType(type, valueBin);
- String fieldName = getNameFromID(nameId);
- if (version >= VERSION_JDK12BETA4) {
- type = signatureFromTypeId(type);
- }
- String signature = "" + ((char) type);
- JavaField f = new JavaField(fieldName, signature);
- statics[i] = new JavaStatic(f, valueBin[0]);
- }
-
- int numFields = in.readUnsignedShort();
- bytesRead += 2;
- JavaField[] fields = new JavaField[numFields];
- for (int i = 0; i < numFields; i++) {
- long nameId = readID();
- bytesRead += identifierSize;
- byte type = in.readByte();
- bytesRead++;
- String fieldName = getNameFromID(nameId);
- if (version >= VERSION_JDK12BETA4) {
- type = signatureFromTypeId(type);
- }
- String signature = "" + ((char) type);
- fields[i] = new JavaField(fieldName, signature);
- }
- String name = classNameFromObjectID.get(id);
- if (name == null) {
- warn("Class name not found for " + toHex(id));
- name = "unknown-name@" + toHex(id);
- }
- JavaClass c = new JavaClass(id, name, superId, classLoaderId, signersId,
- protDomainId, fields, statics,
- instanceSize);
- snapshot.addClass(id, c);
- snapshot.setSiteTrace(c, stackTrace);
-
- return bytesRead;
- }
-
- private String toHex(long addr) {
- return jdk.test.lib.hprof.util.Misc.toHex(addr);
- }
-
- //
- // Handle a HPROF_GC_INSTANCE_DUMP
- // Return number of bytes read
- //
- private int readInstance() throws IOException {
- long start = in.position();
- long id = readID();
- StackTrace stackTrace = getStackTraceFromSerial(in.readInt());
- long classID = readID();
- int bytesFollowing = in.readInt();
- int bytesRead = (2 * identifierSize) + 8 + bytesFollowing;
- JavaObject jobj = new JavaObject(classID, start);
- skipBytes(bytesFollowing);
- snapshot.addHeapObject(id, jobj);
- snapshot.setSiteTrace(jobj, stackTrace);
- return bytesRead;
- }
-
- //
- // Handle a HPROF_GC_OBJ_ARRAY_DUMP or HPROF_GC_PRIM_ARRAY_DUMP
- // Return number of bytes read
- //
- private long readArray(boolean isPrimitive) throws IOException {
- long start = in.position();
- long id = readID();
- StackTrace stackTrace = getStackTraceFromSerial(in.readInt());
- int num = in.readInt();
- long bytesRead = identifierSize + 8;
- long elementClassID;
- if (isPrimitive) {
- elementClassID = in.readByte();
- bytesRead++;
- } else {
- elementClassID = readID();
- bytesRead += identifierSize;
- }
-
- // Check for primitive arrays:
- byte primitiveSignature = 0x00;
- int elSize = 0;
- if (isPrimitive || version < VERSION_JDK12BETA4) {
- switch ((int)elementClassID) {
- case T_BOOLEAN: {
- primitiveSignature = (byte) 'Z';
- elSize = 1;
- break;
- }
- case T_CHAR: {
- primitiveSignature = (byte) 'C';
- elSize = 2;
- break;
- }
- case T_FLOAT: {
- primitiveSignature = (byte) 'F';
- elSize = 4;
- break;
- }
- case T_DOUBLE: {
- primitiveSignature = (byte) 'D';
- elSize = 8;
- break;
- }
- case T_BYTE: {
- primitiveSignature = (byte) 'B';
- elSize = 1;
- break;
- }
- case T_SHORT: {
- primitiveSignature = (byte) 'S';
- elSize = 2;
- break;
- }
- case T_INT: {
- primitiveSignature = (byte) 'I';
- elSize = 4;
- break;
- }
- case T_LONG: {
- primitiveSignature = (byte) 'J';
- elSize = 8;
- break;
- }
- }
- if (version >= VERSION_JDK12BETA4 && primitiveSignature == 0x00) {
- throw new IOException("Unrecognized typecode: "
- + elementClassID);
- }
- }
- if (primitiveSignature != 0x00) {
- long size = elSize * (long)num;
- bytesRead += size;
- JavaValueArray va = new JavaValueArray(primitiveSignature, start);
- skipBytes(size);
- snapshot.addHeapObject(id, va);
- snapshot.setSiteTrace(va, stackTrace);
- } else {
- long sz = (long)num * identifierSize;
- bytesRead += sz;
- JavaObjectArray arr = new JavaObjectArray(elementClassID, start);
- skipBytes(sz);
- snapshot.addHeapObject(id, arr);
- snapshot.setSiteTrace(arr, stackTrace);
- }
- return bytesRead;
- }
-
- private byte signatureFromTypeId(byte typeId) throws IOException {
- switch (typeId) {
- case T_CLASS: {
- return (byte) 'L';
- }
- case T_BOOLEAN: {
- return (byte) 'Z';
- }
- case T_CHAR: {
- return (byte) 'C';
- }
- case T_FLOAT: {
- return (byte) 'F';
- }
- case T_DOUBLE: {
- return (byte) 'D';
- }
- case T_BYTE: {
- return (byte) 'B';
- }
- case T_SHORT: {
- return (byte) 'S';
- }
- case T_INT: {
- return (byte) 'I';
- }
- case T_LONG: {
- return (byte) 'J';
- }
- default: {
- throw new IOException("Invalid type id of " + typeId);
- }
- }
- }
-
- private void handleEOF(EOFException exp, Snapshot snapshot) {
- if (debugLevel > 0) {
- exp.printStackTrace();
- }
- warn("Unexpected EOF. Will miss information...");
- // we have EOF, we have to tolerate missing references
- snapshot.setUnresolvedObjectsOK(true);
- }
-
- private void warn(String msg) {
- System.out.println("WARNING: " + msg);
- }
-
- //
- // A trivial data-holder class for HPROF_GC_ROOT_THREAD_OBJ.
- //
- private class ThreadObject {
-
- long threadId;
- int stackSeq;
-
- ThreadObject(long threadId, int stackSeq) {
- this.threadId = threadId;
- this.stackSeq = stackSeq;
- }
- }
-
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/parser/MappedReadBuffer.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.parser;
-
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.nio.MappedByteBuffer;
-import java.nio.channels.FileChannel;
-
-/**
- * Implementation of ReadBuffer using mapped file buffer
- *
- * @author A. Sundararajan
- */
-class MappedReadBuffer implements ReadBuffer {
- private MappedByteBuffer buf;
- private RandomAccessFile file;
-
- MappedReadBuffer(RandomAccessFile file, MappedByteBuffer buf) {
- this.file = file;
- this.buf = buf;
- }
-
- /**
- * Factory method to create correct ReadBuffer for a given file.
- *
- * The initial purpose of this method was to choose how to read hprof file for parsing
- * depending on the size of the file and the system property 'jhat.disableFileMap':
- * "If file size is more than 2 GB and when file mapping is configured (default),
- * use mapped file reader".
- *
- * However, it has been discovered a problem with this approach.
- * Creating java.nio.MappedByteBuffer from inside the test leads to hprof file
- * is locked on Windows until test process dies since there is no good way to
- * release this resource.
- *
- * java.nio.MappedByteBuffer will be used only if 'jhat.enableFileMap' is set to true.
- * Per default 'jhat.enableFileMap' is not set.
- */
- static ReadBuffer create(RandomAccessFile file) throws IOException {
- if (canUseFileMap()) {
- MappedByteBuffer buf;
- try {
- FileChannel ch = file.getChannel();
- long size = ch.size();
- buf = ch.map(FileChannel.MapMode.READ_ONLY, 0, size);
- ch.close();
- return new MappedReadBuffer(file, buf);
- } catch (IOException exp) {
- exp.printStackTrace();
- System.err.println("File mapping failed, will use direct read");
- // fall through
- }
- } // else fall through
- return new FileReadBuffer(file);
- }
-
- /**
- * Set system property 'jhat.enableFileMap' to 'true' to enable file mapping.
- */
- private static boolean canUseFileMap() {
- String prop = System.getProperty("jhat.enableFileMap");
- return prop != null && prop.equals("true");
- }
-
- private void seek(long pos) throws IOException {
- assert pos <= Integer.MAX_VALUE : "position overflow";
- buf.position((int)pos);
- }
-
- public synchronized void get(long pos, byte[] res) throws IOException {
- seek(pos);
- buf.get(res);
- }
-
- public synchronized char getChar(long pos) throws IOException {
- seek(pos);
- return buf.getChar();
- }
-
- public synchronized byte getByte(long pos) throws IOException {
- seek(pos);
- return buf.get();
- }
-
- public synchronized short getShort(long pos) throws IOException {
- seek(pos);
- return buf.getShort();
- }
-
- public synchronized int getInt(long pos) throws IOException {
- seek(pos);
- return buf.getInt();
- }
-
- public synchronized long getLong(long pos) throws IOException {
- seek(pos);
- return buf.getLong();
- }
-
- @Override
- public void close() throws Exception {
- file.close();
- }
-
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/parser/PositionDataInputStream.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.parser;
-
-import java.io.DataInputStream;
-import java.io.InputStream;
-
-/**
- * A DataInputStream that keeps track of total bytes read
- * (in effect 'position' in stream) so far.
- *
- */
-public class PositionDataInputStream extends DataInputStream {
- public PositionDataInputStream(InputStream in) {
- super(in instanceof PositionInputStream?
- in : new PositionInputStream(in));
- }
-
- public boolean markSupported() {
- return false;
- }
-
- public void mark(int readLimit) {
- throw new UnsupportedOperationException("mark");
- }
-
- public void reset() {
- throw new UnsupportedOperationException("reset");
- }
-
- public long position() {
- return ((PositionInputStream)in).position();
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/parser/PositionInputStream.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.parser;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * InputStream that keeps track of total bytes read (in effect
- * 'position' in stream) from the input stream.
- *
- */
-public class PositionInputStream extends FilterInputStream {
- private long position = 0L;
-
- public PositionInputStream(InputStream in) {
- super(in);
- }
-
- public int read() throws IOException {
- int res = super.read();
- if (res != -1) position++;
- return res;
- }
-
- public int read(byte[] b, int off, int len) throws IOException {
- int res = super.read(b, off, len);
- if (res != -1) position += res;
- return res;
- }
-
- public long skip(long n) throws IOException {
- long res = super.skip(n);
- position += res;
- return res;
- }
-
- public boolean markSupported() {
- return false;
- }
-
- public void mark(int readLimit) {
- throw new UnsupportedOperationException("mark");
- }
-
- public void reset() {
- throw new UnsupportedOperationException("reset");
- }
-
- public long position() {
- return position;
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/parser/ReadBuffer.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.parser;
-
-import java.io.IOException;
-
-/**
- * Positionable read only buffer
- *
- * @author A. Sundararajan
- */
-public interface ReadBuffer extends AutoCloseable {
- // read methods - only byte array and int primitive types.
- // read position has to be specified always.
- public void get(long pos, byte[] buf) throws IOException;
- public char getChar(long pos) throws IOException;
- public byte getByte(long pos) throws IOException;
- public short getShort(long pos) throws IOException;
- public int getInt(long pos) throws IOException;
- public long getLong(long pos) throws IOException;
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/parser/Reader.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.parser;
-
-import java.io.*;
-import jdk.test.lib.hprof.model.*;
-
-/**
- * Abstract base class for reading object dump files. A reader need not be
- * thread-safe.
- *
- * @author Bill Foote
- */
-
-
-public abstract class Reader {
- protected PositionDataInputStream in;
-
- protected Reader(PositionDataInputStream in) {
- this.in = in;
- }
-
- /**
- * Read a snapshot from a data input stream. It is assumed that the magic
- * number has already been read.
- */
- abstract public Snapshot read() throws IOException;
-
- /**
- * Read a snapshot from a file.
- *
- * @param heapFile The name of a file containing a heap dump
- * @param callStack If true, read the call stack of allocaation sites
- */
- public static Snapshot readFile(String heapFile, boolean callStack,
- int debugLevel)
- throws IOException {
- int dumpNumber = 1;
- int pos = heapFile.lastIndexOf('#');
- if (pos > -1) {
- String num = heapFile.substring(pos+1, heapFile.length());
- try {
- dumpNumber = Integer.parseInt(num, 10);
- } catch (java.lang.NumberFormatException ex) {
- String msg = "In file name \"" + heapFile
- + "\", a dump number was "
- + "expected after the :, but \""
- + num + "\" was found instead.";
- System.err.println(msg);
- throw new IOException(msg);
- }
- heapFile = heapFile.substring(0, pos);
- }
- try (PositionDataInputStream in = new PositionDataInputStream(
- new BufferedInputStream(new FileInputStream(heapFile)))) {
- int i = in.readInt();
- if (i == HprofReader.MAGIC_NUMBER) {
- Reader r
- = new HprofReader(heapFile, in, dumpNumber,
- callStack, debugLevel);
- return r.read();
- } else {
- throw new IOException("Unrecognized magic number: " + i);
- }
- }
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/util/ArraySorter.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,147 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.util;
-import java.util.*;
-
-/**
- * A singleton utility class that sorts an array of objects.
- * <p>
- * Use:
- * <pre>
- *
- * Stuff[] arr = ...;
- * ArraySorter.sort(arr, new Comparer() {
- * public int compare(Object lhs, Object rhs) {
- * return ((String) lhs).compareTo((String) rhs);
- * }
- * });
- * </pre>
- *
- * @author Bill Foote
- */
-
-public class ArraySorter {
-
- /**
- * Sort the given array, using c for comparison
- **/
- static public void sort(Object[] arr, Comparer c) {
- quickSort(arr, c, 0, arr.length-1);
- }
-
-
- /**
- * Sort an array of strings, using String.compareTo()
- **/
- static public void sortArrayOfStrings(Object[] arr) {
- sort(arr, new Comparer() {
- public int compare(Object lhs, Object rhs) {
- return ((String) lhs).compareTo((String) rhs);
- }
- });
- }
-
-
- static private void swap(Object[] arr, int a, int b) {
- Object tmp = arr[a];
- arr[a] = arr[b];
- arr[b] = tmp;
- }
-
- //
- // Sorts arr between from and to, inclusive. This is a quick, off-the-top-
- // of-my-head quicksort: I haven't put any thought into optimizing it.
- // I _did_ put thought into making sure it's safe (it will always
- // terminate). Worst-case it's O(n^2), but it will usually run in
- // in O(n log n). It's well-behaved if the list is already sorted,
- // or nearly so.
- //
- static private void quickSort(Object[] arr, Comparer c, int from, int to) {
- if (to <= from)
- return;
- int mid = (from + to) / 2;
- if (mid != from)
- swap(arr, mid, from);
- Object pivot = arr[from]; // Simple-minded, but reasonable
- int highestBelowPivot = from - 1;
- int low = from+1;
- int high = to;
- // We now move low and high toward each other, maintaining the
- // invariants:
- // arr[i] <= pivot for all i < low
- // arr[i] > pivot for all i > high
- // As long as these invariants hold, and every iteration makes
- // progress, we are safe.
- while (low <= high) {
- int cmp = c.compare(arr[low], pivot);
- if (cmp <= 0) { // arr[low] <= pivot
- if (cmp < 0) {
- highestBelowPivot = low;
- }
- low++;
- } else {
- int c2;
- for (;;) {
- // arr[high] > pivot:
- c2 = c.compare(arr[high], pivot);
- if (c2 > 0) {
- high--;
- if (low > high) {
- break;
- }
- } else {
- break;
- }
- }
- // At this point, low is never == high, BTW
- if (low <= high) {
- swap(arr, low, high);
- if (c2 < 0) {
- highestBelowPivot = low;
- }
- low++;
- high--;
- }
- }
- }
- // At this point, low == high+1
- // Now we just need to sort from from..highestBelowPivot
- // and from high+1..to
- if (highestBelowPivot > from) {
- // pivot == pivot, so ensure algorithm terminates
- swap(arr, from, highestBelowPivot);
- quickSort(arr, c, from, highestBelowPivot-1);
- }
- quickSort(arr, c, high+1, to);
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/util/Comparer.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.util;
-
-/**
- * Base class for comparison of two objects.
- * @see VectorSorter
- *
- * @author Bill Foote
- */
-
-abstract public class Comparer {
-
- /**
- * @return a number <, == or > 0 depending on lhs compared to rhs
- * @see java.lang.String.compareTo
- **/
- abstract public int compare(Object lhs, Object rhs);
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/util/CompositeEnumeration.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.util;
-
-import java.util.Enumeration;
-import java.util.NoSuchElementException;
-import jdk.test.lib.hprof.model.JavaHeapObject;
-
-public class CompositeEnumeration implements Enumeration<JavaHeapObject> {
- Enumeration<JavaHeapObject> e1;
- Enumeration<JavaHeapObject> e2;
-
- public CompositeEnumeration(Enumeration<JavaHeapObject> e1, Enumeration<JavaHeapObject> e2) {
- this.e1 = e1;
- this.e2 = e2;
- }
-
- public boolean hasMoreElements() {
- return e1.hasMoreElements() || e2.hasMoreElements();
- }
-
- public JavaHeapObject nextElement() {
- if (e1.hasMoreElements()) {
- return e1.nextElement();
- }
-
- if (e2.hasMoreElements()) {
- return e2.nextElement();
- }
-
- throw new NoSuchElementException();
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/util/Misc.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.util;
-import java.util.*;
-
-/**
- * Miscellaneous functions I couldn't think of a good place to put.
- *
- * @author Bill Foote
- */
-
-
-public class Misc {
-
- private static char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
-
- public final static String toHex(int addr) {
- char[] buf = new char[8];
- int i = 0;
- for (int s = 28; s >= 0; s -= 4) {
- buf[i++] = digits[(addr >> s) & 0xf];
- }
- return "0x" + new String(buf);
- }
-
- public final static String toHex(long addr) {
- return "0x" + Long.toHexString(addr);
- }
-
- public final static long parseHex(String value) {
- long result = 0;
- if (value.length() < 2 || value.charAt(0) != '0' ||
- value.charAt(1) != 'x') {
- return -1L;
- }
- for(int i = 2; i < value.length(); i++) {
- result *= 16;
- char ch = value.charAt(i);
- if (ch >= '0' && ch <= '9') {
- result += (ch - '0');
- } else if (ch >= 'a' && ch <= 'f') {
- result += (ch - 'a') + 10;
- } else if (ch >= 'A' && ch <= 'F') {
- result += (ch - 'A') + 10;
- } else {
- throw new NumberFormatException("" + ch
- + " is not a valid hex digit");
- }
- }
- return result;
- }
-
- public static String encodeHtml(String str) {
- final int len = str.length();
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < len; i++) {
- char ch = str.charAt(i);
- if (ch == '<') {
- sb.append("<");
- } else if (ch == '>') {
- sb.append(">");
- } else if (ch == '"') {
- sb.append(""");
- } else if (ch == '\'') {
- sb.append("'");
- } else if (ch == '&') {
- sb.append("&");
- } else if (ch < ' ') {
- sb.append("&#").append((int)ch).append(';');
- } else {
- int c = (ch & 0xFFFF);
- if (c > 127) {
- sb.append("&#").append(c).append(';');
- } else {
- sb.append(ch);
- }
- }
- }
- return sb.toString();
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/hprof/util/VectorSorter.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/*
- * The Original Code is HAT. The Initial Developer of the
- * Original Code is Bill Foote, with contributions from others
- * at JavaSoft/Sun.
- */
-
-package jdk.test.lib.hprof.util;
-import java.util.*;
-
-/**
- * A singleton utility class that sorts a vector.
- * <p>
- * Use:
- * <pre>
- *
- * Vector v = <a vector of, say, String objects>;
- * VectorSorter.sort(v, new Comparer() {
- * public int compare(Object lhs, Object rhs) {
- * return ((String) lhs).compareTo((String) rhs);
- * }
- * });
- * </pre>
- *
- * @author Bill Foote
- */
-
-
-public class VectorSorter {
-
- /**
- * Sort the given vector, using c for comparison
- **/
- static public void sort(Vector<Object> v, Comparer c) {
- quickSort(v, c, 0, v.size()-1);
- }
-
-
- /**
- * Sort a vector of strings, using String.compareTo()
- **/
- static public void sortVectorOfStrings(Vector<Object> v) {
- sort(v, new Comparer() {
- public int compare(Object lhs, Object rhs) {
- return ((String) lhs).compareTo((String) rhs);
- }
- });
- }
-
-
- static private void swap(Vector<Object> v, int a, int b) {
- Object tmp = v.elementAt(a);
- v.setElementAt(v.elementAt(b), a);
- v.setElementAt(tmp, b);
- }
-
- //
- // Sorts v between from and to, inclusive. This is a quick, off-the-top-
- // of-my-head quicksort: I haven't put any thought into optimizing it.
- // I _did_ put thought into making sure it's safe (it will always
- // terminate). Worst-case it's O(n^2), but it will usually run in
- // in O(n log n). It's well-behaved if the list is already sorted,
- // or nearly so.
- //
- static private void quickSort(Vector<Object> v, Comparer c, int from, int to) {
- if (to <= from)
- return;
- int mid = (from + to) / 2;
- if (mid != from)
- swap(v, mid, from);
- Object pivot = v.elementAt(from);
- // Simple-minded, but reasonable
- int highestBelowPivot = from - 1;
- int low = from+1;
- int high = to;
- // We now move low and high toward eachother, maintaining the
- // invariants:
- // v[i] <= pivot for all i < low
- // v[i] > pivot for all i > high
- // As long as these invariants hold, and every iteration makes
- // progress, we are safe.
- while (low <= high) {
- int cmp = c.compare(v.elementAt(low), pivot);
- if (cmp <= 0) { // v[low] <= pivot
- if (cmp < 0) {
- highestBelowPivot = low;
- }
- low++;
- } else {
- int c2;
- for (;;) {
- c2 = c.compare(v.elementAt(high), pivot);
- // v[high] > pivot:
- if (c2 > 0) {
- high--;
- if (low > high) {
- break;
- }
- } else {
- break;
- }
- }
- // At this point, low is never == high
- if (low <= high) {
- swap(v, low, high);
- if (c2 < 0) {
- highestBelowPivot = low;
- }
- low++;
- high--;
- }
- }
- }
- // Now we just need to sort from from..highestBelowPivot
- // and from high+1..to
- if (highestBelowPivot > from) {
- // pivot == pivot, so ensure algorithm terminates
- swap(v, from, highestBelowPivot);
- quickSort(v, c, from, highestBelowPivot-1);
- }
- quickSort(v, c, high+1, to);
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/process/OutputAnalyzer.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,436 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 jdk.test.lib.process;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public final class OutputAnalyzer {
-
- private final String stdout;
- private final String stderr;
- private final int exitValue;
-
- /**
- * Create an OutputAnalyzer, a utility class for verifying output and exit
- * value from a Process
- *
- * @param process Process to analyze
- * @throws IOException If an I/O error occurs.
- */
- public OutputAnalyzer(Process process) throws IOException {
- OutputBuffer output = ProcessTools.getOutput(process);
- exitValue = process.exitValue();
- this.stdout = output.getStdout();
- this.stderr = output.getStderr();
- }
-
- /**
- * Create an OutputAnalyzer, a utility class for verifying output
- *
- * @param buf String buffer to analyze
- */
- public OutputAnalyzer(String buf) {
- this(buf, buf);
- }
-
- /**
- * Create an OutputAnalyzer, a utility class for verifying output
- *
- * @param stdout stdout buffer to analyze
- * @param stderr stderr buffer to analyze
- */
- public OutputAnalyzer(String stdout, String stderr) {
- this.stdout = stdout;
- this.stderr = stderr;
- exitValue = -1;
- }
-
- /**
- * Verify that the stdout contents of output buffer is empty
- *
- * @throws RuntimeException
- * If stdout was not empty
- */
- public void stdoutShouldBeEmpty() {
- if (!getStdout().isEmpty()) {
- reportDiagnosticSummary();
- throw new RuntimeException("stdout was not empty");
- }
- }
-
- /**
- * Verify that the stderr contents of output buffer is empty
- *
- * @throws RuntimeException
- * If stderr was not empty
- */
- public void stderrShouldBeEmpty() {
- if (!getStderr().isEmpty()) {
- reportDiagnosticSummary();
- throw new RuntimeException("stderr was not empty");
- }
- }
-
- /**
- * Verify that the stdout contents of output buffer is not empty
- *
- * @throws RuntimeException
- * If stdout was empty
- */
- public void stdoutShouldNotBeEmpty() {
- if (getStdout().isEmpty()) {
- reportDiagnosticSummary();
- throw new RuntimeException("stdout was empty");
- }
- }
-
- /**
- * Verify that the stderr contents of output buffer is not empty
- *
- * @throws RuntimeException
- * If stderr was empty
- */
- public void stderrShouldNotBeEmpty() {
- if (getStderr().isEmpty()) {
- reportDiagnosticSummary();
- throw new RuntimeException("stderr was empty");
- }
- }
-
- /**
- * Verify that the stdout and stderr contents of output buffer contains the string
- *
- * @param expectedString String that buffer should contain
- * @throws RuntimeException If the string was not found
- */
- public OutputAnalyzer shouldContain(String expectedString) {
- if (!stdout.contains(expectedString) && !stderr.contains(expectedString)) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr \n");
- }
- return this;
- }
-
- /**
- * Verify that the stdout contents of output buffer contains the string
- *
- * @param expectedString String that buffer should contain
- * @throws RuntimeException If the string was not found
- */
- public OutputAnalyzer stdoutShouldContain(String expectedString) {
- if (!stdout.contains(expectedString)) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + expectedString + "' missing from stdout \n");
- }
- return this;
- }
-
- /**
- * Verify that the stderr contents of output buffer contains the string
- *
- * @param expectedString String that buffer should contain
- * @throws RuntimeException If the string was not found
- */
- public OutputAnalyzer stderrShouldContain(String expectedString) {
- if (!stderr.contains(expectedString)) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + expectedString + "' missing from stderr \n");
- }
- return this;
- }
-
- /**
- * Verify that the stdout and stderr contents of output buffer does not contain the string
- *
- * @param expectedString String that the buffer should not contain
- * @throws RuntimeException If the string was found
- */
- public OutputAnalyzer shouldNotContain(String notExpectedString) {
- if (stdout.contains(notExpectedString)) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
- }
- if (stderr.contains(notExpectedString)) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
- }
- return this;
- }
-
- /**
- * Verify that the stdout contents of output buffer does not contain the string
- *
- * @param expectedString String that the buffer should not contain
- * @throws RuntimeException If the string was found
- */
- public OutputAnalyzer stdoutShouldNotContain(String notExpectedString) {
- if (stdout.contains(notExpectedString)) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
- }
- return this;
- }
-
- /**
- * Verify that the stderr contents of output buffer does not contain the string
- *
- * @param expectedString String that the buffer should not contain
- * @throws RuntimeException If the string was found
- */
- public OutputAnalyzer stderrShouldNotContain(String notExpectedString) {
- if (stderr.contains(notExpectedString)) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
- }
- return this;
- }
-
- /**
- * Verify that the stdout and stderr contents of output buffer matches
- * the pattern
- *
- * @param pattern
- * @throws RuntimeException If the pattern was not found
- */
- public OutputAnalyzer shouldMatch(String pattern) {
- Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
- Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
- if (!stdoutMatcher.find() && !stderrMatcher.find()) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + pattern
- + "' missing from stdout/stderr \n");
- }
- return this;
- }
-
- /**
- * Verify that the stdout contents of output buffer matches the
- * pattern
- *
- * @param pattern
- * @throws RuntimeException If the pattern was not found
- */
- public OutputAnalyzer stdoutShouldMatch(String pattern) {
- Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
- if (!matcher.find()) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + pattern
- + "' missing from stdout \n");
- }
- return this;
- }
-
- /**
- * Verify that the stderr contents of output buffer matches the
- * pattern
- *
- * @param pattern
- * @throws RuntimeException If the pattern was not found
- */
- public OutputAnalyzer stderrShouldMatch(String pattern) {
- Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
- if (!matcher.find()) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + pattern
- + "' missing from stderr \n");
- }
- return this;
- }
-
- /**
- * Verify that the stdout and stderr contents of output buffer does not
- * match the pattern
- *
- * @param pattern
- * @throws RuntimeException If the pattern was found
- */
- public OutputAnalyzer shouldNotMatch(String pattern) {
- Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
- if (matcher.find()) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + pattern
- + "' found in stdout: '" + matcher.group() + "' \n");
- }
- matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
- if (matcher.find()) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + pattern
- + "' found in stderr: '" + matcher.group() + "' \n");
- }
- return this;
- }
-
- /**
- * Verify that the stdout contents of output buffer does not match the
- * pattern
- *
- * @param pattern
- * @throws RuntimeException If the pattern was found
- */
- public OutputAnalyzer stdoutShouldNotMatch(String pattern) {
- Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
- if (matcher.find()) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + pattern
- + "' found in stdout \n");
- }
- return this;
- }
-
- /**
- * Verify that the stderr contents of output buffer does not match the
- * pattern
- *
- * @param pattern
- * @throws RuntimeException If the pattern was found
- */
- public OutputAnalyzer stderrShouldNotMatch(String pattern) {
- Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
- if (matcher.find()) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + pattern
- + "' found in stderr \n");
- }
- return this;
- }
-
- /**
- * Get the captured group of the first string matching the pattern.
- * stderr is searched before stdout.
- *
- * @param pattern The multi-line pattern to match
- * @param group The group to capture
- * @return The matched string or null if no match was found
- */
- public String firstMatch(String pattern, int group) {
- Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
- Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
- if (stderrMatcher.find()) {
- return stderrMatcher.group(group);
- }
- if (stdoutMatcher.find()) {
- return stdoutMatcher.group(group);
- }
- return null;
- }
-
- /**
- * Get the first string matching the pattern.
- * stderr is searched before stdout.
- *
- * @param pattern The multi-line pattern to match
- * @return The matched string or null if no match was found
- */
- public String firstMatch(String pattern) {
- return firstMatch(pattern, 0);
- }
-
- /**
- * Verify the exit value of the process
- *
- * @param expectedExitValue Expected exit value from process
- * @throws RuntimeException If the exit value from the process did not match the expected value
- */
- public OutputAnalyzer shouldHaveExitValue(int expectedExitValue) {
- if (getExitValue() != expectedExitValue) {
- reportDiagnosticSummary();
- throw new RuntimeException("Expected to get exit value of ["
- + expectedExitValue + "]\n");
- }
- return this;
- }
-
-
- /**
- * Report summary that will help to diagnose the problem
- * Currently includes:
- * - standard input produced by the process under test
- * - standard output
- * - exit code
- * Note: the command line is printed by the ProcessTools
- */
- private void reportDiagnosticSummary() {
- String msg =
- " stdout: [" + stdout + "];\n" +
- " stderr: [" + stderr + "]\n" +
- " exitValue = " + getExitValue() + "\n";
-
- System.err.println(msg);
- }
-
-
- /**
- * Get the contents of the output buffer (stdout and stderr)
- *
- * @return Content of the output buffer
- */
- public String getOutput() {
- return stdout + stderr;
- }
-
- /**
- * Get the contents of the stdout buffer
- *
- * @return Content of the stdout buffer
- */
- public String getStdout() {
- return stdout;
- }
-
- /**
- * Get the contents of the stderr buffer
- *
- * @return Content of the stderr buffer
- */
- public String getStderr() {
- return stderr;
- }
-
- /**
- * Get the process exit value
- *
- * @return Process exit value
- */
- public int getExitValue() {
- return exitValue;
- }
-
- /**
- * Get the contents of the output buffer (stdout and stderr) as list of strings.
- * Output will be split by newlines.
- *
- * @return Contents of the output buffer as list of strings
- */
- public List<String> asLines() {
- return asLines(getOutput());
- }
-
- private List<String> asLines(String buffer) {
- return Arrays.asList(buffer.split("(\\r\\n|\\n|\\r)"));
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/process/OutputBuffer.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 jdk.test.lib.process;
-
-public class OutputBuffer {
- private final String stdout;
- private final String stderr;
-
- /**
- * Create an OutputBuffer, a class for storing and managing stdout and stderr
- * results separately
- *
- * @param stdout stdout result
- * @param stderr stderr result
- */
- public OutputBuffer(String stdout, String stderr) {
- this.stdout = stdout;
- this.stderr = stderr;
- }
-
- /**
- * Returns the stdout result
- *
- * @return stdout result
- */
- public String getStdout() {
- return stdout;
- }
-
- /**
- * Returns the stderr result
- *
- * @return stderr result
- */
- public String getStderr() {
- return stderr;
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/process/ProcessTools.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,590 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 jdk.test.lib.process;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.concurrent.CountDownLatch;
-import java.util.Map;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.function.Predicate;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
-
-import jdk.test.lib.JDKToolFinder;
-import jdk.test.lib.Platform;
-import jdk.test.lib.Utils;
-
-public final class ProcessTools {
- private static final class LineForwarder extends StreamPumper.LinePump {
- private final PrintStream ps;
- private final String prefix;
- LineForwarder(String prefix, PrintStream os) {
- this.ps = os;
- this.prefix = prefix;
- }
- @Override
- protected void processLine(String line) {
- ps.println("[" + prefix + "] " + line);
- }
- }
-
- private ProcessTools() {
- }
-
- /**
- * Pumps stdout and stderr from running the process into a String.
- *
- * @param processHandler ProcessHandler to run.
- * @return Output from process.
- * @throws IOException If an I/O error occurs.
- */
- public static OutputBuffer getOutput(ProcessBuilder processBuilder) throws IOException {
- return getOutput(processBuilder.start());
- }
-
- /**
- * Pumps stdout and stderr the running process into a String.
- *
- * @param process Process to pump.
- * @return Output from process.
- * @throws IOException If an I/O error occurs.
- */
- public static OutputBuffer getOutput(Process process) throws IOException {
- ByteArrayOutputStream stderrBuffer = new ByteArrayOutputStream();
- ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream();
- StreamPumper outPumper = new StreamPumper(process.getInputStream(), stdoutBuffer);
- StreamPumper errPumper = new StreamPumper(process.getErrorStream(), stderrBuffer);
- Thread outPumperThread = new Thread(outPumper);
- Thread errPumperThread = new Thread(errPumper);
-
- outPumperThread.setDaemon(true);
- errPumperThread.setDaemon(true);
-
- outPumperThread.start();
- errPumperThread.start();
-
- try {
- process.waitFor();
- outPumperThread.join();
- errPumperThread.join();
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- return null;
- }
-
- return new OutputBuffer(stdoutBuffer.toString(), stderrBuffer.toString());
- }
-
- /**
- * <p>Starts a process from its builder.</p>
- * <span>The default redirects of STDOUT and STDERR are started</span>
- * @param name The process name
- * @param processBuilder The process builder
- * @return Returns the initialized process
- * @throws IOException
- */
- public static Process startProcess(String name,
- ProcessBuilder processBuilder)
- throws IOException {
- return startProcess(name, processBuilder, (Consumer<String>)null);
- }
-
- /**
- * <p>Starts a process from its builder.</p>
- * <span>The default redirects of STDOUT and STDERR are started</span>
- * <p>It is possible to monitor the in-streams via the provided {@code consumer}
- * @param name The process name
- * @param consumer {@linkplain Consumer} instance to process the in-streams
- * @param processBuilder The process builder
- * @return Returns the initialized process
- * @throws IOException
- */
- @SuppressWarnings("overloads")
- public static Process startProcess(String name,
- ProcessBuilder processBuilder,
- Consumer<String> consumer)
- throws IOException {
- try {
- return startProcess(name, processBuilder, consumer, null, -1, TimeUnit.NANOSECONDS);
- } catch (InterruptedException | TimeoutException e) {
- // will never happen
- throw new RuntimeException(e);
- }
- }
-
- /**
- * <p>Starts a process from its builder.</p>
- * <span>The default redirects of STDOUT and STDERR are started</span>
- * <p>
- * It is possible to wait for the process to get to a warmed-up state
- * via {@linkplain Predicate} condition on the STDOUT
- * </p>
- * @param name The process name
- * @param processBuilder The process builder
- * @param linePredicate The {@linkplain Predicate} to use on the STDOUT
- * Used to determine the moment the target app is
- * properly warmed-up.
- * It can be null - in that case the warmup is skipped.
- * @param timeout The timeout for the warmup waiting; -1 = no wait; 0 = wait forever
- * @param unit The timeout {@linkplain TimeUnit}
- * @return Returns the initialized {@linkplain Process}
- * @throws IOException
- * @throws InterruptedException
- * @throws TimeoutException
- */
- public static Process startProcess(String name,
- ProcessBuilder processBuilder,
- final Predicate<String> linePredicate,
- long timeout,
- TimeUnit unit)
- throws IOException, InterruptedException, TimeoutException {
- return startProcess(name, processBuilder, null, linePredicate, timeout, unit);
- }
-
- /**
- * <p>Starts a process from its builder.</p>
- * <span>The default redirects of STDOUT and STDERR are started</span>
- * <p>
- * It is possible to wait for the process to get to a warmed-up state
- * via {@linkplain Predicate} condition on the STDOUT and monitor the
- * in-streams via the provided {@linkplain Consumer}
- * </p>
- * @param name The process name
- * @param processBuilder The process builder
- * @param lineConsumer The {@linkplain Consumer} the lines will be forwarded to
- * @param linePredicate The {@linkplain Predicate} to use on the STDOUT
- * Used to determine the moment the target app is
- * properly warmed-up.
- * It can be null - in that case the warmup is skipped.
- * @param timeout The timeout for the warmup waiting; -1 = no wait; 0 = wait forever
- * @param unit The timeout {@linkplain TimeUnit}
- * @return Returns the initialized {@linkplain Process}
- * @throws IOException
- * @throws InterruptedException
- * @throws TimeoutException
- */
- public static Process startProcess(String name,
- ProcessBuilder processBuilder,
- final Consumer<String> lineConsumer,
- final Predicate<String> linePredicate,
- long timeout,
- TimeUnit unit)
- throws IOException, InterruptedException, TimeoutException {
- System.out.println("["+name+"]:" + processBuilder.command().stream().collect(Collectors.joining(" ")));
- Process p = processBuilder.start();
- StreamPumper stdout = new StreamPumper(p.getInputStream());
- StreamPumper stderr = new StreamPumper(p.getErrorStream());
-
- stdout.addPump(new LineForwarder(name, System.out));
- stderr.addPump(new LineForwarder(name, System.err));
- if (lineConsumer != null) {
- StreamPumper.LinePump pump = new StreamPumper.LinePump() {
- @Override
- protected void processLine(String line) {
- lineConsumer.accept(line);
- }
- };
- stdout.addPump(pump);
- stderr.addPump(pump);
- }
-
-
- CountDownLatch latch = new CountDownLatch(1);
- if (linePredicate != null) {
- StreamPumper.LinePump pump = new StreamPumper.LinePump() {
- @Override
- protected void processLine(String line) {
- if (latch.getCount() > 0 && linePredicate.test(line)) {
- latch.countDown();
- }
- }
- };
- stdout.addPump(pump);
- stderr.addPump(pump);
- } else {
- latch.countDown();
- }
- final Future<Void> stdoutTask = stdout.process();
- final Future<Void> stderrTask = stderr.process();
-
- try {
- if (timeout > -1) {
- if (timeout == 0) {
- latch.await();
- } else {
- if (!latch.await(Utils.adjustTimeout(timeout), unit)) {
- throw new TimeoutException();
- }
- }
- }
- } catch (TimeoutException | InterruptedException e) {
- System.err.println("Failed to start a process (thread dump follows)");
- for(Map.Entry<Thread, StackTraceElement[]> s : Thread.getAllStackTraces().entrySet()) {
- printStack(s.getKey(), s.getValue());
- }
-
- if (p.isAlive()) {
- p.destroyForcibly();
- }
-
- stdoutTask.cancel(true);
- stderrTask.cancel(true);
- throw e;
- }
-
- return new ProcessImpl(p, stdoutTask, stderrTask);
- }
-
- /**
- * <p>Starts a process from its builder.</p>
- * <span>The default redirects of STDOUT and STDERR are started</span>
- * <p>
- * It is possible to wait for the process to get to a warmed-up state
- * via {@linkplain Predicate} condition on the STDOUT. The warm-up will
- * wait indefinitely.
- * </p>
- * @param name The process name
- * @param processBuilder The process builder
- * @param linePredicate The {@linkplain Predicate} to use on the STDOUT
- * Used to determine the moment the target app is
- * properly warmed-up.
- * It can be null - in that case the warmup is skipped.
- * @return Returns the initialized {@linkplain Process}
- * @throws IOException
- * @throws InterruptedException
- * @throws TimeoutException
- */
- @SuppressWarnings("overloads")
- public static Process startProcess(String name,
- ProcessBuilder processBuilder,
- final Predicate<String> linePredicate)
- throws IOException, InterruptedException, TimeoutException {
- return startProcess(name, processBuilder, linePredicate, 0, TimeUnit.SECONDS);
- }
-
- /**
- * Get the process id of the current running Java process
- *
- * @return Process id
- */
- public static long getProcessId() throws Exception {
- return ProcessHandle.current().getPid();
- }
-
- /**
- * Get platform specific VM arguments (e.g. -d64 on 64bit Solaris)
- *
- * @return String[] with platform specific arguments, empty if there are
- * none
- */
- public static String[] getPlatformSpecificVMArgs() {
-
- if (Platform.is64bit() && Platform.isSolaris()) {
- return new String[] { "-d64" };
- }
-
- return new String[] {};
- }
-
-
- /**
- * Create ProcessBuilder using the java launcher from the jdk to be tested and
- * with any platform specific arguments prepended
- */
- public static ProcessBuilder createJavaProcessBuilder(String... command) throws Exception {
- return createJavaProcessBuilder(false, command);
- }
-
- /**
- * Create ProcessBuilder using the java launcher from the jdk to be tested,
- * and with any platform specific arguments prepended.
- *
- * @param addTestVmAndJavaOptions If true, adds test.vm.opts and test.java.opts
- * to the java arguments.
- * @param command Arguments to pass to the java command.
- * @return The ProcessBuilder instance representing the java command.
- */
- public static ProcessBuilder createJavaProcessBuilder(boolean addTestVmAndJavaOptions, String... command) throws Exception {
- String javapath = JDKToolFinder.getJDKTool("java");
-
- ArrayList<String> args = new ArrayList<>();
- args.add(javapath);
- Collections.addAll(args, getPlatformSpecificVMArgs());
-
- if (addTestVmAndJavaOptions) {
- // -cp is needed to make sure the same classpath is used whether the test is
- // run in AgentVM mode or OtherVM mode. It was added to the hotspot version
- // of this API as part of 8077608. However, for the jdk version it is only
- // added when addTestVmAndJavaOptions is true in order to minimize
- // disruption to existing JDK tests, which have yet to be tested with -cp
- // being added. At some point -cp should always be added to be consistent
- // with what the hotspot version does.
- args.add("-cp");
- args.add(System.getProperty("java.class.path"));
- Collections.addAll(args, Utils.getTestJavaOpts());
- }
-
- Collections.addAll(args, command);
-
- // Reporting
- StringBuilder cmdLine = new StringBuilder();
- for (String cmd : args)
- cmdLine.append(cmd).append(' ');
- System.out.println("Command line: [" + cmdLine.toString() + "]");
-
- return new ProcessBuilder(args.toArray(new String[args.size()]));
- }
-
- private static void printStack(Thread t, StackTraceElement[] stack) {
- System.out.println("\t" + t +
- " stack: (length = " + stack.length + ")");
- if (t != null) {
- for (StackTraceElement stack1 : stack) {
- System.out.println("\t" + stack1);
- }
- System.out.println();
- }
- }
-
- /**
- * Executes a test jvm process, waits for it to finish and returns the process output.
- * The default jvm options from jtreg, test.vm.opts and test.java.opts, are added.
- * The java from the test.jdk is used to execute the command.
- *
- * The command line will be like:
- * {test.jdk}/bin/java {test.vm.opts} {test.java.opts} cmds
- *
- * The jvm process will have exited before this method returns.
- *
- * @param cmds User specifed arguments.
- * @return The output from the process.
- */
- public static OutputAnalyzer executeTestJvm(String... cmds) throws Exception {
- ProcessBuilder pb = createJavaProcessBuilder(Utils.addTestJavaOpts(cmds));
- return executeProcess(pb);
- }
-
- /**
- * Executes a process, waits for it to finish and returns the process output.
- * The process will have exited before this method returns.
- * @param pb The ProcessBuilder to execute.
- * @return The {@linkplain OutputAnalyzer} instance wrapping the process.
- */
- public static OutputAnalyzer executeProcess(ProcessBuilder pb) throws Exception {
- OutputAnalyzer output = null;
- Process p = null;
- boolean failed = false;
- try {
- p = pb.start();
- output = new OutputAnalyzer(p);
- p.waitFor();
-
- return output;
- } catch (Throwable t) {
- if (p != null) {
- p.destroyForcibly().waitFor();
- }
-
- failed = true;
- System.out.println("executeProcess() failed: " + t);
- throw t;
- } finally {
- if (failed) {
- System.err.println(getProcessLog(pb, output));
- }
- }
- }
-
- /**
- * Executes a process, waits for it to finish and returns the process output.
- *
- * The process will have exited before this method returns.
- *
- * @param cmds The command line to execute.
- * @return The output from the process.
- */
- public static OutputAnalyzer executeProcess(String... cmds) throws Throwable {
- return executeProcess(new ProcessBuilder(cmds));
- }
-
- /**
- * Used to log command line, stdout, stderr and exit code from an executed process.
- * @param pb The executed process.
- * @param output The output from the process.
- */
- public static String getProcessLog(ProcessBuilder pb, OutputAnalyzer output) {
- String stderr = output == null ? "null" : output.getStderr();
- String stdout = output == null ? "null" : output.getStdout();
- String exitValue = output == null ? "null": Integer.toString(output.getExitValue());
- StringBuilder logMsg = new StringBuilder();
- final String nl = System.getProperty("line.separator");
- logMsg.append("--- ProcessLog ---" + nl);
- logMsg.append("cmd: " + getCommandLine(pb) + nl);
- logMsg.append("exitvalue: " + exitValue + nl);
- logMsg.append("stderr: " + stderr + nl);
- logMsg.append("stdout: " + stdout + nl);
-
- return logMsg.toString();
- }
-
- /**
- * @return The full command line for the ProcessBuilder.
- */
- public static String getCommandLine(ProcessBuilder pb) {
- if (pb == null) {
- return "null";
- }
- StringBuilder cmd = new StringBuilder();
- for (String s : pb.command()) {
- cmd.append(s).append(" ");
- }
- return cmd.toString().trim();
- }
-
- /**
- * Executes a process, waits for it to finish, prints the process output
- * to stdout, and returns the process output.
- *
- * The process will have exited before this method returns.
- *
- * @param cmds The command line to execute.
- * @return The {@linkplain OutputAnalyzer} instance wrapping the process.
- */
- public static OutputAnalyzer executeCommand(String... cmds)
- throws Throwable {
- String cmdLine = Arrays.stream(cmds).collect(Collectors.joining(" "));
- System.out.println("Command line: [" + cmdLine + "]");
- OutputAnalyzer analyzer = ProcessTools.executeProcess(cmds);
- System.out.println(analyzer.getOutput());
- return analyzer;
- }
-
- /**
- * Executes a process, waits for it to finish, prints the process output
- * to stdout and returns the process output.
- *
- * The process will have exited before this method returns.
- *
- * @param pb The ProcessBuilder to execute.
- * @return The {@linkplain OutputAnalyzer} instance wrapping the process.
- */
- public static OutputAnalyzer executeCommand(ProcessBuilder pb)
- throws Throwable {
- String cmdLine = pb.command().stream().collect(Collectors.joining(" "));
- System.out.println("Command line: [" + cmdLine + "]");
- OutputAnalyzer analyzer = ProcessTools.executeProcess(pb);
- System.out.println(analyzer.getOutput());
- return analyzer;
- }
-
- private static class ProcessImpl extends Process {
-
- private final Process p;
- private final Future<Void> stdoutTask;
- private final Future<Void> stderrTask;
-
- public ProcessImpl(Process p, Future<Void> stdoutTask, Future<Void> stderrTask) {
- this.p = p;
- this.stdoutTask = stdoutTask;
- this.stderrTask = stderrTask;
- }
-
- @Override
- public OutputStream getOutputStream() {
- return p.getOutputStream();
- }
-
- @Override
- public InputStream getInputStream() {
- return p.getInputStream();
- }
-
- @Override
- public InputStream getErrorStream() {
- return p.getErrorStream();
- }
-
- @Override
- public int waitFor() throws InterruptedException {
- int rslt = p.waitFor();
- waitForStreams();
- return rslt;
- }
-
- @Override
- public int exitValue() {
- return p.exitValue();
- }
-
- @Override
- public void destroy() {
- p.destroy();
- }
-
- @Override
- public long getPid() {
- return p.getPid();
- }
-
- @Override
- public boolean isAlive() {
- return p.isAlive();
- }
-
- @Override
- public Process destroyForcibly() {
- return p.destroyForcibly();
- }
-
- @Override
- public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException {
- boolean rslt = p.waitFor(timeout, unit);
- if (rslt) {
- waitForStreams();
- }
- return rslt;
- }
-
- private void waitForStreams() throws InterruptedException {
- try {
- stdoutTask.get();
- } catch (ExecutionException e) {
- }
- try {
- stderrTask.get();
- } catch (ExecutionException e) {
- }
- }
- }
-}
--- a/test/lib/share/classes/jdk/test/lib/process/StreamPumper.java Wed Jul 05 22:08:56 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,197 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 jdk.test.lib.process;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.Future;
-import java.util.concurrent.FutureTask;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-public final class StreamPumper implements Runnable {
-
- private static final int BUF_SIZE = 256;
-
- /**
- * Pump will be called by the StreamPumper to process the incoming data
- */
- abstract public static class Pump {
- abstract void register(StreamPumper d);
- }
-
- /**
- * OutputStream -> Pump adapter
- */
- final public static class StreamPump extends Pump {
- private final OutputStream out;
- public StreamPump(OutputStream out) {
- this.out = out;
- }
-
- @Override
- void register(StreamPumper sp) {
- sp.addOutputStream(out);
- }
- }
-
- /**
- * Used to process the incoming data line-by-line
- */
- abstract public static class LinePump extends Pump {
- @Override
- final void register(StreamPumper sp) {
- sp.addLineProcessor(this);
- }
-
- abstract protected void processLine(String line);
- }
-
- private final InputStream in;
- private final Set<OutputStream> outStreams = new HashSet<>();
- private final Set<LinePump> linePumps = new HashSet<>();
-
- private final AtomicBoolean processing = new AtomicBoolean(false);
- private final FutureTask<Void> processingTask = new FutureTask<>(this, null);
-
- public StreamPumper(InputStream in) {
- this.in = in;
- }
-
- /**
- * Create a StreamPumper that reads from in and writes to out.
- *
- * @param in The stream to read from.
- * @param out The stream to write to.
- */
- public StreamPumper(InputStream in, OutputStream out) {
- this(in);
- this.addOutputStream(out);
- }
-
- /**
- * Implements Thread.run(). Continuously read from {@code in} and write to
- * {@code out} until {@code in} has reached end of stream. Abort on
- * interruption. Abort on IOExceptions.
- */
- @Override
- public void run() {
- try (BufferedInputStream is = new BufferedInputStream(in)) {
- ByteArrayOutputStream lineBos = new ByteArrayOutputStream();
- byte[] buf = new byte[BUF_SIZE];
- int len = 0;
- int linelen = 0;
-
- while ((len = is.read(buf)) > 0 && !Thread.interrupted()) {
- for(OutputStream out : outStreams) {
- out.write(buf, 0, len);
- }
- if (!linePumps.isEmpty()) {
- int i = 0;
- int lastcrlf = -1;
- while (i < len) {
- if (buf[i] == '\n' || buf[i] == '\r') {
- int bufLinelen = i - lastcrlf - 1;
- if (bufLinelen > 0) {
- lineBos.write(buf, lastcrlf + 1, bufLinelen);
- }
- linelen += bufLinelen;
-
- if (linelen > 0) {
- lineBos.flush();
- final String line = lineBos.toString();
- linePumps.stream().forEach((lp) -> {
- lp.processLine(line);
- });
- lineBos.reset();
- linelen = 0;
- }
- lastcrlf = i;
- }
-
- i++;
- }
- if (lastcrlf == -1) {
- lineBos.write(buf, 0, len);
- linelen += len;
- } else if (lastcrlf < len - 1) {
- lineBos.write(buf, lastcrlf + 1, len - lastcrlf - 1);
- linelen += len - lastcrlf - 1;
- }
- }
- }
-
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- for(OutputStream out : outStreams) {
- try {
- out.flush();
- } catch (IOException e) {}
- }
- try {
- in.close();
- } catch (IOException e) {}
- }
- }
-
- final void addOutputStream(OutputStream out) {
- outStreams.add(out);
- }
-
- final void addLineProcessor(LinePump lp) {
- linePumps.add(lp);
- }
-
- final public StreamPumper addPump(Pump ... pump) {
- if (processing.get()) {
- throw new IllegalStateException("Can not modify pumper while " +
- "processing is in progress");
- }
- for(Pump p : pump) {
- p.register(this);
- }
- return this;
- }
-
- final public Future<Void> process() {
- if (!processing.compareAndSet(false, true)) {
- throw new IllegalStateException("Can not re-run the processing");
- }
- Thread t = new Thread(new Runnable() {
- @Override
- public void run() {
- processingTask.run();
- }
- });
- t.setDaemon(true);
- t.start();
-
- return processingTask;
- }
-}