8157957: ClassNotFoundException: jdk.test.lib.JDKToolFinder
authorctornqvi
Fri, 19 Aug 2016 10:09:25 -0400
changeset 40614 b5d80754b40e
parent 40324 d8c7cc542d54
child 40615 706122bd4ac9
8157957: ClassNotFoundException: jdk.test.lib.JDKToolFinder Reviewed-by: coleenp, gtriantafill, mseledtsov, iignatyev, dholmes, dsamersoff
make/test/BuildTestLib.gmk
test/lib/ClassFileInstaller.java
test/lib/RedefineClassHelper.java
test/lib/jdk/test/lib/Asserts.java
test/lib/jdk/test/lib/BuildHelper.java
test/lib/jdk/test/lib/ByteCodeLoader.java
test/lib/jdk/test/lib/DynamicVMOption.java
test/lib/jdk/test/lib/FileInstaller.java
test/lib/jdk/test/lib/InMemoryJavaCompiler.java
test/lib/jdk/test/lib/JDKToolFinder.java
test/lib/jdk/test/lib/JDKToolLauncher.java
test/lib/jdk/test/lib/Platform.java
test/lib/jdk/test/lib/Utils.java
test/lib/jdk/test/lib/apps/LingeredApp.java
test/lib/jdk/test/lib/apps/LingeredAppWithDeadlock.java
test/lib/jdk/test/lib/cli/CPUSpecificCommandLineOptionTest.java
test/lib/jdk/test/lib/cli/CommandLineOptionTest.java
test/lib/jdk/test/lib/cli/predicate/AndPredicate.java
test/lib/jdk/test/lib/cli/predicate/CPUSpecificPredicate.java
test/lib/jdk/test/lib/cli/predicate/NotPredicate.java
test/lib/jdk/test/lib/cli/predicate/OrPredicate.java
test/lib/jdk/test/lib/dcmd/CommandExecutor.java
test/lib/jdk/test/lib/dcmd/CommandExecutorException.java
test/lib/jdk/test/lib/dcmd/FileJcmdExecutor.java
test/lib/jdk/test/lib/dcmd/JMXExecutor.java
test/lib/jdk/test/lib/dcmd/JcmdExecutor.java
test/lib/jdk/test/lib/dcmd/MainClassJcmdExecutor.java
test/lib/jdk/test/lib/dcmd/PidJcmdExecutor.java
test/lib/jdk/test/lib/hprof/HprofParser.java
test/lib/jdk/test/lib/hprof/README
test/lib/jdk/test/lib/hprof/model/AbstractJavaHeapObjectVisitor.java
test/lib/jdk/test/lib/hprof/model/ArrayTypeCodes.java
test/lib/jdk/test/lib/hprof/model/HackJavaValue.java
test/lib/jdk/test/lib/hprof/model/JavaBoolean.java
test/lib/jdk/test/lib/hprof/model/JavaByte.java
test/lib/jdk/test/lib/hprof/model/JavaChar.java
test/lib/jdk/test/lib/hprof/model/JavaClass.java
test/lib/jdk/test/lib/hprof/model/JavaDouble.java
test/lib/jdk/test/lib/hprof/model/JavaField.java
test/lib/jdk/test/lib/hprof/model/JavaFloat.java
test/lib/jdk/test/lib/hprof/model/JavaHeapObject.java
test/lib/jdk/test/lib/hprof/model/JavaHeapObjectVisitor.java
test/lib/jdk/test/lib/hprof/model/JavaInt.java
test/lib/jdk/test/lib/hprof/model/JavaLazyReadObject.java
test/lib/jdk/test/lib/hprof/model/JavaLong.java
test/lib/jdk/test/lib/hprof/model/JavaObject.java
test/lib/jdk/test/lib/hprof/model/JavaObjectArray.java
test/lib/jdk/test/lib/hprof/model/JavaObjectRef.java
test/lib/jdk/test/lib/hprof/model/JavaShort.java
test/lib/jdk/test/lib/hprof/model/JavaStatic.java
test/lib/jdk/test/lib/hprof/model/JavaThing.java
test/lib/jdk/test/lib/hprof/model/JavaValue.java
test/lib/jdk/test/lib/hprof/model/JavaValueArray.java
test/lib/jdk/test/lib/hprof/model/ReachableExcludes.java
test/lib/jdk/test/lib/hprof/model/ReachableExcludesImpl.java
test/lib/jdk/test/lib/hprof/model/ReachableObjects.java
test/lib/jdk/test/lib/hprof/model/ReferenceChain.java
test/lib/jdk/test/lib/hprof/model/Root.java
test/lib/jdk/test/lib/hprof/model/Snapshot.java
test/lib/jdk/test/lib/hprof/model/StackFrame.java
test/lib/jdk/test/lib/hprof/model/StackTrace.java
test/lib/jdk/test/lib/hprof/parser/FileReadBuffer.java
test/lib/jdk/test/lib/hprof/parser/HprofReader.java
test/lib/jdk/test/lib/hprof/parser/MappedReadBuffer.java
test/lib/jdk/test/lib/hprof/parser/PositionDataInputStream.java
test/lib/jdk/test/lib/hprof/parser/PositionInputStream.java
test/lib/jdk/test/lib/hprof/parser/ReadBuffer.java
test/lib/jdk/test/lib/hprof/parser/Reader.java
test/lib/jdk/test/lib/hprof/util/ArraySorter.java
test/lib/jdk/test/lib/hprof/util/Comparer.java
test/lib/jdk/test/lib/hprof/util/CompositeEnumeration.java
test/lib/jdk/test/lib/hprof/util/Misc.java
test/lib/jdk/test/lib/hprof/util/VectorSorter.java
test/lib/jdk/test/lib/process/ExitCode.java
test/lib/jdk/test/lib/process/OutputAnalyzer.java
test/lib/jdk/test/lib/process/OutputBuffer.java
test/lib/jdk/test/lib/process/ProcessTools.java
test/lib/jdk/test/lib/process/StreamPumper.java
test/lib/jdk/test/lib/util/Pair.java
test/lib/jdk/test/lib/util/Triple.java
test/lib/jdk/test/lib/wrappers/InfiniteLoop.java
test/lib/jdk/test/lib/wrappers/TimeLimitedRunner.java
test/lib/share/classes/jdk/test/lib/Asserts.java
test/lib/share/classes/jdk/test/lib/JDKToolFinder.java
test/lib/share/classes/jdk/test/lib/JDKToolLauncher.java
test/lib/share/classes/jdk/test/lib/Platform.java
test/lib/share/classes/jdk/test/lib/Utils.java
test/lib/share/classes/jdk/test/lib/apps/LingeredApp.java
test/lib/share/classes/jdk/test/lib/apps/LingeredAppWithDeadlock.java
test/lib/share/classes/jdk/test/lib/hprof/HprofParser.java
test/lib/share/classes/jdk/test/lib/hprof/README
test/lib/share/classes/jdk/test/lib/hprof/model/AbstractJavaHeapObjectVisitor.java
test/lib/share/classes/jdk/test/lib/hprof/model/ArrayTypeCodes.java
test/lib/share/classes/jdk/test/lib/hprof/model/HackJavaValue.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaBoolean.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaByte.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaChar.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaClass.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaDouble.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaField.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaFloat.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaHeapObject.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaHeapObjectVisitor.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaInt.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaLazyReadObject.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaLong.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaObject.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaObjectArray.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaObjectRef.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaShort.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaStatic.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaThing.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaValue.java
test/lib/share/classes/jdk/test/lib/hprof/model/JavaValueArray.java
test/lib/share/classes/jdk/test/lib/hprof/model/ReachableExcludes.java
test/lib/share/classes/jdk/test/lib/hprof/model/ReachableExcludesImpl.java
test/lib/share/classes/jdk/test/lib/hprof/model/ReachableObjects.java
test/lib/share/classes/jdk/test/lib/hprof/model/ReferenceChain.java
test/lib/share/classes/jdk/test/lib/hprof/model/Root.java
test/lib/share/classes/jdk/test/lib/hprof/model/Snapshot.java
test/lib/share/classes/jdk/test/lib/hprof/model/StackFrame.java
test/lib/share/classes/jdk/test/lib/hprof/model/StackTrace.java
test/lib/share/classes/jdk/test/lib/hprof/parser/FileReadBuffer.java
test/lib/share/classes/jdk/test/lib/hprof/parser/HprofReader.java
test/lib/share/classes/jdk/test/lib/hprof/parser/MappedReadBuffer.java
test/lib/share/classes/jdk/test/lib/hprof/parser/PositionDataInputStream.java
test/lib/share/classes/jdk/test/lib/hprof/parser/PositionInputStream.java
test/lib/share/classes/jdk/test/lib/hprof/parser/ReadBuffer.java
test/lib/share/classes/jdk/test/lib/hprof/parser/Reader.java
test/lib/share/classes/jdk/test/lib/hprof/util/ArraySorter.java
test/lib/share/classes/jdk/test/lib/hprof/util/Comparer.java
test/lib/share/classes/jdk/test/lib/hprof/util/CompositeEnumeration.java
test/lib/share/classes/jdk/test/lib/hprof/util/Misc.java
test/lib/share/classes/jdk/test/lib/hprof/util/VectorSorter.java
test/lib/share/classes/jdk/test/lib/process/OutputAnalyzer.java
test/lib/share/classes/jdk/test/lib/process/OutputBuffer.java
test/lib/share/classes/jdk/test/lib/process/ProcessTools.java
test/lib/share/classes/jdk/test/lib/process/StreamPumper.java
--- a/make/test/BuildTestLib.gmk	Mon Aug 15 16:14:59 2016 +0200
+++ b/make/test/BuildTestLib.gmk	Fri Aug 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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("&lt;");
+            } else if (ch == '>') {
+                sb.append("&gt;");
+            } else if (ch == '"') {
+                sb.append("&quot;");
+            } else if (ch == '\'') {
+                sb.append("&#039;");
+            } else if (ch == '&') {
+                sb.append("&amp;");
+            } 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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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 19 10:09:25 2016 -0400
@@ -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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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("&lt;");
-            } else if (ch == '>') {
-                sb.append("&gt;");
-            } else if (ch == '"') {
-                sb.append("&quot;");
-            } else if (ch == '\'') {
-                sb.append("&#039;");
-            } else if (ch == '&') {
-                sb.append("&amp;");
-            } 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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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	Mon Aug 15 16:14:59 2016 +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;
-    }
-}