feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,212 @@
/*
* Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat;
import java.io.IOException;
import java.io.File;
import com.sun.tools.hat.internal.model.Snapshot;
import com.sun.tools.hat.internal.model.ReachableExcludesImpl;
import com.sun.tools.hat.internal.server.QueryListener;
/**
*
* @author Bill Foote
*/
public class Main {
private static String VERSION_STRING = "jhat version 2.0";
private static void usage(String message) {
if ( message != null ) {
System.err.println("ERROR: " + message);
}
System.err.println("Usage: jhat [-stack <bool>] [-refs <bool>] [-port <port>] [-baseline <file>] [-debug <int>] [-version] [-h|-help] <file>");
System.err.println();
System.err.println("\t-J<flag> Pass <flag> directly to the runtime system. For");
System.err.println("\t\t\t example, -J-mx512m to use a maximum heap size of 512MB");
System.err.println("\t-stack false: Turn off tracking object allocation call stack.");
System.err.println("\t-refs false: Turn off tracking of references to objects");
System.err.println("\t-port <port>: Set the port for the HTTP server. Defaults to 7000");
System.err.println("\t-exclude <file>: Specify a file that lists data members that should");
System.err.println("\t\t\t be excluded from the reachableFrom query.");
System.err.println("\t-baseline <file>: Specify a baseline object dump. Objects in");
System.err.println("\t\t\t both heap dumps with the same ID and same class will");
System.err.println("\t\t\t be marked as not being \"new\".");
System.err.println("\t-debug <int>: Set debug level.");
System.err.println("\t\t\t 0: No debug output");
System.err.println("\t\t\t 1: Debug hprof file parsing");
System.err.println("\t\t\t 2: Debug hprof file parsing, no server");
System.err.println("\t-version Report version number");
System.err.println("\t-h|-help Print this help and exit");
System.err.println("\t<file> The file to read");
System.err.println();
System.err.println("For a dump file that contains multiple heap dumps,");
System.err.println("you may specify which dump in the file");
System.err.println("by appending \"#<number>\" to the file name, i.e. \"foo.hprof#3\".");
System.err.println();
System.err.println("All boolean options default to \"true\"");
System.exit(1);
}
//
// Convert s to a boolean. If it's invalid, abort the program.
//
private static boolean booleanValue(String s) {
if ("true".equalsIgnoreCase(s)) {
return true;
} else if ("false".equalsIgnoreCase(s)) {
return false;
} else {
usage("Boolean value must be true or false");
return false; // Never happens
}
}
public static void main(String[] args) {
if (args.length < 1) {
usage("No arguments supplied");
}
boolean parseonly = false;
int portNumber = 7000;
boolean callStack = true;
boolean calculateRefs = true;
String baselineDump = null;
String excludeFileName = null;
int debugLevel = 0;
for (int i = 0; ; i += 2) {
if (i > (args.length - 1)) {
usage("Option parsing error");
}
if ("-version".equals(args[i])) {
System.out.print(VERSION_STRING);
System.out.println(" (java version " + System.getProperty("java.version") + ")");
System.exit(0);
}
if ("-h".equals(args[i]) || "-help".equals(args[i])) {
usage(null);
}
if (i == (args.length - 1)) {
break;
}
String key = args[i];
String value = args[i+1];
if ("-stack".equals(key)) {
callStack = booleanValue(value);
} else if ("-refs".equals(key)) {
calculateRefs = booleanValue(value);
} else if ("-port".equals(key)) {
portNumber = Integer.parseInt(value, 10);
} else if ("-exclude".equals(key)) {
excludeFileName = value;
} else if ("-baseline".equals(key)) {
baselineDump = value;
} else if ("-debug".equals(key)) {
debugLevel = Integer.parseInt(value, 10);
} else if ("-parseonly".equals(key)) {
// Undocumented option. To be used for testing purpose only
parseonly = booleanValue(value);
}
}
String fileName = args[args.length - 1];
Snapshot model = null;
File excludeFile = null;
if (excludeFileName != null) {
excludeFile = new File(excludeFileName);
if (!excludeFile.exists()) {
System.out.println("Exclude file " + excludeFile
+ " does not exist. Aborting.");
System.exit(1);
}
}
System.out.println("Reading from " + fileName + "...");
try {
model = com.sun.tools.hat.internal.parser.Reader.readFile(fileName, callStack, debugLevel);
} catch (IOException ex) {
ex.printStackTrace();
System.exit(1);
} catch (RuntimeException ex) {
ex.printStackTrace();
System.exit(1);
}
System.out.println("Snapshot read, resolving...");
model.resolve(calculateRefs);
System.out.println("Snapshot resolved.");
if (excludeFile != null) {
model.setReachableExcludes(new ReachableExcludesImpl(excludeFile));
}
if (baselineDump != null) {
System.out.println("Reading baseline snapshot...");
Snapshot baseline = null;
try {
baseline = com.sun.tools.hat.internal.parser.Reader.readFile(baselineDump, false,
debugLevel);
} catch (IOException ex) {
ex.printStackTrace();
System.exit(1);
} catch (RuntimeException ex) {
ex.printStackTrace();
System.exit(1);
}
baseline.resolve(false);
System.out.println("Discovering new objects...");
model.markNewRelativeTo(baseline);
baseline = null; // Guard against conservative GC
}
if ( debugLevel == 2 ) {
System.out.println("No server, -debug 2 was used.");
System.exit(0);
}
if (parseonly) {
// do not start web server.
System.out.println("-parseonly is true, exiting..");
System.exit(0);
}
QueryListener listener = new QueryListener(portNumber);
listener.setModel(model);
Thread t = new Thread(listener, "Query Listener");
t.setPriority(Thread.NORM_PRIORITY+1);
t.start();
System.out.println("Started HTTP server on port " + portNumber);
System.out.println("Server is ready.");
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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;
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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;
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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;
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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;
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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);
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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;
}
}

View File

@@ -0,0 +1,503 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.model;
import java.util.Vector;
import java.util.Enumeration;
import com.sun.tools.hat.internal.util.CompositeEnumeration;
import com.sun.tools.hat.internal.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 getInstances(boolean includeSubclasses) {
if (includeSubclasses) {
Enumeration 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;
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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);
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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;
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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);
}
}

View File

@@ -0,0 +1,207 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.model;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import com.sun.tools.hat.internal.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 getReferers() {
if (referersLen != -1) {
throw new RuntimeException("not resolved: " + getIdString());
}
return new Enumeration() {
private int num = 0;
public boolean hasMoreElements() {
return referers != null && num < referers.length;
}
public Object 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;
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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();
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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;
}
}

View File

@@ -0,0 +1,176 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.model;
import java.io.IOException;
import com.sun.tools.hat.internal.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 new Integer((int)id);
} else {
return new Long(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);
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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);
}
}

View File

@@ -0,0 +1,334 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.model;
import java.io.IOException;
import com.sun.tools.hat.internal.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);
}
}

View File

@@ -0,0 +1,172 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.model;
import java.io.IOException;
import com.sun.tools.hat.internal.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;
}
}
}

View File

@@ -0,0 +1,97 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.model;
import com.sun.tools.hat.internal.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);
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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;
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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;
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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());
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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;
}
}

View File

@@ -0,0 +1,433 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.model;
import com.sun.tools.hat.internal.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
StringBuffer result;
byte[] value = getValue();
int max = value.length;
byte elementSignature = getElementType();
if (elementSignature == 'C') {
result = new StringBuffer();
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 StringBuffer("{");
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" + 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();
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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);
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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 methods; // Hashtable<String, String>, 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;
}
}

View File

@@ -0,0 +1,148 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.model;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import com.sun.tools.hat.internal.util.ArraySorter;
import com.sun.tools.hat.internal.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 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;
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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;
}
}

View File

@@ -0,0 +1,174 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.model;
import com.sun.tools.hat.internal.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;
}
}

View File

@@ -0,0 +1,630 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.model;
import java.lang.ref.SoftReference;
import java.util.*;
import com.sun.tools.hat.internal.parser.ReadBuffer;
import com.sun.tools.hat.internal.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 {
public static 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 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 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 new Integer((int)id);
} else {
return new Long(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>();
}
}
}
}
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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);
}
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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;
}
}

View File

