summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Richard Uhler <ruhler@google.com> 2016-12-28 15:46:03 +0000
committer Richard Uhler <ruhler@google.com> 2017-02-20 13:33:41 +0000
commitd640e29f9dad93f51e74026327dd53bb5a30eb33 (patch)
tree07aa0fe0cc35955936c06cb6b9ec6885bac239af
parentf629cfdbf6da3409aff177352e9ff41209b4570c (diff)
Show unreachable objects in ahat.
But don't count them against heap size or instance counts. Bug: 33828707 Test: ahat tests, including new InstanceTest.unreachableReferent. Change-Id: Ic39b6d5569159497dcc76c342e22ed99d2a71307
-rw-r--r--tools/ahat/src/Summarizer.java5
-rw-r--r--tools/ahat/src/heapdump/AhatInstance.java9
-rw-r--r--tools/ahat/src/heapdump/AhatSnapshot.java24
-rw-r--r--tools/ahat/src/heapdump/Site.java24
-rw-r--r--tools/ahat/test-dump/Main.java2
-rw-r--r--tools/ahat/test/InstanceTest.java18
6 files changed, 51 insertions, 31 deletions
diff --git a/tools/ahat/src/Summarizer.java b/tools/ahat/src/Summarizer.java
index 7f4dcbf9c4..016eab44f2 100644
--- a/tools/ahat/src/Summarizer.java
+++ b/tools/ahat/src/Summarizer.java
@@ -50,6 +50,11 @@ class Summarizer {
formatted.append(DocString.removed("del "));
}
+ // Annotate unreachable objects as such.
+ if (!inst.isReachable()) {
+ formatted.append("unreachable ");
+ }
+
// Annotate roots as roots.
if (inst.isRoot()) {
formatted.append("root ");
diff --git a/tools/ahat/src/heapdump/AhatInstance.java b/tools/ahat/src/heapdump/AhatInstance.java
index 24956f2712..e6b9c00384 100644
--- a/tools/ahat/src/heapdump/AhatInstance.java
+++ b/tools/ahat/src/heapdump/AhatInstance.java
@@ -31,6 +31,7 @@ public abstract class AhatInstance implements Diffable<AhatInstance> {
private long mSize;
private long mTotalRetainedSize;
private long mRetainedSizes[]; // Retained size indexed by heap index
+ private boolean mIsReachable;
private AhatHeap mHeap;
private AhatInstance mImmediateDominator;
private AhatInstance mNextInstanceToGcRoot;
@@ -64,6 +65,7 @@ public abstract class AhatInstance implements Diffable<AhatInstance> {
mId = inst.getId();
mSize = inst.getSize();
mTotalRetainedSize = inst.getTotalRetainedSize();
+ mIsReachable = inst.isReachable();
List<AhatHeap> heaps = snapshot.getHeaps();
mRetainedSizes = new long[heaps.size()];
@@ -149,6 +151,13 @@ public abstract class AhatInstance implements Diffable<AhatInstance> {
}
/**
+ * Returns whether this object is strongly-reachable.
+ */
+ public boolean isReachable() {
+ return mIsReachable;
+ }
+
+ /**
* Returns the heap that this instance is allocated on.
*/
public AhatHeap getHeap() {
diff --git a/tools/ahat/src/heapdump/AhatSnapshot.java b/tools/ahat/src/heapdump/AhatSnapshot.java
index 6b4953e77e..20b85da763 100644
--- a/tools/ahat/src/heapdump/AhatSnapshot.java
+++ b/tools/ahat/src/heapdump/AhatSnapshot.java
@@ -106,17 +106,15 @@ public class AhatSnapshot implements Diffable<AhatSnapshot> {
TObjectProcedure<Instance> doCreate = new TObjectProcedure<Instance>() {
@Override
public boolean execute(Instance inst) {
- if (inst.isReachable()) {
- long id = inst.getId();
- if (inst instanceof ClassInstance) {
- mInstances.add(new AhatClassInstance(id));
- } else if (inst instanceof ArrayInstance) {
- mInstances.add(new AhatArrayInstance(id));
- } else if (inst instanceof ClassObj) {
- AhatClassObj classObj = new AhatClassObj(id);
- mInstances.add(classObj);
- mClasses.put(((ClassObj)inst).getClassName(), classObj);
- }
+ long id = inst.getId();
+ if (inst instanceof ClassInstance) {
+ mInstances.add(new AhatClassInstance(id));
+ } else if (inst instanceof ArrayInstance) {
+ mInstances.add(new AhatArrayInstance(id));
+ } else if (inst instanceof ClassObj) {
+ AhatClassObj classObj = new AhatClassObj(id);
+ mInstances.add(classObj);
+ mClasses.put(((ClassObj)inst).getClassName(), classObj);
}
return true;
}
@@ -146,7 +144,9 @@ public class AhatSnapshot implements Diffable<AhatSnapshot> {
mRooted.add(ahat);
}
- ahat.getHeap().addToSize(ahat.getSize());
+ if (inst.isReachable()) {
+ ahat.getHeap().addToSize(ahat.getSize());
+ }
// Update sites.
StackFrame[] frames = null;
diff --git a/tools/ahat/src/heapdump/Site.java b/tools/ahat/src/heapdump/Site.java
index a551901a6d..738eaf0687 100644
--- a/tools/ahat/src/heapdump/Site.java
+++ b/tools/ahat/src/heapdump/Site.java
@@ -129,19 +129,21 @@ public class Site implements Diffable<Site> {
while (true) {
site.mObjects.add(inst);
- AhatHeap heap = inst.getHeap();
- if (heap.getIndex() >= site.mSizesByHeap.length) {
- long[] newSizes = new long[heap.getIndex() + 1];
- for (int i = 0; i < site.mSizesByHeap.length; i++) {
- newSizes[i] = site.mSizesByHeap[i];
+ ObjectsInfo info = site.getObjectsInfo(inst.getHeap(), inst.getClassObj());
+ if (inst.isReachable()) {
+ AhatHeap heap = inst.getHeap();
+ if (heap.getIndex() >= site.mSizesByHeap.length) {
+ long[] newSizes = new long[heap.getIndex() + 1];
+ for (int i = 0; i < site.mSizesByHeap.length; i++) {
+ newSizes[i] = site.mSizesByHeap[i];
+ }
+ site.mSizesByHeap = newSizes;
}
- site.mSizesByHeap = newSizes;
- }
- site.mSizesByHeap[heap.getIndex()] += inst.getSize();
+ site.mSizesByHeap[heap.getIndex()] += inst.getSize();
- ObjectsInfo info = site.getObjectsInfo(inst.getHeap(), inst.getClassObj());
- info.numInstances++;
- info.numBytes += inst.getSize();
+ info.numInstances++;
+ info.numBytes += inst.getSize();
+ }
if (depth > 0) {
StackFrame next = frames[depth - 1];
diff --git a/tools/ahat/test-dump/Main.java b/tools/ahat/test-dump/Main.java
index 4a2234cee7..7a05b1cb89 100644
--- a/tools/ahat/test-dump/Main.java
+++ b/tools/ahat/test-dump/Main.java
@@ -18,6 +18,7 @@ import dalvik.system.VMDebug;
import java.io.IOException;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import org.apache.harmony.dalvik.ddmc.DdmVmInternal;
@@ -73,6 +74,7 @@ public class Main {
public PhantomReference aPhantomReference = new PhantomReference(anObject, referenceQueue);
public WeakReference aWeakReference = new WeakReference(anObject, referenceQueue);
public WeakReference aNullReferentReference = new WeakReference(null, referenceQueue);
+ public SoftReference aSoftReference = new SoftReference(new Object());
public byte[] bigArray;
public ObjectTree[] gcPathArray = new ObjectTree[]{null, null,
new ObjectTree(
diff --git a/tools/ahat/test/InstanceTest.java b/tools/ahat/test/InstanceTest.java
index 7173b1127c..3a50150c0e 100644
--- a/tools/ahat/test/InstanceTest.java
+++ b/tools/ahat/test/InstanceTest.java
@@ -223,6 +223,16 @@ public class InstanceTest {
}
@Test
+ public void unreachableReferent() throws IOException {
+ // The test dump program should never be under enough GC pressure for the
+ // soft reference to be cleared. Ensure that ahat will show the soft
+ // reference as having a non-null referent.
+ TestDump dump = TestDump.getTestDump();
+ AhatInstance ref = dump.getDumpedAhatInstance("aSoftReference");
+ assertNotNull(ref.getReferent());
+ }
+
+ @Test
public void gcRootPath() throws IOException {
TestDump dump = TestDump.getTestDump();
@@ -359,14 +369,6 @@ public class InstanceTest {
}
@Test
- public void reverseReferencesAreNotUnreachable() throws IOException {
- TestDump dump = TestDump.getTestDump();
- AhatInstance obj = dump.getDumpedAhatInstance("basicString");
- assertEquals(2, obj.getHardReverseReferences().size());
- assertEquals(0, obj.getSoftReverseReferences().size());
- }
-
- @Test
public void asStringEmbedded() throws IOException {
// Set up a heap dump with an instance of java.lang.String of
// "hello" with instance id 0x42 that is backed by a char array that is