fix error about usage of DirectBuffer in jdk 16/17
import org.apache.commons.io.IOUtils;
-import sun.nio.ch.DirectBuffer;
-
/**
* {@link InputStream} implementation which uses direct buffer to read a file to avoid extra copy of data between Java
* and native memory which happens when using {@link java.io.BufferedInputStream}. Unfortunately, this is not something
private final FileChannel fileChannel;
+ private static final Class DIRECT_BUFFER_CLASS = getDirectBufferClass();
+
+ private static Class getDirectBufferClass() {
+ Class res = null;
+ try {
+ res = Class.forName("sun.nio.ch.DirectBuffer");
+ } catch (IllegalAccessError | ClassNotFoundException ignored) {
+ }
+ return res;
+ }
+
+ private static boolean isDirectBuffer(Object object) {
+ return DIRECT_BUFFER_CLASS != null && DIRECT_BUFFER_CLASS.isInstance(object);
+ }
+
/**
* Constructs a new instance for the given File.
*
@@ -109,8 +122,8 @@ public synchronized int available() throws IOException {
* @param buffer the buffer to clean.
*/
private void clean(final ByteBuffer buffer) {
- if (buffer instanceof sun.nio.ch.DirectBuffer) {
- clean((sun.nio.ch.DirectBuffer) buffer);
+ if (isDirectBuffer(buffer)) {
+ cleanDirectBuffer(buffer);
}
}
@@ -120,9 +133,9 @@ private void clean(final ByteBuffer buffer) {
* .clean() method is not accessible even with reflection. However sun.misc.Unsafe added a invokeCleaner() method in
* JDK 9+ and this is still accessible with reflection.
*
- * @param buffer the buffer to clean.
+ * @param buffer the buffer to clean. must be a DirectBuffer.
*/
- private void clean(final DirectBuffer buffer) {
+ private void cleanDirectBuffer(final ByteBuffer buffer) {
//
// Ported from StorageUtils.scala.
//
@@ -150,7 +163,7 @@ private void clean(final DirectBuffer buffer) {
// On Java 8, but also compiles on Java 11.
try {
final Class<?> clsCleaner = Class.forName("sun.misc.Cleaner");
- final Method cleanerMethod = DirectBuffer.class.getMethod("cleaner");
+ final Method cleanerMethod = DIRECT_BUFFER_CLASS.getMethod("cleaner");
final Object cleaner = cleanerMethod.invoke(buffer);
if (cleaner != null) {
final Method cleanMethod = clsCleaner.getMethod("clean");
