Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8327707

Memory ordering spec updates in java.lang.ref

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 23
    • core-libs
    • None
    • minimal
    • Spec changes only, no code changes
    • Java API
    • SE

      Summary

      The java.lang.ref package and its classes should specify memory visibility properties.

      Problem

      Among the optimizations the JVM can make when running code, it can determine that an object can become unreachable even if a method on that object is still executing.

      For classes that cleanup using Cleaner or finalizer, this phenomenon can lead to unexpected cleanup because Cleaner and finalizer perform cleanup on their own threads.

      An example excerpt:

      Resource resource = ...;
      
      protected void finalize() { resource.close(); }
      
      public void doSomething() {
          Resource r = this.resource;
      
          // At this point, 'this' is no longer required.
          // It can be collected, and the finalizer run,
          // closing the resource.
      
          tryToUse(r); // use already-cleaned resource
      }

      One can protect against this by using Reference.reachabilityFence():

      public void doSomething() {
          try {
              Resource r = this.resource;
              tryToUse(r);
          } finally {
              Reference.reachabilityFence(this);
          }
      }

      (This technique has fixed actual bugs, e.g. 8311902 : "Concurrency regression in the PBKDF2 key impl of SunJCE provider".)

      Cleanup threads are also subject to Java memory model visibility rules. As such, if a resource is mutated on the main program thread, that mutation may not be seen on the cleanup thread (short of using synchronization actions, volatile variables, etc). This can potentially lead to incorrect cleanup.

      However, the GC and relevant portions of the java.lang.ref package (ReferenceQueue, Reference.reachabilityFence()) already operate in a way that includes sufficient happens-before edges between Reference.reachabilityFence() and cleanup threads such that mutations occurring on a thread prior to reachabilityFence() will be visible on the cleanup thread.

      Thus, the recommended use of try-finally-reachabilityFence() protects against unexpected cleanup AND ensures memory visibility.

      Solution

      We would like to codify these memory visibility properties in the API spec. The following will be updated:

      • java.lang.ref package-info
      • java.lang.ref.Reference
      • java.lang.ref.ReferenceQueue
      • java.lang.ref.Cleaner

      Specification

      The specdiff of the proposed API spec changes are attached. For convenience, the specdiff is also available here:

      https://cr.openjdk.org/~bchristi/8314480/specdiff.10/overview-summary.html

      and a build of the new JavaDoc is here:

      https://cr.openjdk.org/~bchristi/8314480/javadoc.10/api/index.html

            bchristi Brent Christian
            bchristi Brent Christian
            Alan Bateman
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: