This is an automated email from the ASF dual-hosted git repository.
ivandasch pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new eeb5535fe33 IGNITE-20515 Fix MappedFile.map for JDK 14 and newer.
(#10961)
eeb5535fe33 is described below
commit eeb5535fe3323f85b4790b835010287a37f58551
Author: Ivan Daschinskiy <[email protected]>
AuthorDate: Mon Oct 2 14:31:04 2023 +0300
IGNITE-20515 Fix MappedFile.map for JDK 14 and newer. (#10961)
---
.../ignite/internal/mem/file/MappedFile.java | 186 ++++++++++++++++++---
1 file changed, 163 insertions(+), 23 deletions(-)
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/mem/file/MappedFile.java
b/modules/core/src/main/java/org/apache/ignite/internal/mem/file/MappedFile.java
index 4b7552491c6..f264d87a315 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/mem/file/MappedFile.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/mem/file/MappedFile.java
@@ -19,26 +19,28 @@ package org.apache.ignite.internal.mem.file;
import java.io.Closeable;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.internal.mem.DirectMemoryRegion;
import org.apache.ignite.internal.mem.UnsafeChunk;
import org.apache.ignite.internal.util.typedef.internal.U;
import sun.nio.ch.FileChannelImpl;
+import static org.apache.ignite.internal.util.IgniteUtils.jdkVersion;
+import static org.apache.ignite.internal.util.IgniteUtils.majorJavaVersion;
+
/** */
public class MappedFile implements Closeable, DirectMemoryRegion {
- /** */
- private static final Method map0 =
U.findNonPublicMethod(FileChannelImpl.class, "map0", int.class, long.class,
long.class);
-
- /** */
- private static final Method unmap0 =
U.findNonPublicMethod(FileChannelImpl.class, "unmap0", long.class, long.class);
-
/** */
public static final int MAP_RW = 1;
+ /** File memory mapper */
+ private static final Mapper mapper = pickMapper();
+
/** */
private final RandomAccessFile file;
@@ -85,7 +87,7 @@ public class MappedFile implements Closeable,
DirectMemoryRegion {
/** {@inheritDoc} */
@Override public void close() throws IOException {
try {
- unmap(addr, size);
+ mapper.unmap(addr, size);
}
finally {
file.close();
@@ -122,16 +124,7 @@ public class MappedFile implements Closeable,
DirectMemoryRegion {
* @throws IOException
*/
public static long map(RandomAccessFile f, int mode, long start, long
size) throws IOException {
- try {
- return (Long)map0.invoke(f.getChannel(), mode, start, size);
- }
- catch (IllegalAccessException e) {
- throw new IllegalStateException(e);
- }
- catch (InvocationTargetException e) {
- Throwable target = e.getTargetException();
- throw (target instanceof IOException) ? (IOException)target : new
IOException(target);
- }
+ return mapper.map(f, mode, start, size);
}
/**
@@ -141,14 +134,161 @@ public class MappedFile implements Closeable,
DirectMemoryRegion {
* @param size Size of the mapped file.
*/
public static void unmap(long addr, long size) {
- try {
- unmap0.invoke(null, addr, size);
+ mapper.unmap(addr, size);
+ }
+
+ /** */
+ private static Mapper pickMapper() {
+ int javaVersion = majorJavaVersion(jdkVersion());
+
+ if (javaVersion >= 19)
+ return new JDK19Mapper();
+
+ if (javaVersion >= 14)
+ return new JDK14Mapper();
+
+ return new LegacyMapper();
+ }
+
+ /** */
+ private interface Mapper {
+ /** */
+ long map(RandomAccessFile f, int mode, long start, long size) throws
IOException;
+
+ /** */
+ void unmap(long addr, long size);
+ }
+
+ /** */
+ private static class LegacyMapper implements Mapper {
+ /** */
+ private static final Method map0 =
U.findNonPublicMethod(FileChannelImpl.class, "map0", int.class, long.class,
long.class);
+
+ /** */
+ private static final Method unmap0 =
U.findNonPublicMethod(FileChannelImpl.class, "unmap0", long.class, long.class);
+
+
+ /** {@inheritDoc} */
+ @Override public long map(RandomAccessFile f, int mode, long start,
long size) throws IOException {
+ try {
+ return (Long)map0.invoke(f.getChannel(), mode, start, size);
+ }
+ catch (IllegalAccessException e) {
+ throw new IllegalStateException(e);
+ }
+ catch (InvocationTargetException e) {
+ Throwable target = e.getTargetException();
+ throw (target instanceof IOException) ? (IOException)target :
new IOException(target);
+ }
}
- catch (IllegalAccessException e) {
- throw new IllegalStateException(e);
+
+ /** {@inheritDoc} */
+ @Override public void unmap(long addr, long size) {
+ try {
+ unmap0.invoke(null, addr, size);
+ }
+ catch (IllegalAccessException e) {
+ throw new IllegalStateException(e);
+ }
+ catch (InvocationTargetException e) {
+ throw new IllegalStateException(e.getTargetException());
+ }
}
- catch (InvocationTargetException e) {
- throw new IllegalStateException(e.getTargetException());
+ }
+
+ /** */
+ private static class JDK14Mapper extends LegacyMapper {
+ /** Method {@link FileChannelImpl#map0} has additional parameter since
JDK 14, isSync, {@code false} by default. */
+ private static final Method map0 =
U.findNonPublicMethod(FileChannelImpl.class, "map0", int.class, long.class,
+ long.class, boolean.class);
+
+ /** {@inheritDoc} */
+ @Override public long map(RandomAccessFile f, int mode, long start,
long size) throws IOException {
+ try {
+ return (Long)map0.invoke(f.getChannel(), mode, start, size,
false);
+ }
+ catch (IllegalAccessException e) {
+ throw new IllegalStateException(e);
+ }
+ catch (InvocationTargetException e) {
+ Throwable target = e.getTargetException();
+ throw (target instanceof IOException) ? (IOException)target :
new IOException(target);
+ }
+ }
+ }
+
+ /** */
+ private static class JDK19Mapper implements Mapper {
+ /** */
+ private static final Method map;
+
+ /** */
+ private static final Method unmap;
+
+ /** */
+ private static final Object dispatcher;
+
+ static {
+ try {
+ // These methods are still in {@link FileChannelImpl} class in
JDK 19.
+ Method map0 = U.findNonPublicMethod(FileChannelImpl.class,
"map0", FileDescriptor.class, int.class,
+ long.class, long.class, boolean.class);
+
+ Method unmap0 = U.findNonPublicMethod(FileChannelImpl.class,
"unmap0", long.class, long.class);
+
+ if (map0 != null && unmap0 != null) {
+ map = map0;
+ unmap = unmap0;
+ dispatcher = null;
+ }
+ else {
+ // That methods are moved to {@link
sun.nio.ch.FileDispatcher}.
+ Class<?> fileDispatcherCls =
Class.forName("sun.nio.ch.FileDispatcher");
+
+ dispatcher = U.staticField(FileChannelImpl.class, "nd");
+
+ map = U.findNonPublicMethod(fileDispatcherCls, "map",
FileDescriptor.class, int.class,
+ long.class, long.class, boolean.class);
+
+ unmap = U.findNonPublicMethod(fileDispatcherCls, "unmap",
long.class, long.class);
+
+ }
+ }
+ catch (ClassNotFoundException | IgniteCheckedException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public long map(RandomAccessFile f, int mode, long start,
long size) throws IOException {
+ try {
+ Object fd = U.field(f.getChannel(), "fd");
+
+ if (dispatcher != null)
+ return (Long)map.invoke(dispatcher, fd, mode, start, size,
false);
+ else
+ return (Long)map.invoke(f.getChannel(), fd, mode, start,
size, false);
+ }
+ catch (IllegalAccessException e) {
+ throw new IllegalStateException(e);
+ }
+ catch (InvocationTargetException e) {
+ Throwable target = e.getTargetException();
+ throw (target instanceof IOException) ? (IOException)target :
new IOException(target);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void unmap(long addr, long size) {
+ try {
+ unmap.invoke(dispatcher, addr, size); // If dispatcher is
null, the static method will be called.
+ }
+ catch (IllegalAccessException e) {
+ throw new IllegalStateException(e);
+ }
+ catch (InvocationTargetException e) {
+ throw new IllegalStateException(e.getTargetException());
+ }
}
}
}