ahat: support java.lang.ref.Finalizer

Because some implementations use that in contrast to ART's
java.lang.ref.FinalizerReference to track finalizers.

Bug: 111867529
Test: m ahat-test, with new test added.
Change-Id: Id9ae4e32f0e6c852fabbb73c790dbd7d9f28c51f
diff --git a/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassInstance.java b/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassInstance.java
index f377ae3..4c60d8b 100644
--- a/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassInstance.java
+++ b/tools/ahat/src/main/com/android/ahat/heapdump/AhatClassInstance.java
@@ -360,6 +360,7 @@
         case "java.lang.ref.PhantomReference": return Reachability.PHANTOM;
         case "java.lang.ref.WeakReference": return Reachability.WEAK;
         case "java.lang.ref.FinalizerReference": return Reachability.FINALIZER;
+        case "java.lang.ref.Finalizer": return Reachability.FINALIZER;
         case "java.lang.ref.SoftReference": return Reachability.SOFT;
       }
       cls = cls.getSuperClassObj();
diff --git a/tools/ahat/src/ri-test-dump/DumpedStuff.java b/tools/ahat/src/ri-test-dump/DumpedStuff.java
new file mode 100644
index 0000000..3e93ccb
--- /dev/null
+++ b/tools/ahat/src/ri-test-dump/DumpedStuff.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.ref.WeakReference;
+
+/**
+ * References to objects to include in a heap dump for testing purposes.
+ * An instance of DumpedStuff will be included in a heap dump taken for
+ * testing purposes. Instances referenced as fields of DumpedStuff can be
+ * accessed easily from the tests using TestDump.getDumpedAhatInstance.
+ */
+public class DumpedStuff {
+  public static class Finalizable {
+    static int count = 0;
+
+    public Finalizable() {
+      count++;
+    }
+
+    @Override
+    protected void finalize() {
+      count--;
+    }
+  }
+
+  public WeakReference aWeakRefToFinalizable = new WeakReference(new Finalizable());
+}
diff --git a/tools/ahat/src/ri-test-dump/Main.java b/tools/ahat/src/ri-test-dump/Main.java
index 0f5f480..9df53f4 100644
--- a/tools/ahat/src/ri-test-dump/Main.java
+++ b/tools/ahat/src/ri-test-dump/Main.java
@@ -23,6 +23,7 @@
  * Program used to create an RI heap dump for test purposes.
  */
 public class Main {
+  public static DumpedStuff stuff;
 
   public static void main(String[] args) throws IOException {
     if (args.length < 1) {
@@ -31,6 +32,8 @@
     }
     String file = args[0];
 
+    stuff = new DumpedStuff();
+
     // Take a heap dump of this process.
     MBeanServer server = ManagementFactory.getPlatformMBeanServer();
     HotSpotDiagnosticMXBean bean = ManagementFactory.newPlatformMXBeanProxy(server,
diff --git a/tools/ahat/src/test/com/android/ahat/RiTest.java b/tools/ahat/src/test/com/android/ahat/RiTest.java
index 98ab669..5711320 100644
--- a/tools/ahat/src/test/com/android/ahat/RiTest.java
+++ b/tools/ahat/src/test/com/android/ahat/RiTest.java
@@ -16,10 +16,12 @@
 
 package com.android.ahat;
 
+import com.android.ahat.heapdump.AhatInstance;
 import com.android.ahat.heapdump.Reachability;
-
 import java.io.IOException;
 import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 
 public class RiTest {
   @Test
@@ -27,5 +29,17 @@
     // Verify we can load a heap dump generated from the RI.
     TestDump.getTestDump("ri-test-dump.hprof", null, null, Reachability.STRONG);
   }
+
+  @Test
+  public void finalizable() throws IOException {
+    // Verify we can recognize finalizer references in the RI.
+    TestDump dump = TestDump.getTestDump("ri-test-dump.hprof", null, null, Reachability.STRONG);
+    AhatInstance ref = dump.getDumpedAhatInstance("aWeakRefToFinalizable");
+
+    // Hopefully the referent hasn't been cleared yet.
+    AhatInstance referent = ref.getReferent();
+    assertNotNull(referent);
+    assertEquals(Reachability.FINALIZER, referent.getReachability());
+  }
 }