-
Bug
-
Resolution: Duplicate
-
P3
-
None
-
24, 25
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). BeforeJDK-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 ----------
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
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 ----------
- duplicates
-
JDK-8357637 Native resources cached in thread locals not released when FJP common pool threads clears thread locals
-
- In Progress
-
- relates to
-
JDK-8285638 Unexpected change of behavior of ForkJoin common pool clearing thread locals
-
- Open
-
-
JDK-8344882 (bf) Temporary direct buffers should not count against the upper limit on direct buffer memory
-
- Resolved
-