diff options
author | 2016-12-28 15:46:03 +0000 | |
---|---|---|
committer | 2017-02-20 13:33:41 +0000 | |
commit | d640e29f9dad93f51e74026327dd53bb5a30eb33 (patch) | |
tree | 07aa0fe0cc35955936c06cb6b9ec6885bac239af | |
parent | f629cfdbf6da3409aff177352e9ff41209b4570c (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.java | 5 | ||||
-rw-r--r-- | tools/ahat/src/heapdump/AhatInstance.java | 9 | ||||
-rw-r--r-- | tools/ahat/src/heapdump/AhatSnapshot.java | 24 | ||||
-rw-r--r-- | tools/ahat/src/heapdump/Site.java | 24 | ||||
-rw-r--r-- | tools/ahat/test-dump/Main.java | 2 | ||||
-rw-r--r-- | tools/ahat/test/InstanceTest.java | 18 |
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 |