--- old/src/java.base/share/classes/java/lang/ref/Finalizer.java 2018-02-15 19:36:05.334563033 -0800 +++ new/src/java.base/share/classes/java/lang/ref/Finalizer.java 2018-02-15 19:36:05.094560893 -0800 @@ -36,18 +36,18 @@ class */ private static ReferenceQueue queue = new ReferenceQueue<>(); + + /** Head of doubly linked list of Finalizers awaiting finalization. */ private static Finalizer unfinalized = null; - private static final Object lock = new Object(); - private Finalizer - next = null, - prev = null; + /** Lock guarding access to unfinalized list. */ + private static final Object lock = new Object(); - private boolean hasBeenFinalized() { - return (next == this); - } + private Finalizer next, prev; - private void add() { + private Finalizer(Object finalizee) { + super(finalizee, queue); + // push onto unfinalized synchronized (lock) { if (unfinalized != null) { this.next = unfinalized; @@ -57,31 +57,6 @@ } } - private void remove() { - synchronized (lock) { - if (unfinalized == this) { - if (this.next != null) { - unfinalized = this.next; - } else { - unfinalized = this.prev; - } - } - if (this.next != null) { - this.next.prev = this.prev; - } - if (this.prev != null) { - this.prev.next = this.next; - } - this.next = this; /* Indicates that this has been finalized */ - this.prev = this; - } - } - - private Finalizer(Object finalizee) { - super(finalizee, queue); - add(); - } - static ReferenceQueue getQueue() { return queue; } @@ -91,11 +66,24 @@ new Finalizer(finalizee); } - private void runFinalizer(JavaLangAccess jla) { - synchronized (this) { - if (hasBeenFinalized()) return; - remove(); + private void deregisterAndRunFinalizer(JavaLangAccess jla) { + synchronized (lock) { + if (this.next == this) // already finalized + return; + // unlink from unfinalized + if (unfinalized == this) + unfinalized = this.next; + else + this.prev.next = this.next; + if (this.next != null) + this.next.prev = this.prev; + this.prev = null; + this.next = this; // mark as finalized } + runFinalizer(jla); + } + + private void runFinalizer(JavaLangAccess jla) { try { Object finalizee = this.get(); if (finalizee != null && !(finalizee instanceof java.lang.Enum)) { @@ -155,11 +143,8 @@ return; final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); running = true; - for (;;) { - Finalizer f = (Finalizer)queue.poll(); - if (f == null) break; - f.runFinalizer(jla); - } + for (Finalizer f; (f = (Finalizer)queue.poll()) != null; ) + f.deregisterAndRunFinalizer(jla); } }); } @@ -179,11 +164,15 @@ final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); running = true; for (;;) { + // "pollFirst" from unfinalized Finalizer f; synchronized (lock) { f = unfinalized; if (f == null) break; unfinalized = f.next; + if (unfinalized != null) + unfinalized.prev = null; + f.next = f; // mark as finalized } f.runFinalizer(jla); }}}); @@ -214,7 +203,7 @@ for (;;) { try { Finalizer f = (Finalizer)queue.remove(); - f.runFinalizer(jla); + f.deregisterAndRunFinalizer(jla); } catch (InterruptedException x) { // ignore and continue }