8071507: (ref) Clear phantom reference as soft and weak references do
GC clears phantom refs on notification; update spec accordingly. Reviewed-by: mchung, jmasa
This commit is contained in:
parent
dfa133a796
commit
08dadf3015
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, 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
|
||||
@ -29,23 +29,20 @@ package java.lang.ref;
|
||||
/**
|
||||
* Phantom reference objects, which are enqueued after the collector
|
||||
* determines that their referents may otherwise be reclaimed. Phantom
|
||||
* references are most often used for scheduling pre-mortem cleanup actions in
|
||||
* a more flexible way than is possible with the Java finalization mechanism.
|
||||
* references are most often used to schedule post-mortem cleanup actions.
|
||||
*
|
||||
* <p> If the garbage collector determines at a certain point in time that the
|
||||
* referent of a phantom reference is <a
|
||||
* href="package-summary.html#reachability">phantom reachable</a>, then at that
|
||||
* time or at some later time it will enqueue the reference.
|
||||
* <p> Suppose the garbage collector determines at a certain point in time
|
||||
* that an object is <a href="package-summary.html#reachability">
|
||||
* phantom reachable</a>. At that time it will atomically clear
|
||||
* all phantom references to that object and all phantom references to
|
||||
* any other phantom-reachable objects from which that object is reachable.
|
||||
* At the same time or at some later time it will enqueue those newly-cleared
|
||||
* phantom references that are registered with reference queues.
|
||||
*
|
||||
* <p> In order to ensure that a reclaimable object remains so, the referent of
|
||||
* a phantom reference may not be retrieved: The {@code get} method of a
|
||||
* phantom reference always returns {@code null}.
|
||||
*
|
||||
* <p> Unlike soft and weak references, phantom references are not
|
||||
* automatically cleared by the garbage collector as they are enqueued. An
|
||||
* object that is reachable via phantom references will remain so until all
|
||||
* such references are cleared or themselves become unreachable.
|
||||
*
|
||||
* @author Mark Reinhold
|
||||
* @since 1.2
|
||||
*/
|
||||
@ -69,8 +66,8 @@ public class PhantomReference<T> extends Reference<T> {
|
||||
*
|
||||
* <p> It is possible to create a phantom reference with a {@code null}
|
||||
* queue, but such a reference is completely useless: Its {@code get}
|
||||
* method will always return null and, since it does not have a queue, it
|
||||
* will never be enqueued.
|
||||
* method will always return {@code null} and, since it does not have a queue,
|
||||
* it will never be enqueued.
|
||||
*
|
||||
* @param referent the object the new phantom reference will refer to
|
||||
* @param q the queue with which the reference is to be registered,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2015, 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
|
||||
@ -43,8 +43,7 @@
|
||||
* implementing memory-sensitive caches, weak references are for
|
||||
* implementing canonicalizing mappings that do not prevent their keys
|
||||
* (or values) from being reclaimed, and phantom references are for
|
||||
* scheduling pre-mortem cleanup actions in a more flexible way than
|
||||
* is possible with the Java finalization mechanism.
|
||||
* scheduling post-mortem cleanup actions.
|
||||
*
|
||||
* <p> Each reference-object type is implemented by a subclass of the
|
||||
* abstract base {@link java.lang.ref.Reference} class.
|
||||
@ -64,9 +63,9 @@
|
||||
* object with a <em>reference queue</em> at the time the reference
|
||||
* object is created. Some time after the garbage collector
|
||||
* determines that the reachability of the referent has changed to the
|
||||
* value corresponding to the type of the reference, it will add the
|
||||
* reference to the associated queue. At this point, the reference is
|
||||
* considered to be <em>enqueued</em>. The program may remove
|
||||
* value corresponding to the type of the reference, it will clear the
|
||||
* reference and add it to the associated queue. At this point, the
|
||||
* reference is considered to be <em>enqueued</em>. The program may remove
|
||||
* references from a queue either by polling or by blocking until a
|
||||
* reference becomes available. Reference queues are implemented by
|
||||
* the {@link java.lang.ref.ReferenceQueue} class.
|
||||
@ -92,16 +91,6 @@
|
||||
* structure, this check will add little overhead to the hashtable
|
||||
* access methods.
|
||||
*
|
||||
* <h3>Automatically-cleared references</h3>
|
||||
*
|
||||
* Soft and weak references are automatically cleared by the collector
|
||||
* before being added to the queues with which they are registered, if
|
||||
* any. Therefore soft and weak references need not be registered
|
||||
* with a queue in order to be useful, while phantom references do.
|
||||
* An object that is reachable via phantom references will remain so
|
||||
* until all such references are cleared or themselves become
|
||||
* unreachable.
|
||||
*
|
||||
* <a name="reachability"></a>
|
||||
* <h3>Reachability</h3>
|
||||
*
|
||||
|
101
jdk/test/java/lang/ref/PhantomReferentClearing.java
Normal file
101
jdk/test/java/lang/ref/PhantomReferentClearing.java
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8071507
|
||||
* @summary Test that PhantomReferences are cleared when notified.
|
||||
* @run main/othervm PhantomReferentClearing
|
||||
*/
|
||||
|
||||
import java.lang.ref.PhantomReference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PhantomReferentClearing {
|
||||
|
||||
private static final long ENQUEUE_TIMEOUT = 1000; // 1 sec, in millis
|
||||
|
||||
// P1 & P2 are PhantomReference objects
|
||||
// O1 & O2 are objects
|
||||
//
|
||||
// -> is a strong reference
|
||||
// => is a referent reference
|
||||
//
|
||||
// root -> P1
|
||||
// root -> P2
|
||||
// root -> O1
|
||||
// root -> O2
|
||||
// O1 -> O2
|
||||
// P1 => O1
|
||||
// P2 => O2
|
||||
//
|
||||
// (1) Remove root -> O1 and collect. P1 notified, P2 !notified.
|
||||
// (2) Remove root -> O2 and collect.
|
||||
//
|
||||
// If phantom references are cleared when notified, as proposed by
|
||||
// 8071507, then P2 should be notified, and the test passes.
|
||||
//
|
||||
// Otherwise, P2 does not get notified because it remains reachable
|
||||
// from O1, which is being retained by P1. This fails the test.
|
||||
|
||||
private static final ReferenceQueue<Object> Q1 = new ReferenceQueue<>();
|
||||
private static final ReferenceQueue<Object> Q2 = new ReferenceQueue<>();
|
||||
|
||||
private static volatile Object O2 = new Object();
|
||||
private static volatile List<Object> O1 = new ArrayList<>();
|
||||
static {
|
||||
O1.add(O2);
|
||||
}
|
||||
|
||||
private static final PhantomReference<Object> P1 = new PhantomReference<>(O1, Q1);
|
||||
private static final PhantomReference<Object> P2 = new PhantomReference<>(O2, Q2);
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
|
||||
// Collect, and verify neither P1 or P2 notified.
|
||||
System.gc();
|
||||
if (Q1.remove(ENQUEUE_TIMEOUT) != null) {
|
||||
throw new RuntimeException("P1 already notified");
|
||||
} else if (Q2.poll() != null) {
|
||||
throw new RuntimeException("P2 already notified");
|
||||
}
|
||||
|
||||
// Delete root -> O1, collect, verify P1 notified, P2 not notified.
|
||||
O1 = null;
|
||||
System.gc();
|
||||
if (Q1.remove(ENQUEUE_TIMEOUT) == null) {
|
||||
throw new RuntimeException("P1 not notified by O1 deletion");
|
||||
} else if (Q2.remove(ENQUEUE_TIMEOUT) != null) {
|
||||
throw new RuntimeException("P2 notified by O1 deletion.");
|
||||
}
|
||||
|
||||
// Delete root -> O2, collect. P2 should be notified.
|
||||
O2 = null;
|
||||
System.gc();
|
||||
if (Q2.remove(ENQUEUE_TIMEOUT) == null) {
|
||||
throw new RuntimeException("P2 not notified by O2 deletion");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user