Add javadoc for all public ahat API.
And tighten up the API a little more.
The only functional change is to replace the Sort.WithPriority class
with a Sort.withPriority function so that the Sort.WithPriority class
can be made private.
Test: m ahat-test
Change-Id: Iba0ac04767a20c9008f209a777294ecaccc64ffc
diff --git a/tools/ahat/Android.mk b/tools/ahat/Android.mk
index a9a0492..34e6a9c 100644
--- a/tools/ahat/Android.mk
+++ b/tools/ahat/Android.mk
@@ -23,6 +23,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src/main)
LOCAL_JAR_MANIFEST := etc/ahat.mf
LOCAL_JAVA_RESOURCE_FILES := $(LOCAL_PATH)/etc/style.css
+LOCAL_JAVACFLAGS := -Xdoclint:all/protected
LOCAL_IS_HOST_MODULE := true
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := ahat
diff --git a/tools/ahat/etc/ahat_api.txt b/tools/ahat/etc/ahat_api.txt
index 7920ada..93fe46b 100644
--- a/tools/ahat/etc/ahat_api.txt
+++ b/tools/ahat/etc/ahat_api.txt
@@ -9,7 +9,6 @@
package com.android.ahat.dominators {
public class DominatorsComputation {
- ctor public DominatorsComputation();
method public static void computeDominators(com.android.ahat.dominators.DominatorsComputation.Node);
}
@@ -109,7 +108,6 @@
}
public class Diff {
- ctor public Diff();
method public static void snapshots(com.android.ahat.heapdump.AhatSnapshot, com.android.ahat.heapdump.AhatSnapshot);
}
@@ -159,7 +157,6 @@
}
public class Parser {
- ctor public Parser();
method public static com.android.ahat.heapdump.AhatSnapshot parseHeapDump(java.io.File, com.android.ahat.proguard.ProguardMap) throws com.android.ahat.heapdump.HprofFormatException, java.io.IOException;
method public static com.android.ahat.heapdump.AhatSnapshot parseHeapDump(java.nio.ByteBuffer, com.android.ahat.proguard.ProguardMap) throws com.android.ahat.heapdump.HprofFormatException, java.io.IOException;
}
@@ -210,11 +207,9 @@
}
public static class Site.ObjectsInfo implements com.android.ahat.heapdump.Diffable {
- ctor public Site.ObjectsInfo(com.android.ahat.heapdump.AhatHeap, com.android.ahat.heapdump.AhatClassObj);
method public com.android.ahat.heapdump.Site.ObjectsInfo getBaseline();
method public java.lang.String getClassName();
method public boolean isPlaceHolder();
- method public void setBaseline(com.android.ahat.heapdump.Site.ObjectsInfo);
field public com.android.ahat.heapdump.AhatClassObj classObj;
field public com.android.ahat.heapdump.AhatHeap heap;
field public com.android.ahat.heapdump.Size numBytes;
@@ -236,6 +231,7 @@
ctor public Sort();
method public static java.util.Comparator<com.android.ahat.heapdump.AhatInstance> defaultInstanceCompare(com.android.ahat.heapdump.AhatSnapshot);
method public static java.util.Comparator<com.android.ahat.heapdump.Site> defaultSiteCompare(com.android.ahat.heapdump.AhatSnapshot);
+ method public static <T> java.util.Comparator<T> withPriority(java.util.Comparator<T>...);
field public static final java.util.Comparator<com.android.ahat.heapdump.FieldValue> FIELD_VALUE_BY_NAME;
field public static final java.util.Comparator<com.android.ahat.heapdump.FieldValue> FIELD_VALUE_BY_TYPE;
field public static final java.util.Comparator<com.android.ahat.heapdump.AhatInstance> INSTANCE_BY_TOTAL_RETAINED_SIZE;
@@ -246,22 +242,6 @@
field public static final java.util.Comparator<com.android.ahat.heapdump.Size> SIZE_BY_SIZE;
}
- public static class Sort.InstanceByHeapRetainedSize implements java.util.Comparator {
- ctor public Sort.InstanceByHeapRetainedSize(com.android.ahat.heapdump.AhatHeap);
- method public int compare(com.android.ahat.heapdump.AhatInstance, com.android.ahat.heapdump.AhatInstance);
- }
-
- public static class Sort.SiteByHeapSize implements java.util.Comparator {
- ctor public Sort.SiteByHeapSize(com.android.ahat.heapdump.AhatHeap);
- method public int compare(com.android.ahat.heapdump.Site, com.android.ahat.heapdump.Site);
- }
-
- public static class Sort.WithPriority<T> implements java.util.Comparator {
- ctor public Sort.WithPriority(java.util.Comparator<T>...);
- ctor public Sort.WithPriority(java.util.List<java.util.Comparator<T>>);
- method public int compare(T, T);
- }
-
public final class Type extends java.lang.Enum {
method public static com.android.ahat.heapdump.Type valueOf(java.lang.String);
method public static final com.android.ahat.heapdump.Type[] values();
@@ -285,7 +265,6 @@
method public java.lang.Integer asInteger();
method public java.lang.Long asLong();
method public abstract boolean equals(java.lang.Object);
- method public com.android.ahat.heapdump.Value getBaseline();
method public static com.android.ahat.heapdump.Value getBaseline(com.android.ahat.heapdump.Value);
method public static com.android.ahat.heapdump.Type getType(com.android.ahat.heapdump.Value);
method public boolean isAhatInstance();
diff --git a/tools/ahat/src/main/com/android/ahat/Main.java b/tools/ahat/src/main/com/android/ahat/Main.java
index 048573e..04a6012 100644
--- a/tools/ahat/src/main/com/android/ahat/Main.java
+++ b/tools/ahat/src/main/com/android/ahat/Main.java
@@ -30,6 +30,9 @@
import java.text.ParseException;
import java.util.concurrent.Executors;
+/**
+ * Contains the main entry point for the ahat heap dump viewer.
+ */
public class Main {
private Main() {
}
@@ -70,6 +73,14 @@
throw new AssertionError("Unreachable");
}
+ /**
+ * Main entry for ahat heap dump viewer.
+ * Launches an http server on localhost for viewing a given heap dump.
+ * See the ahat README or pass "--help" as one of the arguments to see a
+ * description of what arguments and options are expected.
+ *
+ * @param args the command line arguments
+ */
public static void main(String[] args) {
int port = 7100;
for (String arg : args) {
diff --git a/tools/ahat/src/main/com/android/ahat/SiteHandler.java b/tools/ahat/src/main/com/android/ahat/SiteHandler.java
index 543eaa3..5093f0d 100644
--- a/tools/ahat/src/main/com/android/ahat/SiteHandler.java
+++ b/tools/ahat/src/main/com/android/ahat/SiteHandler.java
@@ -88,7 +88,7 @@
new Column("Class"));
List<Site.ObjectsInfo> infos = site.getObjectsInfos();
- Comparator<Site.ObjectsInfo> compare = new Sort.WithPriority<Site.ObjectsInfo>(
+ Comparator<Site.ObjectsInfo> compare = Sort.withPriority(
Sort.OBJECTS_INFO_BY_HEAP_NAME,
Sort.OBJECTS_INFO_BY_SIZE,
Sort.OBJECTS_INFO_BY_CLASS_NAME);
diff --git a/tools/ahat/src/main/com/android/ahat/dominators/DominatorsComputation.java b/tools/ahat/src/main/com/android/ahat/dominators/DominatorsComputation.java
index 58b7b59..d3fea48 100644
--- a/tools/ahat/src/main/com/android/ahat/dominators/DominatorsComputation.java
+++ b/tools/ahat/src/main/com/android/ahat/dominators/DominatorsComputation.java
@@ -23,38 +23,72 @@
import java.util.Queue;
/**
- * Generic DominatorsComputation.
- *
- * To use the dominators computation, have your graph nodes implement the
- * DominatorsComputation.Node interface, then call
- * DominatorsComputation.computeDominators on the single root node.
+ * Provides a static method for computing the immediate dominators of a
+ * directed graph. It can be used with any directed graph data structure
+ * that implements the {@link DominatorsComputation.Node} interface and has
+ * some root node with no incoming edges.
*/
public class DominatorsComputation {
+ private DominatorsComputation() {
+ }
+
/**
- * Interface for a directed graph to perform the dominators computation on.
+ * Interface for a directed graph to perform immediate dominators
+ * computation on.
+ * The dominators computation can be used with directed graph data
+ * structures that implement this <code>Node</code> interface. To use the
+ * dominators computation on your graph, you must make the following
+ * functionality available to the dominators computation:
+ * <ul>
+ * <li>Efficiently mapping from node to associated internal dominators
+ * computation state using the
+ * {@link #setDominatorsComputationState setDominatorsComputationState} and
+ * {@link #getDominatorsComputationState getDominatorsComputationState} methods.
+ * <li>Iterating over all outgoing edges of an node using the
+ * {@link #getReferencesForDominators getReferencesForDominators} method.
+ * <li>Setting the computed dominator for a node using the
+ * {@link #setDominator setDominator} method.
+ * </ul>
*/
public interface Node {
/**
- * Associate the given dominator state with this node.
+ * Associates the given dominator state with this node. Subsequent calls to
+ * {@link #getDominatorsComputationState getDominatorsComputationState} on
+ * this node should return the state given here. At the conclusion of the
+ * dominators computation, this method will be called for
+ * each node with <code>state</code> set to null.
+ *
+ * @param state the dominator state to associate with this node
*/
void setDominatorsComputationState(Object state);
/**
- * Get the most recent dominator state associated with this node using
- * setDominatorsComputationState. If setDominatorsComputationState has not
- * yet been called, this should return null.
+ * Returns the dominator state most recently associated with this node
+ * by a call to {@link #setDominatorsComputationState setDominatorsComputationState}.
+ * If <code>setDominatorsComputationState</code> has not yet been called
+ * on this node for this dominators computation, this method should return
+ * null.
+ *
+ * @return the associated dominator state
*/
Object getDominatorsComputationState();
/**
- * Return a collection of nodes referenced from this node, for the
- * purposes of computing dominators.
+ * Returns a collection of nodes referenced from this node, for the
+ * purposes of computing dominators. This method will be called at most
+ * once for each node reachable from the root node of the dominators
+ * computation.
+ *
+ * @return an iterable collection of the nodes with an incoming edge from
+ * this node.
*/
Iterable<? extends Node> getReferencesForDominators();
/**
- * Update this node's dominator based on the results of the dominators
+ * Sets the dominator for this node based on the results of the dominators
* computation.
+ *
+ * @param dominator the computed immediate dominator of this node
*/
void setDominator(Node dominator);
}
@@ -112,8 +146,14 @@
}
/**
- * Compute the dominator tree rooted at the given node.
- * There must not be any incoming references to the root node.
+ * Computes the immediate dominators of all nodes reachable from the <code>root</code> node.
+ * There must not be any incoming references to the <code>root</code> node.
+ * <p>
+ * The result of this function is to call the {@link Node#setDominator}
+ * function on every node reachable from the root node.
+ *
+ * @param root the root node of the dominators computation
+ * @see Node
*/
public static void computeDominators(Node root) {
long id = 0;
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/AhatArrayInstance.java b/tools/ahat/src/main/com/android/ahat/heapdump/AhatArrayInstance.java
index ccdd6e4..9c80802 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/AhatArrayInstance.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/AhatArrayInstance.java
@@ -21,6 +21,12 @@
import java.util.Collections;
import java.util.List;
+/**
+ * An array instance from a parsed heap dump.
+ * It is used for both object and primitive arrays. The class provides methods
+ * for accessing the length and elements of the array in addition to those
+ * methods inherited from {@link AhatInstance}.
+ */
public class AhatArrayInstance extends AhatInstance {
// To save space, we store arrays as primitive arrays or AhatInstance arrays
// and provide a wrapper over the arrays to expose a list of Values.
@@ -186,21 +192,30 @@
}
/**
- * Returns the length of the array.
+ * Returns the number of elements in the array.
+ *
+ * @return number of elements in the array.
*/
public int getLength() {
return mValues.size();
}
/**
- * Returns the array's values.
+ * Returns a list of all of the array's elements in order.
+ * The returned list does not support modification.
+ *
+ * @return list of the array's elements.
*/
public List<Value> getValues() {
return mValues;
}
/**
- * Returns the object at the given index of this array.
+ * Returns the value at the given index of this array.
+ *
+ * @param index the index of the value to retrieve
+ * @return the value at the given index
+ * @throws IndexOutOfBoundsException if the index is out of range
*/
public Value getValue(int index) {
return mValues.get(index);
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassInstance.java b/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassInstance.java
index cb9d959..c82ef20 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassInstance.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassInstance.java
@@ -20,6 +20,15 @@
import java.util.Iterator;
import java.util.NoSuchElementException;
+/**
+ * A typical Java object from a parsed heap dump.
+ * Note that this is used for Java objects that are instances of classes (as
+ * opposed to arrays), not for class objects themselves.
+ * See {@link AhatClassObj } for the representation of class objects.
+ * <p>
+ * This class provides a method for iterating over the instance fields of the
+ * object in addition to those methods inherited from {@link AhatInstance}.
+ */
public class AhatClassInstance extends AhatInstance {
// Instance fields of the object. These are stored in order of the instance
// field descriptors from the class object, starting with this class first,
@@ -84,6 +93,10 @@
/**
* Returns the list of class instance fields for this instance.
+ * Includes values of field inherited from the superclass of this instance.
+ * The fields are returned in no particular order.
+ *
+ * @return Iterable over the instance field values.
*/
public Iterable<FieldValue> getInstanceFields() {
return new InstanceFieldIterator(mFields, getClassObj());
@@ -220,7 +233,7 @@
}
- public BufferedImage asBitmap() {
+ @Override public BufferedImage asBitmap() {
BitmapInfo info = getBitmapInfo();
if (info == null) {
return null;
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassObj.java b/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassObj.java
index 3babf76..36ada28 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassObj.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassObj.java
@@ -20,6 +20,13 @@
import java.util.Arrays;
import java.util.List;
+/**
+ * A class from a parsed heap dump.
+ * In addition to those methods inherited from {@link AhatInstance}, the class
+ * provides methods for accessing information about the class object, such as
+ * the class loader, superclass, static field values and instance field
+ * descriptors.
+ */
public class AhatClassObj extends AhatInstance {
private String mClassName;
private AhatClassObj mSuperClassObj;
@@ -56,6 +63,9 @@
/**
* Returns the name of the class this is a class object for.
+ * For example, "java.lang.String".
+ *
+ * @return the name of the class
*/
public String getName() {
return mClassName;
@@ -63,6 +73,8 @@
/**
* Returns the superclass of this class object.
+ *
+ * @return the superclass object
*/
public AhatClassObj getSuperClassObj() {
return mSuperClassObj;
@@ -70,14 +82,18 @@
/**
* Returns the class loader of this class object.
+ *
+ * @return the class loader object
*/
public AhatInstance getClassLoader() {
return mClassLoader;
}
/**
- * Returns the size of instances of this object, as reported in the heap
- * dump.
+ * Returns the size of instances of this object.
+ * The size returned is as reported in the heap dump.
+ *
+ * @return the class instance size
*/
public long getInstanceSize() {
return mInstanceSize;
@@ -85,6 +101,8 @@
/**
* Returns the static field values for this class object.
+ *
+ * @return the static field values
*/
public List<FieldValue> getStaticFieldValues() {
return Arrays.asList(mStaticFieldValues);
@@ -92,6 +110,9 @@
/**
* Returns the fields of instances of this class.
+ * Does not include fields from the super class of this class.
+ *
+ * @return the instance fields
*/
public Field[] getInstanceFields() {
return mInstanceFields;
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/AhatHeap.java b/tools/ahat/src/main/com/android/ahat/heapdump/AhatHeap.java
index b8897a1..60c9a0d 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/AhatHeap.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/AhatHeap.java
@@ -16,6 +16,13 @@
package com.android.ahat.heapdump;
+/**
+ * Used to identify and access basic information about a particular
+ * heap from the heap dump. Standard Java heap dumps have a single heap,
+ * called the "default" heap. Android heap dumps distinguish among "zygote",
+ * "image", and "app" heaps. There will be a single instance of AhatHeap for
+ * each different heap in the heap dump.
+ */
public class AhatHeap implements Diffable<AhatHeap> {
private String mName;
private Size mSize = Size.ZERO;
@@ -61,6 +68,9 @@
/**
* Returns the name of this heap.
+ * For example, "default", "app", "image", or "zygote".
+ *
+ * @return The name of the heap.
*/
public String getName() {
return mName;
@@ -68,6 +78,8 @@
/**
* Returns the total number of bytes allocated on this heap.
+ *
+ * @return the total number of bytes allocated on this heap.
*/
public Size getSize() {
return mSize;
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/AhatInstance.java b/tools/ahat/src/main/com/android/ahat/heapdump/AhatInstance.java
index a9f819f..67253bf 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/AhatInstance.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/AhatInstance.java
@@ -26,6 +26,11 @@
import java.util.List;
import java.util.Queue;
+/**
+ * A Java instance from a parsed heap dump. It is the base class used for all
+ * kinds of Java instances, including normal Java objects, class objects, and
+ * arrays.
+ */
public abstract class AhatInstance implements Diffable<AhatInstance>,
DominatorsComputation.Node {
// The id of this instance from the heap dump.
@@ -80,14 +85,20 @@
}
/**
- * Returns a unique identifier for the instance.
+ * Returns a unique identifier for this instance.
+ *
+ * @return id of the instance
*/
public long getId() {
return mId;
}
/**
- * Returns the shallow number of bytes this object takes up.
+ * Returns the number of bytes used for this object in the heap.
+ * The returned size is a shallow size for the object that does not include
+ * sizes of other objects dominated by this object.
+ *
+ * @return the shallow size of the object
*/
public Size getSize() {
return new Size(mClassObj.getInstanceSize() + getExtraJavaSize(), mRegisteredNativeSize);
@@ -104,8 +115,13 @@
abstract long getExtraJavaSize();
/**
- * Returns the number of bytes belonging to the given heap that this instance
- * retains.
+ * Returns the number of bytes retained by this object in the given heap.
+ * The returned size includes the shallow size of this object and the size
+ * of all objects directly or indirectly retained by this object. Only those
+ * objects allocated on the given heap are included in the reported size.
+ *
+ * @param heap the heap to get the retained size for
+ * @return the retained size of the object
*/
public Size getRetainedSize(AhatHeap heap) {
int index = heap.getIndex();
@@ -116,7 +132,11 @@
}
/**
- * Returns the total number of bytes this instance retains.
+ * Returns the total number of bytes retained by this object. The returned
+ * size includes the shallow size of this object and the size of all objects
+ * directly or indirectly retained by this object.
+ *
+ * @return the total retained size of the object
*/
public Size getTotalRetainedSize() {
Size size = Size.ZERO;
@@ -136,7 +156,11 @@
}
/**
- * Returns true if this object is strongly-reachable.
+ * Returns true if this object is strongly reachable. An object is strongly
+ * reachable if there exists a path of (strong) references from some root
+ * object to this object.
+ *
+ * @return true if the object is strongly reachable
*/
public boolean isStronglyReachable() {
return mImmediateDominator != null;
@@ -144,14 +168,28 @@
/**
* Returns true if this object is reachable only through a
- * soft/weak/phantom/finalizer reference.
+ * soft/weak/phantom/finalizer reference. An object is weakly reachable if
+ * it is not strongly reachable but there still exists a path of references
+ * from some root object to this object. Because the object is not strongly
+ * reachable, any such path must contain a SoftReference, WeakReference,
+ * PhantomReference, or FinalizerReference somewhere along it.
+ * <p>
+ * Unlike a strongly reachable object, a weakly reachable object is allowed
+ * to be garbage collected.
+ *
+ * @return true if the object is weakly reachable
*/
public boolean isWeaklyReachable() {
return !isStronglyReachable() && mNextInstanceToGcRoot != null;
}
/**
- * Returns true if this object is completely unreachable.
+ * Returns true if this object is completely unreachable. An object is
+ * completely unreachable if there is no path to the object from some root
+ * object, neither through strong nor soft/weak/phantom/finalizer
+ * references.
+ *
+ * @return true if the object is completely unreachable
*/
public boolean isUnreachable() {
return !isStronglyReachable() && !isWeaklyReachable();
@@ -159,6 +197,8 @@
/**
* Returns the heap that this instance is allocated on.
+ *
+ * @return heap the instance is allocated on
*/
public AhatHeap getHeap() {
return mHeap;
@@ -171,7 +211,10 @@
abstract Iterable<Reference> getReferences();
/**
- * Returns true if this instance is marked as a root instance.
+ * Returns true if this instance is a GC root.
+ *
+ * @return true if this instance is a GC root.
+ * @see getRootTypes
*/
public boolean isRoot() {
return mRootTypes != 0;
@@ -187,6 +230,8 @@
/**
* Returns a list of the root types of this object.
* Returns null if this object is not a root.
+ *
+ * @return list of the objects root types
*/
public Collection<RootType> getRootTypes() {
if (!isRoot()) {
@@ -205,14 +250,17 @@
/**
* Returns the immediate dominator of this instance.
* Returns null if this is a root instance.
+ *
+ * @return the immediate dominator of this instance
*/
public AhatInstance getImmediateDominator() {
return mImmediateDominator;
}
/**
- * Returns a list of those objects immediately dominated by the given
- * instance.
+ * Returns a list of objects immediately dominated by this instance.
+ *
+ * @return list of immediately dominated objects
*/
public List<AhatInstance> getDominated() {
return mDominated;
@@ -220,13 +268,17 @@
/**
* Returns the site where this instance was allocated.
+ *
+ * @return the object's allocation site
*/
public Site getSite() {
return mSite;
}
/**
- * Returns true if the given instance is a class object
+ * Returns true if this instance is a class object
+ *
+ * @return true if this instance is a class object
*/
public boolean isClassObj() {
// Overridden by AhatClassObj.
@@ -236,6 +288,8 @@
/**
* Returns this as an AhatClassObj if this is an AhatClassObj.
* Returns null if this is not an AhatClassObj.
+ *
+ * @return this instance as a class object
*/
public AhatClassObj asClassObj() {
// Overridden by AhatClassObj.
@@ -243,7 +297,11 @@
}
/**
- * Returns the class object instance for the class of this object.
+ * Returns the class object for this instance.
+ * For example, if this object is an instance of java.lang.String, this
+ * method returns the AhatClassObj for java.lang.String.
+ *
+ * @return the instance's class object
*/
public AhatClassObj getClassObj() {
return mClassObj;
@@ -251,6 +309,10 @@
/**
* Returns the name of the class this object belongs to.
+ * For example, if this object is an instance of java.lang.String, returns
+ * "java.lang.String".
+ *
+ * @return the name of this instance's class
*/
public String getClassName() {
AhatClassObj classObj = getClassObj();
@@ -258,7 +320,9 @@
}
/**
- * Returns true if the given instance is an array instance
+ * Returns true if the given instance is an array instance.
+ *
+ * @return true if the given instance is an array instance
*/
public boolean isArrayInstance() {
// Overridden by AhatArrayInstance.
@@ -268,6 +332,8 @@
/**
* Returns this as an AhatArrayInstance if this is an AhatArrayInstance.
* Returns null if this is not an AhatArrayInstance.
+ *
+ * @return this instance as an array instance
*/
public AhatArrayInstance asArrayInstance() {
// Overridden by AhatArrayInstance.
@@ -275,7 +341,9 @@
}
/**
- * Returns true if the given instance is a class instance
+ * Returns true if this instance is a class instance.
+ *
+ * @return true if this instance is a class instance
*/
public boolean isClassInstance() {
return false;
@@ -284,15 +352,20 @@
/**
* Returns this as an AhatClassInstance if this is an AhatClassInstance.
* Returns null if this is not an AhatClassInstance.
+ *
+ * @return this instance as a class instance
*/
public AhatClassInstance asClassInstance() {
return null;
}
/**
- * Return the referent associated with this instance.
- * This is relevent for instances of java.lang.ref.Reference.
- * Returns null if the instance has no referent associated with it.
+ * Returns the <code>referent</code> associated with this instance.
+ * This is only relevant for instances of java.lang.ref.Reference or its
+ * subclasses. Returns null if the instance has no referent associated with
+ * it.
+ *
+ * @return the referent associated with this instance
*/
public AhatInstance getReferent() {
// Overridden by AhatClassInstance.
@@ -300,7 +373,9 @@
}
/**
- * Returns a list of objects with hard references to this object.
+ * Returns a list of objects with (strong) references to this object.
+ *
+ * @return the objects referencing this object
*/
public List<AhatInstance> getHardReverseReferences() {
if (mHardReverseReferences != null) {
@@ -310,7 +385,10 @@
}
/**
- * Returns a list of objects with soft references to this object.
+ * Returns a list of objects with soft/weak/phantom/finalizer references to
+ * this object.
+ *
+ * @return the objects weakly referencing this object
*/
public List<AhatInstance> getSoftReverseReferences() {
if (mSoftReverseReferences != null) {
@@ -320,9 +398,12 @@
}
/**
- * Returns the value of a field of an instance.
- * Returns null if the field value is null, the field couldn't be read, or
- * there are multiple fields with the same name.
+ * Returns the value of a field of this instance. Returns null if the field
+ * value is null, the field couldn't be read, or there are multiple fields
+ * with the same name.
+ *
+ * @param fieldName the name of the field to get the value of
+ * @return the field value
*/
public Value getField(String fieldName) {
// Overridden by AhatClassInstance.
@@ -330,8 +411,13 @@
}
/**
- * Reads a reference field of this instance.
- * Returns null if the field value is null, or if the field couldn't be read.
+ * Reads a reference field of this instance. Returns null if the field value
+ * is null, of primitive type, or if the field couldn't be read. There is no
+ * way using this method to distinguish between a reference field with value
+ * <code>null</code> and an invalid field.
+ *
+ * @param fieldName the name of the reference field to get the value of
+ * @return the reference field value
*/
public AhatInstance getRefField(String fieldName) {
// Overridden by AhatClassInstance.
@@ -339,30 +425,41 @@
}
/**
- * Assuming inst represents a DexCache object, return the dex location for
- * that dex cache. Returns null if the given instance doesn't represent a
- * DexCache object or the location could not be found.
+ * Returns the dex location associated with this object. Only applies to
+ * instances of dalvik.system.DexCache. If this is an instance of DexCache,
+ * returns the dex location for that dex cache. Otherwise returns null.
* If maxChars is non-negative, the returned location is truncated to
* maxChars in length.
+ *
+ * @param maxChars the maximum length of the returned string
+ * @return the dex location associated with this object
*/
public String getDexCacheLocation(int maxChars) {
return null;
}
/**
- * Return the bitmap instance associated with this object, or null if there
- * is none. This works for android.graphics.Bitmap instances and their
- * underlying Byte[] instances.
+ * Returns the android.graphics.Bitmap instance associated with this object.
+ * Instances of android.graphics.Bitmap return themselves. If this is a
+ * byte[] array containing pixel data for an instance of
+ * android.graphics.Bitmap, that instance of android.graphics.Bitmap is
+ * returned. Otherwise null is returned.
+ *
+ * @return the bitmap instance associated with this object
*/
public AhatInstance getAssociatedBitmapInstance() {
return null;
}
/**
- * Read the string value from this instance.
- * Returns null if this object can't be interpreted as a string.
- * The returned string is truncated to maxChars characters.
- * If maxChars is negative, the returned string is not truncated.
+ * Returns the (bounded-length) string associated with this instance.
+ * Applies to instances of java.lang.String, char[], and in some cases
+ * byte[]. Returns null if this object cannot be interpreted as a string.
+ * If maxChars is non-negative, the returned string is truncated to maxChars
+ * characters in length.
+ *
+ * @param maxChars the maximum length of the returned string
+ * @return the string associated with this instance
*/
public String asString(int maxChars) {
// By default instances can't be interpreted as a string. This method is
@@ -372,17 +469,23 @@
}
/**
- * Reads the string value from an hprof Instance.
- * Returns null if the object can't be interpreted as a string.
+ * Returns the string associated with this instance. Applies to instances of
+ * java.lang.String, char[], and in some cases byte[]. Returns null if this
+ * object cannot be interpreted as a string.
+ *
+ * @return the string associated with this instance
*/
public String asString() {
return asString(-1);
}
/**
- * Return the bitmap associated with the given instance, if any.
+ * Returns the bitmap pixel data associated with this instance.
* This is relevant for instances of android.graphics.Bitmap and byte[].
- * Returns null if there is no bitmap associated with the given instance.
+ * Returns null if there is no bitmap pixel data associated with the given
+ * instance.
+ *
+ * @return the bitmap pixel data associated with this image
*/
public BufferedImage asBitmap() {
return null;
@@ -402,11 +505,23 @@
}
/**
- * Returns a sample path from a GC root to this instance.
- * This instance is included as the last element of the path with an empty
- * field description.
+ * Returns a sample path from a GC root to this instance. The first element
+ * of the returned path is a GC root object. This instance is included as
+ * the last element of the path with an empty field description.
+ * <p>
+ * If the instance is strongly reachable, a path of string references will
+ * be returned. If the instance is weakly reachable, the returned path will
+ * include a soft/weak/phantom/finalizer reference somewhere along it.
+ * Returns null if this instance is not reachable.
+ *
+ * @return sample path from a GC root to this instance
+ * @see PathElement
*/
public List<PathElement> getPathFromGcRoot() {
+ if (isUnreachable()) {
+ return null;
+ }
+
List<PathElement> path = new ArrayList<PathElement>();
AhatInstance dom = this;
@@ -434,12 +549,15 @@
return new PathElement(inst.mNextInstanceToGcRoot, inst.mNextInstanceToGcRootField);
}
- /** Returns a human-readable identifier for this object.
+ /**
+ * Returns a human-readable identifier for this object.
* For class objects, the string is the class name.
* For class instances, the string is the class name followed by '@' and the
* hex id of the instance.
* For array instances, the string is the array type followed by the size in
* square brackets, followed by '@' and the hex id of the instance.
+ *
+ * @return human-readable identifier for this object
*/
@Override public abstract String toString();
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/AhatSnapshot.java b/tools/ahat/src/main/com/android/ahat/heapdump/AhatSnapshot.java
index 59ce5d1..535db08 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/AhatSnapshot.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/AhatSnapshot.java
@@ -19,6 +19,11 @@
import com.android.ahat.dominators.DominatorsComputation;
import java.util.List;
+/**
+ * A parsed heap dump.
+ * It contains methods to access the heaps, allocation sites, roots, classes,
+ * and instances from the parsed heap dump.
+ */
public class AhatSnapshot implements Diffable<AhatSnapshot> {
private final Site mRootSite;
@@ -60,16 +65,24 @@
}
/**
- * Returns the instance with given id in this snapshot.
+ * Returns the instance with the given id in this snapshot.
+ * Where the id of an instance x is x.getId().
* Returns null if no instance with the given id is found.
+ *
+ * @param id the id of the instance to find
+ * @return the instance with the given id
*/
public AhatInstance findInstance(long id) {
return mInstances.get(id);
}
/**
- * Returns the AhatClassObj with given id in this snapshot.
+ * Returns the AhatClassObj with the given id in this snapshot.
+ * Where the id of a class object x is x.getId().
* Returns null if no class object with the given id is found.
+ *
+ * @param id the id of the class object to find
+ * @return the class object with the given id
*/
public AhatClassObj findClassObj(long id) {
AhatInstance inst = findInstance(id);
@@ -77,8 +90,12 @@
}
/**
- * Returns the heap with the given name, if any.
+ * Returns the heap with the given name.
+ * Where the name of a heap x is x.getName().
* Returns null if no heap with the given name could be found.
+ *
+ * @param name the name of the heap to get
+ * @return the heap with the given name
*/
public AhatHeap getHeap(String name) {
// We expect a small number of heaps (maybe 3 or 4 total), so a linear
@@ -93,30 +110,45 @@
/**
* Returns a list of heaps in the snapshot in canonical order.
- * Modifications to the returned list are visible to this AhatSnapshot,
- * which is used by diff to insert place holder heaps.
+ * <p>
+ * Note: modifications to the returned list are visible to this
+ * AhatSnapshot, which is used by diff to insert place holder heaps.
+ *
+ * @return list of heaps
*/
public List<AhatHeap> getHeaps() {
return mHeaps;
}
/**
- * Returns a collection of instances whose immediate dominator is the
- * SENTINEL_ROOT.
+ * Returns a collection of "rooted" instances.
+ * An instance is "rooted" if it is a GC root, or if it is retained by more
+ * than one GC root. These are reachable instances that are not immediately
+ * dominated by any other instance in the heap.
+ *
+ * @return collection of rooted instances
*/
public List<AhatInstance> getRooted() {
return mSuperRoot.getDominated();
}
/**
- * Returns the root site for this snapshot.
+ * Returns the root allocation site for this snapshot.
+ *
+ * @return the root allocation site
*/
public Site getRootSite() {
return mRootSite;
}
- // Get the site associated with the given id.
- // Returns the root site if no such site found.
+ /**
+ * Returns the site associated with the given id.
+ * Where the id of a site x is x.getId().
+ * Returns the root site if no site with the given id is found.
+ *
+ * @param id the id of the site to get
+ * @return the site with the given id
+ */
public Site getSite(long id) {
Site site = mRootSite.findSite(id);
return site == null ? mRootSite : site;
@@ -127,8 +159,10 @@
}
/**
- * Returns true if this snapshot has been diffed against another, different
+ * Returns true if this snapshot has been diffed against a different
* snapshot.
+ *
+ * @return true if the snapshot has been diffed
*/
public boolean isDiffed() {
return mBaseline != this;
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/Diff.java b/tools/ahat/src/main/com/android/ahat/heapdump/Diff.java
index 98c7e58..b35b424 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/Diff.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/Diff.java
@@ -25,9 +25,15 @@
import java.util.Map;
import java.util.Objects;
+/**
+ * Provides a static method to diff two heap dumps.
+ */
public class Diff {
+ private Diff() {
+ }
+
/**
- * Perform a diff between two heap lists.
+ * Performs a diff between two heap lists.
*
* Heaps are diffed based on heap name. PlaceHolder heaps will be added to
* the given lists as necessary so that every heap in A has a corresponding
@@ -312,8 +318,16 @@
}
/**
- * Perform a diff of the two snapshots, setting each as the baseline for the
- * other.
+ * Performs a diff of two snapshots.
+ * Each snapshot will be set as the baseline for the other snapshot.
+ * <p>
+ * The diff algorithm attempts to match instances in snapshot <code>a</code>
+ * to corresponding instances in snapshot <code>b</code>. The snapshots need
+ * not come from the same running process, application version, or platform
+ * version.
+ *
+ * @param a one of the snapshots to diff
+ * @param b the other of the snapshots to diff
*/
public static void snapshots(AhatSnapshot a, AhatSnapshot b) {
a.setBaseline(b);
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/DiffFields.java b/tools/ahat/src/main/com/android/ahat/heapdump/DiffFields.java
index e3c671f..ff07af0 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/DiffFields.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/DiffFields.java
@@ -22,12 +22,16 @@
import java.util.List;
/**
- * This class contains a routine for diffing two collections of static or
- * instance fields.
+ * Provides a routine for diffing two collections of static or instance
+ * fields.
*/
public class DiffFields {
/**
- * Return the result of diffing two collections of field values.
+ * Returns the result of diffing two collections of field values.
+ *
+ * @param current a list of fields in the current heap dump
+ * @param baseline a list of fields in the baseline heap dump
+ * @return list of diffed fields
*/
public static List<DiffedFieldValue> diff(Iterable<FieldValue> current,
Iterable<FieldValue> baseline) {
@@ -85,5 +89,5 @@
* by field name and type.
*/
private static final Comparator<FieldValue> FOR_DIFF
- = new Sort.WithPriority(Sort.FIELD_VALUE_BY_NAME, Sort.FIELD_VALUE_BY_TYPE);
+ = Sort.withPriority(Sort.FIELD_VALUE_BY_NAME, Sort.FIELD_VALUE_BY_TYPE);
}
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/Diffable.java b/tools/ahat/src/main/com/android/ahat/heapdump/Diffable.java
index 53442c8..09c8ee6 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/Diffable.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/Diffable.java
@@ -17,12 +17,19 @@
package com.android.ahat.heapdump;
/**
- * An interface for objects that have corresponding objects in a baseline heap
- * dump.
+ * An interface for instances/sites/heaps/etc in a heap dump that can be
+ * related to corresponding instances/sites/heaps/etc in a second heap dump
+ * when the two heap dumps have been diffed.
*/
public interface Diffable<T> {
/**
- * Return the baseline object that corresponds to this one.
+ * Returns the object in the other heap dump that corresponds to this object.
+ * When two heap dumps are diffed, diffable objects from the first heap dump
+ * will be matched to "baseline" objects from the second heap dump, and
+ * diffable objects from the second heap dump will be matched to "baseline"
+ * objects from the first heap dump.
+ *
+ * @return the matched object from the other heap dump
*/
T getBaseline();
@@ -32,6 +39,8 @@
* baseline heap dump that is not in this heap dump. In that case, we create
* a dummy place holder object in this heap dump as an indicator of the
* object removed from the baseline heap dump.
+ *
+ * @return true if the object is a placeholder
*/
boolean isPlaceHolder();
}
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/DiffedFieldValue.java b/tools/ahat/src/main/com/android/ahat/heapdump/DiffedFieldValue.java
index 3cd273e..8de337e 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/DiffedFieldValue.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/DiffedFieldValue.java
@@ -18,25 +18,65 @@
import java.util.Objects;
-/** DiffedFieldValue is used by the DiffedField class to return the result of
- * diffing two collections of fields.
+/**
+ * Used by the DiffedField class to return the result of diffing two
+ * collections of fields.
*/
public class DiffedFieldValue {
+ /**
+ * The name of the field.
+ */
public final String name;
+
+ /**
+ * The type of the field.
+ */
public final Type type;
+
+ /**
+ * The value of the field in the current heap dump.
+ */
public final Value current;
+
+ /**
+ * The value of the field in the baseline heap dump.
+ */
public final Value baseline;
+ /**
+ * Whether the field was added to, deleted from, or matched with a field in
+ * the baseline heap dump.
+ */
public final Status status;
+ /**
+ * A status enum to indicate whether a field was added to, deleted from, or
+ * matched with a field in the baseline heap dump.
+ */
public static enum Status {
- ADDED, // The current field has no matching baseline value.
- MATCHED, // The current field has a matching baseline value.
- DELETED // The baseline field has no matching current value.
+ /**
+ * The field exists in the current heap dump but not the baseline.
+ */
+ ADDED,
+
+ /**
+ * The field exists in both the current and baseline heap dumps.
+ */
+ MATCHED,
+
+ /**
+ * The field exists in the baseline heap dump but not the current.
+ */
+ DELETED
};
/**
- * Return a DiffedFieldValue where there is both a current and baseline.
+ * Constructs a DiffedFieldValue where there are both current and baseline
+ * fields.
+ *
+ * @param current the current field
+ * @param baseline the baseline field
+ * @return the constructed DiffedFieldValue
*/
public static DiffedFieldValue matched(FieldValue current, FieldValue baseline) {
return new DiffedFieldValue(current.name,
@@ -47,14 +87,20 @@
}
/**
- * Return a DiffedFieldValue where there is no baseline.
+ * Constructs a DiffedFieldValue where there is no baseline field.
+ *
+ * @param current the current field
+ * @return the constructed DiffedFieldValue
*/
public static DiffedFieldValue added(FieldValue current) {
return new DiffedFieldValue(current.name, current.type, current.value, null, Status.ADDED);
}
/**
- * Return a DiffedFieldValue where there is no current.
+ * Constructs a DiffedFieldValue where there is no current field.
+ *
+ * @param baseline the baseline field
+ * @return the constructed DiffedFieldValue
*/
public static DiffedFieldValue deleted(FieldValue baseline) {
return new DiffedFieldValue(baseline.name, baseline.type, null, baseline.value, Status.DELETED);
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/Field.java b/tools/ahat/src/main/com/android/ahat/heapdump/Field.java
index dff4017..6494069 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/Field.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/Field.java
@@ -16,10 +16,26 @@
package com.android.ahat.heapdump;
+/**
+ * A description of a field from a heap dump.
+ */
public class Field {
+ /**
+ * The name of the field.
+ */
public final String name;
+
+ /**
+ * The type of the field.
+ */
public final Type type;
+ /**
+ * Constructs a Field instance.
+ *
+ * @param name name of the field
+ * @param type type of the field
+ */
public Field(String name, Type type) {
this.name = name;
this.type = type;
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/FieldValue.java b/tools/ahat/src/main/com/android/ahat/heapdump/FieldValue.java
index 20e6da7..70314da 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/FieldValue.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/FieldValue.java
@@ -16,11 +16,32 @@
package com.android.ahat.heapdump;
+/**
+ * A description and value of a field from a heap dump.
+ */
public class FieldValue {
+ /**
+ * The name of the field.
+ */
public final String name;
+
+ /**
+ * The type of the field.
+ */
public final Type type;
+
+ /**
+ * The value of the field.
+ */
public final Value value;
+ /**
+ * Constructs an instance of FieldValue.
+ *
+ * @param name name of the field
+ * @param type type of the field
+ * @param value value of the field
+ */
public FieldValue(String name, Type type, Value value) {
this.name = name;
this.type = type;
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/HprofFormatException.java b/tools/ahat/src/main/com/android/ahat/heapdump/HprofFormatException.java
index 256a3b4..29ac9b0 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/HprofFormatException.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/HprofFormatException.java
@@ -16,6 +16,10 @@
package com.android.ahat.heapdump;
+/**
+ * Exception thrown when the heap dump parser detects an improperly formatted
+ * heap dump file.
+ */
public class HprofFormatException extends Exception {
HprofFormatException(String msg) {
super(msg);
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/Parser.java b/tools/ahat/src/main/com/android/ahat/heapdump/Parser.java
index d7b1dd7..58bd373 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/Parser.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/Parser.java
@@ -31,21 +31,43 @@
import java.util.List;
import java.util.Map;
+/**
+ * Provides methods for parsing heap dumps.
+ */
public class Parser {
private static final int ID_SIZE = 4;
+ private Parser() {
+ }
+
/**
- * Parse the given heap dump using the given proguard map for deobfuscation.
- * We make the following assumptions about valid heap dumps:
- * Class serial numbers, stack frames, and stack traces
- * individually satisfy the following:
- * - all elements are defined before they are referenced.
- * - ids are densely packed in some range [a, b] where a is not
- * necessarily 0.
- * - there are not more than 2^31 elements defined.
- * All classes are defined via a LOAD CLASS record before the first heap
- * dump segment.
- * The ID size used in the heap dump is 4 bytes.
+ * Parses a heap dump from a File.
+ * <p>
+ * The heap dump should be a heap dump in the J2SE HPROF format optionally
+ * with Android extensions and satisfying the following additional
+ * constraints:
+ * <ul>
+ * <li>
+ * Class serial numbers, stack frames, and stack traces individually satisfy
+ * the following:
+ * <ul>
+ * <li> All elements are defined before they are referenced.
+ * <li> Ids are densely packed in some range [a, b] where a is not necessarily 0.
+ * <li> There are not more than 2^31 elements defined.
+ * </ul>
+ * <li> All classes are defined via a LOAD CLASS record before the first
+ * heap dump segment.
+ * <li> The ID size used in the heap dump is 4 bytes.
+ * </ul>
+ * <p>
+ * The given proguard map will be used to deobfuscate class names, field
+ * names, and stack traces in the heap dump.
+ *
+ * @param hprof the hprof file to parse
+ * @param map the proguard map for deobfuscation
+ * @return the parsed heap dump
+ * @throws IOException if the heap dump could not be read
+ * @throws HprofFormatException if the heap dump is not properly formatted
*/
public static AhatSnapshot parseHeapDump(File hprof, ProguardMap map)
throws IOException, HprofFormatException {
@@ -57,7 +79,33 @@
}
/**
- * Parse a heap dump from a byte buffer.
+ * Parses a heap dump from a byte buffer.
+ * <p>
+ * The heap dump should be a heap dump in the J2SE HPROF format optionally
+ * with Android extensions and satisfying the following additional
+ * constraints:
+ * <ul>
+ * <li>
+ * Class serial numbers, stack frames, and stack traces individually satisfy
+ * the following:
+ * <ul>
+ * <li> All elements are defined before they are referenced.
+ * <li> Ids are densely packed in some range [a, b] where a is not necessarily 0.
+ * <li> There are not more than 2^31 elements defined.
+ * </ul>
+ * <li> All classes are defined via a LOAD CLASS record before the first
+ * heap dump segment.
+ * <li> The ID size used in the heap dump is 4 bytes.
+ * </ul>
+ * <p>
+ * The given proguard map will be used to deobfuscate class names, field
+ * names, and stack traces in the heap dump.
+ *
+ * @param hprof the bytes of the hprof file to parse
+ * @param map the proguard map for deobfuscation
+ * @return the parsed heap dump
+ * @throws IOException if the heap dump could not be read
+ * @throws HprofFormatException if the heap dump is not properly formatted
*/
public static AhatSnapshot parseHeapDump(ByteBuffer hprof, ProguardMap map)
throws IOException, HprofFormatException {
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/PathElement.java b/tools/ahat/src/main/com/android/ahat/heapdump/PathElement.java
index 196a246..5ce0b1e 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/PathElement.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/PathElement.java
@@ -16,11 +16,51 @@
package com.android.ahat.heapdump;
+/**
+ * A single element along a reference path from a GC root to an instance in
+ * the heap dump.
+ * <p>
+ * For example, assuming object A is a root a path to some object X might look
+ * like:
+ * <pre>
+ * A.x --> B.y --> C.z --> X
+ * </pre>
+ *
+ * A path element is a single node of that path, such as <code>B.y</code>.
+ * @see AhatInstance#getPathFromGcRoot
+ */
public class PathElement implements Diffable<PathElement> {
+ /**
+ * The instance along the reference path that this PathElement is associated
+ * with.
+ */
public final AhatInstance instance;
+
+ /**
+ * A human readable description of which field in <code>instance</code> is
+ * followed to reach the next element in the path.
+ * Some examples:
+ * <ul>
+ * <li> "mBlah" for a class instance
+ * <li> "[4]" for an array instance
+ * <li> "" for the last element of the path
+ * </ul>
+ */
public final String field;
+
+ /**
+ * True if <code>instance</code> is a (not necessarily immediate) dominator
+ * of the final object in the path.
+ */
public boolean isDominator;
+ /**
+ * Constructs a PathElement object.
+ * <code>isDominator</code> is set to false.
+ *
+ * @param instance the path element instance
+ * @param field the path element field
+ */
public PathElement(AhatInstance instance, String field) {
this.instance = instance;
this.field = field;
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/RootType.java b/tools/ahat/src/main/com/android/ahat/heapdump/RootType.java
index 734f889..99d85dc 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/RootType.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/RootType.java
@@ -16,20 +16,80 @@
package com.android.ahat.heapdump;
+/**
+ * Enumeration representing object root types as defined in the binary heap
+ * dump format specification.
+ */
public enum RootType {
+ /**
+ * There is a JNI Global Reference for the object in question.
+ */
JNI_GLOBAL (1 << 0),
+
+ /**
+ * There is a JNI Local Reference for the object in question.
+ */
JNI_LOCAL (1 << 1),
+
+ /**
+ * The object in question is a parameter or local variable of a running
+ * method.
+ */
JAVA_FRAME (1 << 2),
+
+ /**
+ * The object in question is a parameter of a running JNI method.
+ */
NATIVE_STACK (1 << 3),
+
+ /**
+ * The object is a class object that cannot be unloaded.
+ */
STICKY_CLASS (1 << 4),
+
+ /**
+ * The object is referenced from an active thread block.
+ */
THREAD_BLOCK (1 << 5),
+
+ /**
+ * The object's monitor is currently in use.
+ */
MONITOR (1 << 6),
+
+ /**
+ * The object is a running thread.
+ */
THREAD (1 << 7),
+
+ /**
+ * The object is an interned string.
+ */
INTERNED_STRING (1 << 8),
+
+ /**
+ * The object is being used by the debugger.
+ */
DEBUGGER (1 << 9),
+
+ /**
+ * The object is being used by the VM internally.
+ */
VM_INTERNAL (1 << 10),
+
+ /**
+ * The object has no given reason for being considered a root.
+ */
UNKNOWN (1 << 11),
+
+ /**
+ * The object's monitor is currently in use from JNI.
+ */
JNI_MONITOR (1 << 12),
+
+ /**
+ * The object is waiting to be finalized.
+ */
FINALIZING (1 << 13);
final int mask;
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/Site.java b/tools/ahat/src/main/com/android/ahat/heapdump/Site.java
index 4978d52..72c0a4a 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/Site.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/Site.java
@@ -24,6 +24,10 @@
import java.util.List;
import java.util.Map;
+/**
+ * Used to collection information about objects allocated at a particular
+ * allocation site.
+ */
public class Site implements Diffable<Site> {
// The site that this site was directly called from.
// mParent is null for the root site.
@@ -61,18 +65,39 @@
private Site mBaseline;
+ /**
+ * Summary information about instances allocated at a particular allocation
+ * site that are instances of a particular class and allocated on a
+ * particular heap.
+ */
public static class ObjectsInfo implements Diffable<ObjectsInfo> {
+ /**
+ * The heap that the summarized objects belong to.
+ */
public AhatHeap heap;
- public AhatClassObj classObj; // May be null.
+
+ /**
+ * The class of the summarized objects.
+ */
+ public AhatClassObj classObj; // May be null. Not sure why.
+
+ /**
+ * The number of instances included in the summary.
+ */
public long numInstances;
+
+ /**
+ * The sum of the shallow size of each instance included in the summary.
+ */
public Size numBytes;
+
private ObjectsInfo baseline;
/**
- * Construct a new, empty objects info for the given heap and class
+ * Constructs a new, empty objects info for the given heap and class
* combination.
*/
- public ObjectsInfo(AhatHeap heap, AhatClassObj classObj) {
+ ObjectsInfo(AhatHeap heap, AhatClassObj classObj) {
this.heap = heap;
this.classObj = classObj;
this.numInstances = 0;
@@ -82,12 +107,14 @@
/**
* Returns the name of the class this ObjectsInfo is associated with.
+ *
+ * @return the name of this object info's class
*/
public String getClassName() {
return classObj == null ? "???" : classObj.getName();
}
- public void setBaseline(ObjectsInfo baseline) {
+ void setBaseline(ObjectsInfo baseline) {
this.baseline = baseline;
}
@@ -121,11 +148,11 @@
}
/**
- * Get a child site of this site.
- * Returns the site at which the instance was allocated.
- * @param frames - The list of frames in the stack trace, starting with the
- * inner-most frame. May be null, in which case this site is
- * returned.
+ * Gets a child site of this site.
+ * @param frames the list of frames in the stack trace, starting with the
+ * inner-most frame. May be null, in which case this site is
+ * returned.
+ * @return the child site
*/
Site getSite(ProguardMap.Frame[] frames) {
return frames == null ? this : getSite(this, frames);
@@ -211,22 +238,29 @@
return id;
}
- // Get the size of a site for a specific heap.
+ /**
+ * Returns the size of all objects on the given heap allocated at this site.
+ * Includes objects belonging to <code>heap</code> allocated at this and
+ * child sites.
+ *
+ * @param heap the heap to query the size for
+ * @return the total shallow size of objects in this site
+ */
public Size getSize(AhatHeap heap) {
return mSizesByHeap[heap.getIndex()];
}
/**
- * Collect the objects allocated under this site, optionally filtered by
+ * Collects the objects allocated under this site, optionally filtered by
* heap name or class name. Includes objects allocated in children sites.
- * @param heapName - The name of the heap the collected objects should
- * belong to. This may be null to indicate objects of
- * every heap should be collected.
- * @param className - The name of the class the collected objects should
- * belong to. This may be null to indicate objects of
- * every class should be collected.
- * @param objects - Out parameter. A collection of objects that all
- * collected objects should be added to.
+ * @param heapName the name of the heap the collected objects should
+ * belong to. This may be null to indicate objects of
+ * every heap should be collected.
+ * @param className the name of the class the collected objects should
+ * belong to. This may be null to indicate objects of
+ * every class should be collected.
+ * @param objects out parameter. A collection of objects that all
+ * collected objects should be added to.
*/
public void getObjects(String heapName, String className, Collection<AhatInstance> objects) {
for (AhatInstance inst : mObjects) {
@@ -263,11 +297,24 @@
return info;
}
+ /**
+ * Return a summary breakdown of the objects allocated at this site.
+ * Objects are grouped by class and heap and summarized into a single
+ * {@link ObjectsInfo}. This method returns all the groups for this
+ * allocation site.
+ *
+ * @return all ObjectInfo summaries for instances allocated at this site
+ */
public List<ObjectsInfo> getObjectsInfos() {
return mObjectsInfos;
}
- // Get the combined size of the site for all heaps.
+ /**
+ * Returns the combined size of the site for all heaps.
+ * Includes all objects allocated at this and child sites.
+ *
+ * @return total shallow size of objects in this site
+ */
public Size getTotalSize() {
Size total = Size.ZERO;
for (Size size : mSizesByHeap) {
@@ -277,39 +324,70 @@
}
/**
- * Return the site this site was called from.
+ * Returns the site this site was called from.
* Returns null for the root site.
+ *
+ * @return the site this site was called from
*/
public Site getParent() {
return mParent;
}
+ /**
+ * Returns the name of the method this allocation site belongs to.
+ * For example, "equals".
+ *
+ * @return the method name of the allocation site
+ */
public String getMethodName() {
return mMethodName;
}
+ /**
+ * Returns the signature of the method this allocation site belongs to.
+ * For example, "(Ljava/lang/Object;)Z".
+ *
+ * @return the signature of method the allocation site belongs to
+ */
public String getSignature() {
return mSignature;
}
+ /**
+ * Returns the name of the Java file where this allocation site is found.
+ *
+ * @return the file the allocation site belongs to
+ */
public String getFilename() {
return mFilename;
}
+ /**
+ * Returns the line number of the code in the source file that the
+ * allocation site refers to.
+ *
+ * @return the allocation site line number
+ */
public int getLineNumber() {
return mLineNumber;
}
/**
* Returns the unique id of this site.
+ * This is an arbitrary unique id computed after processing the heap dump.
+ *
+ * @return the site id
*/
public long getId() {
return mId;
}
/**
- * Find the child site with the given id.
+ * Returns the child site with the given id.
* Returns null if no such site was found.
+ *
+ * @param id the id of the child site to find
+ * @return the found child site
*/
public Site findSite(long id) {
if (id == mId) {
@@ -341,6 +419,8 @@
/**
* Returns an unmodifiable list of this site's immediate children.
+ *
+ * @return this site's child sites
*/
public List<Site> getChildren() {
return Collections.unmodifiableList(mChildren);
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/Size.java b/tools/ahat/src/main/com/android/ahat/heapdump/Size.java
index 7c8db90..a4593e1 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/Size.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/Size.java
@@ -17,47 +17,76 @@
package com.android.ahat.heapdump;
/**
- * The Size class is used to represent how much space an instance takes up.
- *
+ * Used to represent how much space an instance takes up.
* An abstraction is introduced rather than using a long directly in order to
* more easily keep track of the different components of the size. For
* example, some instances may have associated native, code, or graphics
* sizes.
- *
+ * <p>
* Size objects are immutable.
*/
public class Size {
private final long mJavaSize;
private final long mRegisteredNativeSize;
+ /**
+ * An instance of Size with 0 for all categories.
+ */
public static Size ZERO = new Size(0, 0);
+ /**
+ * Constructs a new instance of Size.
+ *
+ * @param javaSize number of bytes in the java category
+ * @param registeredNativeSize number of bytes in the registeredNativeSize
+ * category
+ */
public Size(long javaSize, long registeredNativeSize) {
mJavaSize = javaSize;
mRegisteredNativeSize = registeredNativeSize;
}
+ /**
+ * Returns the sum of the size of all categories.
+ *
+ * @return the total size
+ */
public long getSize() {
return mJavaSize + mRegisteredNativeSize;
}
+ /**
+ * Returns the size of the java category.
+ *
+ * @return the java category size
+ */
public long getJavaSize() {
return mJavaSize;
}
+ /**
+ * Returns the size of the registered native category.
+ *
+ * @return the registered native category size
+ */
public long getRegisteredNativeSize() {
return mRegisteredNativeSize;
}
/**
- * Returns true if all the fields of this size object are zero.
+ * Returns true if all categories of this size are zero.
+ *
+ * @return true if the size is zero
*/
public boolean isZero() {
return mJavaSize == 0 && mRegisteredNativeSize == 0;
}
/**
- * Return a new Size object that is the sum of this size and the other.
+ * Returns a new Size object that is the sum of this size and the other.
+ *
+ * @param other the size to sum with this size
+ * @return the new size object
*/
public Size plus(Size other) {
if (isZero()) {
@@ -71,8 +100,11 @@
}
/**
- * Return a new Size object that has 'size' more registered native size than
- * this Size object.
+ * Returns a new Size object that has <code>size</code> more registered
+ * native size than this Size object.
+ *
+ * @param size the size to add to the registered native category
+ * @return the new size object
*/
public Size plusRegisteredNativeSize(long size) {
return new Size(mJavaSize, mRegisteredNativeSize + size);
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/Sort.java b/tools/ahat/src/main/com/android/ahat/heapdump/Sort.java
index efe0d6b..a629b3c 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/Sort.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/Sort.java
@@ -25,14 +25,14 @@
/**
* Provides Comparators and helper functions for sorting Instances, Sites, and
* other things.
- *
+ * <p>
* Note: The Comparators defined here impose orderings that are inconsistent
* with equals. They should not be used for element lookup or search. They
* should only be used for showing elements to the user in different orders.
*/
public class Sort {
/**
- * Compare sizes by their total size.
+ * Compares sizes by their total size.
* This sorts sizes from smaller total size to larger total size.
*/
public static final Comparator<Size> SIZE_BY_SIZE = new Comparator<Size>() {
@@ -43,7 +43,7 @@
};
/**
- * Compare instances by their total retained size.
+ * Compares instances by their total retained size.
* Different instances with the same total retained size are considered
* equal for the purposes of comparison.
* This sorts instances from larger retained size to smaller retained size.
@@ -57,12 +57,12 @@
};
/**
- * Compare instances by their retained size for a given heap index.
+ * Compares instances by their retained size for a given heap index.
* Different instances with the same total retained size are considered
* equal for the purposes of comparison.
* This sorts instances from larger retained size to smaller retained size.
*/
- public static class InstanceByHeapRetainedSize implements Comparator<AhatInstance> {
+ private static class InstanceByHeapRetainedSize implements Comparator<AhatInstance> {
private AhatHeap mHeap;
public InstanceByHeapRetainedSize(AhatHeap heap) {
@@ -76,16 +76,28 @@
}
/**
- * Compare objects based on a list of comparators, giving priority to the
+ * Compares objects based on a list of comparators, giving priority to the
* earlier comparators in the list.
*/
- public static class WithPriority<T> implements Comparator<T> {
+ private static class WithPriority<T> implements Comparator<T> {
private List<Comparator<T>> mComparators;
+ /**
+ * Constructs a comparator giving sort priority to earlier comparators in
+ * the list.
+ *
+ * @param comparators the list of comparators to use for sorting
+ */
public WithPriority(Comparator<T>... comparators) {
mComparators = Arrays.asList(comparators);
}
+ /**
+ * Constructs a comparator giving sort priority to earlier comparators in
+ * the list.
+ *
+ * @param comparators the list of comparators to use for sorting
+ */
public WithPriority(List<Comparator<T>> comparators) {
mComparators = comparators;
}
@@ -101,6 +113,27 @@
}
}
+ /**
+ * Returns a comparator that gives sort priority to earlier comparators in
+ * the list.
+ *
+ * @param <T> the type of object being sorted
+ * @param comparators the list of comparators to use for sorting
+ * @return the composite comparator
+ */
+ public static <T> Comparator<T> withPriority(Comparator<T>... comparators) {
+ return new WithPriority(comparators);
+ }
+
+ /**
+ * Returns a comparator that gives a default instance sort for the given
+ * snapshot.
+ * Objects are sorted by retained size, with priority given to the "app"
+ * heap if present.
+ *
+ * @param snapshot the snapshot to use the comparator with
+ * @return the default instance comparator
+ */
public static Comparator<AhatInstance> defaultInstanceCompare(AhatSnapshot snapshot) {
List<Comparator<AhatInstance>> comparators = new ArrayList<Comparator<AhatInstance>>();
@@ -116,14 +149,19 @@
}
/**
- * Compare Sites by the size of objects allocated on a given heap.
+ * Compares Sites by the size of objects allocated on a given heap.
* Different object infos with the same size on the given heap are
* considered equal for the purposes of comparison.
* This sorts sites from larger size to smaller size.
*/
- public static class SiteByHeapSize implements Comparator<Site> {
+ private static class SiteByHeapSize implements Comparator<Site> {
AhatHeap mHeap;
+ /**
+ * Constructs a SiteByHeapSize comparator.
+ *
+ * @param heap the heap to use when comparing sizes
+ */
public SiteByHeapSize(AhatHeap heap) {
mHeap = heap;
}
@@ -135,7 +173,7 @@
}
/**
- * Compare Sites by the total size of objects allocated.
+ * Compares Sites by the total size of objects allocated.
* This sorts sites from larger size to smaller size.
*/
public static final Comparator<Site> SITE_BY_TOTAL_SIZE = new Comparator<Site>() {
@@ -145,6 +183,14 @@
}
};
+ /**
+ * Compares Sites using a default comparison order.
+ * This sorts sites from larger size to smaller size, giving preference to
+ * sites with more allocation on the "app" heap, if present.
+ *
+ * @param snapshot the snapshot to use the comparator with
+ * @return the default site comparator
+ */
public static Comparator<Site> defaultSiteCompare(AhatSnapshot snapshot) {
List<Comparator<Site>> comparators = new ArrayList<Comparator<Site>>();
@@ -174,7 +220,7 @@
};
/**
- * Compare Site.ObjectsInfo by heap name.
+ * Compares Site.ObjectsInfo by heap name.
* Different object infos with the same heap name are considered equal for
* the purposes of comparison.
*/
@@ -187,7 +233,7 @@
};
/**
- * Compare Site.ObjectsInfo by class name.
+ * Compares Site.ObjectsInfo by class name.
* Different object infos with the same class name are considered equal for
* the purposes of comparison.
*/
@@ -202,7 +248,7 @@
};
/**
- * Compare FieldValue by field name.
+ * Compares FieldValue by field name.
*/
public static final Comparator<FieldValue> FIELD_VALUE_BY_NAME
= new Comparator<FieldValue>() {
@@ -213,7 +259,7 @@
};
/**
- * Compare FieldValue by type name.
+ * Compares FieldValue by type name.
*/
public static final Comparator<FieldValue> FIELD_VALUE_BY_TYPE
= new Comparator<FieldValue>() {
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/Type.java b/tools/ahat/src/main/com/android/ahat/heapdump/Type.java
index 4024961..ff79864 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/Type.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/Type.java
@@ -16,18 +16,63 @@
package com.android.ahat.heapdump;
+/**
+ * Enum corresponding to basic types from the binary heap dump format.
+ */
public enum Type {
+ /**
+ * Type used for any Java object.
+ */
OBJECT("Object", 4),
+
+ /**
+ * The primitive boolean type.
+ */
BOOLEAN("boolean", 1),
+
+ /**
+ * The primitive char type.
+ */
CHAR("char", 2),
+
+ /**
+ * The primitive float type.
+ */
FLOAT("float", 4),
+
+ /**
+ * The primitive double type.
+ */
DOUBLE("double", 8),
+
+ /**
+ * The primitive byte type.
+ */
BYTE("byte", 1),
+
+ /**
+ * The primitive short type.
+ */
SHORT("short", 2),
+
+ /**
+ * The primitive int type.
+ */
INT("int", 4),
+
+ /**
+ * The primitive long type.
+ */
LONG("long", 8);
+ /**
+ * The name of the type.
+ */
public final String name;
+
+ /**
+ * The number of bytes taken up by values of this type in the Java heap.
+ */
final int size;
Type(String name, int size) {
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/Value.java b/tools/ahat/src/main/com/android/ahat/heapdump/Value.java
index eea4277..b219bf1 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/Value.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/Value.java
@@ -17,48 +17,107 @@
package com.android.ahat.heapdump;
/**
- * Value represents a field value in a heap dump. The field value is either a
- * subclass of AhatInstance or a primitive Java type.
+ * A Java instance or primitive value from a parsed heap dump.
+ * Note: To save memory, a null Value is used to represent a null Java
+ * instance from the heap dump.
*/
public abstract class Value {
+ /**
+ * Constructs a Value for an AhatInstance.
+ * Note: returns null for null <code>value</code>.
+ *
+ * @param value the AhatInstance to make into a value
+ * @return the constructed value.
+ */
public static Value pack(AhatInstance value) {
return value == null ? null : new InstanceValue(value);
}
+ /**
+ * Constructs a Value for a boolean.
+ *
+ * @param value the boolean to make into a value
+ * @return the constructed value.
+ */
public static Value pack(boolean value) {
return new BooleanValue(value);
}
+ /**
+ * Constructs a Value for a char.
+ *
+ * @param value the char to make into a value
+ * @return the constructed value.
+ */
public static Value pack(char value) {
return new CharValue(value);
}
+ /**
+ * Constructs a Value for a float.
+ *
+ * @param value the float to make into a value
+ * @return the constructed value.
+ */
public static Value pack(float value) {
return new FloatValue(value);
}
+ /**
+ * Constructs a Value for a double.
+ *
+ * @param value the double to make into a value
+ * @return the constructed value.
+ */
public static Value pack(double value) {
return new DoubleValue(value);
}
+ /**
+ * Constructs a Value for a byte.
+ *
+ * @param value the byte to make into a value
+ * @return the constructed value.
+ */
public static Value pack(byte value) {
return new ByteValue(value);
}
+ /**
+ * Constructs a Value for a short.
+ *
+ * @param value the short to make into a value
+ * @return the constructed value.
+ */
public static Value pack(short value) {
return new ShortValue(value);
}
+ /**
+ * Constructs a Value for a int.
+ *
+ * @param value the int to make into a value
+ * @return the constructed value.
+ */
public static Value pack(int value) {
return new IntValue(value);
}
+ /**
+ * Constructs a Value for a long.
+ *
+ * @param value the long to make into a value
+ * @return the constructed value.
+ */
public static Value pack(long value) {
return new LongValue(value);
}
/**
- * Return the type of the given value.
+ * Returns the type of the given value.
+ *
+ * @param value the value to get the type of
+ * @return the value's type
*/
public static Type getType(Value value) {
return value == null ? Type.OBJECT : value.getType();
@@ -70,62 +129,78 @@
abstract Type getType();
/**
- * Returns true if the Value is an AhatInstance, as opposed to a Java
- * primitive value.
+ * Returns true if the Value is an AhatInstance rather than a primitive
+ * value.
+ *
+ * @return true if the value is an AhatInstance
*/
public boolean isAhatInstance() {
return false;
}
/**
- * Return the Value as an AhatInstance if it is one.
+ * Returns the Value as an AhatInstance if it is one.
* Returns null if the Value represents a Java primitive value.
+ *
+ * @return the AhatInstance packed into this value
*/
public AhatInstance asAhatInstance() {
return null;
}
/**
- * Returns true if the Value is an Integer.
+ * Returns true if the Value is an int.
+ *
+ * @return true if the value is an int.
*/
public boolean isInteger() {
return false;
}
/**
- * Return the Value as an Integer if it is one.
- * Returns null if the Value does not represent an Integer.
+ * Returns the Value as an int if it is one.
+ * Returns null if the Value does not represent an int.
+ *
+ * @return the int packed into this value
*/
public Integer asInteger() {
return null;
}
/**
- * Returns true if the Value is an Long.
+ * Returns true if the Value is an long.
+ *
+ * @return true if the value is an long.
*/
public boolean isLong() {
return false;
}
/**
- * Return the Value as an Long if it is one.
- * Returns null if the Value does not represent an Long.
+ * Returns the Value as an long if it is one.
+ * Returns null if the Value does not represent an long.
+ *
+ * @return the long packed into this value
*/
public Long asLong() {
return null;
}
/**
- * Return the Value as a Byte if it is one.
- * Returns null if the Value does not represent a Byte.
+ * Returns the Value as an byte if it is one.
+ * Returns null if the Value does not represent an byte.
+ *
+ * @return the byte packed into this value
*/
public Byte asByte() {
return null;
}
/**
- * Return the Value as a Char if it is one.
- * Returns null if the Value does not represent a Char.
+ * Returns the Value as an char if it is one.
+ * Returns null if the Value does not represent an char.
+ *
+ * @return the char packed into this value
*/
public Character asChar() {
return null;
@@ -134,10 +209,18 @@
@Override
public abstract String toString();
- public Value getBaseline() {
+ private Value getBaseline() {
return this;
}
+ /**
+ * Returns the baseline of the given value for the purposes of diff.
+ * This method can be used to handle the case when the Value is null.
+ *
+ * @param value the value to get the baseline of
+ * @return the baseline of the value
+ * @see Diffable#getBaseline
+ */
public static Value getBaseline(Value value) {
return value == null ? null : value.getBaseline();
}
@@ -313,7 +396,6 @@
return mInstance.toString();
}
- @Override
public Value getBaseline() {
return InstanceValue.pack(mInstance.getBaseline());
}
diff --git a/tools/ahat/src/main/com/android/ahat/proguard/ProguardMap.java b/tools/ahat/src/main/com/android/ahat/proguard/ProguardMap.java
index 32bb209..79a737c 100644
--- a/tools/ahat/src/main/com/android/ahat/proguard/ProguardMap.java
+++ b/tools/ahat/src/main/com/android/ahat/proguard/ProguardMap.java
@@ -26,7 +26,10 @@
import java.util.HashMap;
import java.util.Map;
-// Class used to deobfuscate classes, fields, and stack frames.
+/**
+ * A representation of a proguard mapping for deobfuscating class names,
+ * field names, and stack frames.
+ */
public class ProguardMap {
private static final String ARRAY_SYMBOL = "[]";
@@ -98,6 +101,10 @@
private Map<String, ClassData> mClassesFromClearName = new HashMap<String, ClassData>();
private Map<String, ClassData> mClassesFromObfuscatedName = new HashMap<String, ClassData>();
+ /**
+ * Information associated with a stack frame that identifies a particular
+ * line of source code.
+ */
public static class Frame {
Frame(String method, String signature, String filename, int line) {
this.method = method;
@@ -106,9 +113,28 @@
this.line = line;
}
+ /**
+ * The name of the method the stack frame belongs to.
+ * For example, "equals".
+ */
public final String method;
+
+ /**
+ * The signature of the method the stack frame belongs to.
+ * For example, "(Ljava/lang/Object;)Z".
+ */
public final String signature;
+
+ /**
+ * The name of the file with containing the line of source that the stack
+ * frame refers to.
+ */
public final String filename;
+
+ /**
+ * The line number of the code in the source file that the stack frame
+ * refers to.
+ */
public final int line;
}
@@ -116,13 +142,44 @@
throw new ParseException(msg, 0);
}
- // Read in proguard mapping information from the given file.
+ /**
+ * Creates a new empty proguard mapping.
+ * The {@link #readFromFile readFromFile} and
+ * {@link #readFromReader readFromReader} methods can be used to populate
+ * the proguard mapping with proguard mapping information.
+ */
+ public ProguardMap() {
+ }
+
+ /**
+ * Adds the proguard mapping information in <code>mapFile</code> to this
+ * proguard mapping.
+ * The <code>mapFile</code> should be a proguard mapping file generated with
+ * the <code>-printmapping</code> option when proguard was run.
+ *
+ * @param mapFile the name of a file with proguard mapping information
+ * @throws FileNotFoundException If the <code>mapFile</code> could not be
+ * found
+ * @throws IOException If an input exception occurred.
+ * @throws ParseException If the <code>mapFile</code> is not a properly
+ * formatted proguard mapping file.
+ */
public void readFromFile(File mapFile)
throws FileNotFoundException, IOException, ParseException {
readFromReader(new FileReader(mapFile));
}
- // Read in proguard mapping information from the given Reader.
+ /**
+ * Adds the proguard mapping information read from <code>mapReader</code> to
+ * this proguard mapping.
+ * <code>mapReader</code> should be a Reader of a proguard mapping file
+ * generated with the <code>-printmapping</code> option when proguard was run.
+ *
+ * @param mapReader a Reader for reading the proguard mapping information
+ * @throws IOException If an input exception occurred.
+ * @throws ParseException If the <code>mapFile</code> is not a properly
+ * formatted proguard mapping file.
+ */
public void readFromReader(Reader mapReader) throws IOException, ParseException {
BufferedReader reader = new BufferedReader(mapReader);
String line = reader.readLine();
@@ -207,8 +264,15 @@
reader.close();
}
- // Returns the deobfuscated version of the given class name. If no
- // deobfuscated version is known, the original string is returned.
+ /**
+ * Returns the deobfuscated version of the given obfuscated class name.
+ * If this proguard mapping does not include information about how to
+ * deobfuscate the obfuscated class name, the obfuscated class name
+ * is returned.
+ *
+ * @param obfuscatedClassName the obfuscated class name to deobfuscate
+ * @return the deobfuscated class name.
+ */
public String getClassName(String obfuscatedClassName) {
// Class names for arrays may have trailing [] that need to be
// stripped before doing the lookup.
@@ -224,9 +288,17 @@
return clearBaseName + arraySuffix;
}
- // Returns the deobfuscated version of the given field name for the given
- // (clear) class name. If no deobfuscated version is known, the original
- // string is returned.
+ /**
+ * Returns the deobfuscated version of the obfuscated field name for the
+ * given deobfuscated class name.
+ * If this proguard mapping does not include information about how to
+ * deobfuscate the obfuscated field name, the obfuscated field name is
+ * returned.
+ *
+ * @param clearClass the deobfuscated name of the class the field belongs to
+ * @param obfuscatedField the obfuscated field name to deobfuscate
+ * @return the deobfuscated field name.
+ */
public String getFieldName(String clearClass, String obfuscatedField) {
ClassData classData = mClassesFromClearName.get(clearClass);
if (classData == null) {
@@ -235,8 +307,21 @@
return classData.getField(obfuscatedField);
}
- // Returns the deobfuscated frame for the given obfuscated frame and (clear)
- // class name. As much of the frame is deobfuscated as can be.
+ /**
+ * Returns the deobfuscated version of the obfuscated stack frame
+ * information for the given deobfuscated class name.
+ * If this proguard mapping does not include information about how to
+ * deobfuscate the obfuscated stack frame information, the obfuscated stack
+ * frame information is returned.
+ *
+ * @param clearClassName the deobfuscated name of the class the stack frame's
+ * method belongs to
+ * @param obfuscatedMethodName the obfuscated method name to deobfuscate
+ * @param obfuscatedSignature the obfuscated method signature to deobfuscate
+ * @param obfuscatedFilename the obfuscated file name to deobfuscate.
+ * @param obfuscatedLine the obfuscated line number to deobfuscate.
+ * @return the deobfuscated stack frame information.
+ */
public Frame getFrame(String clearClassName, String obfuscatedMethodName,
String obfuscatedSignature, String obfuscatedFilename, int obfuscatedLine) {
String clearSignature = getSignature(obfuscatedSignature);