Merge
This commit is contained in:
commit
391aa2f5ac
@ -307,3 +307,4 @@ ea38728b4f4bdd8fd0d7a89b18069f521cf05013 jdk9-b61
|
||||
105d045a69174d870b69bfe471b3f2d05a9f8ecc jdk9-b62
|
||||
0b32ed628fa60e4ab99fb0b5866d648e16231f17 jdk9-b63
|
||||
82cf9aab9a83e41c8194ba01af9666afdb856cbe jdk9-b64
|
||||
7c31f9d7b932f7924f1258d52885b1c7c3e078c2 jdk9-b65
|
||||
|
@ -83,7 +83,6 @@ ACCEPTED_BIN_DIFF="
|
||||
./bin/jcmd
|
||||
./bin/jconsole
|
||||
./bin/jdb
|
||||
./bin/jhat
|
||||
./bin/jimage
|
||||
./bin/jinfo
|
||||
./bin/jjs
|
||||
@ -163,7 +162,6 @@ ACCEPTED_BIN_DIFF="
|
||||
./bin/jcmd
|
||||
./bin/jconsole
|
||||
./bin/jdb
|
||||
./bin/jhat
|
||||
./bin/jimage
|
||||
./bin/jinfo
|
||||
./bin/jjs
|
||||
@ -284,7 +282,6 @@ ACCEPTED_SMALL_SIZE_DIFF="
|
||||
./bin/jcmd
|
||||
./bin/jconsole
|
||||
./bin/jdb
|
||||
./bin/jhat
|
||||
./bin/jimage
|
||||
./bin/jinfo
|
||||
./bin/jjs
|
||||
@ -420,7 +417,6 @@ ACCEPTED_SMALL_SIZE_DIFF="
|
||||
./bin/jcmd
|
||||
./bin/jconsole
|
||||
./bin/jdb
|
||||
./bin/jhat
|
||||
./bin/jimage
|
||||
./bin/jinfo
|
||||
./bin/jjs
|
||||
@ -499,7 +495,6 @@ ACCEPTED_SMALL_SIZE_DIFF="
|
||||
./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 @@ ACCEPTED_BIN_DIFF="
|
||||
./bin/jcmd
|
||||
./bin/jconsole
|
||||
./bin/jdb
|
||||
./bin/jhat
|
||||
./bin/jimage
|
||||
./bin/jinfo
|
||||
./bin/jjs
|
||||
|
@ -213,7 +213,6 @@ ifneq ($(OPENJDK_TARGET_OS), windows)
|
||||
jcmd.1 \
|
||||
jdb.1 \
|
||||
jdeps.1 \
|
||||
jhat.1 \
|
||||
jinfo.1 \
|
||||
jmap.1 \
|
||||
jps.1 \
|
||||
|
@ -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 @@ default: all
|
||||
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)
|
||||
|
@ -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 @@ define SetupArchiveBody
|
||||
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 @@ define SetupArchiveBody
|
||||
# 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), \
|
||||
|
@ -428,15 +428,6 @@ my.make.rule.test.targets.hotspot.basicvmtests= \
|
||||
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 @@ my.make.rule.test.targets.hotspot.reg.group= \
|
||||
|
||||
# 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 @@ my.make.rule.test.targets.hotspot.reg= \
|
||||
# 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
|
||||
|
18
modules.xml
18
modules.xml
@ -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>jdk.jfr</to>
|
||||
<to>java.instrument</to>
|
||||
<to>jdk.jfr</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>
|
||||
|
@ -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 @@ OUTPUT_DIR = $(BUILD_DIR)/classes
|
||||
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)
|
||||
|
97
test/lib/share/classes/jdk/test/lib/hprof/HprofParser.java
Normal file
97
test/lib/share/classes/jdk/test/lib/hprof/HprofParser.java
Normal file
@ -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;
|
||||
}
|
||||
|
||||
}
|
13
test/lib/share/classes/jdk/test/lib/hprof/README
Normal file
13
test/lib/share/classes/jdk/test/lib/hprof/README
Normal file
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
503
test/lib/share/classes/jdk/test/lib/hprof/model/JavaClass.java
Normal file
503
test/lib/share/classes/jdk/test/lib/hprof/model/JavaClass.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
54
test/lib/share/classes/jdk/test/lib/hprof/model/JavaInt.java
Normal file
54
test/lib/share/classes/jdk/test/lib/hprof/model/JavaInt.java
Normal file
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
334
test/lib/share/classes/jdk/test/lib/hprof/model/JavaObject.java
Normal file
334
test/lib/share/classes/jdk/test/lib/hprof/model/JavaObject.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
174
test/lib/share/classes/jdk/test/lib/hprof/model/Root.java
Normal file
174
test/lib/share/classes/jdk/test/lib/hprof/model/Root.java
Normal file
@ -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;
|
||||
}
|
||||
|
||||
}
|
637
test/lib/share/classes/jdk/test/lib/hprof/model/Snapshot.java
Normal file
637
test/lib/share/classes/jdk/test/lib/hprof/model/Snapshot.java
Normal file
@ -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();
|
||||
}
|
||||
|
||||
}
|
101
test/lib/share/classes/jdk/test/lib/hprof/model/StackFrame.java
Normal file
101
test/lib/share/classes/jdk/test/lib/hprof/model/StackFrame.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
97
test/lib/share/classes/jdk/test/lib/hprof/parser/Reader.java
Normal file
97
test/lib/share/classes/jdk/test/lib/hprof/parser/Reader.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
147
test/lib/share/classes/jdk/test/lib/hprof/util/ArraySorter.java
Normal file
147
test/lib/share/classes/jdk/test/lib/hprof/util/ArraySorter.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
49
test/lib/share/classes/jdk/test/lib/hprof/util/Comparer.java
Normal file
49
test/lib/share/classes/jdk/test/lib/hprof/util/Comparer.java
Normal file
@ -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);
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
112
test/lib/share/classes/jdk/test/lib/hprof/util/Misc.java
Normal file
112
test/lib/share/classes/jdk/test/lib/hprof/util/Misc.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
148
test/lib/share/classes/jdk/test/lib/hprof/util/VectorSorter.java
Normal file
148
test/lib/share/classes/jdk/test/lib/hprof/util/VectorSorter.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user