Uploaded image for project: 'JikesRVM'
  1. RVM-1067

Overly eager clearing of Soft references

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Medium
    • Resolution: Fixed
    • Affects Version/s: 3.1.3
    • Fix Version/s: 3.1.4
    • Component/s: MMTk
    • Labels:
      None

      Description

      From email to researcher's list by Tomoharu.

      I have found that reference types show a strange behaviour.
      When a soft reference A is reachable only though another soft
      reference B, the garbage collector fails to preserve the correct
      semantics.

      In the attached program RefRef.java, there are 3 objects.
      A "normal" object is directly reachable from a local variable, o.
      A SoftReference object is also directly reachable from a local
      variable, rr. Its referent, call it r, is another SoftReference object,
      which in turn has as its referent, o. Immediately prior to GC,
      r is soft reachable from rr (and only from rr). Thus, using the
      notation s> to indicate a soft reference, and naming objects
      by the variables that point to them, immediately before GC we
      have:

      root --> rr -s> r s> o <--- root

      The specification for soft references permits two actions on a
      softly reachable (and by definition, not strongly reachable) object:
      it preserves the object or it may choose to reclaim it. The only softly
      reachable object in this scenario is r.

      In the former case, the object graph above is unchanged. Specifically,
      r == rr.get() && r.get() == o.
      In the latter case, after GC, rr.get() == null.
      However, r.get() returns null on Jikes RVM, which should be impossible
      since either r == rr.get() == null and we should get an NPE when we call r.get(),
      or r == rr.get() != null and r.get() should return o.

      This bug seem to be caused by an incorrect processing of
      reference table (ReferenceProcessor.references). The reference
      processor retains softly reachable objects (i.e. referents of soft
      references) unless we have insufficient memory. This is realized
      by scanning the reference table and marking referents of live soft
      references. If the reference processor finds a soft reference that
      is not live (not strongly reachable) in the reference table, it
      disposes of this reference, clears the referent field of this
      reference (a comment admits that this is paranoia) and removes the
      reference from the reference table.

      However, in Jikes RVM the disposed reference may still be
      reachable from a referent of another, live soft reference.
      Consequently, Jikes RVM incorrectly allows a user program to access
      the disposed reference and to get its referent (which is now null).

      The error does not lie in clearing the referent field of the disposed
      (softly reachable) reference. Simply retaining the value of the referent
      field would not solve the problem because, (1) the field would not be
      updated if the referent were moved by a moving collector and (2) the
      reference would never be enqueued.

      In Jikes RVM, ReferenceProcessor is too eager to discard reference objects
      that are not marked. Right at the start of
      ReferenceProcessor.processReference(), we have:

      /*

      • If the reference is dead, we're done with it. Let it (and
      • possibly its referent) be garbage-collected.
        */
        if (!trace.isLive(reference))
        Unknown macro: { clearReferent(reference); // Too much paranoia ... if (TRACE_UNREACHABLE) { VM.sysWriteln(" UNREACHABLE reference: ",reference); } if (TRACE_DETAIL) { VM.sysWriteln(" (unreachable)"); } return ObjectReference.nullReference(); }

      This is wrong if we have chosen to preserve soft references
      because this object might be reachable from a live soft reference.

      A solution is as follows.

      1. Usual standard transitive closure, tracing from the usual roots, marking objects.
      2a. If we decide to retain softly reachable objects,
      examine each SoftReference in the table of references
      if the reference is marked, mark the transitive closure of its referent.
      2b. If we decide to reclaim softly reachable objects,
      examine each SoftReference in the table of references
      if its referent is not marked, set the referent to null.
      3. Reclaim any unmarked objects.

        Attachments

          Activity

            People

            • Assignee:
              ebrangs Erik Brangs
              Reporter:
              dgrove dgrove
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: