JDK-8202788 : Explicitly reclaim cached thread-local direct buffers at thread exit
  • Type: Task
  • Component: core-libs
  • Sub-Component: java.nio
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2018-05-08
  • Updated: 2022-07-11
  • Resolved: 2018-06-22
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 12 JDK 8 Other
11 b20Fixed 12Fixed 8u301Fixed openjdk8u322Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Description
Some NIO operations need to use a temporary direct buffer (or buffers). Those buffers are cached in a ThreadLocal to avoid repeated calls to malloc/free. When such a buffer is replaced in the cache (typically with a larger one), the old buffer is explicitly reclaimed. Unfortunately, when a thread exits, any buffers that are still cached are not explicitly reclaimed. We instead have to wait for the GC to find them unreachable so that they are reclaimed when their cleaners are called.

The above is not a huge issue in most cases. However, we've had an issue with one of our services that does churn through Threads (which live long enough for their Thread objects + cached buffers to be moved to the old generation) and also does CMS cycles very, very infrequently (like once every few days). As a result, the old gen grows (slowly) with unreachable direct buffers that are holding on to unused direct memory which cause a nasty native memory leak.

It would be helpful to explicitly reclaim any direct buffers in a thread's cache when a thread exists. This introduces an interesting challenge in that the thread has to notify NIO that it's exiting so that NIO can reclaim any cached buffers. I propose to do that by introducing exit hooks to ThreadLocals. This will of course open a huge can of worms. :-) But, we can structure the initial version so that the exit hooks can only be registered within java.base to avoid having to update the ThreadLocal public API.

I'll post a patch with this change to get feedback on it.

(More on this topic in JDK-4469299)
Comments
Fix Request (8u) I would like to backport this patch to openjdk8u for parity with Oracle 8u321. 8u patch has been reviewed by @phh
05-08-2021

8u code review: https://mail.openjdk.java.net/pipermail/jdk8u-dev/2021-August/014143.html
04-08-2021

The jdb test trace001 now fails due to the extra unexpected method calls on thread exit. JDK-8205540
23-06-2018

URL: http://hg.openjdk.java.net/jdk/jdk/rev/106dc156ce6b User: plevart Date: 2018-06-22 16:19:48 +0000
22-06-2018