OSDN Git Service

Annotate References with their referent.
authorRichard Uhler <ruhler@google.com>
Thu, 29 Oct 2015 20:02:42 +0000 (13:02 -0700)
committerRichard Uhler <ruhler@google.com>
Tue, 3 Nov 2015 18:34:20 +0000 (10:34 -0800)
Also, don't include annotations in an object's link. That way we can
distinguish between the object link and any links in the annotations.

Change-Id: I3fef3f5b2c343699f527cad9efa7c93a4b35a3a4

tools/ahat/src/InstanceUtils.java
tools/ahat/src/Value.java
tools/ahat/test-dump/Main.java
tools/ahat/test/InstanceUtilsTest.java

index c2d75c4..7fa53c7 100644 (file)
@@ -244,6 +244,24 @@ class InstanceUtils {
     return null;
   }
 
+  private static boolean isJavaLangRefReference(Instance inst) {
+    ClassObj cls = (inst == null) ? null : inst.getClassObj();
+    while (cls != null) {
+      if ("java.lang.ref.Reference".equals(cls.getClassName())) {
+        return true;
+      }
+      cls = cls.getSuperClassObj();
+    }
+    return false;
+  }
+
+  public static Instance getReferent(Instance inst) {
+    if (isJavaLangRefReference(inst)) {
+      return getRefField(inst, "referent");
+    }
+    return null;
+  }
+
   /**
    * Assuming inst represents a DexCache object, return the dex location for
    * that dex cache. Returns null if the given instance doesn't represent a
index 4eb27b1..7c969b3 100644 (file)
@@ -45,25 +45,36 @@ class Value {
     }
 
     link.append(inst.toString());
+    URI objTarget = DocString.formattedUri("object?id=%d", inst.getId());
+    DocString formatted = DocString.link(objTarget, link);
 
     // Annotate Strings with their values.
     String stringValue = InstanceUtils.asString(inst, kMaxChars);
     if (stringValue != null) {
-      link.appendFormat("\"%s", stringValue);
-      link.append(kMaxChars == stringValue.length() ? "..." : "\"");
+      formatted.appendFormat(" \"%s", stringValue);
+      formatted.append(kMaxChars == stringValue.length() ? "..." : "\"");
+    }
+
+    // Annotate Reference with its referent
+    Instance referent = InstanceUtils.getReferent(inst);
+    if (referent != null) {
+      formatted.append(" for ");
+
+      // It should not be possible for a referent to refer back to the
+      // reference object, even indirectly, so there shouldn't be any issues
+      // with infinite recursion here.
+      formatted.append(renderInstance(referent));
     }
 
     // Annotate DexCache with its location.
     String dexCacheLocation = InstanceUtils.getDexCacheLocation(inst, kMaxChars);
     if (dexCacheLocation != null) {
-      link.appendFormat(" for %s", dexCacheLocation);
+      formatted.appendFormat(" for %s", dexCacheLocation);
       if (kMaxChars == dexCacheLocation.length()) {
-        link.append("...");
+        formatted.append("...");
       }
     }
 
-    URI objTarget = DocString.formattedUri("object?id=%d", inst.getId());
-    DocString formatted = DocString.link(objTarget, link);
 
     // Annotate bitmaps with a thumbnail.
     Instance bitmap = InstanceUtils.getAssociatedBitmapInstance(inst);
index cea1dc1..7b8774a 100644 (file)
@@ -16,6 +16,9 @@
 
 import dalvik.system.VMDebug;
 import java.io.IOException;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
 
 /**
  * Program used to create a heap dump for test purposes.
@@ -33,6 +36,9 @@ public class Main {
     public String basicString = "hello, world";
     public String nullString = null;
     public Object anObject = new Object();
+    public ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
+    public PhantomReference aPhantomReference = new PhantomReference(anObject, referenceQueue);
+    public WeakReference aWeakReference = new WeakReference(anObject, referenceQueue);
   }
 
   public static void main(String[] args) throws IOException {
index 11f82a2..32f48ce 100644 (file)
@@ -73,4 +73,19 @@ public class InstanceUtilsTest {
     assertNotNull(obj);
     assertNull(InstanceUtils.asString(obj));
   }
+
+  @Test
+  public void basicReference() throws IOException {
+    TestDump dump = TestDump.getTestDump();
+
+    Instance pref = (Instance)dump.getDumpedThing("aPhantomReference");
+    Instance wref = (Instance)dump.getDumpedThing("aWeakReference");
+    Instance referent = (Instance)dump.getDumpedThing("anObject");
+    assertNotNull(pref);
+    assertNotNull(wref);
+    assertNotNull(referent);
+    assertEquals(referent, InstanceUtils.getReferent(pref));
+    assertEquals(referent, InstanceUtils.getReferent(wref));
+    assertNull(InstanceUtils.getReferent(referent));
+  }
 }