Distinguish between weakly reachable and unreachable instances.
Annotate weakly reachable instances with "weak" instead of
unreachable. Don't show a sample path from GC root for unreachable
instances.
Bug: 64785007
Test: m ahat-test
Test: Manually inspect strong, weak, and unreachable instances.
Change-Id: I1cb73d47198be847eaccd5855f6f14acf828a75a
diff --git a/tools/ahat/src/ObjectHandler.java b/tools/ahat/src/ObjectHandler.java
index 79f8b76..c24f22b 100644
--- a/tools/ahat/src/ObjectHandler.java
+++ b/tools/ahat/src/ObjectHandler.java
@@ -66,7 +66,10 @@
doc.big(Summarizer.summarize(inst));
printAllocationSite(doc, query, inst);
- printGcRootPath(doc, query, inst);
+
+ if (!inst.isUnreachable()) {
+ printGcRootPath(doc, query, inst);
+ }
doc.section("Object Info");
AhatClassObj cls = inst.getClassObj();
diff --git a/tools/ahat/src/Summarizer.java b/tools/ahat/src/Summarizer.java
index 50b2e4b..901d5b2 100644
--- a/tools/ahat/src/Summarizer.java
+++ b/tools/ahat/src/Summarizer.java
@@ -51,7 +51,9 @@
}
// Annotate unreachable objects as such.
- if (!inst.isReachable()) {
+ if (inst.isWeaklyReachable()) {
+ formatted.append("weak ");
+ } else if (inst.isUnreachable()) {
formatted.append("unreachable ");
}
diff --git a/tools/ahat/src/heapdump/AhatInstance.java b/tools/ahat/src/heapdump/AhatInstance.java
index c044487..cb2d738 100644
--- a/tools/ahat/src/heapdump/AhatInstance.java
+++ b/tools/ahat/src/heapdump/AhatInstance.java
@@ -136,13 +136,28 @@
}
/**
- * Returns whether this object is strongly-reachable.
+ * Returns true if this object is strongly-reachable.
*/
- public boolean isReachable() {
+ public boolean isStronglyReachable() {
return mImmediateDominator != null;
}
/**
+ * Returns true if this object is reachable only through a
+ * soft/weak/phantom/finalizer reference.
+ */
+ public boolean isWeaklyReachable() {
+ return !isStronglyReachable() && mNextInstanceToGcRoot != null;
+ }
+
+ /**
+ * Returns true if this object is completely unreachable.
+ */
+ public boolean isUnreachable() {
+ return !isStronglyReachable() && !isWeaklyReachable();
+ }
+
+ /**
* Returns the heap that this instance is allocated on.
*/
public AhatHeap getHeap() {
@@ -499,6 +514,10 @@
} else {
if (ref.ref.mSoftReverseReferences == null) {
ref.ref.mSoftReverseReferences = new ArrayList<AhatInstance>();
+ if (ref.ref.mNextInstanceToGcRoot == null) {
+ ref.ref.mNextInstanceToGcRoot = ref.src;
+ ref.ref.mNextInstanceToGcRootField = ref.field;
+ }
}
ref.ref.mSoftReverseReferences.add(ref.src);
}
diff --git a/tools/ahat/src/heapdump/Site.java b/tools/ahat/src/heapdump/Site.java
index 821493f..523550a 100644
--- a/tools/ahat/src/heapdump/Site.java
+++ b/tools/ahat/src/heapdump/Site.java
@@ -186,7 +186,7 @@
// Add all reachable objects allocated at this site.
for (AhatInstance inst : mObjects) {
- if (inst.isReachable()) {
+ if (inst.isStronglyReachable()) {
AhatHeap heap = inst.getHeap();
Size size = inst.getSize();
ObjectsInfo info = getObjectsInfo(heap, inst.getClassObj());
diff --git a/tools/ahat/test/InstanceTest.java b/tools/ahat/test/InstanceTest.java
index 49a21e2..a4908fd 100644
--- a/tools/ahat/test/InstanceTest.java
+++ b/tools/ahat/test/InstanceTest.java
@@ -214,7 +214,9 @@
// reference as having a non-null referent.
TestDump dump = TestDump.getTestDump();
AhatInstance ref = dump.getDumpedAhatInstance("aSoftReference");
- assertNotNull(ref.getReferent());
+ AhatInstance referent = ref.getReferent();
+ assertNotNull(referent);
+ assertTrue(referent.isWeaklyReachable());
}
@Test