CavalliumDBEngine/src/main/java/it/cavallium/dbengine/database/disk/MemorySegmentUtils.java

130 lines
4.1 KiB
Java
Raw Normal View History

2021-09-02 21:14:26 +02:00
package it.cavallium.dbengine.database.disk;
2021-09-17 16:56:28 +02:00
import io.net5.util.internal.PlatformDependent;
2021-09-02 21:14:26 +02:00
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.nio.ByteBuffer;
public class MemorySegmentUtils {
private static final MethodHandle OF_NATIVE_RESTRICTED;
private static final MethodHandle AS_SLICE;
private static final MethodHandle AS_BYTE_BUFFER;
private static Throwable cause;
private static final Object NATIVE;
static {
2021-09-22 11:03:39 +02:00
Lookup lookup = MethodHandles.lookup();
2021-09-02 21:14:26 +02:00
Object nativeVal = null;
2021-09-22 11:03:39 +02:00
var ofNativeRestricted = getJava16NativeRestricted(lookup);
if (ofNativeRestricted == null) {
cause = null;
ofNativeRestricted = getJava17NativeRestricted(lookup);
}
if (ofNativeRestricted != null) {
2021-09-02 21:14:26 +02:00
try {
nativeVal = ofNativeRestricted.invoke();
} catch (Throwable e) {
cause = e;
}
}
OF_NATIVE_RESTRICTED = ofNativeRestricted;
MethodHandle asSlice;
try {
2021-09-22 11:03:39 +02:00
asSlice = lookup.findVirtual(lookup.findClass("jdk.incubator.foreign.MemorySegment"),
2021-09-02 21:14:26 +02:00
"asSlice",
2021-09-22 11:03:39 +02:00
MethodType.methodType(lookup.findClass("jdk.incubator.foreign.MemorySegment"), long.class, long.class)
2021-09-02 21:14:26 +02:00
);
} catch (NoSuchMethodException | IllegalAccessException | ClassNotFoundException e) {
asSlice = null;
cause = e;
}
AS_SLICE = asSlice;
MethodHandle asByteBuffer;
try {
2021-09-22 11:03:39 +02:00
asByteBuffer = lookup.findVirtual(lookup.findClass("jdk.incubator.foreign.MemorySegment"),
2021-09-02 21:14:26 +02:00
"asByteBuffer", MethodType.methodType(ByteBuffer.class));
} catch (NoSuchMethodException | IllegalAccessException | ClassNotFoundException e) {
asByteBuffer = null;
cause = e;
}
AS_BYTE_BUFFER = asByteBuffer;
NATIVE = nativeVal;
}
2021-09-22 11:03:39 +02:00
@SuppressWarnings("JavaLangInvokeHandleSignature")
private static MethodHandle getJava16NativeRestricted(Lookup lookup) {
MethodHandle ofNativeRestricted;
try {
ofNativeRestricted = lookup.findStatic(lookup.findClass("jdk.incubator.foreign.MemorySegment"),
"ofNativeRestricted",
MethodType.methodType(lookup.findClass("jdk.incubator.foreign.MemorySegment"))
);
} catch (NoSuchMethodException | IllegalAccessException | ClassNotFoundException e) {
ofNativeRestricted = null;
cause = e;
}
return ofNativeRestricted;
}
@SuppressWarnings("JavaLangInvokeHandleSignature")
private static MethodHandle getJava17NativeRestricted(Lookup lookup) {
MethodHandle ofNativeRestricted;
try {
ofNativeRestricted = lookup.findStatic(lookup.findClass("jdk.incubator.foreign.MemorySegment"),
"globalNativeSegment",
MethodType.methodType(lookup.findClass("jdk.incubator.foreign.MemorySegment"))
);
} catch (NoSuchMethodException | IllegalAccessException | ClassNotFoundException e) {
ofNativeRestricted = null;
cause = e;
}
return ofNativeRestricted;
}
2021-09-02 21:14:26 +02:00
public static ByteBuffer directBuffer(long address, long size) {
if (address <= 0) {
throw new IllegalArgumentException("Address is " + address);
}
if (size > Integer.MAX_VALUE || size < 0) {
throw new IllegalArgumentException("size is " + size);
}
try {
if (!isSupported()) {
if (PlatformDependent.hasDirectBufferNoCleanerConstructor()) {
2022-01-26 21:45:41 +01:00
return PlatformDependent.directBuffer(address, (int) size, null);
2021-09-02 21:14:26 +02:00
}
2021-09-03 02:22:55 +02:00
throw new UnsupportedOperationException("Foreign Memory Access API is disabled!"
2021-09-22 11:03:39 +02:00
+ " Please set \"" + MemorySegmentUtils.getSuggestedArgs() + "\"",
getUnsupportedCause()
);
2021-09-02 21:14:26 +02:00
}
var memorySegment = AS_SLICE.invoke(NATIVE, address, size);
return (ByteBuffer) AS_BYTE_BUFFER.invoke(memorySegment);
} catch (Throwable e) {
2021-09-03 02:22:55 +02:00
throw new UnsupportedOperationException("Foreign Memory Access API is disabled!"
2021-09-22 11:03:39 +02:00
+ " Please set \"" + MemorySegmentUtils.getSuggestedArgs() + "\"", e);
2021-09-02 21:14:26 +02:00
}
}
public static boolean isSupported() {
return OF_NATIVE_RESTRICTED != null && AS_SLICE != null && AS_BYTE_BUFFER != null && NATIVE != null;
}
public static Throwable getUnsupportedCause() {
return cause;
}
2021-09-22 11:03:39 +02:00
public static String getSuggestedArgs() {
return "--enable-preview --add-modules jdk.incubator.foreign -Dforeign.restricted=permit --enable-native-access=ALL-UNNAMED";
2021-09-22 11:03:39 +02:00
}
2021-09-02 21:14:26 +02:00
}