diff options
| author | 2017-11-16 10:23:41 +0000 | |
|---|---|---|
| committer | 2017-12-04 10:22:44 +0000 | |
| commit | b7732a3fcf06a55075a601dbc593b23a6fc71dbf (patch) | |
| tree | bca727e1c8dfe7a4f7b3fb19cf80ffa72f6e69b8 | |
| parent | a602c56ba1a82d70eb40de35e7c716477a46ee28 (diff) | |
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
27 files changed, 1075 insertions, 199 deletions
diff --git a/tools/ahat/Android.mk b/tools/ahat/Android.mk index a9a0492fe9..34e6a9cd42 100644 --- a/tools/ahat/Android.mk +++ b/tools/ahat/Android.mk @@ -23,6 +23,7 @@ include $(CLEAR_VARS) 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 7920adae55..93fe46bf8b 100644 --- a/tools/ahat/etc/ahat_api.txt +++ b/tools/ahat/etc/ahat_api.txt @@ -9,7 +9,6 @@ package com.android.ahat { 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 @@ package com.android.ahat.heapdump { } 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 @@ package com.android.ahat.heapdump { } 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 @@ package com.android.ahat.heapdump { } 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 @@ package com.android.ahat.heapdump { 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 @@ package com.android.ahat.heapdump { 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 @@ package com.android.ahat.heapdump { 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 048573e915..04a6012a61 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.net.InetSocketAddress; 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 @@ public class Main { 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 543eaa376a..5093f0d43e 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 @@ class SiteHandler implements AhatHandler { 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 58b7b59f9a..d3fea4869a 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.List; 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 @@ public class DominatorsComputation { } /** - * 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 ccdd6e4df7..9c80802673 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.AbstractList; 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 @@ public class AhatArrayInstance extends AhatInstance { } /** - * 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 cb9d959508..c82ef20e9b 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.awt.image.BufferedImage; 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 @@ public class AhatClassInstance extends AhatInstance { /** * 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 class AhatClassInstance extends AhatInstance { } - 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 3babf76842..36ada2857c 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.AbstractList; 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 @@ public class AhatClassObj extends AhatInstance { /** * 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 @@ public class AhatClassObj extends AhatInstance { /** * Returns the superclass of this class object. + * + * @return the superclass object */ public AhatClassObj getSuperClassObj() { return mSuperClassObj; @@ -70,14 +82,18 @@ public class AhatClassObj extends AhatInstance { /** * 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 @@ public class AhatClassObj extends AhatInstance { /** * 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 @@ public class AhatClassObj extends AhatInstance { /** * 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 b8897a182c..60c9a0d086 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 @@ public class AhatHeap implements Diffable<AhatHeap> { /** * 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 @@ public class AhatHeap implements Diffable<AhatHeap> { /** * 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 a9f819f710..67253bf0e7 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.Deque; 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, } /** - * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, } /** - * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, } /** - * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, /** * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, /** * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, /** * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, /** * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, /** * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, /** * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, } /** - * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, /** * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, } /** - * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, /** * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, } /** - * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, /** * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, } /** - * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, } /** - * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, } /** - * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, } /** - * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, } /** - * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, } /** - * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, } /** - * 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 @@ public abstract class AhatInstance implements Diffable<AhatInstance>, 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 59ce5d1c6c..535db082c1 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 @@ package com.android.ahat.heapdump; 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 @@ public class AhatSnapshot implements Diffable<AhatSnapshot> { } /** - * 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 @@ public class AhatSnapshot implements Diffable<AhatSnapshot> { } /** - * 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 @@ public class AhatSnapshot implements Diffable<AhatSnapshot> { /** * 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 @@ public class AhatSnapshot implements Diffable<AhatSnapshot> { } /** - * 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 98c7e58d56..b35b4244ae 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.List; 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 @@ public class Diff { } /** - * 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 e3c671fe21..ff07af0028 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.Comparator; 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 @@ public class DiffFields { * 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 53442c857e..09c8ee6d39 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 @@ public interface Diffable<T> { * 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 3cd273ed98..8de337ea8c 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 @@ package com.android.ahat.heapdump; 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 @@ public class DiffedFieldValue { } /** - * 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 dff401796a..6494069dcb 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 20e6da7271..70314da830 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 256a3b46f6..29ac9b0c5a 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 d7b1dd78d6..58bd373294 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.Iterator; 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 @@ public class Parser { } /** - * 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 196a24628c..5ce0b1edfe 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 734f889af6..99d85dc940 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 4978d52830..72c0a4a750 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.HashMap; 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 @@ public class Site implements Diffable<Site> { 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 @@ public class Site implements Diffable<Site> { /** * 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 @@ public class Site implements Diffable<Site> { } /** - * 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 @@ public class Site implements Diffable<Site> { 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 @@ public class Site implements Diffable<Site> { 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 @@ public class Site implements Diffable<Site> { } /** - * 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 @@ public class Site implements Diffable<Site> { /** * 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 7c8db900df..a4593e195b 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 @@ public class Size { } /** - * 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 efe0d6b59b..a629b3ce7f 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 @@ import java.util.List; /** * 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 @@ public class Sort { }; /** - * 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 @@ public class Sort { }; /** - * 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 @@ public class Sort { } /** - * 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 @@ public class Sort { } } + /** + * 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 @@ public class Sort { } /** - * 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 @@ public class Sort { } /** - * 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 @@ public class Sort { } }; + /** + * 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 @@ public class Sort { }; /** - * 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 @@ public class Sort { }; /** - * 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 @@ public class Sort { }; /** - * 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 @@ public class Sort { }; /** - * 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 40249615a2..ff79864505 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 eea427774b..b219bf1564 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 @@ public abstract class Value { 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 @@ public abstract class Value { @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 @@ public abstract class Value { 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 32bb209dc6..79a737cc18 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.text.ParseException; 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 @@ public class ProguardMap { 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 @@ public class ProguardMap { 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 @@ public class ProguardMap { 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 @@ public class ProguardMap { 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 @@ public class ProguardMap { 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 @@ public class ProguardMap { 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); |