diff --git a/lib/trino-ignite-patched/pom.xml b/lib/trino-ignite-patched/pom.xml
new file mode 100644
index 000000000000..0618b65a7a87
--- /dev/null
+++ b/lib/trino-ignite-patched/pom.xml
@@ -0,0 +1,103 @@
+
+
+
+ 4.0.0
+
+
+ io.trino
+ trino-root
+ 426-SNAPSHOT
+ ../../pom.xml
+
+
+ trino-ignite-patched
+ Trino - patched Ignite client to work with JDK21
+
+
+ ${project.parent.basedir}
+
+
+
+
+ com.google.guava
+ guava
+
+
+
+ org.apache.ignite
+ ignite-core
+ 2.15.0
+
+
+
+ org.jetbrains
+ annotations
+
+
+
+ org.testng
+ testng
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+
+
+ shade
+
+ package
+
+ false
+ false
+ false
+
+
+ org.apache.ignite.shaded
+ org.apache.ignite
+
+
+
+
+ org.apache.ignite:ignite-core
+
+ org/apache/ignite/internal/util/GridUnsafe.class
+ org/apache/ignite/internal/util/GridUnsafe$*.class
+
+
+
+
+
+
+
+
+ org.basepom.maven
+ duplicate-finder-maven-plugin
+
+
+
+ org.apache.ignite
+ ignite-core
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+
+
+
+ true
+
+
+
+
+
+
+
diff --git a/lib/trino-ignite-patched/src/main/java/org/apache/ignite/shaded/internal/util/GridUnsafe.java b/lib/trino-ignite-patched/src/main/java/org/apache/ignite/shaded/internal/util/GridUnsafe.java
new file mode 100644
index 000000000000..e50109eefb01
--- /dev/null
+++ b/lib/trino-ignite-patched/src/main/java/org/apache/ignite/shaded/internal/util/GridUnsafe.java
@@ -0,0 +1,2284 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.shaded.internal.util;
+
+import org.apache.ignite.IgniteSystemProperties;
+import org.apache.ignite.internal.util.DirectBufferCleaner;
+import org.apache.ignite.internal.util.FeatureChecker;
+import org.apache.ignite.internal.util.ReflectiveDirectBufferCleaner;
+import org.apache.ignite.internal.util.UnsafeDirectBufferCleaner;
+import org.apache.ignite.internal.util.typedef.internal.A;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import sun.misc.Unsafe;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+import static com.google.common.base.Preconditions.checkState;
+import static org.apache.ignite.internal.util.IgniteUtils.jdkVersion;
+import static org.apache.ignite.internal.util.IgniteUtils.majorJavaVersion;
+
+/**
+ *
Wrapper for {@link sun.misc.Unsafe} class.
+ *
+ *
+ * The following statements for memory access operations are true:
+ *
+ * - All {@code putXxx(long addr, xxx val)}, {@code getXxx(long addr)}, {@code putXxx(byte[] arr, long off, xxx val)},
+ * {@code getXxx(byte[] arr, long off)} and corresponding methods with {@code LE} suffix are alignment aware
+ * and can be safely used with unaligned pointers.
+ * - All {@code putXxxField(Object obj, long fieldOff, xxx val)} and {@code getXxxField(Object obj, long fieldOff)}
+ * methods are not alignment aware and can't be safely used with unaligned pointers. This methods can be safely used
+ * for object field values access because all object fields addresses are aligned.
+ * - All {@code putXxxLE(...)} and {@code getXxxLE(...)} methods assumes that byte order is fixed as little-endian
+ * while native byte order is big-endian. So it is client code responsibility to check native byte order before
+ * invoking of this methods.
+ *
+ *
+ *
+ * TODO Remove after new version of Ignite is released. Copied from https://github.com/apache/ignite/commit/d837b749962583d30db8ad1ecc512d98887f3895 and formatted.
+ * Applied https://github.com/apache/ignite/commit/fc51f0e43275953ab6a77c7f4d10ba32d1a640b6 from https://github.com/apache/ignite/pull/10764
+ */
+public abstract class GridUnsafe
+{
+ /**
+ *
+ */
+ public static final ByteOrder NATIVE_BYTE_ORDER = ByteOrder.nativeOrder();
+
+ /**
+ * Unsafe.
+ */
+ private static final Unsafe UNSAFE = unsafe();
+
+ /**
+ * Page size.
+ */
+ private static final int PAGE_SIZE = UNSAFE.pageSize();
+
+ /**
+ * Empty page.
+ */
+ private static final byte[] EMPTY_PAGE = new byte[PAGE_SIZE];
+
+ /**
+ * Unaligned flag.
+ */
+ private static final boolean UNALIGNED = unaligned();
+
+ /**
+ * @see IgniteSystemProperties#IGNITE_MEMORY_PER_BYTE_COPY_THRESHOLD
+ */
+ public static final long DFLT_MEMORY_PER_BYTE_COPY_THRESHOLD = 0L;
+
+ /**
+ * Per-byte copy threshold.
+ */
+ private static final long PER_BYTE_THRESHOLD = IgniteSystemProperties.getLong(
+ IgniteSystemProperties.IGNITE_MEMORY_PER_BYTE_COPY_THRESHOLD, DFLT_MEMORY_PER_BYTE_COPY_THRESHOLD);
+
+ /**
+ * Big endian.
+ */
+ public static final boolean BIG_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
+
+ /**
+ * Address size.
+ */
+ public static final int ADDR_SIZE = UNSAFE.addressSize();
+
+ /**
+ *
+ */
+ public static final long BYTE_ARR_OFF = UNSAFE.arrayBaseOffset(byte[].class);
+
+ /**
+ *
+ */
+ public static final int BYTE_ARR_INT_OFF = UNSAFE.arrayBaseOffset(byte[].class);
+
+ /**
+ *
+ */
+ public static final long SHORT_ARR_OFF = UNSAFE.arrayBaseOffset(short[].class);
+
+ /**
+ *
+ */
+ public static final long INT_ARR_OFF = UNSAFE.arrayBaseOffset(int[].class);
+
+ /**
+ *
+ */
+ public static final long LONG_ARR_OFF = UNSAFE.arrayBaseOffset(long[].class);
+
+ /**
+ *
+ */
+ public static final long FLOAT_ARR_OFF = UNSAFE.arrayBaseOffset(float[].class);
+
+ /**
+ *
+ */
+ public static final long DOUBLE_ARR_OFF = UNSAFE.arrayBaseOffset(double[].class);
+
+ /**
+ *
+ */
+ public static final long CHAR_ARR_OFF = UNSAFE.arrayBaseOffset(char[].class);
+
+ /**
+ *
+ */
+ public static final long BOOLEAN_ARR_OFF = UNSAFE.arrayBaseOffset(boolean[].class);
+
+ /**
+ * {@link java.nio.Buffer#address} field offset.
+ */
+ private static final long DIRECT_BUF_ADDR_OFF = bufferAddressOffset();
+
+ /**
+ * Whether to use newDirectByteBuffer(long, long) constructor
+ */
+ private static final boolean IS_DIRECT_BUF_LONG_CAP = majorJavaVersion(jdkVersion()) >= 21;
+
+ /**
+ * Cleaner code for direct {@code java.nio.ByteBuffer}.
+ */
+ private static final DirectBufferCleaner DIRECT_BUF_CLEANER =
+ majorJavaVersion(jdkVersion()) < 9
+ ? new ReflectiveDirectBufferCleaner()
+ : new UnsafeDirectBufferCleaner();
+
+ /**
+ * JavaNioAccess object. If {@code null} then {@link #NEW_DIRECT_BUF_CONSTRUCTOR} should be available.
+ */
+ @Nullable private static final Object JAVA_NIO_ACCESS_OBJ;
+
+ /**
+ * JavaNioAccess#newDirectByteBuffer method. Ususally {@code null} if {@link #JAVA_NIO_ACCESS_OBJ} is {@code null}.
+ * If {@code null} then {@link #NEW_DIRECT_BUF_CONSTRUCTOR} should be available.
+ */
+ @Nullable private static final Method NEW_DIRECT_BUF_MTD;
+
+ /**
+ * New direct buffer class constructor obtained and tested using reflection. If {@code null} then both {@link
+ * #JAVA_NIO_ACCESS_OBJ} and {@link #NEW_DIRECT_BUF_MTD} should be not {@code null}.
+ */
+ @Nullable private static final Constructor> NEW_DIRECT_BUF_CONSTRUCTOR;
+
+ static {
+ Object nioAccessObj = null;
+ Method directBufMtd = null;
+
+ Constructor> directBufCtor = null;
+
+ if (majorJavaVersion(jdkVersion()) < 12) {
+ // for old java prefer Java NIO & Shared Secrets obect init way
+ try {
+ nioAccessObj = javaNioAccessObject();
+ directBufMtd = newDirectBufferMethod(nioAccessObj);
+ }
+ catch (Exception e) {
+ nioAccessObj = null;
+ directBufMtd = null;
+
+ try {
+ directBufCtor = createAndTestNewDirectBufferCtor();
+ }
+ catch (Exception eFallback) {
+ eFallback.printStackTrace();
+
+ e.addSuppressed(eFallback);
+
+ throw e; // fallback was not suceefull
+ }
+
+ if (directBufCtor == null) {
+ throw e;
+ }
+ }
+ }
+ else {
+ try {
+ directBufCtor = createAndTestNewDirectBufferCtor();
+ }
+ catch (Exception e) {
+ try {
+ nioAccessObj = javaNioAccessObject();
+ directBufMtd = newDirectBufferMethod(nioAccessObj);
+ }
+ catch (Exception eFallback) {
+ eFallback.printStackTrace();
+
+ e.addSuppressed(eFallback);
+
+ throw e; //fallback to shared secrets failed.
+ }
+
+ if (nioAccessObj == null || directBufMtd == null) {
+ throw e;
+ }
+ }
+ }
+
+ JAVA_NIO_ACCESS_OBJ = nioAccessObj;
+ NEW_DIRECT_BUF_MTD = directBufMtd;
+
+ NEW_DIRECT_BUF_CONSTRUCTOR = directBufCtor;
+ }
+
+ /**
+ * Ensure singleton.
+ */
+ private GridUnsafe()
+ {
+ // No-op.
+ }
+
+ /**
+ * Wraps pointer to unmanaged memory into direct byte buffer.
+ *
+ * @param ptr Pointer to wrap.
+ * @param len Memory location length.
+ * @return Byte buffer wrapping the given memory.
+ */
+ public static ByteBuffer wrapPointer(long ptr, int len)
+ {
+ if (NEW_DIRECT_BUF_MTD != null && JAVA_NIO_ACCESS_OBJ != null) {
+ return wrapPointerJavaNio(ptr, len, NEW_DIRECT_BUF_MTD, JAVA_NIO_ACCESS_OBJ);
+ }
+ else if (NEW_DIRECT_BUF_CONSTRUCTOR != null) {
+ return wrapPointerDirectBufCtor(ptr, len, NEW_DIRECT_BUF_CONSTRUCTOR);
+ }
+ else {
+ throw new RuntimeException(
+ "All alternative for a new DirectByteBuffer() creation failed: " + FeatureChecker.JAVA_VER_SPECIFIC_WARN);
+ }
+ }
+
+ /**
+ * Wraps pointer to unmanaged memory into direct byte buffer. Uses constructor of a direct byte buffer.
+ *
+ * @param ptr Pointer to wrap.
+ * @param len Memory location length.
+ * @param constructor Constructor to use. Should create an instance of a direct ByteBuffer.
+ * @return Byte buffer wrapping the given memory.
+ */
+ @NotNull
+ private static ByteBuffer wrapPointerDirectBufCtor(long ptr, int len, Constructor> constructor)
+ {
+ try {
+ Object newDirectBuf = constructor.newInstance(ptr, len);
+
+ return ((ByteBuffer) newDirectBuf).order(NATIVE_BYTE_ORDER);
+ }
+ catch (ReflectiveOperationException e) {
+ throw new RuntimeException("DirectByteBuffer#constructor is unavailable."
+ + FeatureChecker.JAVA_VER_SPECIFIC_WARN, e);
+ }
+ }
+
+ /**
+ * Wraps pointer to unmanaged memory into direct byte buffer. Uses JavaNioAccess object.
+ *
+ * @param ptr Pointer to wrap.
+ * @param len Memory location length.
+ * @param newDirectBufMtd Method which should return an instance of a direct byte buffer.
+ * @param javaNioAccessObj Object to invoke method.
+ * @return Byte buffer wrapping the given memory.
+ */
+ @NotNull
+ private static ByteBuffer wrapPointerJavaNio(long ptr,
+ int len,
+ @NotNull Method newDirectBufMtd,
+ @NotNull Object javaNioAccessObj)
+ {
+ try {
+ ByteBuffer buf = (ByteBuffer) newDirectBufMtd.invoke(javaNioAccessObj, ptr, len, null);
+
+ checkState(buf.isDirect(), "buf.isDirect() is false");
+
+ buf.order(NATIVE_BYTE_ORDER);
+
+ return buf;
+ }
+ catch (ReflectiveOperationException e) {
+ throw new RuntimeException("JavaNioAccess#newDirectByteBuffer() method is unavailable."
+ + FeatureChecker.JAVA_VER_SPECIFIC_WARN, e);
+ }
+ }
+
+ /**
+ * @param len Length.
+ * @return Allocated direct buffer.
+ */
+ public static ByteBuffer allocateBuffer(int len)
+ {
+ long ptr = allocateMemory(len);
+
+ return wrapPointer(ptr, len);
+ }
+
+ /**
+ * @param buf Direct buffer allocated by {@link #allocateBuffer(int)}.
+ */
+ public static void freeBuffer(ByteBuffer buf)
+ {
+ long ptr = bufferAddress(buf);
+
+ freeMemory(ptr);
+ }
+
+ /**
+ * @param buf Buffer.
+ * @param len New length.
+ * @return Reallocated direct buffer.
+ */
+ public static ByteBuffer reallocateBuffer(ByteBuffer buf, int len)
+ {
+ long ptr = bufferAddress(buf);
+
+ long newPtr = reallocateMemory(ptr, len);
+
+ return wrapPointer(newPtr, len);
+ }
+
+ /**
+ * Gets boolean value from object field.
+ *
+ * @param obj Object.
+ * @param fieldOff Field offset.
+ * @return Boolean value from object field.
+ */
+ public static boolean getBooleanField(Object obj, long fieldOff)
+ {
+ return UNSAFE.getBoolean(obj, fieldOff);
+ }
+
+ /**
+ * Stores boolean value into object field.
+ *
+ * @param obj Object.
+ * @param fieldOff Field offset.
+ * @param val Value.
+ */
+ public static void putBooleanField(Object obj, long fieldOff, boolean val)
+ {
+ UNSAFE.putBoolean(obj, fieldOff, val);
+ }
+
+ /**
+ * Gets byte value from object field.
+ *
+ * @param obj Object.
+ * @param fieldOff Field offset.
+ * @return Byte value from object field.
+ */
+ public static byte getByteField(Object obj, long fieldOff)
+ {
+ return UNSAFE.getByte(obj, fieldOff);
+ }
+
+ /**
+ * Stores byte value into object field.
+ *
+ * @param obj Object.
+ * @param fieldOff Field offset.
+ * @param val Value.
+ */
+ public static void putByteField(Object obj, long fieldOff, byte val)
+ {
+ UNSAFE.putByte(obj, fieldOff, val);
+ }
+
+ /**
+ * Gets short value from object field.
+ *
+ * @param obj Object.
+ * @param fieldOff Field offset.
+ * @return Short value from object field.
+ */
+ public static short getShortField(Object obj, long fieldOff)
+ {
+ return UNSAFE.getShort(obj, fieldOff);
+ }
+
+ /**
+ * Stores short value into object field.
+ *
+ * @param obj Object.
+ * @param fieldOff Field offset.
+ * @param val Value.
+ */
+ public static void putShortField(Object obj, long fieldOff, short val)
+ {
+ UNSAFE.putShort(obj, fieldOff, val);
+ }
+
+ /**
+ * Gets char value from object field.
+ *
+ * @param obj Object.
+ * @param fieldOff Field offset.
+ * @return Char value from object field.
+ */
+ public static char getCharField(Object obj, long fieldOff)
+ {
+ return UNSAFE.getChar(obj, fieldOff);
+ }
+
+ /**
+ * Stores char value into object field.
+ *
+ * @param obj Object.
+ * @param fieldOff Field offset.
+ * @param val Value.
+ */
+ public static void putCharField(Object obj, long fieldOff, char val)
+ {
+ UNSAFE.putChar(obj, fieldOff, val);
+ }
+
+ /**
+ * Gets integer value from object field.
+ *
+ * @param obj Object.
+ * @param fieldOff Field offset.
+ * @return Integer value from object field.
+ */
+ public static int getIntField(Object obj, long fieldOff)
+ {
+ return UNSAFE.getInt(obj, fieldOff);
+ }
+
+ /**
+ * Stores integer value into object field.
+ *
+ * @param obj Object.
+ * @param fieldOff Field offset.
+ * @param val Value.
+ */
+ public static void putIntField(Object obj, long fieldOff, int val)
+ {
+ UNSAFE.putInt(obj, fieldOff, val);
+ }
+
+ /**
+ * Gets long value from object field.
+ *
+ * @param obj Object.
+ * @param fieldOff Field offset.
+ * @return Long value from object field.
+ */
+ public static long getLongField(Object obj, long fieldOff)
+ {
+ return UNSAFE.getLong(obj, fieldOff);
+ }
+
+ /**
+ * Stores long value into object field.
+ *
+ * @param obj Object.
+ * @param fieldOff Field offset.
+ * @param val Value.
+ */
+ public static void putLongField(Object obj, long fieldOff, long val)
+ {
+ UNSAFE.putLong(obj, fieldOff, val);
+ }
+
+ /**
+ * Gets float value from object field.
+ *
+ * @param obj Object.
+ * @param fieldOff Field offset.
+ * @return Float value from object field.
+ */
+ public static float getFloatField(Object obj, long fieldOff)
+ {
+ return UNSAFE.getFloat(obj, fieldOff);
+ }
+
+ /**
+ * Stores float value into object field.
+ *
+ * @param obj Object.
+ * @param fieldOff Field offset.
+ * @param val Value.
+ */
+ public static void putFloatField(Object obj, long fieldOff, float val)
+ {
+ UNSAFE.putFloat(obj, fieldOff, val);
+ }
+
+ /**
+ * Gets double value from object field.
+ *
+ * @param obj Object.
+ * @param fieldOff Field offset.
+ * @return Double value from object field.
+ */
+ public static double getDoubleField(Object obj, long fieldOff)
+ {
+ return UNSAFE.getDouble(obj, fieldOff);
+ }
+
+ /**
+ * Stores double value into object field.
+ *
+ * @param obj Object.
+ * @param fieldOff Field offset.
+ * @param val Value.
+ */
+ public static void putDoubleField(Object obj, long fieldOff, double val)
+ {
+ UNSAFE.putDouble(obj, fieldOff, val);
+ }
+
+ /**
+ * Gets reference from object field.
+ *
+ * @param obj Object.
+ * @param fieldOff Field offset.
+ * @return Reference from object field.
+ */
+ public static Object getObjectField(Object obj, long fieldOff)
+ {
+ return UNSAFE.getObject(obj, fieldOff);
+ }
+
+ /**
+ * Stores reference value into object field.
+ *
+ * @param obj Object.
+ * @param fieldOff Field offset.
+ * @param val Value.
+ */
+ public static void putObjectField(Object obj, long fieldOff, Object val)
+ {
+ UNSAFE.putObject(obj, fieldOff, val);
+ }
+
+ /**
+ * Gets boolean value from byte array.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @return Boolean value from byte array.
+ */
+ public static boolean getBoolean(byte[] arr, long off)
+ {
+ return UNSAFE.getBoolean(arr, off);
+ }
+
+ /**
+ * Stores boolean value into byte array.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @param val Value.
+ */
+ public static void putBoolean(byte[] arr, long off, boolean val)
+ {
+ UNSAFE.putBoolean(arr, off, val);
+ }
+
+ /**
+ * Gets byte value from byte array.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @return Byte value from byte array.
+ */
+ public static byte getByte(byte[] arr, long off)
+ {
+ return UNSAFE.getByte(arr, off);
+ }
+
+ /**
+ * Stores byte value into byte array.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @param val Value.
+ */
+ public static void putByte(byte[] arr, long off, byte val)
+ {
+ UNSAFE.putByte(arr, off, val);
+ }
+
+ /**
+ * Gets short value from byte array. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @return Short value from byte array.
+ */
+ public static short getShort(byte[] arr, long off)
+ {
+ return UNALIGNED ? UNSAFE.getShort(arr, off) : getShortByByte(arr, off, BIG_ENDIAN);
+ }
+
+ /**
+ * Stores short value into byte array. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @param val Value.
+ */
+ public static void putShort(byte[] arr, long off, short val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putShort(arr, off, val);
+ }
+ else {
+ putShortByByte(arr, off, val, BIG_ENDIAN);
+ }
+ }
+
+ /**
+ * Gets char value from byte array. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @return Char value from byte array.
+ */
+ public static char getChar(byte[] arr, long off)
+ {
+ return UNALIGNED ? UNSAFE.getChar(arr, off) : getCharByByte(arr, off, BIG_ENDIAN);
+ }
+
+ /**
+ * Stores char value into byte array. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @param val Value.
+ */
+ public static void putChar(byte[] arr, long off, char val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putChar(arr, off, val);
+ }
+ else {
+ putCharByByte(arr, off, val, BIG_ENDIAN);
+ }
+ }
+
+ /**
+ * Gets integer value from byte array. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @return Integer value from byte array.
+ */
+ public static int getInt(byte[] arr, long off)
+ {
+ return UNALIGNED ? UNSAFE.getInt(arr, off) : getIntByByte(arr, off, BIG_ENDIAN);
+ }
+
+ /**
+ * Stores integer value into byte array. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @param val Value.
+ */
+ public static void putInt(byte[] arr, long off, int val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putInt(arr, off, val);
+ }
+ else {
+ putIntByByte(arr, off, val, BIG_ENDIAN);
+ }
+ }
+
+ /**
+ * Gets long value from byte array. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @return Long value from byte array.
+ */
+ public static long getLong(byte[] arr, long off)
+ {
+ return UNALIGNED ? UNSAFE.getLong(arr, off) : getLongByByte(arr, off, BIG_ENDIAN);
+ }
+
+ /**
+ * Stores long value into byte array. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @param val Value.
+ */
+ public static void putLong(byte[] arr, long off, long val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putLong(arr, off, val);
+ }
+ else {
+ putLongByByte(arr, off, val, BIG_ENDIAN);
+ }
+ }
+
+ /**
+ * Gets float value from byte array. Alignment aware.
+ *
+ * @param arr Object.
+ * @param off Offset.
+ * @return Float value from byte array.
+ */
+ public static float getFloat(byte[] arr, long off)
+ {
+ return UNALIGNED ? UNSAFE.getFloat(arr, off) : Float.intBitsToFloat(getIntByByte(arr, off, BIG_ENDIAN));
+ }
+
+ /**
+ * Stores float value into byte array. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @param val Value.
+ */
+ public static void putFloat(byte[] arr, long off, float val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putFloat(arr, off, val);
+ }
+ else {
+ putIntByByte(arr, off, Float.floatToIntBits(val), BIG_ENDIAN);
+ }
+ }
+
+ /**
+ * Gets double value from byte array. Alignment aware.
+ *
+ * @param arr byte array.
+ * @param off Offset.
+ * @return Double value from byte array. Alignment aware.
+ */
+ public static double getDouble(byte[] arr, long off)
+ {
+ return UNALIGNED ? UNSAFE.getDouble(arr, off) : Double.longBitsToDouble(getLongByByte(arr, off, BIG_ENDIAN));
+ }
+
+ /**
+ * Stores double value into byte array. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @param val Value.
+ */
+ public static void putDouble(byte[] arr, long off, double val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putDouble(arr, off, val);
+ }
+ else {
+ putLongByByte(arr, off, Double.doubleToLongBits(val), BIG_ENDIAN);
+ }
+ }
+
+ /**
+ * Gets short value from byte array assuming that value stored in little-endian byte order and native byte order
+ * is big-endian. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @return Short value from byte array.
+ */
+ public static short getShortLE(byte[] arr, long off)
+ {
+ return UNALIGNED ? Short.reverseBytes(UNSAFE.getShort(arr, off)) : getShortByByte(arr, off, false);
+ }
+
+ /**
+ * Stores short value into byte array assuming that value should be stored in little-endian byte order and native
+ * byte order is big-endian. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @param val Value.
+ */
+ public static void putShortLE(byte[] arr, long off, short val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putShort(arr, off, Short.reverseBytes(val));
+ }
+ else {
+ putShortByByte(arr, off, val, false);
+ }
+ }
+
+ /**
+ * Gets char value from byte array assuming that value stored in little-endian byte order and native byte order
+ * is big-endian. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @return Char value from byte array.
+ */
+ public static char getCharLE(byte[] arr, long off)
+ {
+ return UNALIGNED ? Character.reverseBytes(UNSAFE.getChar(arr, off)) : getCharByByte(arr, off, false);
+ }
+
+ /**
+ * Stores char value into byte array assuming that value should be stored in little-endian byte order and native
+ * byte order is big-endian. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @param val Value.
+ */
+ public static void putCharLE(byte[] arr, long off, char val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putChar(arr, off, Character.reverseBytes(val));
+ }
+ else {
+ putCharByByte(arr, off, val, false);
+ }
+ }
+
+ /**
+ * Gets integer value from byte array assuming that value stored in little-endian byte order and native byte order
+ * is big-endian. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @return Integer value from byte array.
+ */
+ public static int getIntLE(byte[] arr, long off)
+ {
+ return UNALIGNED ? Integer.reverseBytes(UNSAFE.getInt(arr, off)) : getIntByByte(arr, off, false);
+ }
+
+ /**
+ * Stores integer value into byte array assuming that value should be stored in little-endian byte order and
+ * native byte order is big-endian. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @param val Value.
+ */
+ public static void putIntLE(byte[] arr, long off, int val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putInt(arr, off, Integer.reverseBytes(val));
+ }
+ else {
+ putIntByByte(arr, off, val, false);
+ }
+ }
+
+ /**
+ * Gets long value from byte array assuming that value stored in little-endian byte order and native byte order
+ * is big-endian. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @return Long value from byte array.
+ */
+ public static long getLongLE(byte[] arr, long off)
+ {
+ return UNALIGNED ? Long.reverseBytes(UNSAFE.getLong(arr, off)) : getLongByByte(arr, off, false);
+ }
+
+ /**
+ * Stores long value into byte array assuming that value should be stored in little-endian byte order and native
+ * byte order is big-endian. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @param val Value.
+ */
+ public static void putLongLE(byte[] arr, long off, long val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putLong(arr, off, Long.reverseBytes(val));
+ }
+ else {
+ putLongByByte(arr, off, val, false);
+ }
+ }
+
+ /**
+ * Gets float value from byte array assuming that value stored in little-endian byte order and native byte order
+ * is big-endian. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @return Float value from byte array.
+ */
+ public static float getFloatLE(byte[] arr, long off)
+ {
+ return Float.intBitsToFloat(
+ UNALIGNED ? Integer.reverseBytes(UNSAFE.getInt(arr, off)) : getIntByByte(arr, off, false));
+ }
+
+ /**
+ * Stores float value into byte array assuming that value should be stored in little-endian byte order and native
+ * byte order is big-endian. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @param val Value.
+ */
+ public static void putFloatLE(byte[] arr, long off, float val)
+ {
+ int intVal = Float.floatToIntBits(val);
+
+ if (UNALIGNED) {
+ UNSAFE.putInt(arr, off, Integer.reverseBytes(intVal));
+ }
+ else {
+ putIntByByte(arr, off, intVal, false);
+ }
+ }
+
+ /**
+ * Gets double value from byte array assuming that value stored in little-endian byte order and native byte order
+ * is big-endian. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @return Double value from byte array.
+ */
+ public static double getDoubleLE(byte[] arr, long off)
+ {
+ return Double.longBitsToDouble(
+ UNALIGNED ? Long.reverseBytes(UNSAFE.getLong(arr, off)) : getLongByByte(arr, off, false));
+ }
+
+ /**
+ * Stores double value into byte array assuming that value should be stored in little-endian byte order and
+ * native byte order is big-endian. Alignment aware.
+ *
+ * @param arr Byte array.
+ * @param off Offset.
+ * @param val Value.
+ */
+ public static void putDoubleLE(byte[] arr, long off, double val)
+ {
+ long longVal = Double.doubleToLongBits(val);
+
+ if (UNALIGNED) {
+ UNSAFE.putLong(arr, off, Long.reverseBytes(longVal));
+ }
+ else {
+ putLongByByte(arr, off, longVal, false);
+ }
+ }
+
+ /**
+ * Gets byte value from given address.
+ *
+ * @param addr Address.
+ * @return Byte value from given address.
+ */
+ public static byte getByte(long addr)
+ {
+ return UNSAFE.getByte(addr);
+ }
+
+ /**
+ * Stores given byte value.
+ *
+ * @param addr Address.
+ * @param val Value.
+ */
+ public static void putByte(long addr, byte val)
+ {
+ UNSAFE.putByte(addr, val);
+ }
+
+ /**
+ * Gets short value from given address. Alignment aware.
+ *
+ * @param addr Address.
+ * @return Short value from given address.
+ */
+ public static short getShort(long addr)
+ {
+ return UNALIGNED ? UNSAFE.getShort(addr) : getShortByByte(addr, BIG_ENDIAN);
+ }
+
+ /**
+ * Stores given short value. Alignment aware.
+ *
+ * @param addr Address.
+ * @param val Value.
+ */
+ public static void putShort(long addr, short val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putShort(addr, val);
+ }
+ else {
+ putShortByByte(addr, val, BIG_ENDIAN);
+ }
+ }
+
+ /**
+ * Gets char value from given address. Alignment aware.
+ *
+ * @param addr Address.
+ * @return Char value from given address.
+ */
+ public static char getChar(long addr)
+ {
+ return UNALIGNED ? UNSAFE.getChar(addr) : getCharByByte(addr, BIG_ENDIAN);
+ }
+
+ /**
+ * Stores given char value. Alignment aware.
+ *
+ * @param addr Address.
+ * @param val Value.
+ */
+ public static void putChar(long addr, char val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putChar(addr, val);
+ }
+ else {
+ putCharByByte(addr, val, BIG_ENDIAN);
+ }
+ }
+
+ /**
+ * Gets integer value from given address. Alignment aware.
+ *
+ * @param addr Address.
+ * @return Integer value from given address.
+ */
+ public static int getInt(long addr)
+ {
+ return UNALIGNED ? UNSAFE.getInt(addr) : getIntByByte(addr, BIG_ENDIAN);
+ }
+
+ /**
+ * Stores given integer value. Alignment aware.
+ *
+ * @param addr Address.
+ * @param val Value.
+ */
+ public static void putInt(long addr, int val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putInt(addr, val);
+ }
+ else {
+ putIntByByte(addr, val, BIG_ENDIAN);
+ }
+ }
+
+ /**
+ * Gets long value from given address. Alignment aware.
+ *
+ * @param addr Address.
+ * @return Long value from given address.
+ */
+ public static long getLong(long addr)
+ {
+ return UNALIGNED ? UNSAFE.getLong(addr) : getLongByByte(addr, BIG_ENDIAN);
+ }
+
+ /**
+ * Stores given integer value. Alignment aware.
+ *
+ * @param addr Address.
+ * @param val Value.
+ */
+ public static void putLong(long addr, long val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putLong(addr, val);
+ }
+ else {
+ putLongByByte(addr, val, BIG_ENDIAN);
+ }
+ }
+
+ /**
+ * Gets float value from given address. Alignment aware.
+ *
+ * @param addr Address.
+ * @return Float value from given address.
+ */
+ public static float getFloat(long addr)
+ {
+ return UNALIGNED ? UNSAFE.getFloat(addr) : Float.intBitsToFloat(getIntByByte(addr, BIG_ENDIAN));
+ }
+
+ /**
+ * Stores given float value. Alignment aware.
+ *
+ * @param addr Address.
+ * @param val Value.
+ */
+ public static void putFloat(long addr, float val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putFloat(addr, val);
+ }
+ else {
+ putIntByByte(addr, Float.floatToIntBits(val), BIG_ENDIAN);
+ }
+ }
+
+ /**
+ * Gets double value from given address. Alignment aware.
+ *
+ * @param addr Address.
+ * @return Double value from given address.
+ */
+ public static double getDouble(long addr)
+ {
+ return UNALIGNED ? UNSAFE.getDouble(addr) : Double.longBitsToDouble(getLongByByte(addr, BIG_ENDIAN));
+ }
+
+ /**
+ * Stores given double value. Alignment aware.
+ *
+ * @param addr Address.
+ * @param val Value.
+ */
+ public static void putDouble(long addr, double val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putDouble(addr, val);
+ }
+ else {
+ putLongByByte(addr, Double.doubleToLongBits(val), BIG_ENDIAN);
+ }
+ }
+
+ /**
+ * Gets short value from given address assuming that value stored in little-endian byte order and native byte order
+ * is big-endian. Alignment aware.
+ *
+ * @param addr Address.
+ * @return Short value from given address.
+ */
+ public static short getShortLE(long addr)
+ {
+ return UNALIGNED ? Short.reverseBytes(UNSAFE.getShort(addr)) : getShortByByte(addr, false);
+ }
+
+ /**
+ * Stores given short value assuming that value should be stored in little-endian byte order and native byte
+ * order is big-endian. Alignment aware.
+ *
+ * @param addr Address.
+ * @param val Value.
+ */
+ public static void putShortLE(long addr, short val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putShort(addr, Short.reverseBytes(val));
+ }
+ else {
+ putShortByByte(addr, val, false);
+ }
+ }
+
+ /**
+ * Gets char value from given address assuming that value stored in little-endian byte order and native byte order
+ * is big-endian. Alignment aware.
+ *
+ * @param addr Address.
+ * @return Char value from given address.
+ */
+ public static char getCharLE(long addr)
+ {
+ return UNALIGNED ? Character.reverseBytes(UNSAFE.getChar(addr)) : getCharByByte(addr, false);
+ }
+
+ /**
+ * Stores given char value assuming that value should be stored in little-endian byte order and native byte order
+ * is big-endian. Alignment aware.
+ *
+ * @param addr Address.
+ * @param val Value.
+ */
+ public static void putCharLE(long addr, char val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putChar(addr, Character.reverseBytes(val));
+ }
+ else {
+ putCharByByte(addr, val, false);
+ }
+ }
+
+ /**
+ * Gets integer value from given address assuming that value stored in little-endian byte order
+ * and native byte order is big-endian. Alignment aware.
+ *
+ * @param addr Address.
+ * @return Integer value from given address.
+ */
+ public static int getIntLE(long addr)
+ {
+ return UNALIGNED ? Integer.reverseBytes(UNSAFE.getInt(addr)) : getIntByByte(addr, false);
+ }
+
+ /**
+ * Stores given integer value assuming that value should be stored in little-endian byte order
+ * and native byte order is big-endian. Alignment aware.
+ *
+ * @param addr Address.
+ * @param val Value.
+ */
+ public static void putIntLE(long addr, int val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putInt(addr, Integer.reverseBytes(val));
+ }
+ else {
+ putIntByByte(addr, val, false);
+ }
+ }
+
+ /**
+ * Gets long value from given address assuming that value stored in little-endian byte order
+ * and native byte order is big-endian. Alignment aware.
+ *
+ * @param addr Address.
+ * @return Long value from given address.
+ */
+ public static long getLongLE(long addr)
+ {
+ return UNALIGNED ? Long.reverseBytes(UNSAFE.getLong(addr)) : getLongByByte(addr, false);
+ }
+
+ /**
+ * Stores given integer value assuming that value should be stored in little-endian byte order
+ * and native byte order is big-endian. Alignment aware.
+ *
+ * @param addr Address.
+ * @param val Value.
+ */
+ public static void putLongLE(long addr, long val)
+ {
+ if (UNALIGNED) {
+ UNSAFE.putLong(addr, Long.reverseBytes(val));
+ }
+ else {
+ putLongByByte(addr, val, false);
+ }
+ }
+
+ /**
+ * Gets float value from given address assuming that value stored in little-endian byte order
+ * and native byte order is big-endian. Alignment aware.
+ *
+ * @param addr Address.
+ * @return Float value from given address.
+ */
+ public static float getFloatLE(long addr)
+ {
+ return Float.intBitsToFloat(UNALIGNED ? Integer.reverseBytes(UNSAFE.getInt(addr)) : getIntByByte(addr, false));
+ }
+
+ /**
+ * Stores given float value assuming that value should be stored in little-endian byte order
+ * and native byte order is big-endian. Alignment aware.
+ *
+ * @param addr Address.
+ * @param val Value.
+ */
+ public static void putFloatLE(long addr, float val)
+ {
+ int intVal = Float.floatToIntBits(val);
+
+ if (UNALIGNED) {
+ UNSAFE.putInt(addr, Integer.reverseBytes(intVal));
+ }
+ else {
+ putIntByByte(addr, intVal, false);
+ }
+ }
+
+ /**
+ * Gets double value from given address assuming that value stored in little-endian byte order
+ * and native byte order is big-endian. Alignment aware.
+ *
+ * @param addr Address.
+ * @return Double value from given address.
+ */
+ public static double getDoubleLE(long addr)
+ {
+ return Double.longBitsToDouble(
+ UNALIGNED ? Long.reverseBytes(UNSAFE.getLong(addr)) : getLongByByte(addr, false));
+ }
+
+ /**
+ * Stores given double value assuming that value should be stored in little-endian byte order
+ * and native byte order is big-endian. Alignment aware.
+ *
+ * @param addr Address.
+ * @param val Value.
+ */
+ public static void putDoubleLE(long addr, double val)
+ {
+ long longVal = Double.doubleToLongBits(val);
+
+ if (UNALIGNED) {
+ UNSAFE.putLong(addr, Long.reverseBytes(longVal));
+ }
+ else {
+ putLongByByte(addr, longVal, false);
+ }
+ }
+
+ /**
+ * Returns static field offset.
+ *
+ * @param field Field.
+ * @return Static field offset.
+ */
+ public static long staticFieldOffset(Field field)
+ {
+ return UNSAFE.staticFieldOffset(field);
+ }
+
+ /**
+ * Returns object field offset.
+ *
+ * @param field Field.
+ * @return Object field offset.
+ */
+ public static long objectFieldOffset(Field field)
+ {
+ return UNSAFE.objectFieldOffset(field);
+ }
+
+ /**
+ * Returns static field base.
+ *
+ * @param field Field.
+ * @return Static field base.
+ */
+ public static Object staticFieldBase(Field field)
+ {
+ return UNSAFE.staticFieldBase(field);
+ }
+
+ /**
+ * Allocates memory.
+ *
+ * @param size Size.
+ * @return address.
+ */
+ public static long allocateMemory(long size)
+ {
+ return UNSAFE.allocateMemory(size);
+ }
+
+ /**
+ * Reallocates memory.
+ *
+ * @param addr Address.
+ * @param len Length.
+ * @return address.
+ */
+ public static long reallocateMemory(long addr, long len)
+ {
+ return UNSAFE.reallocateMemory(addr, len);
+ }
+
+ /**
+ * Fills memory with given value.
+ *
+ * @param addr Address.
+ * @param len Length.
+ * @param val Value.
+ */
+ public static void setMemory(long addr, long len, byte val)
+ {
+ UNSAFE.setMemory(addr, len, val);
+ }
+
+ /**
+ * Fills memory with zeroes.
+ *
+ * @param addr Address.
+ * @param len Length.
+ */
+ public static void zeroMemory(long addr, long len)
+ {
+ long off = 0;
+
+ for (; off + PAGE_SIZE <= len; off += PAGE_SIZE) {
+ UNSAFE.copyMemory(EMPTY_PAGE, BYTE_ARR_OFF, null, addr + off, PAGE_SIZE);
+ }
+
+ if (len != off) {
+ UNSAFE.copyMemory(EMPTY_PAGE, BYTE_ARR_OFF, null, addr + off, len - off);
+ }
+ }
+
+ /**
+ * Copy memory between offheap locations.
+ *
+ * @param srcAddr Source address.
+ * @param dstAddr Destination address.
+ * @param len Length.
+ */
+ public static void copyOffheapOffheap(long srcAddr, long dstAddr, long len)
+ {
+ if (len <= PER_BYTE_THRESHOLD) {
+ for (int i = 0; i < len; i++) {
+ UNSAFE.putByte(dstAddr + i, UNSAFE.getByte(srcAddr + i));
+ }
+ }
+ else {
+ UNSAFE.copyMemory(srcAddr, dstAddr, len);
+ }
+ }
+
+ /**
+ * Copy memory from offheap to heap.
+ *
+ * @param srcAddr Source address.
+ * @param dstBase Destination base.
+ * @param dstOff Destination offset.
+ * @param len Length.
+ */
+ public static void copyOffheapHeap(long srcAddr, Object dstBase, long dstOff, long len)
+ {
+ if (len <= PER_BYTE_THRESHOLD) {
+ for (int i = 0; i < len; i++) {
+ UNSAFE.putByte(dstBase, dstOff + i, UNSAFE.getByte(srcAddr + i));
+ }
+ }
+ else {
+ UNSAFE.copyMemory(null, srcAddr, dstBase, dstOff, len);
+ }
+ }
+
+ /**
+ * Copy memory from heap to offheap.
+ *
+ * @param srcBase Source base.
+ * @param srcOff Source offset.
+ * @param dstAddr Destination address.
+ * @param len Length.
+ */
+ public static void copyHeapOffheap(Object srcBase, long srcOff, long dstAddr, long len)
+ {
+ if (len <= PER_BYTE_THRESHOLD) {
+ for (int i = 0; i < len; i++) {
+ UNSAFE.putByte(dstAddr + i, UNSAFE.getByte(srcBase, srcOff + i));
+ }
+ }
+ else {
+ UNSAFE.copyMemory(srcBase, srcOff, null, dstAddr, len);
+ }
+ }
+
+ /**
+ * Copies memory.
+ *
+ * @param src Source.
+ * @param dst Dst.
+ * @param len Length.
+ */
+ public static void copyMemory(long src, long dst, long len)
+ {
+ UNSAFE.copyMemory(src, dst, len);
+ }
+
+ /**
+ * Sets all bytes in a given block of memory to a copy of another block.
+ *
+ * @param srcBase Source base.
+ * @param srcOff Source offset.
+ * @param dstBase Dst base.
+ * @param dstOff Dst offset.
+ * @param len Length.
+ */
+ public static void copyMemory(Object srcBase, long srcOff, Object dstBase, long dstOff, long len)
+ {
+ if (len <= PER_BYTE_THRESHOLD && srcBase != null && dstBase != null) {
+ for (int i = 0; i < len; i++) {
+ UNSAFE.putByte(dstBase, dstOff + i, UNSAFE.getByte(srcBase, srcOff + i));
+ }
+ }
+ else {
+ UNSAFE.copyMemory(srcBase, srcOff, dstBase, dstOff, len);
+ }
+ }
+
+ /**
+ * Frees memory.
+ *
+ * @param addr Address.
+ */
+ public static void freeMemory(long addr)
+ {
+ UNSAFE.freeMemory(addr);
+ }
+
+ /**
+ * Returns the offset of the first element in the storage allocation of a given array class.
+ *
+ * @param cls Class.
+ * @return the offset of the first element in the storage allocation of a given array class.
+ */
+ public static int arrayBaseOffset(Class cls)
+ {
+ return UNSAFE.arrayBaseOffset(cls);
+ }
+
+ /**
+ * Returns the scale factor for addressing elements in the storage allocation of a given array class.
+ *
+ * @param cls Class.
+ * @return the scale factor for addressing elements in the storage allocation of a given array class.
+ */
+ public static int arrayIndexScale(Class> cls)
+ {
+ return UNSAFE.arrayIndexScale(cls);
+ }
+
+ /**
+ * Allocates instance of given class.
+ *
+ * @param cls Class.
+ * @return Allocated instance.
+ */
+ public static Object allocateInstance(Class cls)
+ throws InstantiationException
+ {
+ return UNSAFE.allocateInstance(cls);
+ }
+
+ /**
+ * Integer CAS.
+ *
+ * @param obj Object.
+ * @param off Offset.
+ * @param exp Expected.
+ * @param upd Upd.
+ * @return {@code True} if operation completed successfully, {@code false} - otherwise.
+ */
+ public static boolean compareAndSwapInt(Object obj, long off, int exp, int upd)
+ {
+ return UNSAFE.compareAndSwapInt(obj, off, exp, upd);
+ }
+
+ /**
+ * Long CAS.
+ *
+ * @param obj Object.
+ * @param off Offset.
+ * @param exp Expected.
+ * @param upd Upd.
+ * @return {@code True} if operation completed successfully, {@code false} - otherwise.
+ */
+ public static boolean compareAndSwapLong(Object obj, long off, long exp, long upd)
+ {
+ return UNSAFE.compareAndSwapLong(obj, off, exp, upd);
+ }
+
+ /**
+ * Atomically increments value stored in an integer pointed by {@code ptr}.
+ *
+ * @param ptr Pointer to an integer.
+ * @return Updated value.
+ */
+ public static int incrementAndGetInt(long ptr)
+ {
+ return UNSAFE.getAndAddInt(null, ptr, 1) + 1;
+ }
+
+ /**
+ * Atomically increments value stored in an integer pointed by {@code ptr}.
+ *
+ * @param ptr Pointer to an integer.
+ * @return Updated value.
+ */
+ public static int decrementAndGetInt(long ptr)
+ {
+ return UNSAFE.getAndAddInt(null, ptr, -1) - 1;
+ }
+
+ /**
+ * Gets byte value with volatile semantic.
+ *
+ * @param obj Object.
+ * @param off Offset.
+ * @return Byte value.
+ */
+ public static byte getByteVolatile(Object obj, long off)
+ {
+ return UNSAFE.getByteVolatile(obj, off);
+ }
+
+ /**
+ * Stores byte value with volatile semantic.
+ *
+ * @param obj Object.
+ * @param off Offset.
+ * @param val Value.
+ */
+ public static void putByteVolatile(Object obj, long off, byte val)
+ {
+ UNSAFE.putByteVolatile(obj, off, val);
+ }
+
+ /**
+ * Gets integer value with volatile semantic.
+ *
+ * @param obj Object.
+ * @param off Offset.
+ * @return Integer value.
+ */
+ public static int getIntVolatile(Object obj, long off)
+ {
+ return UNSAFE.getIntVolatile(obj, off);
+ }
+
+ /**
+ * Stores integer value with volatile semantic.
+ *
+ * @param obj Object.
+ * @param off Offset.
+ * @param val Value.
+ */
+ public static void putIntVolatile(Object obj, long off, int val)
+ {
+ UNSAFE.putIntVolatile(obj, off, val);
+ }
+
+ /**
+ * Gets long value with volatile semantic.
+ *
+ * @param obj Object.
+ * @param off Offset.
+ * @return Long value.
+ */
+ public static long getLongVolatile(Object obj, long off)
+ {
+ return UNSAFE.getLongVolatile(obj, off);
+ }
+
+ /**
+ * Stores long value with volatile semantic.
+ *
+ * @param obj Object.
+ * @param off Offset.
+ * @param val Value.
+ */
+ public static void putLongVolatile(Object obj, long off, long val)
+ {
+ UNSAFE.putLongVolatile(obj, off, val);
+ }
+
+ /**
+ * Stores reference value with volatile semantic.
+ *
+ * @param obj Object.
+ * @param off Offset.
+ * @param val Value.
+ */
+ public static void putObjectVolatile(Object obj, long off, Object val)
+ {
+ UNSAFE.putObjectVolatile(obj, off, val);
+ }
+
+ /**
+ * Returns page size.
+ *
+ * @return Page size.
+ */
+ public static int pageSize()
+ {
+ return UNSAFE.pageSize();
+ }
+
+ /**
+ * Returns address of {@link Buffer} instance.
+ *
+ * @param buf Buffer.
+ * @return Buffer memory address.
+ */
+ public static long bufferAddress(ByteBuffer buf)
+ {
+ checkState(buf.isDirect(), "buf.isDirect() is false");
+
+ return UNSAFE.getLong(buf, DIRECT_BUF_ADDR_OFF);
+ }
+
+ /**
+ * Invokes some method on {@code sun.misc.Unsafe} instance.
+ *
+ * @param mtd Method.
+ * @param args Arguments.
+ */
+ public static Object invoke(Method mtd, Object... args)
+ {
+ try {
+ return mtd.invoke(UNSAFE, args);
+ }
+ catch (IllegalAccessException | InvocationTargetException e) {
+ throw new RuntimeException("Unsafe invocation failed [cls=" + UNSAFE.getClass() + ", mtd=" + mtd + ']', e);
+ }
+ }
+
+ /**
+ * Cleans direct {@code java.nio.ByteBuffer}
+ *
+ * @param buf Direct buffer.
+ */
+ public static void cleanDirectBuffer(ByteBuffer buf)
+ {
+ checkState(buf.isDirect(), "buf.isDirect() is false");
+
+ DIRECT_BUF_CLEANER.clean(buf);
+ }
+
+ /**
+ * Returns unaligned flag.
+ */
+ private static boolean unaligned()
+ {
+ String arch = System.getProperty("os.arch");
+
+ boolean res = arch.equals("i386") || arch.equals("x86") || arch.equals("amd64") || arch.equals("x86_64");
+
+ if (!res) {
+ res = IgniteSystemProperties.getBoolean(IgniteSystemProperties.IGNITE_MEMORY_UNALIGNED_ACCESS, false);
+ }
+
+ return res;
+ }
+
+ /**
+ * @return Instance of Unsafe class.
+ */
+ private static Unsafe unsafe()
+ {
+ try {
+ return Unsafe.getUnsafe();
+ }
+ catch (SecurityException ignored) {
+ try {
+ return AccessController.doPrivileged(
+ new PrivilegedExceptionAction()
+ {
+ @Override
+ public Unsafe run()
+ throws Exception
+ {
+ Field f = Unsafe.class.getDeclaredField("theUnsafe");
+
+ f.setAccessible(true);
+
+ return (Unsafe) f.get(null);
+ }
+ });
+ }
+ catch (PrivilegedActionException e) {
+ throw new RuntimeException("Could not initialize intrinsics.", e.getCause());
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ private static long bufferAddressOffset()
+ {
+ final ByteBuffer maybeDirectBuf = ByteBuffer.allocateDirect(1);
+
+ Field addrField = AccessController.doPrivileged(new PrivilegedAction()
+ {
+ @Override
+ public Field run()
+ {
+ try {
+ Field addrFld = Buffer.class.getDeclaredField("address");
+
+ addrFld.setAccessible(true);
+
+ if (addrFld.getLong(maybeDirectBuf) == 0) {
+ throw new RuntimeException("java.nio.DirectByteBuffer.address field is unavailable.");
+ }
+
+ return addrFld;
+ }
+ catch (Exception e) {
+ throw new RuntimeException("java.nio.DirectByteBuffer.address field is unavailable.", e);
+ }
+ }
+ });
+
+ return UNSAFE.objectFieldOffset(addrField);
+ }
+
+ /**
+ * Returns {@code JavaNioAccess} instance from private API for corresponding Java version.
+ *
+ * @return {@code JavaNioAccess} instance for corresponding Java version.
+ * @throws RuntimeException If getting access to the private API is failed.
+ */
+ private static Object javaNioAccessObject()
+ {
+ String pkgName = miscPackage();
+
+ try {
+ Class> cls = Class.forName(pkgName + ".misc.SharedSecrets");
+
+ Method mth = cls.getMethod("getJavaNioAccess");
+
+ return mth.invoke(null);
+ }
+ catch (ReflectiveOperationException e) {
+ throw new RuntimeException(pkgName + ".misc.JavaNioAccess class is unavailable."
+ + FeatureChecker.JAVA_VER_SPECIFIC_WARN, e);
+ }
+ }
+
+ /**
+ * Returns reference to {@code JavaNioAccess.newDirectByteBuffer} method
+ * from private API for corresponding Java version.
+ *
+ * @param nioAccessObj Java NIO access object.
+ * @return Reference to {@code JavaNioAccess.newDirectByteBuffer} method
+ * @throws RuntimeException If getting access to the private API is failed.
+ */
+ private static Method newDirectBufferMethod(Object nioAccessObj)
+ {
+ try {
+ Class> cls = nioAccessObj.getClass();
+
+ Method mtd = IS_DIRECT_BUF_LONG_CAP ? cls.getMethod("newDirectByteBuffer", long.class, long.class, Object.class) :
+ cls.getMethod("newDirectByteBuffer", long.class, int.class, Object.class);
+
+ mtd.setAccessible(true);
+
+ return mtd;
+ }
+ catch (ReflectiveOperationException e) {
+ throw new RuntimeException(miscPackage() + ".JavaNioAccess#newDirectByteBuffer() method is unavailable."
+ + FeatureChecker.JAVA_VER_SPECIFIC_WARN, e);
+ }
+ }
+
+ /**
+ *
+ */
+ @NotNull
+ private static String miscPackage()
+ {
+ int javaVer = majorJavaVersion(jdkVersion());
+
+ return javaVer < 9 ? "sun" : "jdk.internal";
+ }
+
+ /**
+ * Creates and tests contructor for Direct ByteBuffer. Test is wrapping one-byte unsafe memory into a buffer.
+ *
+ * @return constructor for creating direct ByteBuffers.
+ */
+ @NotNull
+ private static Constructor> createAndTestNewDirectBufferCtor()
+ {
+ Constructor> ctorCandidate = createNewDirectBufferCtor();
+
+ int l = 1;
+ long ptr = UNSAFE.allocateMemory(l);
+
+ try {
+ ByteBuffer buf = wrapPointerDirectBufCtor(ptr, l, ctorCandidate);
+
+ A.ensure(buf.isDirect(), "Buffer expected to be direct, internal error during #wrapPointerDirectBufCtor()");
+ }
+ finally {
+ UNSAFE.freeMemory(ptr);
+ }
+
+ return ctorCandidate;
+ }
+
+ /**
+ * Simply create some instance of direct Byte Buffer and try to get it's class declared constructor.
+ *
+ * @return constructor for creating direct ByteBuffers.
+ */
+ @NotNull
+ private static Constructor> createNewDirectBufferCtor()
+ {
+ try {
+ ByteBuffer buf = ByteBuffer.allocateDirect(1).order(NATIVE_BYTE_ORDER);
+
+ Constructor> ctor = IS_DIRECT_BUF_LONG_CAP ? buf.getClass().getDeclaredConstructor(long.class, long.class) :
+ buf.getClass().getDeclaredConstructor(long.class, int.class);
+
+ ctor.setAccessible(true);
+
+ return ctor;
+ }
+ catch (NoSuchMethodException | SecurityException e) {
+ throw new RuntimeException("Unable to set up byte buffer creation using reflections :" + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * @param obj Object.
+ * @param off Offset.
+ * @param bigEndian Order of value bytes in memory. If {@code true} - big-endian, otherwise little-endian.
+ */
+ private static short getShortByByte(Object obj, long off, boolean bigEndian)
+ {
+ if (bigEndian) {
+ return (short) (UNSAFE.getByte(obj, off) << 8 | (UNSAFE.getByte(obj, off + 1) & 0xff));
+ }
+ else {
+ return (short) (UNSAFE.getByte(obj, off + 1) << 8 | (UNSAFE.getByte(obj, off) & 0xff));
+ }
+ }
+
+ /**
+ * @param obj Object.
+ * @param off Offset.
+ * @param val Value.
+ * @param bigEndian Order of value bytes in memory. If {@code true} - big-endian, otherwise little-endian.
+ */
+ private static void putShortByByte(Object obj, long off, short val, boolean bigEndian)
+ {
+ if (bigEndian) {
+ UNSAFE.putByte(obj, off, (byte) (val >> 8));
+ UNSAFE.putByte(obj, off + 1, (byte) val);
+ }
+ else {
+ UNSAFE.putByte(obj, off + 1, (byte) (val >> 8));
+ UNSAFE.putByte(obj, off, (byte) val);
+ }
+ }
+
+ /**
+ * @param obj Object.
+ * @param off Offset.
+ * @param bigEndian Order of value bytes in memory. If {@code true} - big-endian, otherwise little-endian.
+ */
+ private static char getCharByByte(Object obj, long off, boolean bigEndian)
+ {
+ if (bigEndian) {
+ return (char) (UNSAFE.getByte(obj, off) << 8 | (UNSAFE.getByte(obj, off + 1) & 0xff));
+ }
+ else {
+ return (char) (UNSAFE.getByte(obj, off + 1) << 8 | (UNSAFE.getByte(obj, off) & 0xff));
+ }
+ }
+
+ /**
+ * @param obj Object.
+ * @param addr Address.
+ * @param val Value.
+ * @param bigEndian Order of value bytes in memory. If {@code true} - big-endian, otherwise little-endian.
+ */
+ private static void putCharByByte(Object obj, long addr, char val, boolean bigEndian)
+ {
+ if (bigEndian) {
+ UNSAFE.putByte(obj, addr, (byte) (val >> 8));
+ UNSAFE.putByte(obj, addr + 1, (byte) val);
+ }
+ else {
+ UNSAFE.putByte(obj, addr + 1, (byte) (val >> 8));
+ UNSAFE.putByte(obj, addr, (byte) val);
+ }
+ }
+
+ /**
+ * @param obj Object.
+ * @param addr Address.
+ * @param bigEndian Order of value bytes in memory. If {@code true} - big-endian, otherwise little-endian.
+ */
+ private static int getIntByByte(Object obj, long addr, boolean bigEndian)
+ {
+ if (bigEndian) {
+ return (((int) UNSAFE.getByte(obj, addr)) << 24) |
+ (((int) UNSAFE.getByte(obj, addr + 1) & 0xff) << 16) |
+ (((int) UNSAFE.getByte(obj, addr + 2) & 0xff) << 8) |
+ (((int) UNSAFE.getByte(obj, addr + 3) & 0xff));
+ }
+ else {
+ return (((int) UNSAFE.getByte(obj, addr + 3)) << 24) |
+ (((int) UNSAFE.getByte(obj, addr + 2) & 0xff) << 16) |
+ (((int) UNSAFE.getByte(obj, addr + 1) & 0xff) << 8) |
+ (((int) UNSAFE.getByte(obj, addr) & 0xff));
+ }
+ }
+
+ /**
+ * @param obj Object.
+ * @param addr Address.
+ * @param val Value.
+ * @param bigEndian Order of value bytes in memory. If {@code true} - big-endian, otherwise little-endian.
+ */
+ private static void putIntByByte(Object obj, long addr, int val, boolean bigEndian)
+ {
+ if (bigEndian) {
+ UNSAFE.putByte(obj, addr, (byte) (val >> 24));
+ UNSAFE.putByte(obj, addr + 1, (byte) (val >> 16));
+ UNSAFE.putByte(obj, addr + 2, (byte) (val >> 8));
+ UNSAFE.putByte(obj, addr + 3, (byte) (val));
+ }
+ else {
+ UNSAFE.putByte(obj, addr + 3, (byte) (val >> 24));
+ UNSAFE.putByte(obj, addr + 2, (byte) (val >> 16));
+ UNSAFE.putByte(obj, addr + 1, (byte) (val >> 8));
+ UNSAFE.putByte(obj, addr, (byte) (val));
+ }
+ }
+
+ /**
+ * @param obj Object.
+ * @param addr Address.
+ * @param bigEndian Order of value bytes in memory. If {@code true} - big-endian, otherwise little-endian.
+ */
+ private static long getLongByByte(Object obj, long addr, boolean bigEndian)
+ {
+ if (bigEndian) {
+ return (((long) UNSAFE.getByte(obj, addr)) << 56) |
+ (((long) UNSAFE.getByte(obj, addr + 1) & 0xff) << 48) |
+ (((long) UNSAFE.getByte(obj, addr + 2) & 0xff) << 40) |
+ (((long) UNSAFE.getByte(obj, addr + 3) & 0xff) << 32) |
+ (((long) UNSAFE.getByte(obj, addr + 4) & 0xff) << 24) |
+ (((long) UNSAFE.getByte(obj, addr + 5) & 0xff) << 16) |
+ (((long) UNSAFE.getByte(obj, addr + 6) & 0xff) << 8) |
+ (((long) UNSAFE.getByte(obj, addr + 7) & 0xff));
+ }
+ else {
+ return (((long) UNSAFE.getByte(obj, addr + 7)) << 56) |
+ (((long) UNSAFE.getByte(obj, addr + 6) & 0xff) << 48) |
+ (((long) UNSAFE.getByte(obj, addr + 5) & 0xff) << 40) |
+ (((long) UNSAFE.getByte(obj, addr + 4) & 0xff) << 32) |
+ (((long) UNSAFE.getByte(obj, addr + 3) & 0xff) << 24) |
+ (((long) UNSAFE.getByte(obj, addr + 2) & 0xff) << 16) |
+ (((long) UNSAFE.getByte(obj, addr + 1) & 0xff) << 8) |
+ (((long) UNSAFE.getByte(obj, addr) & 0xff));
+ }
+ }
+
+ /**
+ * @param obj Object.
+ * @param addr Address.
+ * @param val Value.
+ * @param bigEndian Order of value bytes in memory. If {@code true} - big-endian, otherwise little-endian.
+ */
+ private static void putLongByByte(Object obj, long addr, long val, boolean bigEndian)
+ {
+ if (bigEndian) {
+ UNSAFE.putByte(obj, addr, (byte) (val >> 56));
+ UNSAFE.putByte(obj, addr + 1, (byte) (val >> 48));
+ UNSAFE.putByte(obj, addr + 2, (byte) (val >> 40));
+ UNSAFE.putByte(obj, addr + 3, (byte) (val >> 32));
+ UNSAFE.putByte(obj, addr + 4, (byte) (val >> 24));
+ UNSAFE.putByte(obj, addr + 5, (byte) (val >> 16));
+ UNSAFE.putByte(obj, addr + 6, (byte) (val >> 8));
+ UNSAFE.putByte(obj, addr + 7, (byte) (val));
+ }
+ else {
+ UNSAFE.putByte(obj, addr + 7, (byte) (val >> 56));
+ UNSAFE.putByte(obj, addr + 6, (byte) (val >> 48));
+ UNSAFE.putByte(obj, addr + 5, (byte) (val >> 40));
+ UNSAFE.putByte(obj, addr + 4, (byte) (val >> 32));
+ UNSAFE.putByte(obj, addr + 3, (byte) (val >> 24));
+ UNSAFE.putByte(obj, addr + 2, (byte) (val >> 16));
+ UNSAFE.putByte(obj, addr + 1, (byte) (val >> 8));
+ UNSAFE.putByte(obj, addr, (byte) (val));
+ }
+ }
+
+ /**
+ * @param addr Address.
+ * @param bigEndian Order of value bytes in memory. If {@code true} - big-endian, otherwise little-endian.
+ */
+ private static short getShortByByte(long addr, boolean bigEndian)
+ {
+ if (bigEndian) {
+ return (short) (UNSAFE.getByte(addr) << 8 | (UNSAFE.getByte(addr + 1) & 0xff));
+ }
+ else {
+ return (short) (UNSAFE.getByte(addr + 1) << 8 | (UNSAFE.getByte(addr) & 0xff));
+ }
+ }
+
+ /**
+ * @param addr Address.
+ * @param val Value.
+ * @param bigEndian Order of value bytes in memory. If {@code true} - big-endian, otherwise little-endian.
+ */
+ private static void putShortByByte(long addr, short val, boolean bigEndian)
+ {
+ if (bigEndian) {
+ UNSAFE.putByte(addr, (byte) (val >> 8));
+ UNSAFE.putByte(addr + 1, (byte) val);
+ }
+ else {
+ UNSAFE.putByte(addr + 1, (byte) (val >> 8));
+ UNSAFE.putByte(addr, (byte) val);
+ }
+ }
+
+ /**
+ * @param addr Address.
+ * @param bigEndian Order of value bytes in memory. If {@code true} - big-endian, otherwise little-endian.
+ */
+ private static char getCharByByte(long addr, boolean bigEndian)
+ {
+ if (bigEndian) {
+ return (char) (UNSAFE.getByte(addr) << 8 | (UNSAFE.getByte(addr + 1) & 0xff));
+ }
+ else {
+ return (char) (UNSAFE.getByte(addr + 1) << 8 | (UNSAFE.getByte(addr) & 0xff));
+ }
+ }
+
+ /**
+ * @param addr Address.
+ * @param val Value.
+ * @param bigEndian Order of value bytes in memory. If {@code true} - big-endian, otherwise little-endian.
+ */
+ private static void putCharByByte(long addr, char val, boolean bigEndian)
+ {
+ if (bigEndian) {
+ UNSAFE.putByte(addr, (byte) (val >> 8));
+ UNSAFE.putByte(addr + 1, (byte) val);
+ }
+ else {
+ UNSAFE.putByte(addr + 1, (byte) (val >> 8));
+ UNSAFE.putByte(addr, (byte) val);
+ }
+ }
+
+ /**
+ * @param addr Address.
+ * @param bigEndian Order of value bytes in memory. If {@code true} - big-endian, otherwise little-endian.
+ */
+ private static int getIntByByte(long addr, boolean bigEndian)
+ {
+ if (bigEndian) {
+ return (((int) UNSAFE.getByte(addr)) << 24) |
+ (((int) UNSAFE.getByte(addr + 1) & 0xff) << 16) |
+ (((int) UNSAFE.getByte(addr + 2) & 0xff) << 8) |
+ (((int) UNSAFE.getByte(addr + 3) & 0xff));
+ }
+ else {
+ return (((int) UNSAFE.getByte(addr + 3)) << 24) |
+ (((int) UNSAFE.getByte(addr + 2) & 0xff) << 16) |
+ (((int) UNSAFE.getByte(addr + 1) & 0xff) << 8) |
+ (((int) UNSAFE.getByte(addr) & 0xff));
+ }
+ }
+
+ /**
+ * @param addr Address.
+ * @param val Value.
+ * @param bigEndian Order of value bytes in memory. If {@code true} - big-endian, otherwise little-endian.
+ */
+ private static void putIntByByte(long addr, int val, boolean bigEndian)
+ {
+ if (bigEndian) {
+ UNSAFE.putByte(addr, (byte) (val >> 24));
+ UNSAFE.putByte(addr + 1, (byte) (val >> 16));
+ UNSAFE.putByte(addr + 2, (byte) (val >> 8));
+ UNSAFE.putByte(addr + 3, (byte) (val));
+ }
+ else {
+ UNSAFE.putByte(addr + 3, (byte) (val >> 24));
+ UNSAFE.putByte(addr + 2, (byte) (val >> 16));
+ UNSAFE.putByte(addr + 1, (byte) (val >> 8));
+ UNSAFE.putByte(addr, (byte) (val));
+ }
+ }
+
+ /**
+ * @param addr Address.
+ * @param bigEndian Order of value bytes in memory. If {@code true} - big-endian, otherwise little-endian.
+ */
+ private static long getLongByByte(long addr, boolean bigEndian)
+ {
+ if (bigEndian) {
+ return (((long) UNSAFE.getByte(addr)) << 56) |
+ (((long) UNSAFE.getByte(addr + 1) & 0xff) << 48) |
+ (((long) UNSAFE.getByte(addr + 2) & 0xff) << 40) |
+ (((long) UNSAFE.getByte(addr + 3) & 0xff) << 32) |
+ (((long) UNSAFE.getByte(addr + 4) & 0xff) << 24) |
+ (((long) UNSAFE.getByte(addr + 5) & 0xff) << 16) |
+ (((long) UNSAFE.getByte(addr + 6) & 0xff) << 8) |
+ (((long) UNSAFE.getByte(addr + 7) & 0xff));
+ }
+ else {
+ return (((long) UNSAFE.getByte(addr + 7)) << 56) |
+ (((long) UNSAFE.getByte(addr + 6) & 0xff) << 48) |
+ (((long) UNSAFE.getByte(addr + 5) & 0xff) << 40) |
+ (((long) UNSAFE.getByte(addr + 4) & 0xff) << 32) |
+ (((long) UNSAFE.getByte(addr + 3) & 0xff) << 24) |
+ (((long) UNSAFE.getByte(addr + 2) & 0xff) << 16) |
+ (((long) UNSAFE.getByte(addr + 1) & 0xff) << 8) |
+ (((long) UNSAFE.getByte(addr) & 0xff));
+ }
+ }
+
+ /**
+ * @param addr Address.
+ * @param val Value.
+ * @param bigEndian Order of value bytes in memory. If {@code true} - big-endian, otherwise little-endian.
+ */
+ private static void putLongByByte(long addr, long val, boolean bigEndian)
+ {
+ if (bigEndian) {
+ UNSAFE.putByte(addr, (byte) (val >> 56));
+ UNSAFE.putByte(addr + 1, (byte) (val >> 48));
+ UNSAFE.putByte(addr + 2, (byte) (val >> 40));
+ UNSAFE.putByte(addr + 3, (byte) (val >> 32));
+ UNSAFE.putByte(addr + 4, (byte) (val >> 24));
+ UNSAFE.putByte(addr + 5, (byte) (val >> 16));
+ UNSAFE.putByte(addr + 6, (byte) (val >> 8));
+ UNSAFE.putByte(addr + 7, (byte) (val));
+ }
+ else {
+ UNSAFE.putByte(addr + 7, (byte) (val >> 56));
+ UNSAFE.putByte(addr + 6, (byte) (val >> 48));
+ UNSAFE.putByte(addr + 5, (byte) (val >> 40));
+ UNSAFE.putByte(addr + 4, (byte) (val >> 32));
+ UNSAFE.putByte(addr + 3, (byte) (val >> 24));
+ UNSAFE.putByte(addr + 2, (byte) (val >> 16));
+ UNSAFE.putByte(addr + 1, (byte) (val >> 8));
+ UNSAFE.putByte(addr, (byte) (val));
+ }
+ }
+}
diff --git a/lib/trino-ignite-patched/src/test/java/org/apache/ignite/TestDummy.java b/lib/trino-ignite-patched/src/test/java/org/apache/ignite/TestDummy.java
new file mode 100644
index 000000000000..eabaf8f7d7a4
--- /dev/null
+++ b/lib/trino-ignite-patched/src/test/java/org/apache/ignite/TestDummy.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ignite;
+
+import org.testng.annotations.Test;
+
+public class TestDummy
+{
+ @Test
+ public void buildRequiresTestToExist() {}
+}
diff --git a/plugin/trino-ignite/pom.xml b/plugin/trino-ignite/pom.xml
index a9fd3beb7706..535990dc625e 100644
--- a/plugin/trino-ignite/pom.xml
+++ b/plugin/trino-ignite/pom.xml
@@ -39,6 +39,18 @@
trino-base-jdbc
+
+
+ io.trino
+ trino-ignite-patched
+
+
+ org.apache.ignite
+ *
+
+
+
+
io.trino
trino-matching
@@ -60,12 +72,6 @@
jakarta.validation-api
-
- org.apache.ignite
- ignite-core
- 2.15.0
-
-
com.fasterxml.jackson.core
jackson-annotations
@@ -214,4 +220,29 @@
test
+
+
+
+
+ lib/tools.jar
+
+
+ idea.maven.embedder.version
+
+
+
+
+ org.apache.ignite
+ ignite-core
+ 2.15.0
+ provided
+ true
+
+
+
+
diff --git a/pom.xml b/pom.xml
index 30397c5519f5..4884874ac84b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,8 @@
lib/trino-hadoop-toolkit
lib/trino-hdfs
lib/trino-hive-formats
+
+ lib/trino-ignite-patched
lib/trino-matching
lib/trino-memory-context
lib/trino-orc
@@ -1035,6 +1037,13 @@
${project.version}
+
+
+ io.trino
+ trino-ignite-patched
+ ${project.version}
+
+
io.trino
trino-jdbc