On 04/06/2018 10:02 AM, Alan Bateman wrote:
On 05/04/2018 22:45, Tony Printezis wrote:
Hi all,
We recently hit another interesting issue with the NIO thread-local
DirectByteBuffer cache. One of our services seems to create and drop
threads at regular intervals. I assume this is due to a thread pool
dynamically resizing itself.
Let's say a thread starts, lives long enough for its Thread object to be
promoted to the old gen (along with its cached direct buffer), then
exits.
This will result in its cached direct buffer(s) being unreachable in the
old gen and will only be reclaimed after the next full GC /
concurrent GC
cycle.
Right, if a short lived thread does I/O with a buffer backed by an
array in the heap then any direct buffers in its thread local cache
won't be freed until there is a GC and reference processing. It's
something that I've prototyped a few times and always leaned towards
not exposing anything in the API, instead just hooking into the thread
exit to clear the buffer cache. One thing to watch out for is that the
buffer cache may not exist (as the thread didn't do any I/O with heap
buffers) so you'll end up creating (an empty) buffer cache at thread
exit. That is benign of course but still unsettling to have additional
code executing at this time.
-Alan
An internal method, let's say ThreadLocal.probe(), that would return
thread-local value only if it has already been initialized, would be
helpfull. Maybe it could be exposed as new public API too. I remember
that I needed it in the past:
public T probe() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return null;
}
Regards, Peter