Message-ID: From: "vlsi (@vlsi)" To: "pgjdbc/pgjdbc" Date: Wed, 03 Dec 2025 08:14:22 +0000 Subject: [pgjdbc/pgjdbc] PR #3886: fix: avoid memory leaks in Java <= 21 caused by Thread.inheritedAccessControlContext List-Id: X-GitHub-Author-Id: 213894 X-GitHub-Author-Login: vlsi X-GitHub-Issue: 3886 X-GitHub-Labels: bug X-GitHub-Repo: pgjdbc/pgjdbc X-GitHub-State: merged X-GitHub-Type: pull_request X-GitHub-Url: https://github.com/pgjdbc/pgjdbc/pull/3886 Content-Type: text/plain; charset=utf-8 `Thread.inheritedAccessControlContext` inherits the caller `ProtectionDomain`, thus it effectively holds its classloader. There's no way to "unset `inheritedAccessControlContext`". We workaround that by going for ForkJoinPool + ManagedBlocker so it is JDK that creates a thread, thus it should have no `inheritedAccessControlContext`. The logic is as follows: 1) ForkJoinPool task runs on CPU and it processes the queue 2) If the queue is empty, the blocking call delegates to ManagedBlocker It fits nice with FJP: CPU tasks do not create extra threads, and blocking queue operations do not starve FJP CPU threads. See https://stackoverflow.com/questions/78163385/does-postgres-jdbc-lazycleaner-cause-a-classloader-memory-leak/79835942 --- An alternative option could be going for native `java.lang.ref.Cleaner` when running with Java 9+, however, it would still be nice to have a solution for Java 8.