Add reachabilityFence, ReachabilitySensitive

Add the @ReachabilitySensitive annotation itself, and use it
in libcore itself, where needed.

Import OpenJDK9+181's reachabilityFence, so that it can be used in
preference to the annotation where it makes sense. Java 9's
stopgap reachabilityFence implementation doesn't work for us,
so replace it with a different stopgap.

The libcore changes correct many situations in which finalizers
could previously run prematurely according to the JLS. Or they
would correct them if we had a real implementation for
@ReachabilitySensitive.

The ZipFile constructor could close the file before notifying the
CloseGuard that it was open.

Aside from the ZipFile change, there should be no functional
change, yet.

Note that the ExemptionMechanism.java fix is the same as upstream.

Conspicuously missing:

- Any code, e.g. in ART or D8, that actually looks for the annotation.
- Uses in frameworks code, where it's probably most critical.

Bug: 63934467
Bug: 70906684
Bug: 28342794
Test: Build & boot AOSP
Change-Id: I652f0625b39b2ba9ac901d4f63e6aa6cf3b74af5
diff --git a/dalvik/src/main/java/dalvik/annotation/optimization/ReachabilitySensitive.java b/dalvik/src/main/java/dalvik/annotation/optimization/ReachabilitySensitive.java
new file mode 100644
index 0000000..35a6563
--- /dev/null
+++ b/dalvik/src/main/java/dalvik/annotation/optimization/ReachabilitySensitive.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+package dalvik.annotation.optimization;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Applied to non-static fields (instance variables) that act as handles to data that is
+ * explicitly cleaned up in response to the containing object becoming unreachable. Such cleanup
+ * is triggered by the garbage collector, typically by enqueuing a java.lang.ref.Reference, or by
+ * invoking an overridden finalize() method. The annotation is needed only when such explicit
+ * GC-triggered cleanup mechanisms are used.
+ *
+ * Most commonly, the fields f annotated this way will have primitive long type, but actually hold
+ * native pointers, as in: <pre>   {@code
+ *
+ * {@literal @}ReachabilitySensitive
+ * private long nativePtr; // C++ pointer to NativeFoo.
+ * }</pre>
+ *
+ * Less frequently, such fields may also be e.g. Java references to Java objects that in turn
+ * contain such native pointers. Or they may be e.g. Java ints that are used to access Java data
+ * external to the object containing f.
+ *
+ * Specifically, an access inside a (static or instance) method of class C to a non-static
+ * field f of C declared ReachabilitySensitive behaves as though it results in the introduction of
+ * java.lang.ref.Reference.reachabilityFence()s according to the following rules:
+ *
+ * 1) For every local reference variable v declared immediately inside lexical scope s, if s
+ * contains such an access a, such that the field f accessed by a is reachable from v, then
+ * Reference.reachabilityFence(v) will be executed just before either (1) the exit of the scope s,
+ * or (2) just before any assignment to v. For our purposes, “this” is treated as a variable
+ * declared at method scope, as if it were an explicit parameter.
+ *
+ * 2) Define the full-expression containing e to be the largest enclosing expression f containing
+ * e, such that there is no statement both containing e and properly contained in f.  If the
+ * full-expression containing the allocation of the object containing the field f is the same
+ * full-expression as the full-expression containing the access a, then
+ * Reference.reachabilityFence(p), where p is a reference to the object containing f, is executed
+ * at the end of the full expression.
+ *
+ * Some tools may implement these semantics by simply refusing to eliminate any dead references
+ * in a method accessing an @ReachabilitySensitive field of the same class.
+ *
+ * If the annotation is applied to an instance method, calls to that method are treated
+ * as accesses to a ReachabilitySensitive field of that object. Classes will normally
+ * not provide getter methods for ReachabilitySensitive fields, since that introduces a
+ * subtle dependency between the useful lifetime of the return value and the reachability
+ * of the original object. However if this cannot be avoided, such a getter method should
+ * be annotated as @ReachabilitySensitive.
+ *
+ * The annotation directly affects only methods of the containing class. There are situations in
+ * which accesses from another class (or calls from another class to an annotated method) are
+ * unavoidable. Normally all such accesses should be accompanied by corresponding
+ * reachabilityFence() calls. The @ReachabilitySensitive annotation allows tools to check that
+ * this is done.
+ *
+ * Note that the annotation also does not affect subclass methods. That is commonly OK. For
+ * example, native pointers should normally be declared private, and thus will only be accessed
+ * by methods of the same class. If an access from a subclass is unavoidable, again the
+ * annotation may allow tools to check for the required reachabilityFences.
+ *
+ * @hide
+ */
+@Retention(RetentionPolicy.RUNTIME)  // Let the GC or interpreter ask, if they need to.
+                                     // TODO: Reconsider later. b/72332040 .
+@Target({ElementType.FIELD, ElementType.METHOD})
+public @interface ReachabilitySensitive {}
diff --git a/dalvik/src/main/java/dalvik/system/CloseGuard.java b/dalvik/src/main/java/dalvik/system/CloseGuard.java
index e718ee7..ba844cf 100644
--- a/dalvik/src/main/java/dalvik/system/CloseGuard.java
+++ b/dalvik/src/main/java/dalvik/system/CloseGuard.java
@@ -24,6 +24,7 @@
  * A simple example: <pre>   {@code
  *   class Foo {
  *
+ *       {@literal @}ReachabilitySensitive
  *       private final CloseGuard guard = CloseGuard.get();
  *
  *       ...
@@ -52,11 +53,12 @@
  *   }
  * }</pre>
  *
