Hi Kim,
On 2015-12-02 19:37, Kim Barrett wrote:
Please review this change to PhantomReference processing, changing the
GC-based notification to automatically clear the referent.
This change provides performance benefits by eliminating the work
involved in keeping the otherwise inaccessible referent objects alive,
as required by the existing specification. This not only immediately
removes some work, but may enable further performance improvements.
It also allows the referent objects to be immediately reclaimed in
the GC cycle in which they were determined to be inaccessible, rather
than lingering as a form of floating garbage until the application
deals with the notified reference.
This change results in a behavioral change to application code, as
demonstrated by the associated test. Under the old specification, a
reference R with referent X may be kept alive because it is referenced
by an otherwise inaccessible referent Y of phantom reference P. This
will result in X being treated as strongly referenced and prevent R
from being notified, even if R is a phantom reference and X has become
inaccessible to the application. With this change, Y is reclaimed
when it becomes inaccessible and P is notified, and no longer prevents
X from itself becoming a candidate for reclaimation once it is no
longer accessible to the application. While this is a change in
behavior, it seems unlikely to affect applications negatively.
CR:
https://bugs.openjdk.java.net/browse/JDK-8071507
Webrevs:
http://cr.openjdk.java.net/~kbarrett/8071507/jdk.05/
test/java/lang/ref/PhantomReferentClearing.java:
85 // Delete root -> O1, collect, verify P1 notified, P2 not
notified.
86 O1 = null;
87 System.gc();
88 if (Q1.remove(ENQUEUE_TIMEOUT) == null) {
89 throw new RuntimeException("P1 not notified by O1
deletion");
90 } else if (Q2.remove(ENQUEUE_TIMEOUT) != null) {
91 throw new RuntimeException("P2 notified by O1 deletion.");
92 }
93
94 // Delete root -> O2, collect. P2 should be notified.
95 O2 = null;
96 System.gc();
97 if (Q2.remove(ENQUEUE_TIMEOUT) == null) {
98 throw new RuntimeException("P2 not notified by O2
deletion");
99 }
The calls to System.gc() isn't guaranteed to do what the test expects
here. As you know, System.gc(), might not actually do anything,
depending on which collector is used and the current circumstances (GC
locker held, a concurrent GC is already in process, etc). To make the
test robust I'd suggest you call System.gc() and check the queue in a
loop, and fail after some reasonable amount of time/iterations.
cheers,
/Per
http://cr.openjdk.java.net/~kbarrett/8071507/hotspot.05/
Testing:
jprt, aurora ad hoc (defaults, GC/Runtime nightly, JCK)