-
Bug
-
Resolution: Duplicate
-
P4
-
None
-
11, 17, 18
-
generic
-
generic
ADDITIONAL SYSTEM INFORMATION :
Tested on Mac and Linux with JDK 17.0.1, but probably broken on other platforms / versions as well.
A DESCRIPTION OF THE PROBLEM :
Found this bug while adding direct IO support to Elasticsearch. A similar bug was reported by someone else inJDK-8248910, but that one was closed as the test case to reproduce it was using JDK-internal APIs. This bug report has a simple reproducing test case using standard Java APIs (+extended open option for direct IO).
The gist of the bug is that using heap byte buffers with direct IO causes an aligned direct byte buffer slice to be added to the buffer cache. This byte buffer does not have a cleaner. When another entry is requested from the cache (with a larger size for example), and no suitable buffer found, the previous one is removed and freed. This freeing of the buffer expects a cleaner to be present, and fails with a NullPointerException.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
The steps to reproduce this issue are shown using a simple Java program below
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Program completes successfully
ACTUAL -
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "jdk.internal.ref.Cleaner.clean()" because the return value of "sun.nio.ch.DirectBuffer.cleaner()" is null
at java.base/sun.nio.ch.Util.free(Util.java:328)
at java.base/sun.nio.ch.Util.getTemporaryDirectBuffer(Util.java:241)
at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:89)
at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:67)
at java.base/sun.nio.ch.FileChannelImpl.write(FileChannelImpl.java:285)
at BugMain.main(BugMain.java:30)
---------- BEGIN SOURCE ----------
import com.sun.nio.file.ExtendedOpenOption;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class BugMain {
public static void main(String... args) throws IOException {
FileChannel chan1 = FileChannel.open(Paths.get("bla1"),
StandardOpenOption.WRITE, StandardOpenOption.CREATE, ExtendedOpenOption.DIRECT);
FileChannel chan2 = FileChannel.open(Paths.get("bla2"),
StandardOpenOption.WRITE, StandardOpenOption.CREATE);
int blockSize = Math.toIntExact(Files.getFileStore(Paths.get("bla1")).getBlockSize());
chan1.write(ByteBuffer.allocate(blockSize));
chan2.write(ByteBuffer.allocate(blockSize + 1));
}
}
---------- END SOURCE ----------
Tested on Mac and Linux with JDK 17.0.1, but probably broken on other platforms / versions as well.
A DESCRIPTION OF THE PROBLEM :
Found this bug while adding direct IO support to Elasticsearch. A similar bug was reported by someone else in
The gist of the bug is that using heap byte buffers with direct IO causes an aligned direct byte buffer slice to be added to the buffer cache. This byte buffer does not have a cleaner. When another entry is requested from the cache (with a larger size for example), and no suitable buffer found, the previous one is removed and freed. This freeing of the buffer expects a cleaner to be present, and fails with a NullPointerException.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
The steps to reproduce this issue are shown using a simple Java program below
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Program completes successfully
ACTUAL -
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "jdk.internal.ref.Cleaner.clean()" because the return value of "sun.nio.ch.DirectBuffer.cleaner()" is null
at java.base/sun.nio.ch.Util.free(Util.java:328)
at java.base/sun.nio.ch.Util.getTemporaryDirectBuffer(Util.java:241)
at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:89)
at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:67)
at java.base/sun.nio.ch.FileChannelImpl.write(FileChannelImpl.java:285)
at BugMain.main(BugMain.java:30)
---------- BEGIN SOURCE ----------
import com.sun.nio.file.ExtendedOpenOption;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class BugMain {
public static void main(String... args) throws IOException {
FileChannel chan1 = FileChannel.open(Paths.get("bla1"),
StandardOpenOption.WRITE, StandardOpenOption.CREATE, ExtendedOpenOption.DIRECT);
FileChannel chan2 = FileChannel.open(Paths.get("bla2"),
StandardOpenOption.WRITE, StandardOpenOption.CREATE);
int blockSize = Math.toIntExact(Files.getFileStore(Paths.get("bla1")).getBlockSize());
chan1.write(ByteBuffer.allocate(blockSize));
chan2.write(ByteBuffer.allocate(blockSize + 1));
}
}
---------- END SOURCE ----------
- relates to
-
JDK-8248910 NPE when freeing the memory for a slice from a buffer
-
- Closed
-