ahat: show sample path through strong references.
Instead of showing a sample path through weak references, which is
much less useful for debugging why the object is retained.
Change-Id: I2b8d8bc9368cdcabd7a369e45278ba9b44a38e40
Bug: 64592321
Test: m ahat-test, with new gcRootPathNotWeak test added.
diff --git a/tools/ahat/src/heapdump/AhatInstance.java b/tools/ahat/src/heapdump/AhatInstance.java
index 8905b76..39a844a 100644
--- a/tools/ahat/src/heapdump/AhatInstance.java
+++ b/tools/ahat/src/heapdump/AhatInstance.java
@@ -396,13 +396,6 @@
return new PathElement(inst.mNextInstanceToGcRoot, inst.mNextInstanceToGcRootField);
}
- void setNextInstanceToGcRoot(AhatInstance inst, String field) {
- if (mNextInstanceToGcRoot == null && !isRoot()) {
- mNextInstanceToGcRoot = inst;
- mNextInstanceToGcRootField = field;
- }
- }
-
/** 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
@@ -456,8 +449,9 @@
while (!bfs.isEmpty()) {
Reference ref = bfs.poll();
- if (ref.ref.mHardReverseReferences == null) {
- // This is the first time we are seeing ref.ref.
+ if (ref.ref.mHardReverseReferences == null && ref.strong) {
+ // This is the first time we are seeing ref.ref through a strong
+ // reference.
ref.ref.mNextInstanceToGcRoot = ref.src;
ref.ref.mNextInstanceToGcRootField = ref.field;
ref.ref.mHardReverseReferences = new ArrayList<AhatInstance>();
diff --git a/tools/ahat/test-dump/Main.java b/tools/ahat/test-dump/Main.java
index 13fd102..14c09af 100644
--- a/tools/ahat/test-dump/Main.java
+++ b/tools/ahat/test-dump/Main.java
@@ -91,6 +91,8 @@
new ObjectTree(null, new ObjectTree(null, null)),
new ObjectTree(null, null)),
null};
+ public Reference aLongStrongPathToSamplePathObject;
+ public WeakReference aShortWeakPathToSamplePathObject;
public Object[] basicStringRef;
public AddedObject addedObject;
public UnchangedObject unchangedObject = new UnchangedObject();
@@ -113,6 +115,11 @@
Main.class.getClassLoader(), 0x12345, 50000);
registry.registerNativeAllocation(anObject, 0xABCDABCD);
+ aLongStrongPathToSamplePathObject = new Reference(new Reference(new Object()));
+ aShortWeakPathToSamplePathObject = new WeakReference(
+ ((Reference)aLongStrongPathToSamplePathObject.referent).referent,
+ referenceQueue);
+
addedObject = baseline ? null : new AddedObject();
removedObject = baseline ? new RemovedObject() : null;
modifiedObject = new ModifiedObject();
diff --git a/tools/ahat/test/InstanceTest.java b/tools/ahat/test/InstanceTest.java
index f0e7f44..e05782c 100644
--- a/tools/ahat/test/InstanceTest.java
+++ b/tools/ahat/test/InstanceTest.java
@@ -285,6 +285,18 @@
}
@Test
+ public void gcRootPathNotWeak() throws IOException {
+ TestDump dump = TestDump.getTestDump();
+
+ AhatInstance strong = dump.getDumpedAhatInstance("aLongStrongPathToSamplePathObject");
+ AhatInstance strong2 = strong.getField("referent").asAhatInstance();
+ AhatInstance object = strong2.getField("referent").asAhatInstance();
+
+ List<PathElement> path = object.getPathFromGcRoot();
+ assertEquals(strong2, path.get(path.size() - 2).instance);
+ }
+
+ @Test
public void retainedSize() throws IOException {
TestDump dump = TestDump.getTestDump();