97 lines
3.1 KiB
Java
97 lines
3.1 KiB
Java
package it.cavallium.dbengine.database.disk;
|
|
|
|
import io.net5.util.internal.PlatformDependent;
|
|
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 {
|
|
Lookup lookup = MethodHandles.publicLookup();
|
|
|
|
Object nativeVal = null;
|
|
|
|
MethodHandle ofNativeRestricted;
|
|
try {
|
|
ofNativeRestricted = lookup.findStatic(Class.forName("jdk.incubator.foreign.MemorySegment"),
|
|
"ofNativeRestricted",
|
|
MethodType.methodType(Class.forName("jdk.incubator.foreign.MemorySegment"))
|
|
);
|
|
try {
|
|
nativeVal = ofNativeRestricted.invoke();
|
|
} catch (Throwable e) {
|
|
cause = e;
|
|
}
|
|
} catch (NoSuchMethodException | IllegalAccessException | ClassNotFoundException e) {
|
|
ofNativeRestricted = null;
|
|
cause = e;
|
|
}
|
|
OF_NATIVE_RESTRICTED = ofNativeRestricted;
|
|
|
|
MethodHandle asSlice;
|
|
try {
|
|
asSlice = lookup.findVirtual(Class.forName("jdk.incubator.foreign.MemorySegment"),
|
|
"asSlice",
|
|
MethodType.methodType(Class.forName("jdk.incubator.foreign.MemorySegment"), long.class, long.class)
|
|
);
|
|
} catch (NoSuchMethodException | IllegalAccessException | ClassNotFoundException e) {
|
|
asSlice = null;
|
|
cause = e;
|
|
}
|
|
AS_SLICE = asSlice;
|
|
|
|
MethodHandle asByteBuffer;
|
|
try {
|
|
asByteBuffer = lookup.findVirtual(Class.forName("jdk.incubator.foreign.MemorySegment"),
|
|
"asByteBuffer", MethodType.methodType(ByteBuffer.class));
|
|
} catch (NoSuchMethodException | IllegalAccessException | ClassNotFoundException e) {
|
|
asByteBuffer = null;
|
|
cause = e;
|
|
}
|
|
AS_BYTE_BUFFER = asByteBuffer;
|
|
|
|
NATIVE = nativeVal;
|
|
}
|
|
|
|
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()) {
|
|
return PlatformDependent.directBuffer(address, (int) size);
|
|
}
|
|
throw new UnsupportedOperationException("Foreign Memory Access API is disabled!"
|
|
+ " Please set \"--enable-preview --add-modules jdk.incubator.foreign -Dforeign.restricted=permit\"");
|
|
}
|
|
var memorySegment = AS_SLICE.invoke(NATIVE, address, size);
|
|
return (ByteBuffer) AS_BYTE_BUFFER.invoke(memorySegment);
|
|
} catch (Throwable e) {
|
|
throw new UnsupportedOperationException("Foreign Memory Access API is disabled!"
|
|
+ " Please set \"--enable-preview --add-modules jdk.incubator.foreign -Dforeign.restricted=permit\"", e);
|
|
}
|
|
}
|
|
|
|
public static boolean isSupported() {
|
|
return OF_NATIVE_RESTRICTED != null && AS_SLICE != null && AS_BYTE_BUFFER != null && NATIVE != null;
|
|
}
|
|
|
|
public static Throwable getUnsupportedCause() {
|
|
return cause;
|
|
}
|
|
}
|