@@ -0,0 +1,311 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.oql;
import com.sun.tools.hat.internal.model.*;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
/**
* This is Object Query Language Interpreter
*
*/
public class OQLEngine {
static {
try {
// Do we have javax.script support?
// create ScriptEngineManager
Class<?> managerClass = Class.forName("javax.script.ScriptEngineManager");
Object manager = managerClass.newInstance();
// create JavaScript engine
Method getEngineMethod = managerClass.getMethod("getEngineByName",
new Class[] { String.class });
Object jse = getEngineMethod.invoke(manager, new Object[] {"js"});
oqlSupported = (jse != null);
} catch (Exception exp) {
oqlSupported = false;
}
}
// check OQL is supported or not before creating OQLEngine
public static boolean isOQLSupported() {
return oqlSupported;
}
public OQLEngine(Snapshot snapshot) {
if (!isOQLSupported()) {
throw new UnsupportedOperationException("OQL not supported");
}
init(snapshot);
}
/**
Query is of the form
select &lt;java script code to select&gt;
[ from [instanceof] &lt;class name&gt; [&lt;identifier&gt;]
[ where &lt;java script boolean expression&gt; ]
]
*/
public synchronized void executeQuery(String query, ObjectVisitor visitor)
throws OQLException {
debugPrint("query : " + query);
StringTokenizer st = new StringTokenizer(query);
if (st.hasMoreTokens()) {
String first = st.nextToken();
if (! first.equals("select") ) {
// Query does not start with 'select' keyword.
// Just treat it as plain JavaScript and eval it.
try {
Object res = evalScript(query);
visitor.visit(res);
} catch (Exception e) {
throw new OQLException(e);
}
return;
}
} else {
throw new OQLException("query syntax error: no 'select' clause");
}
String selectExpr = "";
boolean seenFrom = false;
while (st.hasMoreTokens()) {
String tok = st.nextToken();
if (tok.equals("from")) {
seenFrom = true;
break;
}
selectExpr += " " + tok;
}
if (selectExpr.equals("")) {
throw new OQLException("query syntax error: 'select' expression can not be empty");
}
String className = null;
boolean isInstanceOf = false;
String whereExpr = null;
String identifier = null;
if (seenFrom) {
if (st.hasMoreTokens()) {
String tmp = st.nextToken();
if (tmp.equals("instanceof")) {
isInstanceOf = true;
if (! st.hasMoreTokens()) {
throw new OQLException("no class name after 'instanceof'");
}
className = st.nextToken();
} else {
className = tmp;
}
} else {
throw new OQLException("query syntax error: class name must follow 'from'");
}
if (st.hasMoreTokens()) {
identifier = st.nextToken();
if (identifier.equals("where")) {
throw new OQLException("query syntax error: identifier should follow class name");
}
if (st.hasMoreTokens()) {
String tmp = st.nextToken();
if (! tmp.equals("where")) {
throw new OQLException("query syntax error: 'where' clause expected after 'from' clause");
}
whereExpr = "";
while (st.hasMoreTokens()) {
whereExpr += " " + st.nextToken();
}
if (whereExpr.equals("")) {
throw new OQLException("query syntax error: 'where' clause cannot have empty expression");
}
}
} else {
throw new OQLException("query syntax error: identifier should follow class name");
}
}
executeQuery(new OQLQuery(selectExpr, isInstanceOf, className,
identifier, whereExpr), visitor);
}
private void executeQuery(OQLQuery q, ObjectVisitor visitor)
throws OQLException {
JavaClass clazz = null;
if (q.className != null) {
clazz = snapshot.findClass(q.className);
if (clazz == null) {
throw new OQLException(q.className + " is not found!");
}
}
StringBuffer buf = new StringBuffer();
buf.append("function __select__(");
if (q.identifier != null) {
buf.append(q.identifier);
}
buf.append(") { return ");
buf.append(q.selectExpr.replace('\n', ' '));
buf.append("; }");
String selectCode = buf.toString();
debugPrint(selectCode);
String whereCode = null;
if (q.whereExpr != null) {
buf = new StringBuffer();
buf.append("function __where__(");
buf.append(q.identifier);
buf.append(") { return ");
buf.append(q.whereExpr.replace('\n', ' '));
buf.append("; }");
whereCode = buf.toString();
}
debugPrint(whereCode);
// compile select expression and where condition
try {
evalMethod.invoke(engine, new Object[] { selectCode });
if (whereCode != null) {
evalMethod.invoke(engine, new Object[] { whereCode });
}
if (q.className != null) {
Enumeration objects = clazz.getInstances(q.isInstanceOf);
while (objects.hasMoreElements()) {
JavaHeapObject obj = (JavaHeapObject) objects.nextElement();
Object[] args = new Object[] { wrapJavaObject(obj) };
boolean b = (whereCode == null);
if (!b) {
Object res = call("__where__", args);
if (res instanceof Boolean) {
b = ((Boolean)res).booleanValue();
} else if (res instanceof Number) {
b = ((Number)res).intValue() != 0;
} else {
b = (res != null);
}
}
if (b) {
Object select = call("__select__", args);
if (visitor.visit(select)) return;
}
}
} else {
// simple "select <expr>" query
Object select = call("__select__", new Object[] {});
visitor.visit(select);
}
} catch (Exception e) {
throw new OQLException(e);
}
}
public Object evalScript(String script) throws Exception {
return evalMethod.invoke(engine, new Object[] { script });
}
public Object wrapJavaObject(JavaHeapObject obj) throws Exception {
return call("wrapJavaObject", new Object[] { obj });
}
public Object toHtml(Object obj) throws Exception {
return call("toHtml", new Object[] { obj });
}
public Object call(String func, Object[] args) throws Exception {
return invokeMethod.invoke(engine, new Object[] { func, args });
}
private static void debugPrint(String msg) {
if (debug) System.out.println(msg);
}
private void init(Snapshot snapshot) throws RuntimeException {
this.snapshot = snapshot;
try {
// create ScriptEngineManager
Class<?> managerClass = Class.forName("javax.script.ScriptEngineManager");
Object manager = managerClass.newInstance();
// create JavaScript engine
Method getEngineMethod = managerClass.getMethod("getEngineByName",
new Class[] { String.class });
engine = getEngineMethod.invoke(manager, new Object[] {"js"});
// initialize engine with init file (hat.js)
InputStream strm = getInitStream();
Class<?> engineClass = Class.forName("javax.script.ScriptEngine");
evalMethod = engineClass.getMethod("eval",
new Class[] { Reader.class });
evalMethod.invoke(engine, new Object[] {new InputStreamReader(strm)});
// initialize ScriptEngine.eval(String) and
// Invocable.invokeFunction(String, Object[]) methods.
Class<?> invocableClass = Class.forName("javax.script.Invocable");
evalMethod = engineClass.getMethod("eval",
new Class[] { String.class });
invokeMethod = invocableClass.getMethod("invokeFunction",
new Class[] { String.class, Object[].class });
// initialize ScriptEngine.put(String, Object) method
Method putMethod = engineClass.getMethod("put",
new Class[] { String.class, Object.class });
// call ScriptEngine.put to initialize built-in heap object
putMethod.invoke(engine, new Object[] {
"heap", call("wrapHeapSnapshot", new Object[] { snapshot })
});
} catch (Exception e) {
if (debug) e.printStackTrace();
throw new RuntimeException(e);
}
}
private InputStream getInitStream() {
return getClass().getResourceAsStream("/com/sun/tools/hat/resources/hat.js");
}
private Object engine;
private Method evalMethod;
private Method invokeMethod;
private Snapshot snapshot;
private static boolean debug = false;
private static boolean oqlSupported;
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.oql;
/**
* OQLException is thrown if OQL execution results in error
*
*/
public class OQLException extends Exception {
public OQLException(String msg) {
super(msg);
}
public OQLException(String msg, Throwable cause) {
super(msg, cause);
}
public OQLException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.oql;
/**
* This represents a parsed OQL query
*
*/
class OQLQuery {
OQLQuery(String selectExpr, boolean isInstanceOf,
String className, String identifier, String whereExpr) {
this.selectExpr = selectExpr;
this.isInstanceOf = isInstanceOf;
this.className = className;
this.identifier = identifier;
this.whereExpr = whereExpr;
}
String selectExpr;
boolean isInstanceOf;
String className;
String identifier;
String whereExpr;
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.oql;
/**
* This visitor is supplied to OQLEngine.executeQuery
* to receive result set objects one by one.
*
*/
public interface ObjectVisitor {
// return true to terminate the result set callback earlier
public boolean visit(Object o);
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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();
}
}

View File

@@ -0,0 +1,899 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.parser;
import java.io.*;
import java.util.Date;
import java.util.Hashtable;
import com.sun.tools.hat.internal.model.ArrayTypeCodes;
import com.sun.tools.hat.internal.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(new Long(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 = new Long(classID);
String nm = getNameFromID(classNameID).replace('/', '.');
classNameFromObjectID.put(classIdI, nm);
if (classNameFromSerialNo != null) {
classNameFromSerialNo.put(new Integer(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(new Integer(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(new Long(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(new Long(fid));
if (frames[i] == null) {
throw new IOException("Stack frame " + toHex(fid) + " not found");
}
}
stackTraces.put(new Integer(serialNo),
new StackTrace(frames));
}
break;
}
case HPROF_UNLOAD_CLASS:
case HPROF_ALLOC_SITES:
case HPROF_START_THREAD:
case HPROF_END_THREAD:
case HPROF_HEAP_SUMMARY:
case HPROF_CPU_SAMPLES:
case HPROF_CONTROL_SETTINGS:
case HPROF_LOCKSTATS_WAIT_TIME:
case HPROF_LOCKSTATS_HOLD_TIME:
{
// Ignore these record types
skipBytes(length);
break;
}
default: {
skipBytes(length);
warn("Ignoring unrecognized record type " + type);
}
}
}
return snapshot;
}
private void skipBytes(long length) throws IOException {
while (length > 0) {
long skipped = in.skip(length);
length -= skipped;
if (skipped == 0) {
// EOF or other problem, throw exception
throw new EOFException("Couldn't skip enough bytes");
}
}
}
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(new Integer(threadSeq),
new ThreadObject(id, stackSeq));
break;
}
case HPROF_GC_ROOT_JNI_GLOBAL: {
long id = readID();
long globalRefId = readID(); // Ignored, for now
bytesLeft -= 2*identifierSize;
snapshot.addRoot(new Root(id, 0, Root.NATIVE_STATIC, ""));
break;
}
case HPROF_GC_ROOT_JNI_LOCAL: {
long id = readID();
int threadSeq = in.readInt();
int depth = in.readInt();
bytesLeft -= identifierSize + 8;
ThreadObject to = getThreadObjectFromSequence(threadSeq);
StackTrace st = getStackTraceFromSerial(to.stackSeq);
if (st != null) {
st = st.traceForDepth(depth+1);
}
snapshot.addRoot(new Root(id, to.threadId,
Root.NATIVE_LOCAL, "", st));
break;
}
case HPROF_GC_ROOT_JAVA_FRAME: {
long id = readID();
int threadSeq = in.readInt();
int depth = in.readInt();
bytesLeft -= identifierSize + 8;
ThreadObject to = getThreadObjectFromSequence(threadSeq);
StackTrace st = getStackTraceFromSerial(to.stackSeq);
if (st != null) {
st = st.traceForDepth(depth+1);
}
snapshot.addRoot(new Root(id, to.threadId,
Root.JAVA_LOCAL, "", st));
break;
}
case HPROF_GC_ROOT_NATIVE_STACK: {
long id = readID();
int threadSeq = in.readInt();
bytesLeft -= identifierSize + 4;
ThreadObject to = getThreadObjectFromSequence(threadSeq);
StackTrace st = getStackTraceFromSerial(to.stackSeq);
snapshot.addRoot(new Root(id, to.threadId,
Root.NATIVE_STACK, "", st));
break;
}
case HPROF_GC_ROOT_STICKY_CLASS: {
long id = readID();
bytesLeft -= identifierSize;
snapshot.addRoot(new Root(id, 0, Root.SYSTEM_CLASS, ""));
break;
}
case HPROF_GC_ROOT_THREAD_BLOCK: {
long id = readID();
int threadSeq = in.readInt();
bytesLeft -= identifierSize + 4;
ThreadObject to = getThreadObjectFromSequence(threadSeq);
StackTrace st = getStackTraceFromSerial(to.stackSeq);
snapshot.addRoot(new Root(id, to.threadId,
Root.THREAD_BLOCK, "", st));
break;
}
case HPROF_GC_ROOT_MONITOR_USED: {
long id = readID();
bytesLeft -= identifierSize;
snapshot.addRoot(new Root(id, 0, Root.BUSY_MONITOR, ""));
break;
}
case HPROF_GC_CLASS_DUMP: {
int bytesRead = readClass();
bytesLeft -= bytesRead;
break;
}
case HPROF_GC_INSTANCE_DUMP: {
int bytesRead = readInstance();
bytesLeft -= bytesRead;
break;
}
case HPROF_GC_OBJ_ARRAY_DUMP: {
long bytesRead = readArray(false);
bytesLeft -= bytesRead;
break;
}
case HPROF_GC_PRIM_ARRAY_DUMP: {
long bytesRead = readArray(true);
bytesLeft -= bytesRead;
break;
}
default: {
throw new IOException("Unrecognized heap dump sub-record type: " + type);
}
}
}
if (bytesLeft != 0) {
warn("Error reading heap dump or heap dump segment: Byte count is " + bytesLeft + " instead of 0");
skipBytes(bytesLeft);
}
if (debugLevel > 0) {
System.out.println(" Finished heap sub-records.");
}
}
private long readID() throws IOException {
return (identifierSize == 4)?
(Snapshot.SMALL_ID_MASK & (long)in.readInt()) : in.readLong();
}
//
// Read a java value. If result is non-null, it's expected to be an
// array of one element. We use it to fake multiple return values.
// @returns the number of bytes read
//
private int readValue(JavaThing[] resultArr) throws IOException {
byte type = in.readByte();
return 1 + readValueForType(type, resultArr);
}
private int readValueForType(byte type, JavaThing[] resultArr)
throws IOException {
if (version >= VERSION_JDK12BETA4) {
type = signatureFromTypeId(type);
}
return readValueForTypeSignature(type, resultArr);
}
private int readValueForTypeSignature(byte type, JavaThing[] resultArr)
throws IOException {
switch (type) {
case '[':
case 'L': {
long id = readID();
if (resultArr != null) {
resultArr[0] = new JavaObjectRef(id);
}
return identifierSize;
}
case 'Z': {
int b = in.readByte();
if (b != 0 && b != 1) {
warn("Illegal boolean value read");
}
if (resultArr != null) {
resultArr[0] = new JavaBoolean(b != 0);
}
return 1;
}
case 'B': {
byte b = in.readByte();
if (resultArr != null) {
resultArr[0] = new JavaByte(b);
}
return 1;
}
case 'S': {
short s = in.readShort();
if (resultArr != null) {
resultArr[0] = new JavaShort(s);
}
return 2;
}
case 'C': {
char ch = in.readChar();
if (resultArr != null) {
resultArr[0] = new JavaChar(ch);
}
return 2;
}
case 'I': {
int val = in.readInt();
if (resultArr != null) {
resultArr[0] = new JavaInt(val);
}
return 4;
}
case 'J': {
long val = in.readLong();
if (resultArr != null) {
resultArr[0] = new JavaLong(val);
}
return 8;
}
case 'F': {
float val = in.readFloat();
if (resultArr != null) {
resultArr[0] = new JavaFloat(val);
}
return 4;
}
case 'D': {
double val = in.readDouble();
if (resultArr != null) {
resultArr[0] = new JavaDouble(val);
}
return 8;
}
default: {
throw new IOException("Bad value signature: " + type);
}
}
}
private ThreadObject getThreadObjectFromSequence(int threadSeq)
throws IOException {
ThreadObject to = threadObjects.get(new Integer(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(new Long(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(new Integer(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(new Long(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 com.sun.tools.hat.internal.util.Misc.toHex(addr);
}
//
// Handle a HPROF_GC_INSTANCE_DUMP
// Return number of bytes read
//
private int readInstance() throws IOException {
long start = in.position();
long id = readID();
StackTrace stackTrace = getStackTraceFromSerial(in.readInt());
long classID = readID();
int bytesFollowing = in.readInt();
int bytesRead = (2 * identifierSize) + 8 + bytesFollowing;
JavaObject jobj = new JavaObject(classID, start);
skipBytes(bytesFollowing);
snapshot.addHeapObject(id, jobj);
snapshot.setSiteTrace(jobj, stackTrace);
return bytesRead;
}
//
// Handle a HPROF_GC_OBJ_ARRAY_DUMP or HPROF_GC_PRIM_ARRAY_DUMP
// Return number of bytes read
//
private long readArray(boolean isPrimitive) throws IOException {
long start = in.position();
long id = readID();
StackTrace stackTrace = getStackTraceFromSerial(in.readInt());
int num = in.readInt();
long bytesRead = identifierSize + 8;
long elementClassID;
if (isPrimitive) {
elementClassID = in.readByte();
bytesRead++;
} else {
elementClassID = readID();
bytesRead += identifierSize;
}
// Check for primitive arrays:
byte primitiveSignature = 0x00;
int elSize = 0;
if (isPrimitive || version < VERSION_JDK12BETA4) {
switch ((int)elementClassID) {
case T_BOOLEAN: {
primitiveSignature = (byte) 'Z';
elSize = 1;
break;
}
case T_CHAR: {
primitiveSignature = (byte) 'C';
elSize = 2;
break;
}
case T_FLOAT: {
primitiveSignature = (byte) 'F';
elSize = 4;
break;
}
case T_DOUBLE: {
primitiveSignature = (byte) 'D';
elSize = 8;
break;
}
case T_BYTE: {
primitiveSignature = (byte) 'B';
elSize = 1;
break;
}
case T_SHORT: {
primitiveSignature = (byte) 'S';
elSize = 2;
break;
}
case T_INT: {
primitiveSignature = (byte) 'I';
elSize = 4;
break;
}
case T_LONG: {
primitiveSignature = (byte) 'J';
elSize = 8;
break;
}
}
if (version >= VERSION_JDK12BETA4 && primitiveSignature == 0x00) {
throw new IOException("Unrecognized typecode: "
+ elementClassID);
}
}
if (primitiveSignature != 0x00) {
long size = elSize * (long)num;
bytesRead += size;
JavaValueArray va = new JavaValueArray(primitiveSignature, start);
skipBytes(size);
snapshot.addHeapObject(id, va);
snapshot.setSiteTrace(va, stackTrace);
} else {
long sz = (long)num * identifierSize;
bytesRead += sz;
JavaObjectArray arr = new JavaObjectArray(elementClassID, start);
skipBytes(sz);
snapshot.addHeapObject(id, arr);
snapshot.setSiteTrace(arr, stackTrace);
}
return bytesRead;
}
private byte signatureFromTypeId(byte typeId) throws IOException {
switch (typeId) {
case T_CLASS: {
return (byte) 'L';
}
case T_BOOLEAN: {
return (byte) 'Z';
}
case T_CHAR: {
return (byte) 'C';
}
case T_FLOAT: {
return (byte) 'F';
}
case T_DOUBLE: {
return (byte) 'D';
}
case T_BYTE: {
return (byte) 'B';
}
case T_SHORT: {
return (byte) 'S';
}
case T_INT: {
return (byte) 'I';
}
case T_LONG: {
return (byte) 'J';
}
default: {
throw new IOException("Invalid type id of " + typeId);
}
}
}
private void handleEOF(EOFException exp, Snapshot snapshot) {
if (debugLevel > 0) {
exp.printStackTrace();
}
warn("Unexpected EOF. Will miss information...");
// we have EOF, we have to tolerate missing references
snapshot.setUnresolvedObjectsOK(true);
}
private void warn(String msg) {
System.out.println("WARNING: " + msg);
}
//
// A trivial data-holder class for HPROF_GC_ROOT_THREAD_OBJ.
//
private class ThreadObject {
long threadId;
int stackSeq;
ThreadObject(long threadId, int stackSeq) {
this.threadId = threadId;
this.stackSeq = stackSeq;
}
}
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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;
MappedReadBuffer(MappedByteBuffer buf) {
this.buf = buf;
}
// factory method to create correct ReadBuffer for a given file
static ReadBuffer create(RandomAccessFile file) throws IOException {
FileChannel ch = file.getChannel();
long size = ch.size();
// if file size is more than 2 GB and when file mapping is
// configured (default), use mapped file reader
if (canUseFileMap() && (size <= Integer.MAX_VALUE)) {
MappedByteBuffer buf;
try {
buf = ch.map(FileChannel.MapMode.READ_ONLY, 0, size);
ch.close();
return new MappedReadBuffer(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);
}
private static boolean canUseFileMap() {
// set jhat.disableFileMap to any value other than "false"
// to disable file mapping
String prop = System.getProperty("jhat.disableFileMap");
return prop == null || prop.equals("false");
}
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();
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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();
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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;
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.parser;
import java.io.IOException;
/**
* Positionable read only buffer
*
* @author A. Sundararajan
*/
public interface ReadBuffer {
// 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;
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.parser;
import java.io.*;
import com.sun.tools.hat.internal.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);
}
PositionDataInputStream in = new PositionDataInputStream(
new BufferedInputStream(new FileInputStream(heapFile)));
try {
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);
}
} finally {
in.close();
}
}
}

View File

@@ -0,0 +1,150 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.server;
import com.sun.tools.hat.internal.model.*;
import java.util.Iterator;
/**
*
* @author Bill Foote
*/
class AllClassesQuery extends QueryHandler {
boolean excludePlatform;
boolean oqlSupported;
public AllClassesQuery(boolean excludePlatform, boolean oqlSupported) {
this.excludePlatform = excludePlatform;
this.oqlSupported = oqlSupported;
}
public void run() {
if (excludePlatform) {
startHtml("All Classes (excluding platform)");
} else {
startHtml("All Classes (including platform)");
}
Iterator classes = snapshot.getClasses();
String lastPackage = null;
while (classes.hasNext()) {
JavaClass clazz = (JavaClass) classes.next();
if (excludePlatform && PlatformClasses.isPlatformClass(clazz)) {
// skip this..
continue;
}
String name = clazz.getName();
int pos = name.lastIndexOf(".");
String pkg;
if (name.startsWith("[")) { // Only in ancient heap dumps
pkg = "<Arrays>";
} else if (pos == -1) {
pkg = "<Default Package>";
} else {
pkg = name.substring(0, pos);
}
if (!pkg.equals(lastPackage)) {
out.print("<h2>Package ");
print(pkg);
out.println("</h2>");
}
lastPackage = pkg;
printClass(clazz);
if (clazz.getId() != -1) {
print(" [" + clazz.getIdString() + "]");
}
out.println("<br>");
}
out.println("<h2>Other Queries</h2>");
out.println("<ul>");
out.println("<li>");
printAnchorStart();
if (excludePlatform) {
out.print("allClassesWithPlatform/\">");
print("All classes including platform");
} else {
out.print("\">");
print("All classes excluding platform");
}
out.println("</a>");
out.println("<li>");
printAnchorStart();
out.print("showRoots/\">");
print("Show all members of the rootset");
out.println("</a>");
out.println("<li>");
printAnchorStart();
out.print("showInstanceCounts/includePlatform/\">");
print("Show instance counts for all classes (including platform)");
out.println("</a>");
out.println("<li>");
printAnchorStart();
out.print("showInstanceCounts/\">");
print("Show instance counts for all classes (excluding platform)");
out.println("</a>");
out.println("<li>");
printAnchorStart();
out.print("histo/\">");
print("Show heap histogram");
out.println("</a>");
out.println("<li>");
printAnchorStart();
out.print("finalizerSummary/\">");
print("Show finalizer summary");
out.println("</a>");
if (oqlSupported) {
out.println("<li>");
printAnchorStart();
out.print("oql/\">");
print("Execute Object Query Language (OQL) query");
out.println("</a>");
}
out.println("</ul>");
endHtml();
}
}

View File

@@ -0,0 +1,108 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.server;
import java.util.Vector;
import com.sun.tools.hat.internal.model.*;
import com.sun.tools.hat.internal.util.ArraySorter;
import com.sun.tools.hat.internal.util.Comparer;
/**
*
* @author Bill Foote
*/
class AllRootsQuery extends QueryHandler {
public AllRootsQuery() {
}
public void run() {
startHtml("All Members of the Rootset");
Root[] roots = snapshot.getRootsArray();
ArraySorter.sort(roots, new Comparer() {
public int compare(Object lhs, Object rhs) {
Root left = (Root) lhs;
Root right = (Root) rhs;
int d = left.getType() - right.getType();
if (d != 0) {
return -d; // More interesting values are *higher*
}
return left.getDescription().compareTo(right.getDescription());
}
});
int lastType = Root.INVALID_TYPE;
for (int i= 0; i < roots.length; i++) {
Root root = roots[i];
if (root.getType() != lastType) {
lastType = root.getType();
out.print("<h2>");
print(root.getTypeName() + " References");
out.println("</h2>");
}
printRoot(root);
if (root.getReferer() != null) {
out.print("<small> (from ");
printThingAnchorTag(root.getReferer().getId());
print(root.getReferer().toString());
out.print(")</a></small>");
}
out.print(" :<br>");
JavaThing t = snapshot.findThing(root.getId());
if (t != null) { // It should always be
print("--> ");
printThing(t);
out.println("<br>");
}
}
out.println("<h2>Other Queries</h2>");
out.println("<ul>");
out.println("<li>");
printAnchorStart();
out.print("\">");
print("Show All Classes");
out.println("</a>");
out.println("</ul>");
endHtml();
}
}

View File

@@ -0,0 +1,190 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.server;
import com.sun.tools.hat.internal.model.*;
import com.sun.tools.hat.internal.util.ArraySorter;
import com.sun.tools.hat.internal.util.Comparer;
import java.util.Enumeration;
/**
*
* @author Bill Foote
*/
class ClassQuery extends QueryHandler {
public ClassQuery() {
}
public void run() {
startHtml("Class " + query);
JavaClass clazz = snapshot.findClass(query);
if (clazz == null) {
error("class not found: " + query);
} else {
printFullClass(clazz);
}
endHtml();
}
protected void printFullClass(JavaClass clazz) {
out.print("<h1>");
print(clazz.toString());
out.println("</h1>");
out.println("<h2>Superclass:</h2>");
printClass(clazz.getSuperclass());
out.println("<h2>Loader Details</h2>");
out.println("<h3>ClassLoader:</h3>");
printThing(clazz.getLoader());
out.println("<h3>Signers:</h3>");
printThing(clazz.getSigners());
out.println("<h3>Protection Domain:</h3>");
printThing(clazz.getProtectionDomain());
out.println("<h2>Subclasses:</h2>");
JavaClass[] sc = clazz.getSubclasses();
for (int i = 0; i < sc.length; i++) {
out.print(" ");
printClass(sc[i]);
out.println("<br>");
}
out.println("<h2>Instance Data Members:</h2>");
JavaField[] ff = clazz.getFields().clone();
ArraySorter.sort(ff, new Comparer() {
public int compare(Object lhs, Object rhs) {
JavaField left = (JavaField) lhs;
JavaField right = (JavaField) rhs;
return left.getName().compareTo(right.getName());
}
});
for (int i = 0; i < ff.length; i++) {
out.print(" ");
printField(ff[i]);
out.println("<br>");
}
out.println("<h2>Static Data Members:</h2>");
JavaStatic[] ss = clazz.getStatics();
for (int i = 0; i < ss.length; i++) {
printStatic(ss[i]);
out.println("<br>");
}
out.println("<h2>Instances</h2>");
printAnchorStart();
print("instances/" + encodeForURL(clazz));
out.print("\">");
out.println("Exclude subclasses</a><br>");
printAnchorStart();
print("allInstances/" + encodeForURL(clazz));
out.print("\">");
out.println("Include subclasses</a><br>");
if (snapshot.getHasNewSet()) {
out.println("<h2>New Instances</h2>");
printAnchorStart();
print("newInstances/" + encodeForURL(clazz));
out.print("\">");
out.println("Exclude subclasses</a><br>");
printAnchorStart();
print("allNewInstances/" + encodeForURL(clazz));
out.print("\">");
out.println("Include subclasses</a><br>");
}
out.println("<h2>References summary by Type</h2>");
printAnchorStart();
print("refsByType/" + encodeForURL(clazz));
out.print("\">");
out.println("References summary by type</a>");
printReferencesTo(clazz);
}
protected void printReferencesTo(JavaHeapObject obj) {
if (obj.getId() == -1) {
return;
}
out.println("<h2>References to this object:</h2>");
out.flush();
Enumeration referers = obj.getReferers();
while (referers.hasMoreElements()) {
JavaHeapObject ref = (JavaHeapObject) referers.nextElement();
printThing(ref);
print (" : " + ref.describeReferenceTo(obj, snapshot));
// If there are more than one references, this only gets the
// first one.
out.println("<br>");
}
out.println("<h2>Other Queries</h2>");
out.println("Reference Chains from Rootset");
long id = obj.getId();
out.print("<ul><li>");
printAnchorStart();
out.print("roots/");
printHex(id);
out.print("\">");
out.println("Exclude weak refs</a>");
out.print("<li>");
printAnchorStart();
out.print("allRoots/");
printHex(id);
out.print("\">");
out.println("Include weak refs</a></ul>");
printAnchorStart();
out.print("reachableFrom/");
printHex(id);
out.print("\">");
out.println("Objects reachable from here</a><br>");
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.server;
import com.sun.tools.hat.internal.model.*;
import java.util.*;
public class FinalizerObjectsQuery extends QueryHandler {
public void run() {
Enumeration objs = snapshot.getFinalizerObjects();
startHtml("Objects pending finalization");
out.println("<a href='/finalizerSummary/'>Finalizer summary</a>");
out.println("<h1>Objects pending finalization</h1>");
while (objs.hasMoreElements()) {
printThing((JavaHeapObject)objs.nextElement());
out.println("<br>");
}
endHtml();
}
}

View File

@@ -0,0 +1,128 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.server;
import com.sun.tools.hat.internal.model.*;
import java.util.*;
public class FinalizerSummaryQuery extends QueryHandler {
public void run() {
Enumeration objs = snapshot.getFinalizerObjects();
startHtml("Finalizer Summary");
out.println("<p align='center'>");
out.println("<b><a href='/'>All Classes (excluding platform)</a></b>");
out.println("</p>");
printFinalizerSummary(objs);
endHtml();
}
private static class HistogramElement {
public HistogramElement(JavaClass clazz) {
this.clazz = clazz;
}
public void updateCount() {
this.count++;
}
public int compare(HistogramElement other) {
long diff = other.count - count;
return (diff == 0L)? 0 : ((diff > 0L)? +1 : -1);
}
public JavaClass getClazz() {
return clazz;
}
public long getCount() {
return count;
}
private JavaClass clazz;
private long count;
}
private void printFinalizerSummary(Enumeration objs) {
int count = 0;
Map<JavaClass, HistogramElement> map = new HashMap<JavaClass, HistogramElement>();
while (objs.hasMoreElements()) {
JavaHeapObject obj = (JavaHeapObject) objs.nextElement();
count++;
JavaClass clazz = obj.getClazz();
if (! map.containsKey(clazz)) {
map.put(clazz, new HistogramElement(clazz));
}
HistogramElement element = map.get(clazz);
element.updateCount();
}
out.println("<p align='center'>");
out.println("<b>");
out.println("Total ");
if (count != 0) {
out.print("<a href='/finalizerObjects/'>instances</a>");
} else {
out.print("instances");
}
out.println(" pending finalization: ");
out.print(count);
out.println("</b></p><hr>");
if (count == 0) {
return;
}
// calculate and print histogram
HistogramElement[] elements = new HistogramElement[map.size()];
map.values().toArray(elements);
Arrays.sort(elements, new Comparator<HistogramElement>() {
public int compare(HistogramElement o1, HistogramElement o2) {
return o1.compare(o2);
}
});
out.println("<table border=1 align=center>");
out.println("<tr><th>Count</th><th>Class</th></tr>");
for (int j = 0; j < elements.length; j++) {
out.println("<tr><td>");
out.println(elements[j].getCount());
out.println("</td><td>");
printClass(elements[j].getClazz());
out.println("</td><tr>");
}
out.println("</table>");
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.server;
import com.sun.tools.hat.internal.model.JavaClass;
import java.util.Arrays;
import java.util.Comparator;
/**
* Prints histogram sortable by class name, count and size.
*
*/
public class HistogramQuery extends QueryHandler {
public void run() {
JavaClass[] classes = snapshot.getClassesArray();
Comparator<JavaClass> comparator;
if (query.equals("count")) {
comparator = new Comparator<JavaClass>() {
public int compare(JavaClass first, JavaClass second) {
long diff = (second.getInstancesCount(false) -
first.getInstancesCount(false));
return (diff == 0)? 0: ((diff < 0)? -1 : + 1);
}
};
} else if (query.equals("class")) {
comparator = new Comparator<JavaClass>() {
public int compare(JavaClass first, JavaClass second) {
return first.getName().compareTo(second.getName());
}
};
} else {
// default sort is by total size
comparator = new Comparator<JavaClass>() {
public int compare(JavaClass first, JavaClass second) {
long diff = (second.getTotalInstanceSize() -
first.getTotalInstanceSize());
return (diff == 0)? 0: ((diff < 0)? -1 : + 1);
}
};
}
Arrays.sort(classes, comparator);
startHtml("Heap Histogram");
out.println("<p align='center'>");
out.println("<b><a href='/'>All Classes (excluding platform)</a></b>");
out.println("</p>");
out.println("<table align=center border=1>");
out.println("<tr><th><a href='/histo/class'>Class</a></th>");
out.println("<th><a href='/histo/count'>Instance Count</a></th>");
out.println("<th><a href='/histo/size'>Total Size</a></th></tr>");
for (int i = 0; i < classes.length; i++) {
JavaClass clazz = classes[i];
out.println("<tr><td>");
printClass(clazz);
out.println("</td>");
out.println("<td>");
out.println(clazz.getInstancesCount(false));
out.println("</td>");
out.println("<td>");
out.println(clazz.getTotalInstanceSize());
out.println("</td></tr>");
}
out.println("</table>");
endHtml();
}
}

View File

@@ -0,0 +1,220 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.server;
/**
* Reads a single HTTP query from a socket, and starts up a QueryHandler
* to server it.
*
* @author Bill Foote
*/
import java.net.Socket;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.BufferedWriter;
import java.io.PrintWriter;
import java.io.OutputStreamWriter;
import com.sun.tools.hat.internal.model.Snapshot;
import com.sun.tools.hat.internal.oql.OQLEngine;
import com.sun.tools.hat.internal.util.Misc;
public class HttpReader implements Runnable {
private Socket socket;
private PrintWriter out;
private Snapshot snapshot;
private OQLEngine engine;
public HttpReader (Socket s, Snapshot snapshot, OQLEngine engine) {
this.socket = s;
this.snapshot = snapshot;
this.engine = engine;
}
public void run() {
InputStream in = null;
try {
in = new BufferedInputStream(socket.getInputStream());
out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(
socket.getOutputStream())));
out.println("HTTP/1.0 200 OK");
out.println("Cache-Control: no-cache");
out.println("Pragma: no-cache");
out.println();
if (in.read() != 'G' || in.read() != 'E'
|| in.read() != 'T' || in.read() != ' ') {
outputError("Protocol error");
}
int data;
StringBuilder queryBuf = new StringBuilder();
while ((data = in.read()) != -1 && data != ' ') {
char ch = (char) data;
queryBuf.append(ch);
}
String query = queryBuf.toString();
query = java.net.URLDecoder.decode(query, "UTF-8");
QueryHandler handler = null;
if (snapshot == null) {
outputError("The heap snapshot is still being read.");
return;
} else if (query.equals("/")) {
handler = new AllClassesQuery(true, engine != null);
handler.setUrlStart("");
handler.setQuery("");
} else if (query.startsWith("/oql/")) {
if (engine != null) {
handler = new OQLQuery(engine);
handler.setUrlStart("");
handler.setQuery(query.substring(5));
}
} else if (query.startsWith("/oqlhelp/")) {
if (engine != null) {
handler = new OQLHelp();
handler.setUrlStart("");
handler.setQuery("");
}
} else if (query.equals("/allClassesWithPlatform/")) {
handler = new AllClassesQuery(false, engine != null);
handler.setUrlStart("../");
handler.setQuery("");
} else if (query.equals("/showRoots/")) {
handler = new AllRootsQuery();
handler.setUrlStart("../");
handler.setQuery("");
} else if (query.equals("/showInstanceCounts/includePlatform/")) {
handler = new InstancesCountQuery(false);
handler.setUrlStart("../../");
handler.setQuery("");
} else if (query.equals("/showInstanceCounts/")) {
handler = new InstancesCountQuery(true);
handler.setUrlStart("../");
handler.setQuery("");
} else if (query.startsWith("/instances/")) {
handler = new InstancesQuery(false);
handler.setUrlStart("../");
handler.setQuery(query.substring(11));
} else if (query.startsWith("/newInstances/")) {
handler = new InstancesQuery(false, true);
handler.setUrlStart("../");
handler.setQuery(query.substring(14));
} else if (query.startsWith("/allInstances/")) {
handler = new InstancesQuery(true);
handler.setUrlStart("../");
handler.setQuery(query.substring(14));
} else if (query.startsWith("/allNewInstances/")) {
handler = new InstancesQuery(true, true);
handler.setUrlStart("../");
handler.setQuery(query.substring(17));
} else if (query.startsWith("/object/")) {
handler = new ObjectQuery();
handler.setUrlStart("../");
handler.setQuery(query.substring(8));
} else if (query.startsWith("/class/")) {
handler = new ClassQuery();
handler.setUrlStart("../");
handler.setQuery(query.substring(7));
} else if (query.startsWith("/roots/")) {
handler = new RootsQuery(false);
handler.setUrlStart("../");
handler.setQuery(query.substring(7));
} else if (query.startsWith("/allRoots/")) {
handler = new RootsQuery(true);
handler.setUrlStart("../");
handler.setQuery(query.substring(10));
} else if (query.startsWith("/reachableFrom/")) {
handler = new ReachableQuery();
handler.setUrlStart("../");
handler.setQuery(query.substring(15));
} else if (query.startsWith("/rootStack/")) {
handler = new RootStackQuery();
handler.setUrlStart("../");
handler.setQuery(query.substring(11));
} else if (query.startsWith("/histo/")) {
handler = new HistogramQuery();
handler.setUrlStart("../");
handler.setQuery(query.substring(7));
} else if (query.startsWith("/refsByType/")) {
handler = new RefsByTypeQuery();
handler.setUrlStart("../");
handler.setQuery(query.substring(12));
} else if (query.startsWith("/finalizerSummary/")) {
handler = new FinalizerSummaryQuery();
handler.setUrlStart("../");
handler.setQuery("");
} else if (query.startsWith("/finalizerObjects/")) {
handler = new FinalizerObjectsQuery();
handler.setUrlStart("../");
handler.setQuery("");
}
if (handler != null) {
handler.setOutput(out);
handler.setSnapshot(snapshot);
handler.run();
} else {
outputError("Query '" + query + "' not implemented");
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (out != null) {
out.close();
}
try {
if (in != null) {
in.close();
}
} catch (IOException ignored) {
}
try {
socket.close();
} catch (IOException ignored) {
}
}
}
private void outputError(String msg) {
out.println();
out.println("<html><body bgcolor=\"#ffffff\">");
out.println(Misc.encodeHtml(msg));
out.println("</body></html>");
}
}

View File

@@ -0,0 +1,169 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.server;
import com.sun.tools.hat.internal.model.*;
import com.sun.tools.hat.internal.util.ArraySorter;
import com.sun.tools.hat.internal.util.Comparer;
import java.util.Enumeration;
/**
*
* @author Bill Foote
*/
class InstancesCountQuery extends QueryHandler {
private boolean excludePlatform;
public InstancesCountQuery(boolean excludePlatform) {
this.excludePlatform = excludePlatform;
}
public void run() {
if (excludePlatform) {
startHtml("Instance Counts for All Classes (excluding platform)");
} else {
startHtml("Instance Counts for All Classes (including platform)");
}
JavaClass[] classes = snapshot.getClassesArray();
if (excludePlatform) {
int num = 0;
for (int i = 0; i < classes.length; i++) {
if (! PlatformClasses.isPlatformClass(classes[i])) {
classes[num++] = classes[i];
}
}
JavaClass[] tmp = new JavaClass[num];
System.arraycopy(classes, 0, tmp, 0, tmp.length);
classes = tmp;
}
ArraySorter.sort(classes, new Comparer() {
public int compare(Object lhso, Object rhso) {
JavaClass lhs = (JavaClass) lhso;
JavaClass rhs = (JavaClass) rhso;
int diff = lhs.getInstancesCount(false)
- rhs.getInstancesCount(false);
if (diff != 0) {
return -diff; // Sort from biggest to smallest
}
String left = lhs.getName();
String right = rhs.getName();
if (left.startsWith("[") != right.startsWith("[")) {
// Arrays at the end
if (left.startsWith("[")) {
return 1;
} else {
return -1;
}
}
return left.compareTo(right);
}
});
String lastPackage = null;
long totalSize = 0;
long instances = 0;
for (int i = 0; i < classes.length; i++) {
JavaClass clazz = classes[i];
int count = clazz.getInstancesCount(false);
print("" + count);
printAnchorStart();
print("instances/" + encodeForURL(classes[i]));
out.print("\"> ");
if (count == 1) {
print("instance");
} else {
print("instances");
}
out.print("</a> ");
if (snapshot.getHasNewSet()) {
Enumeration objects = clazz.getInstances(false);
int newInst = 0;
while (objects.hasMoreElements()) {
JavaHeapObject obj = (JavaHeapObject)objects.nextElement();
if (obj.isNew()) {
newInst++;
}
}
print("(");
printAnchorStart();
print("newInstances/" + encodeForURL(classes[i]));
out.print("\">");
print("" + newInst + " new");
out.print("</a>) ");
}
print("of ");
printClass(classes[i]);
out.println("<br>");
instances += count;
totalSize += classes[i].getTotalInstanceSize();
}
out.println("<h2>Total of " + instances + " instances occupying " + totalSize + " bytes.</h2>");
out.println("<h2>Other Queries</h2>");
out.println("<ul>");
out.print("<li>");
printAnchorStart();
if (!excludePlatform) {
out.print("showInstanceCounts/\">");
print("Show instance counts for all classes (excluding platform)");
} else {
out.print("showInstanceCounts/includePlatform/\">");
print("Show instance counts for all classes (including platform)");
}
out.println("</a>");
out.print("<li>");
printAnchorStart();
out.print("allClassesWithPlatform/\">");
print("Show All Classes (including platform)");
out.println("</a>");
out.print("<li>");
printAnchorStart();
out.print("\">");
print("Show All Classes (excluding platform)");
out.println("</a>");
out.println("</ul>");
endHtml();
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.server;
import com.sun.tools.hat.internal.model.*;
import java.util.Enumeration;
/**
*
* @author Bill Foote
*/
class InstancesQuery extends QueryHandler {
private boolean includeSubclasses;
private boolean newObjects;
public InstancesQuery(boolean includeSubclasses) {
this.includeSubclasses = includeSubclasses;
}
public InstancesQuery(boolean includeSubclasses, boolean newObjects) {
this.includeSubclasses = includeSubclasses;
this.newObjects = newObjects;
}
public void run() {
JavaClass clazz = snapshot.findClass(query);
String instancesOf;
if (newObjects)
instancesOf = "New instances of ";
else
instancesOf = "Instances of ";
if (includeSubclasses) {
startHtml(instancesOf + query + " (including subclasses)");
} else {
startHtml(instancesOf + query);
}
if (clazz == null) {
error("Class not found");
} else {
out.print("<strong>");
printClass(clazz);
out.print("</strong><br><br>");
Enumeration objects = clazz.getInstances(includeSubclasses);
long totalSize = 0;
long instances = 0;
while (objects.hasMoreElements()) {
JavaHeapObject obj = (JavaHeapObject) objects.nextElement();
if (newObjects && !obj.isNew())
continue;
printThing(obj);
out.println("<br>");
totalSize += obj.getSize();
instances++;
}
out.println("<h2>Total of " + instances + " instances occupying " + totalSize + " bytes.</h2>");
}
endHtml();
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.server;
import java.io.*;
/**
* This handles Object Query Language (OQL) help.
*
* @author A. Sundararajan
*/
class OQLHelp extends QueryHandler {
public OQLHelp() {
}
public void run() {
InputStream is = getClass().getResourceAsStream("/com/sun/tools/hat/resources/oqlhelp.html");
int ch = -1;
try {
is = new BufferedInputStream(is);
while ( (ch = is.read()) != -1) {
out.print((char)ch);
}
} catch (Exception exp) {
printException(exp);
}
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.server;
import com.sun.tools.hat.internal.oql.*;
/**
* This handles Object Query Language (OQL) queries.
*
* @author A. Sundararajan
*/
class OQLQuery extends QueryHandler {
public OQLQuery(OQLEngine engine) {
this.engine = engine;
}
public void run() {
startHtml("Object Query Language (OQL) query");
String oql = null;
if (query != null && !query.equals("")) {
int index = query.indexOf("?query=");
if (index != -1 && query.length() > 7) {
oql = query.substring(index + 7);
}
}
out.println("<p align='center'><table>");
out.println("<tr><td><b>");
out.println("<a href='/'>All Classes (excluding platform)</a>");
out.println("</b></td>");
out.println("<td><b><a href='/oqlhelp/'>OQL Help</a></b></td></tr>");
out.println("</table></p>");
out.println("<form action='/oql/' method='get'>");
out.println("<p align='center'>");
out.println("<textarea name='query' cols=80 rows=10>");
if (oql != null) {
println(oql);
}
out.println("</textarea>");
out.println("</p>");
out.println("<p align='center'>");
out.println("<input type='submit' value='Execute'></input>");
out.println("</p>");
out.println("</form>");
if (oql != null) {
executeQuery(oql);
}
endHtml();
}
private void executeQuery(String q) {
try {
out.println("<table border='1'>");
engine.executeQuery(q, new ObjectVisitor() {
public boolean visit(Object o) {
out.println("<tr><td>");
try {
out.println(engine.toHtml(o));
} catch (Exception e) {
printException(e);
}
out.println("</td></tr>");
return false;
}
});
out.println("</table>");
} catch (OQLException exp) {
printException(exp);
}
}
private OQLEngine engine;
}

View File

@@ -0,0 +1,146 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.server;
import java.util.Enumeration;
import com.sun.tools.hat.internal.model.*;
import com.sun.tools.hat.internal.util.ArraySorter;
import com.sun.tools.hat.internal.util.Comparer;
/**
*
* @author Bill Foote
*/
class ObjectQuery extends ClassQuery {
// We inherit printFullClass from ClassQuery
public ObjectQuery() {
}
public void run() {
startHtml("Object at " + query);
long id = parseHex(query);
JavaHeapObject thing = snapshot.findThing(id);
//
// In the following, I suppose we really should use a visitor
// pattern. I'm not that strongly motivated to do this, however:
// This is the only typecase there is, and the default for an
// unrecognized type is to do something reasonable.
//
if (thing == null) {
error("object not found");
} else if (thing instanceof JavaClass) {
printFullClass((JavaClass) thing);
} else if (thing instanceof JavaValueArray) {
print(((JavaValueArray) thing).valueString(true));
printAllocationSite(thing);
printReferencesTo(thing);
} else if (thing instanceof JavaObjectArray) {
printFullObjectArray((JavaObjectArray) thing);
printAllocationSite(thing);
printReferencesTo(thing);
} else if (thing instanceof JavaObject) {
printFullObject((JavaObject) thing);
printAllocationSite(thing);
printReferencesTo(thing);
} else {
// We should never get here
print(thing.toString());
printReferencesTo(thing);
}
endHtml();
}
private void printFullObject(JavaObject obj) {
out.print("<h1>instance of ");
print(obj.toString());
out.print(" <small>(" + obj.getSize() + " bytes)</small>");
out.println("</h1>\n");
out.println("<h2>Class:</h2>");
printClass(obj.getClazz());
out.println("<h2>Instance data members:</h2>");
final JavaThing[] things = obj.getFields();
final JavaField[] fields = obj.getClazz().getFieldsForInstance();
Integer[] hack = new Integer[things.length];
for (int i = 0; i < things.length; i++) {
hack[i] = new Integer(i);
}
ArraySorter.sort(hack, new Comparer() {
public int compare(Object lhs, Object rhs) {
JavaField left = fields[((Integer) lhs).intValue()];
JavaField right = fields[((Integer) rhs).intValue()];
return left.getName().compareTo(right.getName());
}
});
for (int i = 0; i < things.length; i++) {
int index = hack[i].intValue();
printField(fields[index]);
out.print(" : ");
printThing(things[index]);
out.println("<br>");
}
}
private void printFullObjectArray(JavaObjectArray arr) {
JavaThing[] elements = arr.getElements();
out.println("<h1>Array of " + elements.length + " objects</h1>");
out.println("<h2>Class:</h2>");
printClass(arr.getClazz());
out.println("<h2>Values</h2>");
for (int i = 0; i < elements.length; i++) {
out.print("" + i + " : ");
printThing(elements[i]);
out.println("<br>");
}
}
//
// Print the StackTrace where this was allocated
//
private void printAllocationSite(JavaHeapObject obj) {
StackTrace trace = obj.getAllocatedFrom();
if (trace == null || trace.getFrames().length == 0) {
return;
}
out.println("<h2>Object allocated from:</h2>");
printStackTrace(trace);
}
}

View File

@@ -0,0 +1,119 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.server;
import com.sun.tools.hat.internal.model.JavaClass;
import com.sun.tools.hat.internal.model.Snapshot;
import java.util.LinkedList;
import java.io.InputStream;
import java.io.Reader;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;
/**
* This class is a helper that determines if a class is a "platform"
* class or not. It's a platform class if its name starts with one of
* the prefixes to be found in /com/sun/tools/hat/resources/platform_names.txt.
*
* @author Bill Foote
*/
public class PlatformClasses {
static String[] names = null;
public static synchronized String[] getNames() {
if (names == null) {
LinkedList<String> list = new LinkedList<String>();
InputStream str
= PlatformClasses.class
.getResourceAsStream("/com/sun/tools/hat/resources/platform_names.txt");
if (str != null) {
try {
BufferedReader rdr
= new BufferedReader(new InputStreamReader(str));
for (;;) {
String s = rdr.readLine();
if (s == null) {
break;
} else if (s.length() > 0) {
list.add(s);
}
}
rdr.close();
str.close();
} catch (IOException ex) {
ex.printStackTrace();
// Shouldn't happen, and if it does, continuing
// is the right thing to do anyway.
}
}
names = list.toArray(new String[list.size()]);
}
return names;
}
public static boolean isPlatformClass(JavaClass clazz) {
// all classes loaded by bootstrap loader are considered
// platform classes. In addition, the older name based filtering
// is also done for compatibility.
if (clazz.isBootstrap()) {
return true;
}
String name = clazz.getName();
// skip even the array classes of the skipped classes.
if (name.startsWith("[")) {
int index = name.lastIndexOf('[');
if (index != -1) {
if (name.charAt(index + 1) != 'L') {
// some primitive array.
return true;
}
// skip upto 'L' after the last '['.
name = name.substring(index + 2);
}
}
String[] nms = getNames();
for (int i = 0; i < nms.length; i++) {
if (name.startsWith(nms[i])) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,239 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.server;
import java.io.PrintWriter;
import com.sun.tools.hat.internal.model.*;
import com.sun.tools.hat.internal.util.Misc;
import java.io.StringWriter;
import java.net.URLEncoder;
import java.io.UnsupportedEncodingException;
/**
*
* @author Bill Foote
*/
abstract class QueryHandler {
protected String urlStart;
protected String query;
protected PrintWriter out;
protected Snapshot snapshot;
abstract void run();
void setUrlStart(String s) {
urlStart = s;
}
void setQuery(String s) {
query = s;
}
void setOutput(PrintWriter o) {
this.out = o;
}
void setSnapshot(Snapshot ss) {
this.snapshot = ss;
}
protected String encodeForURL(String s) {
try {
s = URLEncoder.encode(s, "UTF-8");
} catch (UnsupportedEncodingException ex) {
// Should never happen
ex.printStackTrace();
}
return s;
}
protected void startHtml(String title) {
out.print("<html><title>");
print(title);
out.println("</title>");
out.println("<body bgcolor=\"#ffffff\"><center><h1>");
print(title);
out.println("</h1></center>");
}
protected void endHtml() {
out.println("</body></html>");
}
protected void error(String msg) {
println(msg);
}
protected void printAnchorStart() {
out.print("<a href=\"");
out.print(urlStart);
}
protected void printThingAnchorTag(long id) {
printAnchorStart();
out.print("object/");
printHex(id);
out.print("\">");
}
protected void printObject(JavaObject obj) {
printThing(obj);
}
protected void printThing(JavaThing thing) {
if (thing == null) {
out.print("null");
return;
}
if (thing instanceof JavaHeapObject) {
JavaHeapObject ho = (JavaHeapObject) thing;
long id = ho.getId();
if (id != -1L) {
if (ho.isNew())
out.println("<strong>");
printThingAnchorTag(id);
}
print(thing.toString());
if (id != -1) {
if (ho.isNew())
out.println("[new]</strong>");
out.print(" (" + ho.getSize() + " bytes)");
out.println("</a>");
}
} else {
print(thing.toString());
}
}
protected void printRoot(Root root) {
StackTrace st = root.getStackTrace();
boolean traceAvailable = (st != null) && (st.getFrames().length != 0);
if (traceAvailable) {
printAnchorStart();
out.print("rootStack/");
printHex(root.getIndex());
out.print("\">");
}
print(root.getDescription());
if (traceAvailable) {
out.print("</a>");
}
}
protected void printClass(JavaClass clazz) {
if (clazz == null) {
out.println("null");
return;
}
printAnchorStart();
out.print("class/");
print(encodeForURL(clazz));
out.print("\">");
print(clazz.toString());
out.println("</a>");
}
protected String encodeForURL(JavaClass clazz) {
if (clazz.getId() == -1) {
return encodeForURL(clazz.getName());
} else {
return clazz.getIdString();
}
}
protected void printField(JavaField field) {
print(field.getName() + " (" + field.getSignature() + ")");
}
protected void printStatic(JavaStatic member) {
JavaField f = member.getField();
printField(f);
out.print(" : ");
if (f.hasId()) {
JavaThing t = member.getValue();
printThing(t);
} else {
print(member.getValue().toString());
}
}
protected void printStackTrace(StackTrace trace) {
StackFrame[] frames = trace.getFrames();
for (int i = 0; i < frames.length; i++) {
StackFrame f = frames[i];
String clazz = f.getClassName();
out.print("<font color=purple>");
print(clazz);
out.print("</font>");
print("." + f.getMethodName() + "(" + f.getMethodSignature() + ")");
out.print(" <bold>:</bold> ");
print(f.getSourceFileName() + " line " + f.getLineNumber());
out.println("<br>");
}
}
protected void printException(Throwable t) {
println(t.getMessage());
out.println("<pre>");
StringWriter sw = new StringWriter();
t.printStackTrace(new PrintWriter(sw));
print(sw.toString());
out.println("</pre>");
}
protected void printHex(long addr) {
if (snapshot.getIdentifierSize() == 4) {
out.print(Misc.toHex((int)addr));
} else {
out.print(Misc.toHex(addr));
}
}
protected long parseHex(String value) {
return Misc.parseHex(value);
}
protected void print(String str) {
out.print(Misc.encodeHtml(str));
}
protected void println(String str) {
out.println(Misc.encodeHtml(str));
}
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.server;
/**
*
* @author Bill Foote
*/
import java.net.Socket;
import java.net.ServerSocket;
import java.net.InetAddress;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.Writer;
import java.io.BufferedWriter;
import java.io.PrintWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.BufferedOutputStream;
import com.sun.tools.hat.internal.model.Snapshot;
import com.sun.tools.hat.internal.oql.OQLEngine;
public class QueryListener implements Runnable {
private Snapshot snapshot;
private OQLEngine engine;
private int port;
public QueryListener(int port) {
this.port = port;
this.snapshot = null; // Client will setModel when it's ready
this.engine = null; // created when snapshot is set
}
public void setModel(Snapshot ss) {
this.snapshot = ss;
if (OQLEngine.isOQLSupported()) {
this.engine = new OQLEngine(ss);
}
}
public void run() {
try {
waitForRequests();
} catch (IOException ex) {
ex.printStackTrace();
System.exit(1);
}
}
private void waitForRequests() throws IOException {
ServerSocket ss = new ServerSocket(port);
Thread last = null;
for (;;) {
Socket s = ss.accept();
Thread t = new Thread(new HttpReader(s, snapshot, engine));
if (snapshot == null) {
t.setPriority(Thread.NORM_PRIORITY+1);
} else {
t.setPriority(Thread.NORM_PRIORITY-1);
if (last != null) {
try {
last.setPriority(Thread.NORM_PRIORITY-2);
} catch (Throwable ignored) {
}
// If the thread is no longer alive, we'll get a
// NullPointerException
}
}
t.start();
last = t;
}
}
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.server;
import com.sun.tools.hat.internal.model.*;
/**
*
* @author Bill Foote
*/
class ReachableQuery extends QueryHandler {
// We inherit printFullClass from ClassQuery
public ReachableQuery() {
}
public void run() {
startHtml("Objects Reachable From " + query);
long id = parseHex(query);
JavaHeapObject root = snapshot.findThing(id);
ReachableObjects ro = new ReachableObjects(root,
snapshot.getReachableExcludes());
// Now, print out the sorted list, but start with root
long totalSize = ro.getTotalSize();
JavaThing[] things = ro.getReachables();
long instances = things.length;
out.print("<strong>");
printThing(root);
out.println("</strong><br>");
out.println("<br>");
for (int i = 0; i < things.length; i++) {
printThing(things[i]);
out.println("<br>");
}
printFields(ro.getUsedFields(), "Data Members Followed");
printFields(ro.getExcludedFields(), "Excluded Data Members");
out.println("<h2>Total of " + instances + " instances occupying " + totalSize + " bytes.</h2>");
endHtml();
}
private void printFields(String[] fields, String title) {
if (fields.length == 0) {
return;
}
out.print("<h3>");
print(title);
out.println("</h3>");
for (int i = 0; i < fields.length; i++) {
print(fields[i]);
out.println("<br>");
}
}
}

View File

@@ -0,0 +1,138 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.server;
import com.sun.tools.hat.internal.model.*;
import java.util.*;
/**
* References by type summary
*
*/
public class RefsByTypeQuery extends QueryHandler {
public void run() {
JavaClass clazz = snapshot.findClass(query);
if (clazz == null) {
error("class not found: " + query);
} else {
Map<JavaClass, Long> referrersStat = new HashMap<JavaClass, Long>();
final Map<JavaClass, Long> refereesStat = new HashMap<JavaClass, Long>();
Enumeration instances = clazz.getInstances(false);
while (instances.hasMoreElements()) {
JavaHeapObject instance = (JavaHeapObject) instances.nextElement();
if (instance.getId() == -1) {
continue;
}
Enumeration e = instance.getReferers();
while (e.hasMoreElements()) {
JavaHeapObject ref = (JavaHeapObject) e.nextElement();
JavaClass cl = ref.getClazz();
if (cl == null) {
System.out.println("null class for " + ref);
continue;
}
Long count = referrersStat.get(cl);
if (count == null) {
count = new Long(1);
} else {
count = new Long(count.longValue() + 1);
}
referrersStat.put(cl, count);
}
instance.visitReferencedObjects(
new AbstractJavaHeapObjectVisitor() {
public void visit(JavaHeapObject obj) {
JavaClass cl = obj.getClazz();
Long count = refereesStat.get(cl);
if (count == null) {
count = new Long(1);
} else {
count = new Long(count.longValue() + 1);
}
refereesStat.put(cl, count);
}
}
);
} // for each instance
startHtml("References by Type");
out.println("<p align='center'>");
printClass(clazz);
if (clazz.getId() != -1) {
println("[" + clazz.getIdString() + "]");
}
out.println("</p>");
if (referrersStat.size() != 0) {
out.println("<h3 align='center'>Referrers by Type</h3>");
print(referrersStat);
}
if (refereesStat.size() != 0) {
out.println("<h3 align='center'>Referees by Type</h3>");
print(refereesStat);
}
endHtml();
} // clazz != null
} // run
private void print(final Map<JavaClass, Long> map) {
out.println("<table border='1' align='center'>");
Set<JavaClass> keys = map.keySet();
JavaClass[] classes = new JavaClass[keys.size()];
keys.toArray(classes);
Arrays.sort(classes, new Comparator<JavaClass>() {
public int compare(JavaClass first, JavaClass second) {
Long count1 = map.get(first);
Long count2 = map.get(second);
return count2.compareTo(count1);
}
});
out.println("<tr><th>Class</th><th>Count</th></tr>");
for (int i = 0; i < classes.length; i++) {
JavaClass clazz = classes[i];
out.println("<tr><td>");
out.print("<a href='/refsByType/");
print(clazz.getIdString());
out.print("'>");
print(clazz.getName());
out.println("</a>");
out.println("</td><td>");
out.println(map.get(clazz));
out.println("</td></tr>");
}
out.println("</table>");
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.server;
import com.sun.tools.hat.internal.model.*;
/**
* Query to show the StackTrace for a given root
*
* @author Bill Foote
*/
class RootStackQuery extends QueryHandler {
public RootStackQuery() {
}
public void run() {
int index = (int) parseHex(query);
Root root = snapshot.getRootAt(index);
if (root == null) {
error("Root at " + index + " not found");
return;
}
StackTrace st = root.getStackTrace();
if (st == null || st.getFrames().length == 0) {
error("No stack trace for " + root.getDescription());
return;
}
startHtml("Stack Trace for " + root.getDescription());
out.println("<p>");
printStackTrace(st);
out.println("</p>");
endHtml();
}
}

View File

@@ -0,0 +1,147 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.server;
import java.util.Vector;
import com.sun.tools.hat.internal.model.*;
import com.sun.tools.hat.internal.util.ArraySorter;
import com.sun.tools.hat.internal.util.Comparer;
/**
*
* @author Bill Foote
*/
class RootsQuery extends QueryHandler {
private boolean includeWeak;
public RootsQuery(boolean includeWeak) {
this.includeWeak = includeWeak;
}
public void run() {
long id = parseHex(query);
JavaHeapObject target = snapshot.findThing(id);
if (target == null) {
startHtml("Object not found for rootset");
error("object not found");
endHtml();
return;
}
if (includeWeak) {
startHtml("Rootset references to " + target
+ " (includes weak refs)");
} else {
startHtml("Rootset references to " + target
+ " (excludes weak refs)");
}
out.flush();
ReferenceChain[] refs
= snapshot.rootsetReferencesTo(target, includeWeak);
ArraySorter.sort(refs, new Comparer() {
public int compare(Object lhs, Object rhs) {
ReferenceChain left = (ReferenceChain) lhs;
ReferenceChain right = (ReferenceChain) rhs;
Root leftR = left.getObj().getRoot();
Root rightR = right.getObj().getRoot();
int d = leftR.getType() - rightR.getType();
if (d != 0) {
return -d; // More interesting values are *higher*
}
return left.getDepth() - right.getDepth();
}
});
out.print("<h1>References to ");
printThing(target);
out.println("</h1>");
int lastType = Root.INVALID_TYPE;
for (int i= 0; i < refs.length; i++) {
ReferenceChain ref = refs[i];
Root root = ref.getObj().getRoot();
if (root.getType() != lastType) {
lastType = root.getType();
out.print("<h2>");
print(root.getTypeName() + " References");
out.println("</h2>");
}
out.print("<h3>");
printRoot(root);
if (root.getReferer() != null) {
out.print("<small> (from ");
printThingAnchorTag(root.getReferer().getId());
print(root.getReferer().toString());
out.print(")</a></small>");
}
out.print(" :</h3>");
while (ref != null) {
ReferenceChain next = ref.getNext();
JavaHeapObject obj = ref.getObj();
print("--> ");
printThing(obj);
if (next != null) {
print(" (" +
obj.describeReferenceTo(next.getObj(), snapshot)
+ ":)");
}
out.println("<br>");
ref = next;
}
}
out.println("<h2>Other queries</h2>");
if (includeWeak) {
printAnchorStart();
out.print("roots/");
printHex(id);
out.print("\">");
out.println("Exclude weak refs</a><br>");
endHtml();
}
if (!includeWeak) {
printAnchorStart();
out.print("allRoots/");
printHex(id);
out.print("\">");
out.println("Include weak refs</a><br>");
}
}
}

View File

@@ -0,0 +1,147 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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);
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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);
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.util;
import java.util.Enumeration;
import java.util.NoSuchElementException;
public class CompositeEnumeration implements Enumeration {
Enumeration e1;
Enumeration e2;
public CompositeEnumeration(Enumeration e1, Enumeration e2) {
this.e1 = e1;
this.e2 = e2;
}
public boolean hasMoreElements() {
return e1.hasMoreElements() || e2.hasMoreElements();
}
public Object nextElement() {
if (e1.hasMoreElements()) {
return e1.nextElement();
}
if (e2.hasMoreElements()) {
return e2.nextElement();
}
throw new NoSuchElementException();
}
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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();
StringBuffer buf = new StringBuffer();
for (int i = 0; i < len; i++) {
char ch = str.charAt(i);
if (ch == '<') {
buf.append("&lt;");
} else if (ch == '>') {
buf.append("&gt;");
} else if (ch == '"') {
buf.append("&quot;");
} else if (ch == '\'') {
buf.append("&#039;");
} else if (ch == '&') {
buf.append("&amp;");
} else if (ch < ' ') {
buf.append("&#" + Integer.toString(ch) + ";");
} else {
int c = (ch & 0xFFFF);
if (c > 127) {
buf.append("&#" + Integer.toString(c) + ";");
} else {
buf.append(ch);
}
}
}
return buf.toString();
}
}

View File

@@ -0,0 +1,148 @@
/*
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* The Original Code is HAT. The Initial Developer of the
* Original Code is Bill Foote, with contributions from others
* at JavaSoft/Sun.
*/
package com.sun.tools.hat.internal.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);
}
}