8202788: Explicitly reclaim cached thread-local direct buffers at thread exit

Add internal TerminatingThreadLocal and use it to free cached thread-local direct buffers and nio-fs native buffers

Reviewed-by: tonyp, alanb
This commit is contained in:
Peter Levart 2018-06-22 17:56:55 +02:00
parent 578576f523
commit 6ec2cfcc49
8 changed files with 398 additions and 47 deletions

View file

@ -36,6 +36,8 @@ import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.LockSupport;
import jdk.internal.misc.TerminatingThreadLocal;
import sun.nio.ch.Interruptible;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
@ -838,6 +840,9 @@ class Thread implements Runnable {
* a chance to clean up before it actually exits.
*/
private void exit() {
if (TerminatingThreadLocal.REGISTRY.isPresent()) {
TerminatingThreadLocal.threadTerminated();
}
if (group != null) {
group.threadTerminated(this);
group = null;

View file

@ -24,6 +24,8 @@
*/
package java.lang;
import jdk.internal.misc.TerminatingThreadLocal;
import java.lang.ref.*;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
@ -170,6 +172,19 @@ public class ThreadLocal<T> {
return setInitialValue();
}
/**
* Returns {@code true} if there is a value in the current thread's copy of
* this thread-local variable, even if that values is {@code null}.
*
* @return {@code true} if current thread has associated value in this
* thread-local variable; {@code false} if not
*/
boolean isPresent() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
return map != null && map.getEntry(this) != null;
}
/**
* Variant of set() to establish initialValue. Used instead
* of set() in case user has overridden the set() method.
@ -180,10 +195,14 @@ public class ThreadLocal<T> {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
if (map != null) {
map.set(this, value);
else
} else {
createMap(t, value);
}
if (this instanceof TerminatingThreadLocal) {
TerminatingThreadLocal.register((TerminatingThreadLocal<?>) this);
}
return value;
}
@ -199,10 +218,11 @@ public class ThreadLocal<T> {
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
if (map != null) {
map.set(this, value);
else
} else {
createMap(t, value);
}
}
/**
@ -218,8 +238,9 @@ public class ThreadLocal<T> {
*/
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
if (m != null) {
m.remove(this);
}
}
/**