- * In usage where the resource to be explicitly cleaned up are
+ * In usage where the resource to be explicitly cleaned up is
  * allocated after object construction, CloseGuard protection can
  * be deferred. For example: <pre>   {@code
  *   class Bar {
  *
+ *       {@literal @}ReachabilitySensitive
  *       private final CloseGuard guard = CloseGuard.get();
  *
  *       ...
@@ -89,13 +91,21 @@
  *   }
  * }</pre>
  *
- * When used in a constructor calls to {@code open} should occur at
+ * When used in a constructor, calls to {@code open} should occur at
  * the end of the constructor since an exception that would cause
  * abrupt termination of the constructor will mean that the user will
  * not have a reference to the object to cleanup explicitly. When used
  * in a method, the call to {@code open} should occur just after
  * resource acquisition.
  *
+ * The @ReachabilitySensitive annotation ensures that finalize() cannot be
+ * called during the explicit call to cleanup(), prior to the guard.close call.
+ * There is an extremely small chance that, for code that neglects to call
+ * cleanup(), finalize() and thus cleanup() will be called while a method on
+ * the object is still active, but the "this" reference is no longer required.
+ * If missing cleanup() calls are expected, additional @ReachabilitySensitive
+ * annotations or reachabilityFence() calls may be required.
+ *
  * @hide
  */
 public final class CloseGuard {
diff --git a/dalvik/src/main/java/dalvik/system/DexFile.java b/dalvik/src/main/java/dalvik/system/DexFile.java
index d54a08e..3a7773d 100644
--- a/dalvik/src/main/java/dalvik/system/DexFile.java
+++ b/dalvik/src/main/java/dalvik/system/DexFile.java
@@ -18,6 +18,7 @@
 
 import android.system.ErrnoException;
 import android.system.StructStat;
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -44,7 +45,9 @@
    * If close is called, mCookie becomes null but the internal cookie is preserved if the close
    * failed so that we can free resources in the finalizer.
    */
+    @ReachabilitySensitive
     private Object mCookie;
+
     private Object mInternalCookie;
     private final String mFileName;
 
diff --git a/luni/src/main/java/java/math/BigInt.java b/luni/src/main/java/java/math/BigInt.java
index 5e28a73..9faac81 100644
--- a/luni/src/main/java/java/math/BigInt.java
+++ b/luni/src/main/java/java/math/BigInt.java
@@ -16,6 +16,7 @@
 
 package java.math;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import libcore.util.NativeAllocationRegistry;
 
 /*
@@ -29,15 +30,16 @@
             BigInt.class.getClassLoader(), NativeBN.getNativeFinalizer(), NativeBN.size());
 
     /* Fields used for the internal representation. */
-    transient long bignum = 0;
+    @ReachabilitySensitive
+    private transient long bignum = 0;
 
     @Override
     public String toString() {
         return this.decString();
     }
 
-    long getNativeBIGNUM() {
-        return this.bignum;
+    boolean hasNativeBignum() {
+        return this.bignum != 0;
     }
 
     private void makeValid() {
diff --git a/luni/src/main/java/java/math/BigInteger.java b/luni/src/main/java/java/math/BigInteger.java
index b911901..1353344 100644
--- a/luni/src/main/java/java/math/BigInteger.java
+++ b/luni/src/main/java/java/math/BigInteger.java
@@ -92,7 +92,7 @@
     private transient int hashCode = 0;
 
     BigInteger(BigInt bigInt) {
-        if (bigInt == null || bigInt.getNativeBIGNUM() == 0) {
+        if (bigInt == null || !bigInt.hasNativeBignum()) {
             throw new AssertionError();
         }
         setBigInt(bigInt);
diff --git a/luni/src/main/java/java/nio/charset/CharsetDecoderICU.java b/luni/src/main/java/java/nio/charset/CharsetDecoderICU.java
index fca2900..f695694 100644
--- a/luni/src/main/java/java/nio/charset/CharsetDecoderICU.java
+++ b/luni/src/main/java/java/nio/charset/CharsetDecoderICU.java
@@ -14,6 +14,7 @@
   */
 package java.nio.charset;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import libcore.icu.ICU;
@@ -33,7 +34,8 @@
      */
     private final int[] data = new int[3];
 
-    /* handle to the ICU converter that is opened */
+    /* Handle to the ICU converter that is opened, cleaned up via NativeAllocationRegistry. */
+    @ReachabilitySensitive
     private long converterHandle = 0;
 
     private byte[] input = null;
@@ -75,7 +77,7 @@
 
     @Override protected void implReplaceWith(String newReplacement) {
         updateCallback();
-     }
+    }
 
     @Override protected final void implOnMalformedInput(CodingErrorAction newAction) {
         updateCallback();
diff --git a/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java b/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java
index a347db8c0..c57aafd 100644
--- a/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java
+++ b/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java
@@ -14,6 +14,7 @@
  */
 package java.nio.charset;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.util.HashMap;
@@ -21,7 +22,6 @@
 import libcore.icu.ICU;
 import libcore.icu.NativeConverter;
 import libcore.util.EmptyArray;
-import libcore.util.NativeAllocationRegistry;
 
 final class CharsetEncoderICU extends CharsetEncoder {
     private static final Map<String, byte[]> DEFAULT_REPLACEMENTS = new HashMap<String, byte[]>();
@@ -50,6 +50,7 @@
     private int[] data = new int[3];
 
     /* handle to the ICU converter that is opened */
+    @ReachabilitySensitive
     private final long converterHandle;
 
     private char[] input = null;
diff --git a/luni/src/main/java/libcore/util/ZoneInfoDB.java b/luni/src/main/java/libcore/util/ZoneInfoDB.java
index 3132c13..9e58070 100644
--- a/luni/src/main/java/libcore/util/ZoneInfoDB.java
+++ b/luni/src/main/java/libcore/util/ZoneInfoDB.java
@@ -17,6 +17,7 @@
 package libcore.util;
 
 import android.system.ErrnoException;
+import dalvik.annotation.optimization.ReachabilitySensitive;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -70,6 +71,8 @@
      * nice property that even if someone replaces the file under us (because multiple gservices
      * updates have gone out, say), we still get a consistent (if outdated) view of the world.
      */
+    // Android-added: @ReachabilitySensitive
+    @ReachabilitySensitive
     private MemoryMappedFile mappedFile;
 
     private String version;
diff --git a/luni/src/main/java/org/apache/harmony/xml/ExpatParser.java b/luni/src/main/java/org/apache/harmony/xml/ExpatParser.java
index fa6308e..4e3cedc 100644
--- a/luni/src/main/java/org/apache/harmony/xml/ExpatParser.java
+++ b/luni/src/main/java/org/apache/harmony/xml/ExpatParser.java
@@ -16,6 +16,7 @@
 
 package org.apache.harmony.xml;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.Reader;
@@ -44,6 +45,9 @@
     private static final int BUFFER_SIZE = 8096; // in bytes
 
     /** Pointer to XML_Parser instance. */
+    // A few native methods taking the pointer value are static; @ReachabilitySensitive is
+    // necessary to ensure the Java object is kept reachable sufficiently long in these cases.
+    @ReachabilitySensitive
     private long pointer;
 
     private boolean inStartElement = false;
@@ -618,6 +622,9 @@
      * Used for cloned attributes.
      */
     private static class ClonedAttributes extends ExpatAttributes {
+    // TODO: Can we please remove this? It appears unused, and the finalizer
+    // asynchronously invalidates the result returned by getPointer() at a
+    // largely unpredictable time. b/70989581
 
         private static final Attributes EMPTY = new ClonedAttributes(0, 0, 0);
 
diff --git a/non_openjdk_java_files.bp b/non_openjdk_java_files.bp
index 449e4d0..0bc2221 100644
--- a/non_openjdk_java_files.bp
+++ b/non_openjdk_java_files.bp
@@ -40,6 +40,7 @@
         "dalvik/src/main/java/dalvik/annotation/Throws.java",
         "dalvik/src/main/java/dalvik/annotation/optimization/CriticalNative.java",
         "dalvik/src/main/java/dalvik/annotation/optimization/FastNative.java",
+        "dalvik/src/main/java/dalvik/annotation/optimization/ReachabilitySensitive.java",
         "dalvik/src/main/java/dalvik/bytecode/OpcodeInfo.java",
         "dalvik/src/main/java/dalvik/bytecode/Opcodes.java",
         "libart/src/main/java/dalvik/system/AnnotatedStackTraceElement.java",
diff --git a/ojluni/src/main/java/java/io/FileInputStream.java b/ojluni/src/main/java/java/io/FileInputStream.java
index b44bc5a..db7ba65 100755
--- a/ojluni/src/main/java/java/io/FileInputStream.java
+++ b/ojluni/src/main/java/java/io/FileInputStream.java
@@ -28,6 +28,7 @@
 
 import java.nio.channels.FileChannel;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import dalvik.system.BlockGuard;
 import dalvik.system.CloseGuard;
 import sun.nio.ch.FileChannelImpl;
@@ -55,6 +56,8 @@
 class FileInputStream extends InputStream
 {
     /* File Descriptor - handle to the open file */
+    // Android-added: @ReachabilitySensitive
+    @ReachabilitySensitive
     private final FileDescriptor fd;
 
     /**
@@ -72,6 +75,7 @@
     private final boolean isFdOwner;
 
     // Android-added: CloseGuard support.
+    @ReachabilitySensitive
     private final CloseGuard guard = CloseGuard.get();
 
     // Android-added: Tracking of unbuffered I/O.
diff --git a/ojluni/src/main/java/java/io/FileOutputStream.java b/ojluni/src/main/java/java/io/FileOutputStream.java
index 79e7690..f29a741 100755
--- a/ojluni/src/main/java/java/io/FileOutputStream.java
+++ b/ojluni/src/main/java/java/io/FileOutputStream.java
@@ -28,6 +28,7 @@
 
 import java.nio.channels.FileChannel;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import dalvik.system.BlockGuard;
 import dalvik.system.CloseGuard;
 import sun.nio.ch.FileChannelImpl;
@@ -60,6 +61,8 @@
     /**
      * The system dependent file descriptor.
      */
+    // Android-added: @ReachabilitySensitive
+    @ReachabilitySensitive
     private final FileDescriptor fd;
 
     /**
@@ -82,6 +85,7 @@
     private volatile boolean closed = false;
 
     // Android-added: CloseGuard support: Log if the stream is not closed.
+    @ReachabilitySensitive
     private final CloseGuard guard = CloseGuard.get();
 
     // Android-added: Field for tracking whether the stream owns the underlying FileDescriptor.
@@ -422,6 +426,8 @@
      * @exception  IOException  if an I/O error occurs.
      * @see        java.io.FileDescriptor
      */
+     // Android-added: @ReachabilitySensitive
+     @ReachabilitySensitive
      public final FileDescriptor getFD()  throws IOException {
         if (fd != null) {
             return fd;
diff --git a/ojluni/src/main/java/java/io/RandomAccessFile.java b/ojluni/src/main/java/java/io/RandomAccessFile.java
index 985f8ed..a83829f 100755
--- a/ojluni/src/main/java/java/io/RandomAccessFile.java
+++ b/ojluni/src/main/java/java/io/RandomAccessFile.java
@@ -26,6 +26,7 @@
 
 package java.io;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import java.nio.channels.FileChannel;
 import sun.nio.ch.FileChannelImpl;
 import android.system.Os;
@@ -67,6 +68,7 @@
 public class RandomAccessFile implements DataOutput, DataInput, Closeable {
 
     // BEGIN Android-added: CloseGuard and some helper fields for Android changes in this file.
+    @ReachabilitySensitive
     private final CloseGuard guard = CloseGuard.get();
     private final byte[] scratch = new byte[8];
 
@@ -78,6 +80,8 @@
     private int mode;
     // END Android-added: CloseGuard and some helper fields for Android changes in this file.
 
+    // Android-added: @ReachabilitySensitive
+    @ReachabilitySensitive
     private FileDescriptor fd;
     private FileChannel channel = null;
     private boolean rw;
diff --git a/ojluni/src/main/java/java/lang/ref/Reference.java b/ojluni/src/main/java/java/lang/ref/Reference.java
index d628fab..06b517e 100644
--- a/ojluni/src/main/java/java/lang/ref/Reference.java
+++ b/ojluni/src/main/java/java/lang/ref/Reference.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,8 @@
  * @author   Mark Reinhold
  * @since    1.2
  */
+// Android-changed: Major parts of the code below were changed to accomodate a
+// different GC and compiler. ClassLinker knows about the fields of this class.
 
 public abstract class Reference<T> {
     /**
@@ -56,7 +58,10 @@
      */
     private static boolean slowPathEnabled = false;
 
-    volatile T referent;         /* Treated specially by GC */
+    // Treated specially by GC. ART's ClassLinker::LinkFields() knows this is the
+    // alphabetically last non-static field.
+    volatile T referent;
+
     final ReferenceQueue<? super T> queue;
 
     /*
@@ -162,4 +167,139 @@
         this.referent = referent;
         this.queue = queue;
     }
+
+    // BEGIN Android-added: reachabilityFence() documentation from upstream OpenJDK9+181
+    /**
+     * Ensures that the object referenced by the given reference remains
+     * <a href="package-summary.html#reachability"><em>strongly reachable</em></a>,
+     * regardless of any prior actions of the program that might otherwise cause
+     * the object to become unreachable; thus, the referenced object is not
+     * reclaimable by garbage collection at least until after the invocation of
+     * this method.  Invocation of this method does not itself initiate garbage
+     * collection or finalization.
+     *
+     * <p> This method establishes an ordering for
+     * <a href="package-summary.html#reachability"><em>strong reachability</em></a>
+     * with respect to garbage collection.  It controls relations that are
+     * otherwise only implicit in a program -- the reachability conditions
+     * triggering garbage collection.  This method is designed for use in
+     * uncommon situations of premature finalization where using
+     * {@code synchronized} blocks or methods, or using other synchronization
+     * facilities are not possible or do not provide the desired control.  This
+     * method is applicable only when reclamation may have visible effects,
+     * which is possible for objects with finalizers (See
+     * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.6">
+     * Section 12.6 17 of <cite>The Java&trade; Language Specification</cite></a>)
+     * that are implemented in ways that rely on ordering control for correctness.
+     *
+     * @apiNote
+     * Finalization may occur whenever the virtual machine detects that no
+     * reference to an object will ever be stored in the heap: The garbage
+     * collector may reclaim an object even if the fields of that object are
+     * still in use, so long as the object has otherwise become unreachable.
+     * This may have surprising and undesirable effects in cases such as the
+     * following example in which the bookkeeping associated with a class is
+     * managed through array indices.  Here, method {@code action} uses a
+     * {@code reachabilityFence} to ensure that the {@code Resource} object is
+     * not reclaimed before bookkeeping on an associated
+     * {@code ExternalResource} has been performed; in particular here, to
+     * ensure that the array slot holding the {@code ExternalResource} is not
+     * nulled out in method {@link Object#finalize}, which may otherwise run
+     * concurrently.
+     *
+     * <pre> {@code
+     * class Resource {
+     *   private static ExternalResource[] externalResourceArray = ...
+     *
+     *   int myIndex;
+     *   Resource(...) {
+     *     myIndex = ...
+     *     externalResourceArray[myIndex] = ...;
+     *     ...
+     *   }
+     *   protected void finalize() {
+     *     externalResourceArray[myIndex] = null;
+     *     ...
+     *   }
+     *   public void action() {
+     *     try {
+     *       // ...
+     *       int i = myIndex;
+     *       Resource.update(externalResourceArray[i]);
+     *     } finally {
+     *       Reference.reachabilityFence(this);
+     *     }
+     *   }
+     *   private static void update(ExternalResource ext) {
+     *     ext.status = ...;
+     *   }
+     * }}</pre>
+     *
+     * Here, the invocation of {@code reachabilityFence} is nonintuitively
+     * placed <em>after</em> the call to {@code update}, to ensure that the
+     * array slot is not nulled out by {@link Object#finalize} before the
+     * update, even if the call to {@code action} was the last use of this
+     * object.  This might be the case if, for example a usage in a user program
+     * had the form {@code new Resource().action();} which retains no other
+     * reference to this {@code Resource}.  While probably overkill here,
+     * {@code reachabilityFence} is placed in a {@code finally} block to ensure
+     * that it is invoked across all paths in the method.  In a method with more
+     * complex control paths, you might need further precautions to ensure that
+     * {@code reachabilityFence} is encountered along all of them.
+     *
+     * <p> It is sometimes possible to better encapsulate use of
+     * {@code reachabilityFence}.  Continuing the above example, if it were
+     * acceptable for the call to method {@code update} to proceed even if the
+     * finalizer had already executed (nulling out slot), then you could
+     * localize use of {@code reachabilityFence}:
+     *
+     * <pre> {@code
+     * public void action2() {
+     *   // ...
+     *   Resource.update(getExternalResource());
+     * }
+     * private ExternalResource getExternalResource() {
+     *   ExternalResource ext = externalResourceArray[myIndex];
+     *   Reference.reachabilityFence(this);
+     *   return ext;
+     * }}</pre>
+     *
+     * <p> Method {@code reachabilityFence} is not required in constructions
+     * that themselves ensure reachability.  For example, because objects that
+     * are locked cannot, in general, be reclaimed, it would suffice if all
+     * accesses of the object, in all methods of class {@code Resource}
+     * (including {@code finalize}) were enclosed in {@code synchronized (this)}
+     * blocks.  (Further, such blocks must not include infinite loops, or
+     * themselves be unreachable, which fall into the corner case exceptions to
+     * the "in general" disclaimer.)  However, method {@code reachabilityFence}
+     * remains a better option in cases where this approach is not as efficient,
+     * desirable, or possible; for example because it would encounter deadlock.
+     *
+     * @param ref the reference. If {@code null}, this method has no effect.
+     * @since 9
+     */
+    // END Android-added: reachabilityFence() documentation from upstream OpenJDK9+181
+
+    // Android-changed: reachabilityFence implementation differs from OpenJDK9.
+    public static void reachabilityFence(Object ref) {
+        SinkHolder.sink = ref;
+        // TODO: This is a horrible implementation. Fix it. Remove SinkHolder.
+        // b/72698200 .
+    }
+
+    private static class SinkHolder {
+        static volatile Object sink;
+
+        // Ensure that sink looks live to even a reasonably clever compiler.
+        private static int finalize_count = 0;
+
+        private static Object sinkUser = new Object() {
+            protected void finalize() {
+                if (sink == null && finalize_count > 0) {
+                    throw new AssertionError("Can't get here");
+                }
+                finalize_count++;
+            }
+        };
+    }
 }
diff --git a/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java b/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java
index e5b0301..a36dae4 100644
--- a/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java
+++ b/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java
@@ -31,6 +31,7 @@
 import java.io.OutputStream;
 import java.io.FileDescriptor;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import dalvik.system.BlockGuard;
 import dalvik.system.CloseGuard;
 import dalvik.system.SocketTagger;
@@ -62,6 +63,10 @@
     protected int fdUseCount = 0;
 
     /* lock when increment/decrementing fdUseCount */
+    // Android-added: @ReachabilitySensitive
+    // Marked mostly because it's used where fd is, and fd isn't declared here.
+    // This adds reachabilityFences where we would if fd were annotated.
+    @ReachabilitySensitive
     protected final Object fdLock = new Object();
 
     /* indicates a close is pending on the file descriptor */
@@ -96,6 +101,7 @@
     // END Android-removed: Android doesn't need to load native net library
 
     // Android-added: logs a warning if socket is not closed
+    @ReachabilitySensitive
     private final CloseGuard guard = CloseGuard.get();
 
     /**
diff --git a/ojluni/src/main/java/java/util/Timer.java b/ojluni/src/main/java/java/util/Timer.java
index df18d79..487db0d 100644
--- a/ojluni/src/main/java/java/util/Timer.java
+++ b/ojluni/src/main/java/java/util/Timer.java
@@ -24,6 +24,7 @@
  */
 
 package java.util;
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import java.util.Date;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -93,11 +94,17 @@
      * and the timer thread consumes, executing timer tasks as appropriate,
      * and removing them from the queue when they're obsolete.
      */
+    // Android-added: @ReachabilitySensitive
+    // Otherwise the finalizer may cancel the Timer in the middle of a
+    // sched() call.
+    @ReachabilitySensitive
     private final TaskQueue queue = new TaskQueue();
 
     /**
      * The timer thread.
      */
+    // Android-added: @ReachabilitySensitive
+    @ReachabilitySensitive
     private final TimerThread thread = new TimerThread(queue);
 
     /**
diff --git a/ojluni/src/main/java/java/util/concurrent/Executors.java b/ojluni/src/main/java/java/util/concurrent/Executors.java
index bf2b8e8..9244136 100644
--- a/ojluni/src/main/java/java/util/concurrent/Executors.java
+++ b/ojluni/src/main/java/java/util/concurrent/Executors.java
@@ -35,6 +35,7 @@
 
 package java.util.concurrent;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import java.security.AccessControlContext;
 import java.security.AccessControlException;
 import java.security.AccessController;
@@ -615,6 +616,9 @@
      */
     private static class DelegatedExecutorService
             extends AbstractExecutorService {
+        // Android-added: @ReachabilitySensitive
+        // Needed for FinalizableDelegatedExecutorService below.
+        @ReachabilitySensitive
         private final ExecutorService e;
         DelegatedExecutorService(ExecutorService executor) { e = executor; }
         public void execute(Runnable command) { e.execute(command); }
diff --git a/ojluni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java b/ojluni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
index 2f87c41..b7d2246 100644
--- a/ojluni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
+++ b/ojluni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
@@ -35,6 +35,7 @@
 
 package java.util.concurrent;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import java.util.ArrayList;
 import java.util.ConcurrentModificationException;
 import java.util.HashSet;
@@ -393,6 +394,8 @@
      * that workerCount is 0 (which sometimes entails a recheck -- see
      * below).
      */
+    // Android-added: @ReachabilitySensitive
+    @ReachabilitySensitive
     private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
     private static final int COUNT_BITS = Integer.SIZE - 3;
     private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
@@ -481,6 +484,8 @@
      * Set containing all worker threads in pool. Accessed only when
      * holding mainLock.
      */
+    // Android-added: @ReachabilitySensitive
+    @ReachabilitySensitive
     private final HashSet<Worker> workers = new HashSet<>();
 
     /**
diff --git a/ojluni/src/main/java/java/util/regex/Matcher.java b/ojluni/src/main/java/java/util/regex/Matcher.java
index 156b8bd..a665011 100644
--- a/ojluni/src/main/java/java/util/regex/Matcher.java
+++ b/ojluni/src/main/java/java/util/regex/Matcher.java
@@ -26,6 +26,7 @@
 
 package java.util.regex;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import libcore.util.NativeAllocationRegistry;
 
 /**
@@ -107,12 +108,17 @@
     /**
      * The Pattern object that created this Matcher.
      */
+    // Patterns also contain cleanup code and a ReachabilitySensitive field.
+    // This ensures that "this" and pattern remain reachable while we're using pattern.address
+    // directly.
+    @ReachabilitySensitive
     private Pattern pattern;
 
     /**
      * The address of the native peer.
      * Uses of this must be manually synchronized to avoid native crashes.
      */
+    @ReachabilitySensitive
     private long address;
 
     /**
diff --git a/ojluni/src/main/java/java/util/regex/Pattern.java b/ojluni/src/main/java/java/util/regex/Pattern.java
index 5da11c8..3049ecd 100644
--- a/ojluni/src/main/java/java/util/regex/Pattern.java
+++ b/ojluni/src/main/java/java/util/regex/Pattern.java
@@ -26,6 +26,7 @@
 
 package java.util.regex;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import libcore.util.NativeAllocationRegistry;
 
 import java.util.Iterator;
@@ -927,6 +928,7 @@
      */
     private final int flags;
 
+    @ReachabilitySensitive
     transient long address;
 
     private static final NativeAllocationRegistry registry = new NativeAllocationRegistry(
diff --git a/ojluni/src/main/java/java/util/zip/Deflater.java b/ojluni/src/main/java/java/util/zip/Deflater.java
index ca9fc14..578bd56 100644
--- a/ojluni/src/main/java/java/util/zip/Deflater.java
+++ b/ojluni/src/main/java/java/util/zip/Deflater.java
@@ -25,6 +25,7 @@
 
 package java.util.zip;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import dalvik.system.CloseGuard;
 
 /**
@@ -75,6 +76,12 @@
 public
 class Deflater {
 
+    // Android-added: @ReachabilitySensitive
+    // Finalization clears zsRef, and thus can't be allowed to occur early.
+    // Unlike some other CloseGuard uses, the spec allows clients to rely on finalization
+    // here.  Thus dropping a deflater without calling close() should work correctly.
+    // It thus does not suffice to just rely on the CloseGuard annotation.
+    @ReachabilitySensitive
     private final ZStreamRef zsRef;
     private byte[] buf = new byte[0];
     private int off, len;
@@ -85,6 +92,7 @@
     private long bytesWritten;
 
     // Android-changed: added close guard
+    @ReachabilitySensitive
     private final CloseGuard guard = CloseGuard.get();
 
     /**
diff --git a/ojluni/src/main/java/java/util/zip/Inflater.java b/ojluni/src/main/java/java/util/zip/Inflater.java
index 245d0d9..8a1ba6f 100644
--- a/ojluni/src/main/java/java/util/zip/Inflater.java
+++ b/ojluni/src/main/java/java/util/zip/Inflater.java
@@ -26,6 +26,7 @@
 
 package java.util.zip;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import dalvik.system.CloseGuard;
 
 /**
@@ -76,6 +77,12 @@
 public
 class Inflater {
 
+    // Android-added: @ReachabilitySensitive
+    // Finalization clears zsRef, and thus can't be allowed to occur early.
+    // Unlike some other CloseGuard uses, the spec allows clients to rely on finalization
+    // here.  Thus dropping a deflater without calling close() should work correctly.
+    // It thus does not suffice to just rely on the CloseGuard annotation.
+    @ReachabilitySensitive
     private final ZStreamRef zsRef;
     private byte[] buf = defaultBuf;
     private int off, len;
@@ -85,6 +92,7 @@
     private long bytesWritten;
 
     // Android-changed: added CloseGuard instance
+    @ReachabilitySensitive
     private final CloseGuard guard = CloseGuard.get();
 
     private static final byte[] defaultBuf = new byte[0];
diff --git a/ojluni/src/main/java/java/util/zip/ZipFile.java b/ojluni/src/main/java/java/util/zip/ZipFile.java
index 797f2c6..bc2e6cf 100644
--- a/ojluni/src/main/java/java/util/zip/ZipFile.java
+++ b/ojluni/src/main/java/java/util/zip/ZipFile.java
@@ -68,6 +68,9 @@
     private final boolean locsig;  // if zip file starts with LOCSIG (usually true)
     private volatile boolean closeRequested = false;
 
+    // Android-added: CloseGuard support
+    // Not declared @ReachabilitySensitive, since all relevant methods, including finalize()
+    // synchronize on this, preventing premature finalization.
     private final CloseGuard guard = CloseGuard.get();
 
     // Android-changed, needed for alternative OPEN_DELETE implementation
@@ -241,13 +244,14 @@
         this.locsig = startsWithLOC(jzfile);
         Enumeration<? extends ZipEntry> entries = entries();
 
+        guard.open("close");
+
         // Android-changed: Error out early if the zipfile has no entries.
         if (size() == 0 || !entries.hasMoreElements()) {
             close();
             throw new ZipException("No entries");
         }
 
-        guard.open("close");
     }
 
     /**
@@ -694,11 +698,14 @@
      * @see    java.util.zip.ZipFile#close()
      */
     protected void finalize() throws IOException {
+        // Android-note: finalize() won't be invoked while important instance methods are running.
+        // Both those methods and this method synchronize on "this", ensuring reachability
+        // until the monitor is released.
         if (guard != null) {
             guard.warnIfOpen();
         }
 
-        close();
+        close();  // Synchronizes on "this".
     }
 
     private static native void close(long jzfile);
diff --git a/ojluni/src/main/java/javax/crypto/ExemptionMechanism.java b/ojluni/src/main/java/javax/crypto/ExemptionMechanism.java
index 889d81b..6cc37e4 100644
--- a/ojluni/src/main/java/javax/crypto/ExemptionMechanism.java
+++ b/ojluni/src/main/java/javax/crypto/ExemptionMechanism.java
@@ -475,12 +475,12 @@
         return n;
     }
 
-    /**
-     * Ensures that the key stored away by this ExemptionMechanism
-     * object will be wiped out when there are no more references to it.
-     */
+    // Android-removed: Unnecessary finalize() method.
+    // OpenJDK 9 also removed the method.
+    /*
     protected void finalize() {
         keyStored = null;
         // Are there anything else we could do?
     }
+    */
 }
diff --git a/ojluni/src/main/java/sun/net/www/MeteredStream.java b/ojluni/src/main/java/sun/net/www/MeteredStream.java
index 26fe85d..c50c457 100644
--- a/ojluni/src/main/java/sun/net/www/MeteredStream.java
+++ b/ojluni/src/main/java/sun/net/www/MeteredStream.java
@@ -157,7 +157,10 @@
         return n;
     }
 
-    public void close() throws IOException {
+    // Android-changed: Added synchronize to prevent concurrent finalization.
+    // Since other relevant methods also synchronize on the same object, this prevents
+    // finalization while those methods are running.
+    public synchronized void close() throws IOException {
         if (closed) {
             return;
         }
diff --git a/ojluni/src/main/java/sun/net/www/protocol/jar/URLJarFile.java b/ojluni/src/main/java/sun/net/www/protocol/jar/URLJarFile.java
index 410ba0a..18cdff7 100644
--- a/ojluni/src/main/java/sun/net/www/protocol/jar/URLJarFile.java
+++ b/ojluni/src/main/java/sun/net/www/protocol/jar/URLJarFile.java
@@ -112,6 +112,8 @@
     /*
      * close the jar file.
      */
+    // Android-note: All important methods here and in superclasses should synchronize on this
+    // to avoid premature finalization. The actual close implementation in ZipFile does.
     protected void finalize() throws IOException {
         close();
     }
diff --git a/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java
index 1a8e56b..0338f01 100644
--- a/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java
@@ -53,6 +53,7 @@
 import java.util.HashSet;
 import java.util.Set;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import dalvik.system.BlockGuard;
 import dalvik.system.CloseGuard;
 import sun.net.ExtendedOptionsImpl;
@@ -72,6 +73,8 @@
 
     // Our file descriptor
     // Android-changed: Make the fd package visible so that we can expose it through DatagramSocketAdaptor.
+    // Android-added: @ReachabilitySensitive.
+    @ReachabilitySensitive
     final FileDescriptor fd;
 
     // fd value needed for dev/poll. This value will remain valid
@@ -128,6 +131,7 @@
     // -- End of fields protected by stateLock
 
     // Android-added: CloseGuard support.
+    @ReachabilitySensitive
     private final CloseGuard guard = CloseGuard.get();
 
     public DatagramChannelImpl(SelectorProvider sp)
diff --git a/ojluni/src/main/java/sun/nio/ch/FileChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/FileChannelImpl.java
index 758514b..d752d1a 100644
--- a/ojluni/src/main/java/sun/nio/ch/FileChannelImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/FileChannelImpl.java
@@ -49,6 +49,7 @@
 import java.util.List;
 import libcore.io.Libcore;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import dalvik.system.BlockGuard;
 import dalvik.system.CloseGuard;
 import sun.misc.Cleaner;
@@ -64,7 +65,12 @@
     private final FileDispatcher nd;
 
     // File descriptor
-    // Android-changed: make public.
+    // Android-added: @ReachabilitySensitive
+    // If this were reclaimed while we're in an operation on fd, the associated Stream
+    // could be finalized, closing the fd while still in use. This is not the case upstream,
+    // since there the Stream is accessible from the FileDescriptor.
+    // Android-changed: make public. Used by NioUtils.getFD(), and possibly others.
+    @ReachabilitySensitive
     public final FileDescriptor fd;
 
     // File access mode (immutable)
@@ -86,6 +92,7 @@
     private final Object positionLock = new Object();
 
     // Android-added: CloseGuard support.
+    @ReachabilitySensitive
     private final CloseGuard guard = CloseGuard.get();
 
     private FileChannelImpl(FileDescriptor fd, String path, boolean readable,
diff --git a/ojluni/src/main/java/sun/nio/ch/SocketChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/SocketChannelImpl.java
index a997351..e4dbb5d 100644
--- a/ojluni/src/main/java/sun/nio/ch/SocketChannelImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/SocketChannelImpl.java
@@ -51,6 +51,7 @@
 import java.util.HashSet;
 import java.util.Set;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import dalvik.system.BlockGuard;
 import dalvik.system.CloseGuard;
 import sun.net.ExtendedOptionsImpl;
@@ -119,6 +120,7 @@
     // -- End of fields protected by stateLock
 
     // Android-added: CloseGuard support.
+    @ReachabilitySensitive
     private final CloseGuard guard = CloseGuard.get();
 
     // Constructor for normal connecting sockets
diff --git a/ojluni/src/main/java/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java
index aad7cad..cb5a33b 100644
--- a/ojluni/src/main/java/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java
@@ -35,6 +35,7 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import dalvik.system.CloseGuard;
 
 /**
@@ -70,6 +71,7 @@
     private AccessControlContext acceptAcc;
 
     // Android-added: CloseGuard support.
+    @ReachabilitySensitive
     private final CloseGuard guard = CloseGuard.get();
 
 
diff --git a/ojluni/src/main/java/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java
index ce33a86..cac9744 100644
--- a/ojluni/src/main/java/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java
@@ -35,6 +35,7 @@
 import sun.net.NetHooks;
 import sun.security.action.GetPropertyAction;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import dalvik.system.CloseGuard;
 
 /**
@@ -92,6 +93,7 @@
     private Future<?> writeTimer;
 
     // Android-added: CloseGuard support.
+    @ReachabilitySensitive
     private final CloseGuard guard = CloseGuard.get();
 
     UnixAsynchronousSocketChannelImpl(Port port)
diff --git a/ojluni/src/main/java/sun/nio/fs/LinuxWatchService.java b/ojluni/src/main/java/sun/nio/fs/LinuxWatchService.java
index 5c42d54..5044045 100644
--- a/ojluni/src/main/java/sun/nio/fs/LinuxWatchService.java
+++ b/ojluni/src/main/java/sun/nio/fs/LinuxWatchService.java
@@ -35,6 +35,7 @@
 import java.util.Map;
 import java.util.Set;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import dalvik.system.CloseGuard;
 import sun.misc.Unsafe;
 
@@ -195,6 +196,7 @@
         private final long address;
 
         // Android-added: CloseGuard support.
+        @ReachabilitySensitive
         private final CloseGuard guard = CloseGuard.get();
 
         Poller(UnixFileSystem fs, LinuxWatchService watcher, int ifd, int[] sp) {
diff --git a/ojluni/src/main/java/sun/nio/fs/UnixSecureDirectoryStream.java b/ojluni/src/main/java/sun/nio/fs/UnixSecureDirectoryStream.java
index 321b4d0..7ac3861 100644
--- a/ojluni/src/main/java/sun/nio/fs/UnixSecureDirectoryStream.java
+++ b/ojluni/src/main/java/sun/nio/fs/UnixSecureDirectoryStream.java
@@ -32,6 +32,7 @@
 import java.util.concurrent.TimeUnit;
 import java.io.IOException;
 
+import dalvik.annotation.optimization.ReachabilitySensitive;
 import dalvik.system.CloseGuard;
 
 import static sun.nio.fs.UnixNativeDispatcher.*;
@@ -45,9 +46,13 @@
     implements SecureDirectoryStream<Path>
 {
     private final UnixDirectoryStream ds;
+
+    // Android-added: @ReachabilitySensitive
+    @ReachabilitySensitive
     private final int dfd;
 
     // Android-added: CloseGuard support.
+    @ReachabilitySensitive
     private final CloseGuard guard = CloseGuard.get();
 
     UnixSecureDirectoryStream(UnixPath dir,