JDK-8358054 : Memory leak in getTemporaryDirectBuffer when used with the common fork-join pool
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 24,25
  • Priority: P3
  • Status: New
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2025-05-28
  • Updated: 2025-05-29
Related Reports
Relates :  
Relates :  
Description
A DESCRIPTION OF THE PROBLEM :
https://bugs.openjdk.org/browse/JDK-8344882 causes a memory leak when doing I/O using the common fork-join pool, in particular when using anything that calls into Util.getTemporaryDirectBuffer (which includes many basic I/O classes: NioSocketImpl, SocketChannelImpl, IOUtils). The problem is that the common fork-join pool clears thread locals after task completion (https://bugs.openjdk.org/browse/JDK-8285638) and then the thread local BufferCache in sun.nio.ch.Util simply gets garbage collected without freeing the buffers potentially present in the cache (previously manually allocated using Unsafe.allocateMemory). Before JDK-8344882 the buffers allocated by Util.getTemporaryDirectBuffer were registered in a cleaner that correctly ran the cleanup before the buffers in the BufferCache were GCed. 

REGRESSION : Last worked in version 23

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the test case code. To debug this I also instrumented the JVM so that each temporary buffer a) gets its own unique id, b) is flagged when it is correctly freed, c) it is registered in a cleaner that prints a warning whenever a buffer is about to get GCed before the underlying memory was freed.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No memory leak
ACTUAL -
Memory leak

---------- BEGIN SOURCE ----------
import java.io.*;
import java.net.*;
import java.util.stream.*;
import java.util.concurrent.ThreadLocalRandom;

public class Test {
	public void run() {
		while (true) {
			IntStream.rangeClosed(0, 24).boxed().parallel().forEach(x -> {				
				try {
					Thread.sleep(ThreadLocalRandom.current().nextInt(50));
					URL google = new URL("https://www.google.com/");
					URLConnection conn = google.openConnection();
					BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
					String inputLine;
					while ((inputLine = in.readLine()) != null) {
					}
					in.close();
				} catch (IOException e) {
					System.out.println(e);
				} catch (InterruptedException e) {
					System.out.println(e);
				}
			});
		}
	}

	public void fetchGoogle() {
	}

	public static void main(String[] args) {
		Test test = new Test();
		test.run();
	}
}
---------- END SOURCE ----------


Comments
Impact -> H (Regression) Likelihood -> L (No significant memory leaks) Workaround -> M (Somewhere in-between the extremes) Priority -> P3
29-05-2025

The observations on Windows 11: JDK 24.0.1+2: As shown in the attached snapshot of jconsole, there seems no significant memory leaks.
29-05-2025

This looks like a duplicate of JDK-8357637.
29-05-2025