On Wed, 28 May 2025 14:27:40 GMT, Viktor Klang <vkl...@openjdk.org> wrote:
>> A ForkJoinPool can be created with worker threads that clear thread locals >> between tasks, thus avoiding a build up of thread locals left behind by >> tasks executed in the pool. The common pool does this. Erasing thread locals >> (by writing null to Thread.threadLocals) grinds with thread locals that keep >> native memory alive, esp. when there isn't a Cleaner or other means to free >> the memory. >> >> For the JDK, this is currently an issue for the NIO direct buffer cache. If >> a task running on a thread in the common pool does socket or network channel >> I/O then it can leak when the task terminates. Prior to JDK 24 each buffer >> in the cache had a cleaner, as if allocated by ByteBuffer.allocateDirect, so >> it had some chance of being released. The changes in >> [JDK-8344882](https://bugs.openjdk.org/browse/JDK-8344882) mean there is no >> longer is cleaner for buffers in the cache. >> >> The options in the short term are to restore the cleaner, register a clearer >> for the buffer cache, have the FJP resetThreadLocals special case >> "terminating thread locals", or move the terminating thread locals to a >> different TL map. Viktor Klang, Doug Lea, and I discussed this topic >> recently and agreed the best short term approach is to split the map. As >> terminating thread locals are for platform threads then the map can be in >> the Thread.FieldHolder and avoid adding another field to Thread. Medium to >> long term require further thought in this area, including seeing what might >> be useful (and safe) to expose. >> >> Testing 1-5. Performance testing ongoing. > > src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java line 549: > >> 547: void removeCarrierThreadLocal(CarrierThreadLocal<?> local); >> 548: >> 549: /** > > Copyright update? It's already up to date so no change. > src/java.base/share/classes/jdk/internal/misc/TerminatingThreadLocal.java > line 82: > >> 80: */ >> 81: public static void register(TerminatingThreadLocal<?> tl) { >> 82: if (tl != REGISTRY) { > > Would this happen in any well-behaved application? If not, might be better to > throw an exception? 🤔 It's just a consequence of the registry being a ttl, we either check it here or in set, it's more local here. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/25457#discussion_r2115634840 PR Review Comment: https://git.openjdk.org/jdk/pull/25457#discussion_r2115633931