mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8187443: Forest Consolidation: Move files to unified layout
Reviewed-by: darcy, ihse
This commit is contained in:
parent
270fe13182
commit
3789983e89
56923 changed files with 3 additions and 15727 deletions
237
src/java.base/share/classes/java/lang/ref/Cleaner.java
Normal file
237
src/java.base/share/classes/java/lang/ref/Cleaner.java
Normal file
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package java.lang.ref;
|
||||
|
||||
import jdk.internal.ref.CleanerImpl;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* {@code Cleaner} manages a set of object references and corresponding cleaning actions.
|
||||
* <p>
|
||||
* Cleaning actions are {@link #register(Object object, Runnable action) registered}
|
||||
* to run after the cleaner is notified that the object has become
|
||||
* phantom reachable.
|
||||
* The cleaner uses {@link PhantomReference} and {@link ReferenceQueue} to be
|
||||
* notified when the <a href="package-summary.html#reachability">reachability</a>
|
||||
* changes.
|
||||
* <p>
|
||||
* Each cleaner operates independently, managing the pending cleaning actions
|
||||
* and handling threading and termination when the cleaner is no longer in use.
|
||||
* Registering an object reference and corresponding cleaning action returns
|
||||
* a {@link Cleanable Cleanable}. The most efficient use is to explicitly invoke
|
||||
* the {@link Cleanable#clean clean} method when the object is closed or
|
||||
* no longer needed.
|
||||
* The cleaning action is a {@link Runnable} to be invoked at most once when
|
||||
* the object has become phantom reachable unless it has already been explicitly cleaned.
|
||||
* Note that the cleaning action must not refer to the object being registered.
|
||||
* If so, the object will not become phantom reachable and the cleaning action
|
||||
* will not be invoked automatically.
|
||||
* <p>
|
||||
* The execution of the cleaning action is performed
|
||||
* by a thread associated with the cleaner.
|
||||
* All exceptions thrown by the cleaning action are ignored.
|
||||
* The cleaner and other cleaning actions are not affected by
|
||||
* exceptions in a cleaning action.
|
||||
* The thread runs until all registered cleaning actions have
|
||||
* completed and the cleaner itself is reclaimed by the garbage collector.
|
||||
* <p>
|
||||
* The behavior of cleaners during {@link System#exit(int) System.exit}
|
||||
* is implementation specific. No guarantees are made relating
|
||||
* to whether cleaning actions are invoked or not.
|
||||
* <p>
|
||||
* Unless otherwise noted, passing a {@code null} argument to a constructor or
|
||||
* method in this class will cause a
|
||||
* {@link java.lang.NullPointerException NullPointerException} to be thrown.
|
||||
*
|
||||
* @apiNote
|
||||
* The cleaning action is invoked only after the associated object becomes
|
||||
* phantom reachable, so it is important that the object implementing the
|
||||
* cleaning action does not hold references to the object.
|
||||
* In this example, a static class encapsulates the cleaning state and action.
|
||||
* An "inner" class, anonymous or not, must not be used because it implicitly
|
||||
* contains a reference to the outer instance, preventing it from becoming
|
||||
* phantom reachable.
|
||||
* The choice of a new cleaner or sharing an existing cleaner is determined
|
||||
* by the use case.
|
||||
* <p>
|
||||
* If the CleaningExample is used in a try-finally block then the
|
||||
* {@code close} method calls the cleaning action.
|
||||
* If the {@code close} method is not called, the cleaning action is called
|
||||
* by the Cleaner when the CleaningExample instance has become phantom reachable.
|
||||
* <pre>{@code
|
||||
* public class CleaningExample implements AutoCloseable {
|
||||
* // A cleaner, preferably one shared within a library
|
||||
* private static final Cleaner cleaner = <cleaner>;
|
||||
*
|
||||
* static class State implements Runnable {
|
||||
*
|
||||
* State(...) {
|
||||
* // initialize State needed for cleaning action
|
||||
* }
|
||||
*
|
||||
* public void run() {
|
||||
* // cleanup action accessing State, executed at most once
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* private final State;
|
||||
* private final Cleaner.Cleanable cleanable
|
||||
*
|
||||
* public CleaningExample() {
|
||||
* this.state = new State(...);
|
||||
* this.cleanable = cleaner.register(this, state);
|
||||
* }
|
||||
*
|
||||
* public void close() {
|
||||
* cleanable.clean();
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
* The cleaning action could be a lambda but all too easily will capture
|
||||
* the object reference, by referring to fields of the object being cleaned,
|
||||
* preventing the object from becoming phantom reachable.
|
||||
* Using a static nested class, as above, will avoid accidentally retaining the
|
||||
* object reference.
|
||||
* <p>
|
||||
* <a id="compatible-cleaners"></a>
|
||||
* Cleaning actions should be prepared to be invoked concurrently with
|
||||
* other cleaning actions.
|
||||
* Typically the cleaning actions should be very quick to execute
|
||||
* and not block. If the cleaning action blocks, it may delay processing
|
||||
* other cleaning actions registered to the same cleaner.
|
||||
* All cleaning actions registered to a cleaner should be mutually compatible.
|
||||
* @since 9
|
||||
*/
|
||||
public final class Cleaner {
|
||||
|
||||
/**
|
||||
* The Cleaner implementation.
|
||||
*/
|
||||
final CleanerImpl impl;
|
||||
|
||||
static {
|
||||
CleanerImpl.setCleanerImplAccess(new Function<Cleaner, CleanerImpl>() {
|
||||
@Override
|
||||
public CleanerImpl apply(Cleaner cleaner) {
|
||||
return cleaner.impl;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a Cleaner implementation and start it.
|
||||
*/
|
||||
private Cleaner() {
|
||||
impl = new CleanerImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@code Cleaner}.
|
||||
* <p>
|
||||
* The cleaner creates a {@link Thread#setDaemon(boolean) daemon thread}
|
||||
* to process the phantom reachable objects and to invoke cleaning actions.
|
||||
* The {@linkplain java.lang.Thread#getContextClassLoader context class loader}
|
||||
* of the thread is set to the
|
||||
* {@link ClassLoader#getSystemClassLoader() system class loader}.
|
||||
* The thread has no permissions, enforced only if a
|
||||
* {@link java.lang.System#setSecurityManager(SecurityManager) SecurityManager is set}.
|
||||
* <p>
|
||||
* The cleaner terminates when it is phantom reachable and all of the
|
||||
* registered cleaning actions are complete.
|
||||
*
|
||||
* @return a new {@code Cleaner}
|
||||
*
|
||||
* @throws SecurityException if the current thread is not allowed to
|
||||
* create or start the thread.
|
||||
*/
|
||||
public static Cleaner create() {
|
||||
Cleaner cleaner = new Cleaner();
|
||||
cleaner.impl.start(cleaner, null);
|
||||
return cleaner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@code Cleaner} using a {@code Thread} from the {@code ThreadFactory}.
|
||||
* <p>
|
||||
* A thread from the thread factory's {@link ThreadFactory#newThread(Runnable) newThread}
|
||||
* method is set to be a {@link Thread#setDaemon(boolean) daemon thread}
|
||||
* and started to process phantom reachable objects and invoke cleaning actions.
|
||||
* On each call the {@link ThreadFactory#newThread(Runnable) thread factory}
|
||||
* must provide a Thread that is suitable for performing the cleaning actions.
|
||||
* <p>
|
||||
* The cleaner terminates when it is phantom reachable and all of the
|
||||
* registered cleaning actions are complete.
|
||||
*
|
||||
* @param threadFactory a {@code ThreadFactory} to return a new {@code Thread}
|
||||
* to process cleaning actions
|
||||
* @return a new {@code Cleaner}
|
||||
*
|
||||
* @throws IllegalThreadStateException if the thread from the thread
|
||||
* factory was {@link Thread.State#NEW not a new thread}.
|
||||
* @throws SecurityException if the current thread is not allowed to
|
||||
* create or start the thread.
|
||||
*/
|
||||
public static Cleaner create(ThreadFactory threadFactory) {
|
||||
Objects.requireNonNull(threadFactory, "threadFactory");
|
||||
Cleaner cleaner = new Cleaner();
|
||||
cleaner.impl.start(cleaner, threadFactory);
|
||||
return cleaner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an object and a cleaning action to run when the object
|
||||
* becomes phantom reachable.
|
||||
* Refer to the <a href="#compatible-cleaners">API Note</a> above for
|
||||
* cautions about the behavior of cleaning actions.
|
||||
*
|
||||
* @param obj the object to monitor
|
||||
* @param action a {@code Runnable} to invoke when the object becomes phantom reachable
|
||||
* @return a {@code Cleanable} instance
|
||||
*/
|
||||
public Cleanable register(Object obj, Runnable action) {
|
||||
Objects.requireNonNull(obj, "obj");
|
||||
Objects.requireNonNull(action, "action");
|
||||
return new CleanerImpl.PhantomCleanableRef(obj, this, action);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code Cleanable} represents an object and a
|
||||
* cleaning action registered in a {@code Cleaner}.
|
||||
* @since 9
|
||||
*/
|
||||
public interface Cleanable {
|
||||
/**
|
||||
* Unregisters the cleanable and invokes the cleaning action.
|
||||
* The cleanable's cleaning action is invoked at most once
|
||||
* regardless of the number of calls to {@code clean}.
|
||||
*/
|
||||
void clean();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2017, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package java.lang.ref;
|
||||
|
||||
/**
|
||||
* Final references, used to implement finalization
|
||||
*/
|
||||
class FinalReference<T> extends Reference<T> {
|
||||
|
||||
public FinalReference(T referent, ReferenceQueue<? super T> q) {
|
||||
super(referent, q);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean enqueue() {
|
||||
throw new InternalError("should never reach here");
|
||||
}
|
||||
}
|
236
src/java.base/share/classes/java/lang/ref/Finalizer.java
Normal file
236
src/java.base/share/classes/java/lang/ref/Finalizer.java
Normal file
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package java.lang.ref;
|
||||
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.AccessController;
|
||||
import jdk.internal.misc.JavaLangAccess;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import jdk.internal.misc.VM;
|
||||
|
||||
final class Finalizer extends FinalReference<Object> { /* Package-private; must be in
|
||||
same package as the Reference
|
||||
class */
|
||||
|
||||
private static ReferenceQueue<Object> queue = new ReferenceQueue<>();
|
||||
private static Finalizer unfinalized = null;
|
||||
private static final Object lock = new Object();
|
||||
|
||||
private Finalizer
|
||||
next = null,
|
||||
prev = null;
|
||||
|
||||
private boolean hasBeenFinalized() {
|
||||
return (next == this);
|
||||
}
|
||||
|
||||
private void add() {
|
||||
synchronized (lock) {
|
||||
if (unfinalized != null) {
|
||||
this.next = unfinalized;
|
||||
unfinalized.prev = this;
|
||||
}
|
||||
unfinalized = this;
|
||||
}
|
||||
}
|
||||
|
||||
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<Object> getQueue() {
|
||||
return queue;
|
||||
}
|
||||
|
||||
/* Invoked by VM */
|
||||
static void register(Object finalizee) {
|
||||
new Finalizer(finalizee);
|
||||
}
|
||||
|
||||
private void runFinalizer(JavaLangAccess jla) {
|
||||
synchronized (this) {
|
||||
if (hasBeenFinalized()) return;
|
||||
remove();
|
||||
}
|
||||
try {
|
||||
Object finalizee = this.get();
|
||||
if (finalizee != null && !(finalizee instanceof java.lang.Enum)) {
|
||||
jla.invokeFinalize(finalizee);
|
||||
|
||||
/* Clear stack slot containing this variable, to decrease
|
||||
the chances of false retention with a conservative GC */
|
||||
finalizee = null;
|
||||
}
|
||||
} catch (Throwable x) { }
|
||||
super.clear();
|
||||
}
|
||||
|
||||
/* Create a privileged secondary finalizer thread in the system thread
|
||||
group for the given Runnable, and wait for it to complete.
|
||||
|
||||
This method is used by both runFinalization and runFinalizersOnExit.
|
||||
The former method invokes all pending finalizers, while the latter
|
||||
invokes all uninvoked finalizers if on-exit finalization has been
|
||||
enabled.
|
||||
|
||||
These two methods could have been implemented by offloading their work
|
||||
to the regular finalizer thread and waiting for that thread to finish.
|
||||
The advantage of creating a fresh thread, however, is that it insulates
|
||||
invokers of these methods from a stalled or deadlocked finalizer thread.
|
||||
*/
|
||||
private static void forkSecondaryFinalizer(final Runnable proc) {
|
||||
AccessController.doPrivileged(
|
||||
new PrivilegedAction<>() {
|
||||
public Void run() {
|
||||
ThreadGroup tg = Thread.currentThread().getThreadGroup();
|
||||
for (ThreadGroup tgn = tg;
|
||||
tgn != null;
|
||||
tg = tgn, tgn = tg.getParent());
|
||||
Thread sft = new Thread(tg, proc, "Secondary finalizer", 0, false);
|
||||
sft.start();
|
||||
try {
|
||||
sft.join();
|
||||
} catch (InterruptedException x) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
return null;
|
||||
}});
|
||||
}
|
||||
|
||||
/* Called by Runtime.runFinalization() */
|
||||
static void runFinalization() {
|
||||
if (VM.initLevel() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
forkSecondaryFinalizer(new Runnable() {
|
||||
private volatile boolean running;
|
||||
public void run() {
|
||||
// in case of recursive call to run()
|
||||
if (running)
|
||||
return;
|
||||
final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
|
||||
running = true;
|
||||
for (;;) {
|
||||
Finalizer f = (Finalizer)queue.poll();
|
||||
if (f == null) break;
|
||||
f.runFinalizer(jla);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* Invoked by java.lang.Shutdown */
|
||||
static void runAllFinalizers() {
|
||||
if (VM.initLevel() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
forkSecondaryFinalizer(new Runnable() {
|
||||
private volatile boolean running;
|
||||
public void run() {
|
||||
// in case of recursive call to run()
|
||||
if (running)
|
||||
return;
|
||||
final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
|
||||
running = true;
|
||||
for (;;) {
|
||||
Finalizer f;
|
||||
synchronized (lock) {
|
||||
f = unfinalized;
|
||||
if (f == null) break;
|
||||
unfinalized = f.next;
|
||||
}
|
||||
f.runFinalizer(jla);
|
||||
}}});
|
||||
}
|
||||
|
||||
private static class FinalizerThread extends Thread {
|
||||
private volatile boolean running;
|
||||
FinalizerThread(ThreadGroup g) {
|
||||
super(g, null, "Finalizer", 0, false);
|
||||
}
|
||||
public void run() {
|
||||
// in case of recursive call to run()
|
||||
if (running)
|
||||
return;
|
||||
|
||||
// Finalizer thread starts before System.initializeSystemClass
|
||||
// is called. Wait until JavaLangAccess is available
|
||||
while (VM.initLevel() == 0) {
|
||||
// delay until VM completes initialization
|
||||
try {
|
||||
VM.awaitInitLevel(1);
|
||||
} catch (InterruptedException x) {
|
||||
// ignore and continue
|
||||
}
|
||||
}
|
||||
final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
|
||||
running = true;
|
||||
for (;;) {
|
||||
try {
|
||||
Finalizer f = (Finalizer)queue.remove();
|
||||
f.runFinalizer(jla);
|
||||
} catch (InterruptedException x) {
|
||||
// ignore and continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
ThreadGroup tg = Thread.currentThread().getThreadGroup();
|
||||
for (ThreadGroup tgn = tg;
|
||||
tgn != null;
|
||||
tg = tgn, tgn = tg.getParent());
|
||||
Thread finalizer = new FinalizerThread(tg);
|
||||
finalizer.setPriority(Thread.MAX_PRIORITY - 2);
|
||||
finalizer.setDaemon(true);
|
||||
finalizer.start();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package java.lang.ref;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* This FinalizerHistogram class is for GC.finalizer_info diagnostic command support.
|
||||
* It is invoked by the VM.
|
||||
*/
|
||||
|
||||
final class FinalizerHistogram {
|
||||
|
||||
private static final class Entry {
|
||||
private int instanceCount;
|
||||
private final String className;
|
||||
|
||||
int getInstanceCount() {
|
||||
return instanceCount;
|
||||
}
|
||||
|
||||
void increment() {
|
||||
instanceCount += 1;
|
||||
}
|
||||
|
||||
Entry(String className) {
|
||||
this.className = className;
|
||||
}
|
||||
}
|
||||
|
||||
// Method below is called by VM and VM expect certain
|
||||
// entry class layout.
|
||||
|
||||
static Entry[] getFinalizerHistogram() {
|
||||
Map<String, Entry> countMap = new HashMap<>();
|
||||
ReferenceQueue<Object> queue = Finalizer.getQueue();
|
||||
queue.forEach(r -> {
|
||||
Object referent = r.get();
|
||||
if (referent != null) {
|
||||
countMap.computeIfAbsent(
|
||||
referent.getClass().getName(), Entry::new).increment();
|
||||
/* Clear stack slot containing this variable, to decrease
|
||||
the chances of false retention with a conservative GC */
|
||||
referent = null;
|
||||
}
|
||||
});
|
||||
|
||||
Entry fhe[] = countMap.values().toArray(new Entry[countMap.size()]);
|
||||
Arrays.sort(fhe,
|
||||
Comparator.comparingInt(Entry::getInstanceCount).reversed());
|
||||
return fhe;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
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 to schedule post-mortem cleanup actions.
|
||||
*
|
||||
* <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}.
|
||||
*
|
||||
* @author Mark Reinhold
|
||||
* @since 1.2
|
||||
*/
|
||||
|
||||
public class PhantomReference<T> extends Reference<T> {
|
||||
|
||||
/**
|
||||
* Returns this reference object's referent. Because the referent of a
|
||||
* phantom reference is always inaccessible, this method always returns
|
||||
* {@code null}.
|
||||
*
|
||||
* @return {@code null}
|
||||
*/
|
||||
public T get() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new phantom reference that refers to the given object and
|
||||
* is registered with the given queue.
|
||||
*
|
||||
* <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 {@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,
|
||||
* or {@code null} if registration is not required
|
||||
*/
|
||||
public PhantomReference(T referent, ReferenceQueue<? super T> q) {
|
||||
super(referent, q);
|
||||
}
|
||||
|
||||
}
|
433
src/java.base/share/classes/java/lang/ref/Reference.java
Normal file
433
src/java.base/share/classes/java/lang/ref/Reference.java
Normal file
|
@ -0,0 +1,433 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2017, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package java.lang.ref;
|
||||
|
||||
import jdk.internal.vm.annotation.DontInline;
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
import jdk.internal.misc.JavaLangRefAccess;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import jdk.internal.ref.Cleaner;
|
||||
|
||||
/**
|
||||
* Abstract base class for reference objects. This class defines the
|
||||
* operations common to all reference objects. Because reference objects are
|
||||
* implemented in close cooperation with the garbage collector, this class may
|
||||
* not be subclassed directly.
|
||||
*
|
||||
* @author Mark Reinhold
|
||||
* @since 1.2
|
||||
*/
|
||||
|
||||
public abstract class Reference<T> {
|
||||
|
||||
/* A Reference instance is in one of four possible internal states:
|
||||
*
|
||||
* Active: Subject to special treatment by the garbage collector. Some
|
||||
* time after the collector detects that the reachability of the
|
||||
* referent has changed to the appropriate state, it changes the
|
||||
* instance's state to either Pending or Inactive, depending upon
|
||||
* whether or not the instance was registered with a queue when it was
|
||||
* created. In the former case it also adds the instance to the
|
||||
* pending-Reference list. Newly-created instances are Active.
|
||||
*
|
||||
* Pending: An element of the pending-Reference list, waiting to be
|
||||
* enqueued by the Reference-handler thread. Unregistered instances
|
||||
* are never in this state.
|
||||
*
|
||||
* Enqueued: An element of the queue with which the instance was
|
||||
* registered when it was created. When an instance is removed from
|
||||
* its ReferenceQueue, it is made Inactive. Unregistered instances are
|
||||
* never in this state.
|
||||
*
|
||||
* Inactive: Nothing more to do. Once an instance becomes Inactive its
|
||||
* state will never change again.
|
||||
*
|
||||
* The state is encoded in the queue and next fields as follows:
|
||||
*
|
||||
* Active: queue = ReferenceQueue with which instance is registered, or
|
||||
* ReferenceQueue.NULL if it was not registered with a queue; next =
|
||||
* null.
|
||||
*
|
||||
* Pending: queue = ReferenceQueue with which instance is registered;
|
||||
* next = this
|
||||
*
|
||||
* Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance
|
||||
* in queue, or this if at end of list.
|
||||
*
|
||||
* Inactive: queue = ReferenceQueue.NULL; next = this.
|
||||
*
|
||||
* With this scheme the collector need only examine the next field in order
|
||||
* to determine whether a Reference instance requires special treatment: If
|
||||
* the next field is null then the instance is active; if it is non-null,
|
||||
* then the collector should treat the instance normally.
|
||||
*
|
||||
* To ensure that a concurrent collector can discover active Reference
|
||||
* objects without interfering with application threads that may apply
|
||||
* the enqueue() method to those objects, collectors should link
|
||||
* discovered objects through the discovered field. The discovered
|
||||
* field is also used for linking Reference objects in the pending list.
|
||||
*/
|
||||
|
||||
private T referent; /* Treated specially by GC */
|
||||
|
||||
volatile ReferenceQueue<? super T> queue;
|
||||
|
||||
/* When active: NULL
|
||||
* pending: this
|
||||
* Enqueued: next reference in queue (or this if last)
|
||||
* Inactive: this
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
volatile Reference next;
|
||||
|
||||
/* When active: next element in a discovered reference list maintained by GC (or this if last)
|
||||
* pending: next element in the pending list (or null if last)
|
||||
* otherwise: NULL
|
||||
*/
|
||||
private transient Reference<T> discovered; /* used by VM */
|
||||
|
||||
|
||||
/* High-priority thread to enqueue pending References
|
||||
*/
|
||||
private static class ReferenceHandler extends Thread {
|
||||
|
||||
private static void ensureClassInitialized(Class<?> clazz) {
|
||||
try {
|
||||
Class.forName(clazz.getName(), true, clazz.getClassLoader());
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw (Error) new NoClassDefFoundError(e.getMessage()).initCause(e);
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
// pre-load and initialize Cleaner class so that we don't
|
||||
// get into trouble later in the run loop if there's
|
||||
// memory shortage while loading/initializing it lazily.
|
||||
ensureClassInitialized(Cleaner.class);
|
||||
}
|
||||
|
||||
ReferenceHandler(ThreadGroup g, String name) {
|
||||
super(g, null, name, 0, false);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (true) {
|
||||
processPendingReferences();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* system property to disable clearing before enqueuing.
|
||||
*/
|
||||
private static final class ClearBeforeEnqueue {
|
||||
static final boolean DISABLE =
|
||||
Boolean.getBoolean("jdk.lang.ref.disableClearBeforeEnqueue");
|
||||
}
|
||||
|
||||
/*
|
||||
* Atomically get and clear (set to null) the VM's pending list.
|
||||
*/
|
||||
private static native Reference<Object> getAndClearReferencePendingList();
|
||||
|
||||
/*
|
||||
* Test whether the VM's pending list contains any entries.
|
||||
*/
|
||||
private static native boolean hasReferencePendingList();
|
||||
|
||||
/*
|
||||
* Wait until the VM's pending list may be non-null.
|
||||
*/
|
||||
private static native void waitForReferencePendingList();
|
||||
|
||||
private static final Object processPendingLock = new Object();
|
||||
private static boolean processPendingActive = false;
|
||||
|
||||
private static void processPendingReferences() {
|
||||
// Only the singleton reference processing thread calls
|
||||
// waitForReferencePendingList() and getAndClearReferencePendingList().
|
||||
// These are separate operations to avoid a race with other threads
|
||||
// that are calling waitForReferenceProcessing().
|
||||
waitForReferencePendingList();
|
||||
Reference<Object> pendingList;
|
||||
synchronized (processPendingLock) {
|
||||
pendingList = getAndClearReferencePendingList();
|
||||
processPendingActive = true;
|
||||
}
|
||||
while (pendingList != null) {
|
||||
Reference<Object> ref = pendingList;
|
||||
pendingList = ref.discovered;
|
||||
ref.discovered = null;
|
||||
|
||||
if (ref instanceof Cleaner) {
|
||||
((Cleaner)ref).clean();
|
||||
// Notify any waiters that progress has been made.
|
||||
// This improves latency for nio.Bits waiters, which
|
||||
// are the only important ones.
|
||||
synchronized (processPendingLock) {
|
||||
processPendingLock.notifyAll();
|
||||
}
|
||||
} else {
|
||||
ReferenceQueue<? super Object> q = ref.queue;
|
||||
if (q != ReferenceQueue.NULL) q.enqueue(ref);
|
||||
}
|
||||
}
|
||||
// Notify any waiters of completion of current round.
|
||||
synchronized (processPendingLock) {
|
||||
processPendingActive = false;
|
||||
processPendingLock.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for progress in reference processing.
|
||||
//
|
||||
// Returns true after waiting (for notification from the reference
|
||||
// processing thread) if either (1) the VM has any pending
|
||||
// references, or (2) the reference processing thread is
|
||||
// processing references. Otherwise, returns false immediately.
|
||||
private static boolean waitForReferenceProcessing()
|
||||
throws InterruptedException
|
||||
{
|
||||
synchronized (processPendingLock) {
|
||||
if (processPendingActive || hasReferencePendingList()) {
|
||||
// Wait for progress, not necessarily completion.
|
||||
processPendingLock.wait();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
ThreadGroup tg = Thread.currentThread().getThreadGroup();
|
||||
for (ThreadGroup tgn = tg;
|
||||
tgn != null;
|
||||
tg = tgn, tgn = tg.getParent());
|
||||
Thread handler = new ReferenceHandler(tg, "Reference Handler");
|
||||
/* If there were a special system-only priority greater than
|
||||
* MAX_PRIORITY, it would be used here
|
||||
*/
|
||||
handler.setPriority(Thread.MAX_PRIORITY);
|
||||
handler.setDaemon(true);
|
||||
handler.start();
|
||||
|
||||
// provide access in SharedSecrets
|
||||
SharedSecrets.setJavaLangRefAccess(new JavaLangRefAccess() {
|
||||
@Override
|
||||
public boolean waitForReferenceProcessing()
|
||||
throws InterruptedException
|
||||
{
|
||||
return Reference.waitForReferenceProcessing();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* -- Referent accessor and setters -- */
|
||||
|
||||
/**
|
||||
* Returns this reference object's referent. If this reference object has
|
||||
* been cleared, either by the program or by the garbage collector, then
|
||||
* this method returns <code>null</code>.
|
||||
*
|
||||
* @return The object to which this reference refers, or
|
||||
* <code>null</code> if this reference object has been cleared
|
||||
*/
|
||||
@HotSpotIntrinsicCandidate
|
||||
public T get() {
|
||||
return this.referent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears this reference object. Invoking this method will not cause this
|
||||
* object to be enqueued.
|
||||
*
|
||||
* <p> This method is invoked only by Java code; when the garbage collector
|
||||
* clears references it does so directly, without invoking this method.
|
||||
*/
|
||||
public void clear() {
|
||||
this.referent = null;
|
||||
}
|
||||
|
||||
/* -- Queue operations -- */
|
||||
|
||||
/**
|
||||
* Tells whether or not this reference object has been enqueued, either by
|
||||
* the program or by the garbage collector. If this reference object was
|
||||
* not registered with a queue when it was created, then this method will
|
||||
* always return <code>false</code>.
|
||||
*
|
||||
* @return <code>true</code> if and only if this reference object has
|
||||
* been enqueued
|
||||
*/
|
||||
public boolean isEnqueued() {
|
||||
return (this.queue == ReferenceQueue.ENQUEUED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears this reference object and adds it to the queue with which
|
||||
* it is registered, if any.
|
||||
*
|
||||
* <p> This method is invoked only by Java code; when the garbage collector
|
||||
* enqueues references it does so directly, without invoking this method.
|
||||
*
|
||||
* @return <code>true</code> if this reference object was successfully
|
||||
* enqueued; <code>false</code> if it was already enqueued or if
|
||||
* it was not registered with a queue when it was created
|
||||
*/
|
||||
public boolean enqueue() {
|
||||
if (!ClearBeforeEnqueue.DISABLE)
|
||||
this.referent = null;
|
||||
return this.queue.enqueue(this);
|
||||
}
|
||||
|
||||
/* -- Constructors -- */
|
||||
|
||||
Reference(T referent) {
|
||||
this(referent, null);
|
||||
}
|
||||
|
||||
Reference(T referent, ReferenceQueue<? super T> queue) {
|
||||
this.referent = referent;
|
||||
this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the object referenced by the given reference remains
|
||||
* <a href="package-summary.html#reachability"><em>strongly reachable</em></a>,
|
||||
* regardless of any prior actions of the program that might otherwise cause
|
||||
* the object to become unreachable; thus, the referenced object is not
|
||||
* reclaimable by garbage collection at least until after the invocation of
|
||||
* this method. Invocation of this method does not itself initiate garbage
|
||||
* collection or finalization.
|
||||
*
|
||||
* <p> This method establishes an ordering for
|
||||
* <a href="package-summary.html#reachability"><em>strong reachability</em></a>
|
||||
* with respect to garbage collection. It controls relations that are
|
||||
* otherwise only implicit in a program -- the reachability conditions
|
||||
* triggering garbage collection. This method is designed for use in
|
||||
* uncommon situations of premature finalization where using
|
||||
* {@code synchronized} blocks or methods, or using other synchronization
|
||||
* facilities are not possible or do not provide the desired control. This
|
||||
* method is applicable only when reclamation may have visible effects,
|
||||
* which is possible for objects with finalizers (See
|
||||
* <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.6">
|
||||
* Section 12.6 17 of <cite>The Java™ Language Specification</cite></a>)
|
||||
* that are implemented in ways that rely on ordering control for correctness.
|
||||
*
|
||||
* @apiNote
|
||||
* Finalization may occur whenever the virtual machine detects that no
|
||||
* reference to an object will ever be stored in the heap: The garbage
|
||||
* collector may reclaim an object even if the fields of that object are
|
||||
* still in use, so long as the object has otherwise become unreachable.
|
||||
* This may have surprising and undesirable effects in cases such as the
|
||||
* following example in which the bookkeeping associated with a class is
|
||||
* managed through array indices. Here, method {@code action} uses a
|
||||
* {@code reachabilityFence} to ensure that the {@code Resource} object is
|
||||
* not reclaimed before bookkeeping on an associated
|
||||
* {@code ExternalResource} has been performed; in particular here, to
|
||||
* ensure that the array slot holding the {@code ExternalResource} is not
|
||||
* nulled out in method {@link Object#finalize}, which may otherwise run
|
||||
* concurrently.
|
||||
*
|
||||
* <pre> {@code
|
||||
* class Resource {
|
||||
* private static ExternalResource[] externalResourceArray = ...
|
||||
*
|
||||
* int myIndex;
|
||||
* Resource(...) {
|
||||
* myIndex = ...
|
||||
* externalResourceArray[myIndex] = ...;
|
||||
* ...
|
||||
* }
|
||||
* protected void finalize() {
|
||||
* externalResourceArray[myIndex] = null;
|
||||
* ...
|
||||
* }
|
||||
* public void action() {
|
||||
* try {
|
||||
* // ...
|
||||
* int i = myIndex;
|
||||
* Resource.update(externalResourceArray[i]);
|
||||
* } finally {
|
||||
* Reference.reachabilityFence(this);
|
||||
* }
|
||||
* }
|
||||
* private static void update(ExternalResource ext) {
|
||||
* ext.status = ...;
|
||||
* }
|
||||
* }}</pre>
|
||||
*
|
||||
* Here, the invocation of {@code reachabilityFence} is nonintuitively
|
||||
* placed <em>after</em> the call to {@code update}, to ensure that the
|
||||
* array slot is not nulled out by {@link Object#finalize} before the
|
||||
* update, even if the call to {@code action} was the last use of this
|
||||
* object. This might be the case if, for example a usage in a user program
|
||||
* had the form {@code new Resource().action();} which retains no other
|
||||
* reference to this {@code Resource}. While probably overkill here,
|
||||
* {@code reachabilityFence} is placed in a {@code finally} block to ensure
|
||||
* that it is invoked across all paths in the method. In a method with more
|
||||
* complex control paths, you might need further precautions to ensure that
|
||||
* {@code reachabilityFence} is encountered along all of them.
|
||||
*
|
||||
* <p> It is sometimes possible to better encapsulate use of
|
||||
* {@code reachabilityFence}. Continuing the above example, if it were
|
||||
* acceptable for the call to method {@code update} to proceed even if the
|
||||
* finalizer had already executed (nulling out slot), then you could
|
||||
* localize use of {@code reachabilityFence}:
|
||||
*
|
||||
* <pre> {@code
|
||||
* public void action2() {
|
||||
* // ...
|
||||
* Resource.update(getExternalResource());
|
||||
* }
|
||||
* private ExternalResource getExternalResource() {
|
||||
* ExternalResource ext = externalResourceArray[myIndex];
|
||||
* Reference.reachabilityFence(this);
|
||||
* return ext;
|
||||
* }}</pre>
|
||||
*
|
||||
* <p> Method {@code reachabilityFence} is not required in constructions
|
||||
* that themselves ensure reachability. For example, because objects that
|
||||
* are locked cannot, in general, be reclaimed, it would suffice if all
|
||||
* accesses of the object, in all methods of class {@code Resource}
|
||||
* (including {@code finalize}) were enclosed in {@code synchronized (this)}
|
||||
* blocks. (Further, such blocks must not include infinite loops, or
|
||||
* themselves be unreachable, which fall into the corner case exceptions to
|
||||
* the "in general" disclaimer.) However, method {@code reachabilityFence}
|
||||
* remains a better option in cases where this approach is not as efficient,
|
||||
* desirable, or possible; for example because it would encounter deadlock.
|
||||
*
|
||||
* @param ref the reference. If {@code null}, this method has no effect.
|
||||
* @since 9
|
||||
*/
|
||||
@DontInline
|
||||
public static void reachabilityFence(Object ref) {
|
||||
// Does nothing, because this method is annotated with @DontInline
|
||||
// HotSpot needs to retain the ref and not GC it before a call to this
|
||||
// method
|
||||
}
|
||||
}
|
203
src/java.base/share/classes/java/lang/ref/ReferenceQueue.java
Normal file
203
src/java.base/share/classes/java/lang/ref/ReferenceQueue.java
Normal file
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package java.lang.ref;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import jdk.internal.misc.VM;
|
||||
|
||||
/**
|
||||
* Reference queues, to which registered reference objects are appended by the
|
||||
* garbage collector after the appropriate reachability changes are detected.
|
||||
*
|
||||
* @author Mark Reinhold
|
||||
* @since 1.2
|
||||
*/
|
||||
|
||||
public class ReferenceQueue<T> {
|
||||
|
||||
/**
|
||||
* Constructs a new reference-object queue.
|
||||
*/
|
||||
public ReferenceQueue() { }
|
||||
|
||||
private static class Null<S> extends ReferenceQueue<S> {
|
||||
boolean enqueue(Reference<? extends S> r) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static ReferenceQueue<Object> NULL = new Null<>();
|
||||
static ReferenceQueue<Object> ENQUEUED = new Null<>();
|
||||
|
||||
private static class Lock { };
|
||||
private Lock lock = new Lock();
|
||||
private volatile Reference<? extends T> head;
|
||||
private long queueLength = 0;
|
||||
|
||||
boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */
|
||||
synchronized (lock) {
|
||||
// Check that since getting the lock this reference hasn't already been
|
||||
// enqueued (and even then removed)
|
||||
ReferenceQueue<?> queue = r.queue;
|
||||
if ((queue == NULL) || (queue == ENQUEUED)) {
|
||||
return false;
|
||||
}
|
||||
assert queue == this;
|
||||
r.next = (head == null) ? r : head;
|
||||
head = r;
|
||||
queueLength++;
|
||||
// Update r.queue *after* adding to list, to avoid race
|
||||
// with concurrent enqueued checks and fast-path poll().
|
||||
// Volatiles ensure ordering.
|
||||
r.queue = ENQUEUED;
|
||||
if (r instanceof FinalReference) {
|
||||
VM.addFinalRefCount(1);
|
||||
}
|
||||
lock.notifyAll();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private Reference<? extends T> reallyPoll() { /* Must hold lock */
|
||||
Reference<? extends T> r = head;
|
||||
if (r != null) {
|
||||
r.queue = NULL;
|
||||
// Update r.queue *before* removing from list, to avoid
|
||||
// race with concurrent enqueued checks and fast-path
|
||||
// poll(). Volatiles ensure ordering.
|
||||
@SuppressWarnings("unchecked")
|
||||
Reference<? extends T> rn = r.next;
|
||||
head = (rn == r) ? null : rn;
|
||||
r.next = r;
|
||||
queueLength--;
|
||||
if (r instanceof FinalReference) {
|
||||
VM.addFinalRefCount(-1);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls this queue to see if a reference object is available. If one is
|
||||
* available without further delay then it is removed from the queue and
|
||||
* returned. Otherwise this method immediately returns {@code null}.
|
||||
*
|
||||
* @return A reference object, if one was immediately available,
|
||||
* otherwise {@code null}
|
||||
*/
|
||||
public Reference<? extends T> poll() {
|
||||
if (head == null)
|
||||
return null;
|
||||
synchronized (lock) {
|
||||
return reallyPoll();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the next reference object in this queue, blocking until either
|
||||
* one becomes available or the given timeout period expires.
|
||||
*
|
||||
* <p> This method does not offer real-time guarantees: It schedules the
|
||||
* timeout as if by invoking the {@link Object#wait(long)} method.
|
||||
*
|
||||
* @param timeout If positive, block for up to {@code timeout}
|
||||
* milliseconds while waiting for a reference to be
|
||||
* added to this queue. If zero, block indefinitely.
|
||||
*
|
||||
* @return A reference object, if one was available within the specified
|
||||
* timeout period, otherwise {@code null}
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the value of the timeout argument is negative
|
||||
*
|
||||
* @throws InterruptedException
|
||||
* If the timeout wait is interrupted
|
||||
*/
|
||||
public Reference<? extends T> remove(long timeout)
|
||||
throws IllegalArgumentException, InterruptedException
|
||||
{
|
||||
if (timeout < 0) {
|
||||
throw new IllegalArgumentException("Negative timeout value");
|
||||
}
|
||||
synchronized (lock) {
|
||||
Reference<? extends T> r = reallyPoll();
|
||||
if (r != null) return r;
|
||||
long start = (timeout == 0) ? 0 : System.nanoTime();
|
||||
for (;;) {
|
||||
lock.wait(timeout);
|
||||
r = reallyPoll();
|
||||
if (r != null) return r;
|
||||
if (timeout != 0) {
|
||||
long end = System.nanoTime();
|
||||
timeout -= (end - start) / 1000_000;
|
||||
if (timeout <= 0) return null;
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the next reference object in this queue, blocking until one
|
||||
* becomes available.
|
||||
*
|
||||
* @return A reference object, blocking until one becomes available
|
||||
* @throws InterruptedException If the wait is interrupted
|
||||
*/
|
||||
public Reference<? extends T> remove() throws InterruptedException {
|
||||
return remove(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate queue and invoke given action with each Reference.
|
||||
* Suitable for diagnostic purposes.
|
||||
* WARNING: any use of this method should make sure to not
|
||||
* retain the referents of iterated references (in case of
|
||||
* FinalReference(s)) so that their life is not prolonged more
|
||||
* than necessary.
|
||||
*/
|
||||
void forEach(Consumer<? super Reference<? extends T>> action) {
|
||||
for (Reference<? extends T> r = head; r != null;) {
|
||||
action.accept(r);
|
||||
@SuppressWarnings("unchecked")
|
||||
Reference<? extends T> rn = r.next;
|
||||
if (rn == r) {
|
||||
if (r.queue == ENQUEUED) {
|
||||
// still enqueued -> we reached end of chain
|
||||
r = null;
|
||||
} else {
|
||||
// already dequeued: r.queue == NULL; ->
|
||||
// restart from head when overtaken by queue poller(s)
|
||||
r = head;
|
||||
}
|
||||
} else {
|
||||
// next in chain
|
||||
r = rn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
118
src/java.base/share/classes/java/lang/ref/SoftReference.java
Normal file
118
src/java.base/share/classes/java/lang/ref/SoftReference.java
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2003, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package java.lang.ref;
|
||||
|
||||
|
||||
/**
|
||||
* Soft reference objects, which are cleared at the discretion of the garbage
|
||||
* collector in response to memory demand. Soft references are most often used
|
||||
* to implement memory-sensitive caches.
|
||||
*
|
||||
* <p> Suppose that the garbage collector determines at a certain point in time
|
||||
* that an object is <a href="package-summary.html#reachability">softly
|
||||
* reachable</a>. At that time it may choose to clear atomically all soft
|
||||
* references to that object and all soft references to any other
|
||||
* softly-reachable objects from which that object is reachable through a chain
|
||||
* of strong references. At the same time or at some later time it will
|
||||
* enqueue those newly-cleared soft references that are registered with
|
||||
* reference queues.
|
||||
*
|
||||
* <p> All soft references to softly-reachable objects are guaranteed to have
|
||||
* been cleared before the virtual machine throws an
|
||||
* {@code OutOfMemoryError}. Otherwise no constraints are placed upon the
|
||||
* time at which a soft reference will be cleared or the order in which a set
|
||||
* of such references to different objects will be cleared. Virtual machine
|
||||
* implementations are, however, encouraged to bias against clearing
|
||||
* recently-created or recently-used soft references.
|
||||
*
|
||||
* <p> Direct instances of this class may be used to implement simple caches;
|
||||
* this class or derived subclasses may also be used in larger data structures
|
||||
* to implement more sophisticated caches. As long as the referent of a soft
|
||||
* reference is strongly reachable, that is, is actually in use, the soft
|
||||
* reference will not be cleared. Thus a sophisticated cache can, for example,
|
||||
* prevent its most recently used entries from being discarded by keeping
|
||||
* strong referents to those entries, leaving the remaining entries to be
|
||||
* discarded at the discretion of the garbage collector.
|
||||
*
|
||||
* @author Mark Reinhold
|
||||
* @since 1.2
|
||||
*/
|
||||
|
||||
public class SoftReference<T> extends Reference<T> {
|
||||
|
||||
/**
|
||||
* Timestamp clock, updated by the garbage collector
|
||||
*/
|
||||
private static long clock;
|
||||
|
||||
/**
|
||||
* Timestamp updated by each invocation of the get method. The VM may use
|
||||
* this field when selecting soft references to be cleared, but it is not
|
||||
* required to do so.
|
||||
*/
|
||||
private long timestamp;
|
||||
|
||||
/**
|
||||
* Creates a new soft reference that refers to the given object. The new
|
||||
* reference is not registered with any queue.
|
||||
*
|
||||
* @param referent object the new soft reference will refer to
|
||||
*/
|
||||
public SoftReference(T referent) {
|
||||
super(referent);
|
||||
this.timestamp = clock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new soft reference that refers to the given object and is
|
||||
* registered with the given queue.
|
||||
*
|
||||
* @param referent object the new soft reference will refer to
|
||||
* @param q the queue with which the reference is to be registered,
|
||||
* or {@code null} if registration is not required
|
||||
*
|
||||
*/
|
||||
public SoftReference(T referent, ReferenceQueue<? super T> q) {
|
||||
super(referent, q);
|
||||
this.timestamp = clock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this reference object's referent. If this reference object has
|
||||
* been cleared, either by the program or by the garbage collector, then
|
||||
* this method returns {@code null}.
|
||||
*
|
||||
* @return The object to which this reference refers, or
|
||||
* {@code null} if this reference object has been cleared
|
||||
*/
|
||||
public T get() {
|
||||
T o = super.get();
|
||||
if (o != null && this.timestamp != clock)
|
||||
this.timestamp = clock;
|
||||
return o;
|
||||
}
|
||||
|
||||
}
|
72
src/java.base/share/classes/java/lang/ref/WeakReference.java
Normal file
72
src/java.base/share/classes/java/lang/ref/WeakReference.java
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2003, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package java.lang.ref;
|
||||
|
||||
|
||||
/**
|
||||
* Weak reference objects, which do not prevent their referents from being
|
||||
* made finalizable, finalized, and then reclaimed. Weak references are most
|
||||
* often used to implement canonicalizing mappings.
|
||||
*
|
||||
* <p> Suppose that the garbage collector determines at a certain point in time
|
||||
* that an object is <a href="package-summary.html#reachability">weakly
|
||||
* reachable</a>. At that time it will atomically clear all weak references to
|
||||
* that object and all weak references to any other weakly-reachable objects
|
||||
* from which that object is reachable through a chain of strong and soft
|
||||
* references. At the same time it will declare all of the formerly
|
||||
* weakly-reachable objects to be finalizable. At the same time or at some
|
||||
* later time it will enqueue those newly-cleared weak references that are
|
||||
* registered with reference queues.
|
||||
*
|
||||
* @author Mark Reinhold
|
||||
* @since 1.2
|
||||
*/
|
||||
|
||||
public class WeakReference<T> extends Reference<T> {
|
||||
|
||||
/**
|
||||
* Creates a new weak reference that refers to the given object. The new
|
||||
* reference is not registered with any queue.
|
||||
*
|
||||
* @param referent object the new weak reference will refer to
|
||||
*/
|
||||
public WeakReference(T referent) {
|
||||
super(referent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new weak reference that refers to the given object and is
|
||||
* registered with the given queue.
|
||||
*
|
||||
* @param referent object the new weak reference will refer to
|
||||
* @param q the queue with which the reference is to be registered,
|
||||
* or {@code null} if registration is not required
|
||||
*/
|
||||
public WeakReference(T referent, ReferenceQueue<? super T> q) {
|
||||
super(referent, q);
|
||||
}
|
||||
|
||||
}
|
131
src/java.base/share/classes/java/lang/ref/package-info.java
Normal file
131
src/java.base/share/classes/java/lang/ref/package-info.java
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2016, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides reference-object classes, which support a limited degree
|
||||
* of interaction with the garbage collector. A program may use a
|
||||
* reference object to maintain a reference to some other object in
|
||||
* such a way that the latter object may still be reclaimed by the
|
||||
* collector. A program may also arrange to be notified some time
|
||||
* after the collector has determined that the reachability of a given
|
||||
* object has changed.
|
||||
*
|
||||
*<h2>Package Specification</h2>
|
||||
*
|
||||
* A <em>reference object</em> encapsulates a reference to some other
|
||||
* object so that the reference itself may be examined and manipulated
|
||||
* like any other object. Three types of reference objects are
|
||||
* provided, each weaker than the last: <em>soft</em>, <em>weak</em>,
|
||||
* and <em>phantom</em>. Each type corresponds to a different level
|
||||
* of reachability, as defined below. Soft references are for
|
||||
* 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 post-mortem cleanup actions.
|
||||
* Post-mortem cleanup actions can be registered and managed by a
|
||||
* {@link java.lang.ref.Cleaner}.
|
||||
*
|
||||
* <p> Each reference-object type is implemented by a subclass of the
|
||||
* abstract base {@link java.lang.ref.Reference} class.
|
||||
* An instance of one of these subclasses encapsulates a single
|
||||
* reference to a particular object, called the <em>referent</em>.
|
||||
* Every reference object provides methods for getting and clearing
|
||||
* the reference. Aside from the clearing operation reference objects
|
||||
* are otherwise immutable, so no {@code set} operation is
|
||||
* provided. A program may further subclass these subclasses, adding
|
||||
* whatever fields and methods are required for its purposes, or it
|
||||
* may use these subclasses without change.
|
||||
*
|
||||
* <h3>Notification</h3>
|
||||
*
|
||||
* A program may request to be notified of changes in an object's
|
||||
* reachability by <em>registering</em> an appropriate reference
|
||||
* 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 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.
|
||||
*
|
||||
* <p> The relationship between a registered reference object and its
|
||||
* queue is one-sided. That is, a queue does not keep track of the
|
||||
* references that are registered with it. If a registered reference
|
||||
* becomes unreachable itself, then it will never be enqueued. It is
|
||||
* the responsibility of the program using reference objects to ensure
|
||||
* that the objects remain reachable for as long as the program is
|
||||
* interested in their referents.
|
||||
*
|
||||
* <p> While some programs will choose to dedicate a thread to
|
||||
* removing reference objects from one or more queues and processing
|
||||
* them, this is by no means necessary. A tactic that often works
|
||||
* well is to examine a reference queue in the course of performing
|
||||
* some other fairly-frequent action. For example, a hashtable that
|
||||
* uses weak references to implement weak keys could poll its
|
||||
* reference queue each time the table is accessed. This is how the
|
||||
* {@link java.util.WeakHashMap} class works. Because
|
||||
* the {@link java.lang.ref.ReferenceQueue#poll
|
||||
* ReferenceQueue.poll} method simply checks an internal data
|
||||
* structure, this check will add little overhead to the hashtable
|
||||
* access methods.
|
||||
*
|
||||
* <a id="reachability"></a>
|
||||
* <h3>Reachability</h3>
|
||||
*
|
||||
* Going from strongest to weakest, the different levels of
|
||||
* reachability reflect the life cycle of an object. They are
|
||||
* operationally defined as follows:
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li> An object is <em>strongly reachable</em> if it can be reached
|
||||
* by some thread without traversing any reference objects. A
|
||||
* newly-created object is strongly reachable by the thread that
|
||||
* created it.
|
||||
*
|
||||
* <li> An object is <em>softly reachable</em> if it is not strongly
|
||||
* reachable but can be reached by traversing a soft reference.
|
||||
*
|
||||
* <li> An object is <em>weakly reachable</em> if it is neither
|
||||
* strongly nor softly reachable but can be reached by traversing a
|
||||
* weak reference. When the weak references to a weakly-reachable
|
||||
* object are cleared, the object becomes eligible for finalization.
|
||||
*
|
||||
* <li> An object is <em>phantom reachable</em> if it is neither
|
||||
* strongly, softly, nor weakly reachable, it has been finalized, and
|
||||
* some phantom reference refers to it.
|
||||
*
|
||||
* <li> Finally, an object is <em>unreachable</em>, and therefore
|
||||
* eligible for reclamation, when it is not reachable in any of the
|
||||
* above ways.
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* @author Mark Reinhold
|
||||
* @since 1.2
|
||||
*/
|
||||
package java.lang.ref;
|
Loading…
Add table
Add a link
Reference in a new issue