--- a/common/bin/compare_exceptions.sh.incl Thu May 21 10:07:34 2015 -0700
+++ b/common/bin/compare_exceptions.sh.incl Thu May 21 16:19:08 2015 -0700
@@ -83,7 +83,6 @@
./bin/jcmd
./bin/jconsole
./bin/jdb
-./bin/jhat
./bin/jimage
./bin/jinfo
./bin/jjs
@@ -163,7 +162,6 @@
./bin/jcmd
./bin/jconsole
./bin/jdb
-./bin/jhat
./bin/jimage
./bin/jinfo
./bin/jjs
@@ -284,7 +282,6 @@
./bin/jcmd
./bin/jconsole
./bin/jdb
-./bin/jhat
./bin/jimage
./bin/jinfo
./bin/jjs
@@ -420,7 +417,6 @@
./bin/jcmd
./bin/jconsole
./bin/jdb
-./bin/jhat
./bin/jimage
./bin/jinfo
./bin/jjs
@@ -499,7 +495,6 @@
./bin/jcmd.exe
./bin/jconsole.exe
./bin/jdb.exe
-./bin/jhat.exe
./bin/jimage.exe
./bin/jinfo.exe
./bin/jjs.exe
@@ -579,7 +574,6 @@
./bin/jcmd
./bin/jconsole
./bin/jdb
-./bin/jhat
./bin/jimage
./bin/jinfo
./bin/jjs
--- a/make/Images.gmk Thu May 21 10:07:34 2015 -0700
+++ b/make/Images.gmk Thu May 21 16:19:08 2015 -0700
@@ -213,7 +213,6 @@
jcmd.1 \
jdb.1 \
jdeps.1 \
- jhat.1 \
jinfo.1 \
jmap.1 \
jps.1 \
--- a/make/JrtfsJar.gmk Thu May 21 10:07:34 2015 -0700
+++ b/make/JrtfsJar.gmk Thu May 21 16:19:08 2015 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 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
@@ -28,10 +28,20 @@
include $(SPEC)
include MakeBase.gmk
include JavaCompilation.gmk
+include TextFileProcessing.gmk
+
+# This rule will be depended on due to the MANIFEST line
+$(eval $(call SetupTextFileProcessing, BUILD_JAVA_MANIFEST, \
+ SOURCE_FILES := $(JDK_TOPDIR)/make/data/mainmanifest/manifest.mf, \
+ OUTPUT_FILE := $(SUPPORT_OUTPUTDIR)/java-main-manifest.mf, \
+ REPLACEMENTS := \
+ @@RELEASE@@ => $(RELEASE) ; \
+ @@COMPANY_NAME@@ => $(COMPANY_NAME) , \
+))
$(eval $(call SetupArchive,JRTFS_JAR, , \
SRCS := $(BUILDTOOLS_OUTPUTDIR)/interim_jimage_classes, \
JAR := $(SUPPORT_OUTPUTDIR)/jrt-fs.jar, \
- MANIFEST := $(JDK_TOPDIR)/make/data/mainmanifest/manifest.mf))
+ MANIFEST := $(SUPPORT_OUTPUTDIR)/java-main-manifest.mf))
all: $(JRTFS_JAR)
--- a/make/common/JavaCompilation.gmk Thu May 21 10:07:34 2015 -0700
+++ b/make/common/JavaCompilation.gmk Thu May 21 16:19:08 2015 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -265,7 +265,7 @@
endif
# Include all variables of significance in the vardeps file
- $1_VARDEPS := $(JAR) $$($1_JAR_CREATE_OPTIONS) $$($1_MANIFEST) $(RELEASE) $(COMPANY_NAME) \
+ $1_VARDEPS := $(JAR) $$($1_JAR_CREATE_OPTIONS) $$($1_MANIFEST) \
$$($1_JARMAIN) $$($1_EXTRA_MANIFEST_ATTR)
$1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$(dir $$($1_JAR))_the.$$($1_JARNAME).vardeps)
@@ -280,8 +280,7 @@
# potential changes.
$$(if $$(filter $$($1_VARDEPS_FILE) $$($1_MANIFEST), $$?), \
$$(if $$($1_MANIFEST), \
- $(SED) -e "s#@@RELEASE@@#$(RELEASE)#" \
- -e "s#@@COMPANY_NAME@@#$(COMPANY_NAME)#" $$($1_MANIFEST) > $$($1_MANIFEST_FILE) $$(NEWLINE) \
+ $(CP) $$($1_MANIFEST) $$($1_MANIFEST_FILE) $$(NEWLINE) \
, \
$(RM) $$($1_MANIFEST_FILE) && $(TOUCH) $$($1_MANIFEST_FILE) $$(NEWLINE)) \
$$(if $$($1_JARMAIN), \
--- a/make/jprt.properties Thu May 21 10:07:34 2015 -0700
+++ b/make/jprt.properties Thu May 21 16:19:08 2015 -0700
@@ -428,15 +428,6 @@
windows_i586_6.2-*-default-hotspot_basicvmtest, \
windows_x64_6.2-*-default-hotspot_basicvmtest
-my.make.rule.test.targets.hotspot.internalvmtests= \
- solaris_sparcv9_5.11-fastdebug-c2-hotspot_internalvmtests, \
- solaris_x64_5.11-fastdebug-c2-hotspot_internalvmtests, \
- linux_i586_2.6-fastdebug-c2-hotspot_internalvmtests, \
- linux_x64_2.6-fastdebug-c2-hotspot_internalvmtests, \
- macosx_x64_10.9-fastdebug-c2-hotspot_internalvmtests, \
- windows_i586_6.2-fastdebug-c2-hotspot_internalvmtests, \
- windows_x64_6.2-fastdebug-c2-hotspot_internalvmtests
-
my.make.rule.test.targets.hotspot.reg.group= \
solaris_sparcv9_5.11-fastdebug-c2-GROUP, \
solaris_x64_5.11-fastdebug-c2-GROUP, \
@@ -450,7 +441,6 @@
# Hotspot jtreg tests
my.make.rule.test.targets.hotspot.reg= \
- ${my.make.rule.test.targets.hotspot.reg.group:GROUP=hotspot_wbapitest}, \
${my.make.rule.test.targets.hotspot.reg.group:GROUP=hotspot_compiler_1}, \
${my.make.rule.test.targets.hotspot.reg.group:GROUP=hotspot_compiler_2}, \
${my.make.rule.test.targets.hotspot.reg.group:GROUP=hotspot_compiler_3}, \
@@ -466,7 +456,6 @@
# Other Makefile based Hotspot tests
my.make.rule.test.targets.hotspot.other= \
${my.make.rule.test.targets.hotspot.basicvmtests}, \
- ${my.make.rule.test.targets.hotspot.internalvmtests}, \
${my.additional.make.rule.test.targets.hotspot.other}
# All the makefile based tests to run
--- a/modules.xml Thu May 21 10:07:34 2015 -0700
+++ b/modules.xml Thu May 21 16:19:08 2015 -0700
@@ -2,7 +2,7 @@
<!--
- Copyright (c) 2014, 2015 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2014, 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
@@ -216,19 +216,19 @@
</export>
<export>
<name>jdk.internal.jimage</name>
- <to>jdk.dev</to>
+ <to>jdk.dev</to>
</export>
<export>
<name>jdk.internal.org.objectweb.asm</name>
+ <to>java.instrument</to>
<to>jdk.jfr</to>
<to>jdk.scripting.nashorn</to>
- <to>java.instrument</to>
</export>
<export>
<name>jdk.internal.org.objectweb.asm.commons</name>
+ <to>java.instrument</to>
<to>jdk.jfr</to>
<to>jdk.scripting.nashorn</to>
- <to>java.instrument</to>
</export>
<export>
<name>jdk.internal.org.objectweb.asm.signature</name>
@@ -236,19 +236,20 @@
</export>
<export>
<name>jdk.internal.org.objectweb.asm.tree</name>
+ <to>java.instrument</to>
<to>jdk.jfr</to>
- <to>java.instrument</to>
</export>
<export>
<name>jdk.internal.org.objectweb.asm.util</name>
+ <to>java.instrument</to>
<to>jdk.jfr</to>
<to>jdk.scripting.nashorn</to>
- <to>java.instrument</to>
</export>
<export>
<name>sun.misc</name>
<to>java.corba</to>
<to>java.desktop</to>
+ <to>java.instrument</to>
<to>java.logging</to>
<to>java.management</to>
<to>java.naming</to>
@@ -266,6 +267,7 @@
<to>jdk.jartool</to>
<to>jdk.jconsole</to>
<to>jdk.jvmstat</to>
+ <to>jdk.management.resource</to>
<to>jdk.pack200</to>
<to>jdk.security.auth</to>
<to>jdk.security.jgss</to>
@@ -301,6 +303,7 @@
<to>java.management</to>
<to>jdk.crypto.pkcs11</to>
<to>jdk.crypto.ucrypto</to>
+ <to>jdk.management.resource</to>
<to>jdk.sctp</to>
</export>
<export>
@@ -311,11 +314,11 @@
<export>
<name>sun.reflect</name>
<to>java.corba</to>
+ <to>java.instrument</to>
<to>java.logging</to>
<to>java.sql</to>
<to>java.sql.rowset</to>
<to>jdk.scripting.nashorn</to>
- <to>java.instrument</to>
</export>
<export>
<name>sun.reflect.annotation</name>
@@ -774,6 +777,7 @@
<export>
<name>jdk.internal.instrumentation</name>
<to>jdk.jfr</to>
+ <to>jdk.management.resource</to>
</export>
</module>
<module>
--- a/test/lib/Makefile Thu May 21 10:07:34 2015 -0700
+++ b/test/lib/Makefile Thu May 21 16:19:08 2015 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+# 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
@@ -41,25 +41,38 @@
JAVAC = $(JDK_HOME)/bin/javac
JAR = $(JDK_HOME)/bin/jar
-SRC_FILES = $(shell find $(SRC_DIR) -name '*.java')
+WB_SRC_FILES = $(shell find $(SRC_DIR)/sun/hotspot -name '*.java')
+SHARE_SRC_FILES = $(shell find $(SRC_DIR)/share/classes -name '*.java')
-.PHONY: filelist clean cleantmp
+.PHONY: wb.filelist share.filelist clean cleantmp
-all: wb.jar cleantmp
+all: wb.jar test-lib.jar cleantmp
-wb.jar: filelist
+wb.jar: wb.filelist
@mkdir -p $(OUTPUT_DIR)
- $(JAVAC) -sourcepath $(SRC_DIR) -d $(OUTPUT_DIR) -cp $(OUTPUT_DIR) @filelist
+ $(JAVAC) -sourcepath $(SRC_DIR) -d $(OUTPUT_DIR) -cp $(OUTPUT_DIR) @wb.filelist
$(JAR) cf wb.jar -C $(OUTPUT_DIR) .
@rm -rf $(OUTPUT_DIR)
-filelist: $(SRC_FILES)
+wb.filelist: $(WB_SRC_FILES)
@rm -f $@
- @echo $(SRC_FILES) > $@
+ @echo $(WB_SRC_FILES) > $@
+
+test-lib.jar: share.filelist
+ @mkdir -p $(OUTPUT_DIR)
+ $(JAVAC) -sourcepath $(SRC_DIR) -d $(OUTPUT_DIR) -cp $(OUTPUT_DIR) @share.filelist
+ $(JAR) cf test-lib.jar -C $(OUTPUT_DIR) .
+ @rm -rf $(OUTPUT_DIR)
+
+share.filelist: $(SHARE_SRC_FILES)
+ @rm -f $@
+ @echo $(SHARE_SRC_FILES) > $@
clean: cleantmp
@rm -rf wb.jar
+ @rm -rf test-list.jar
cleantmp:
- @rm -rf filelist
+ @rm -rf wb.filelist
+ @rm -rf share.filelist
@rm -rf $(BUILD_DIR)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/HprofParser.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,97 @@
+/*
+ * 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;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/README Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,13 @@
+The jhat tool has been removed. jhat hprof file parser/validator
+are needed for tests. The old packages for jhat were moved here:
+com.sun.tools.hat.internal.model -> jdk.test.lib.hprof.model
+com.sun.tools.hat.internal.parser -> jdk.test.lib.hprof.parser
+com.sun.tools.hat.internal.util -> jdk.test.lib.hprof.util
+
+jhat was added in JDK 6 and its original implementation was from
+java.net HAT project [1]. jhat is an experimental, unsupported tool.
+There hasn't been much update to jhat tool in the JDK. In addition,
+there are several better heap dump visualizer/analyzer emerged since
+JDK 5/6 serviceability support.
+
+[1] https://java.net/projects/hat
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/AbstractJavaHeapObjectVisitor.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,60 @@
+/*
+ * 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;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/ArrayTypeCodes.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,50 @@
+/*
+ * 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;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/HackJavaValue.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,65 @@
+/*
+ * 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;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaBoolean.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,54 @@
+/*
+ * 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;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaByte.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,54 @@
+/*
+ * 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);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaChar.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,54 @@
+/*
+ * 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;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaClass.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,503 @@
+/*
+ * 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;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaDouble.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,53 @@
+/*
+ * 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);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaField.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,69 @@
+/*
+ * 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;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaFloat.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,53 @@
+/*
+ * 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);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaHeapObject.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,207 @@
+/*
+ * 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;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaHeapObjectVisitor.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,55 @@
+/*
+ * 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();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaInt.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,54 @@
+/*
+ * 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;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaLazyReadObject.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,176 @@
+/*
+ * 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);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaLong.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,53 @@
+/*
+ * 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);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaObject.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,334 @@
+/*
+ * 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);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaObjectArray.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,172 @@
+/*
+ * 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;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaObjectRef.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,97 @@
+/*
+ * 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);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaShort.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,54 @@
+/*
+ * 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;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaStatic.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,79 @@
+/*
+ * 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;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaThing.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,99 @@
+/*
+ * 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());
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaValue.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,61 @@
+/*
+ * 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;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/JavaValueArray.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,433 @@
+/*
+ * 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();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/ReachableExcludes.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,50 @@
+/*
+ * 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);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/ReachableExcludesImpl.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,103 @@
+/*
+ * 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;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/ReachableObjects.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,148 @@
+/*
+ * 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;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/ReferenceChain.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,69 @@
+/*
+ * 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;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/Root.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,174 @@
+/*
+ * 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;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/Snapshot.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,637 @@
+/*
+ * 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");
+ if (weakReferenceClass == null) { // JDK 1.1.x
+ weakReferenceClass = findClass("sun.misc.Ref");
+ referentFieldIndex = 0;
+ } else {
+ 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/share/classes/jdk/test/lib/hprof/model/StackFrame.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,101 @@
+/*
+ * 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);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/model/StackTrace.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,77 @@
+/*
+ * 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;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/parser/FileReadBuffer.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,89 @@
+/*
+ * 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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/parser/HprofReader.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,892 @@
+/*
+ * 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 {
+ in.skipBytes((int)length);
+ }
+
+ 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: {
+ int bytesRead = readArray(false);
+ bytesLeft -= bytesRead;
+ break;
+ }
+ case HPROF_GC_PRIM_ARRAY_DUMP: {
+ int 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 int readArray(boolean isPrimitive) throws IOException {
+ long start = in.position();
+ long id = readID();
+ StackTrace stackTrace = getStackTraceFromSerial(in.readInt());
+ int num = in.readInt();
+ int 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) {
+ int size = elSize * num;
+ bytesRead += size;
+ JavaValueArray va = new JavaValueArray(primitiveSignature, start);
+ skipBytes(size);
+ snapshot.addHeapObject(id, va);
+ snapshot.setSiteTrace(va, stackTrace);
+ } else {
+ int sz = 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/share/classes/jdk/test/lib/hprof/parser/MappedReadBuffer.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,136 @@
+/*
+ * 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();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/parser/PositionDataInputStream.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,64 @@
+/*
+ * 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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/parser/PositionInputStream.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,84 @@
+/*
+ * 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;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/parser/ReadBuffer.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,51 @@
+/*
+ * 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;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/parser/Reader.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,97 @@
+/*
+ * 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);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/util/ArraySorter.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,147 @@
+/*
+ * 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);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/util/Comparer.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,49 @@
+/*
+ * 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);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/util/CompositeEnumeration.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,63 @@
+/*
+ * 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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/util/Misc.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * The Original Code is HAT. The Initial Developer of the
+ * Original Code is Bill Foote, with contributions from others
+ * at JavaSoft/Sun.
+ */
+
+package jdk.test.lib.hprof.util;
+import java.util.*;
+
+/**
+ * Miscellaneous functions I couldn't think of a good place to put.
+ *
+ * @author Bill Foote
+ */
+
+
+public class Misc {
+
+ private static char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+ public final static String toHex(int addr) {
+ char[] buf = new char[8];
+ int i = 0;
+ for (int s = 28; s >= 0; s -= 4) {
+ buf[i++] = digits[(addr >> s) & 0xf];
+ }
+ return "0x" + new String(buf);
+ }
+
+ public final static String toHex(long addr) {
+ return "0x" + Long.toHexString(addr);
+ }
+
+ public final static long parseHex(String value) {
+ long result = 0;
+ if (value.length() < 2 || value.charAt(0) != '0' ||
+ value.charAt(1) != 'x') {
+ return -1L;
+ }
+ for(int i = 2; i < value.length(); i++) {
+ result *= 16;
+ char ch = value.charAt(i);
+ if (ch >= '0' && ch <= '9') {
+ result += (ch - '0');
+ } else if (ch >= 'a' && ch <= 'f') {
+ result += (ch - 'a') + 10;
+ } else if (ch >= 'A' && ch <= 'F') {
+ result += (ch - 'A') + 10;
+ } else {
+ throw new NumberFormatException("" + ch
+ + " is not a valid hex digit");
+ }
+ }
+ return result;
+ }
+
+ public static String encodeHtml(String str) {
+ final int len = str.length();
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < len; i++) {
+ char ch = str.charAt(i);
+ if (ch == '<') {
+ sb.append("<");
+ } else if (ch == '>') {
+ sb.append(">");
+ } else if (ch == '"') {
+ sb.append(""");
+ } else if (ch == '\'') {
+ sb.append("'");
+ } else if (ch == '&') {
+ sb.append("&");
+ } else if (ch < ' ') {
+ sb.append("&#").append((int)ch).append(';');
+ } else {
+ int c = (ch & 0xFFFF);
+ if (c > 127) {
+ sb.append("&#").append(c).append(';');
+ } else {
+ sb.append(ch);
+ }
+ }
+ }
+ return sb.toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/hprof/util/VectorSorter.java Thu May 21 16:19:08 2015 -0700
@@ -0,0 +1,148 @@
+/*
+ * 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);
+ }
+}