You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ib...@apache.org on 2025/05/06 07:20:17 UTC

(ignite-3) branch main updated: IGNITE-25284 Remove polymorphism from "wrapPointer" (#5741)

This is an automated email from the ASF dual-hosted git repository.

ibessonov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new 416adbe9f05 IGNITE-25284 Remove polymorphism from "wrapPointer" (#5741)
416adbe9f05 is described below

commit 416adbe9f0597dac8a48927536b6d2a0185858d8
Author: Ivan Bessonov <be...@gmail.com>
AuthorDate: Tue May 6 10:20:11 2025 +0300

    IGNITE-25284 Remove polymorphism from "wrapPointer" (#5741)
---
 .../internal/util/BrokenPointerWrapping.java       |  31 ---
 .../apache/ignite/internal/util/GridUnsafe.java    | 249 +------------------
 .../internal/util/JavaNioPointerWrapping.java      |  53 -----
 .../ignite/internal/util/PointerWrapping.java      | 263 ++++++++++++++++++++-
 .../util/WrapWithIntDirectBufferConstructor.java   |  38 ---
 .../util/WrapWithLongDirectBufferConstructor.java  |  38 ---
 .../ignite/internal/util/WrapPointerBenchmark.java |  71 ++++++
 7 files changed, 333 insertions(+), 410 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/BrokenPointerWrapping.java b/modules/core/src/main/java/org/apache/ignite/internal/util/BrokenPointerWrapping.java
deleted file mode 100644
index 7f0f5ad6db8..00000000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/BrokenPointerWrapping.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.internal.util;
-
-import java.nio.ByteBuffer;
-
-/**
- * Always fails with an exception.
- */
-class BrokenPointerWrapping implements PointerWrapping {
-    @Override
-    public ByteBuffer wrapPointer(long ptr, int len) {
-        throw new RuntimeException(
-                "All alternatives for a new DirectByteBuffer() creation failed: " + FeatureChecker.JAVA_STARTUP_PARAMS_WARN);
-    }
-}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/GridUnsafe.java b/modules/core/src/main/java/org/apache/ignite/internal/util/GridUnsafe.java
index c1fa4c35ffd..253fb27fba1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/GridUnsafe.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/GridUnsafe.java
@@ -17,13 +17,6 @@
 
 package org.apache.ignite.internal.util;
 
-import static org.apache.ignite.internal.util.IgniteUtils.jdkVersion;
-import static org.apache.ignite.internal.util.IgniteUtils.majorJavaVersion;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -57,7 +50,7 @@ public abstract class GridUnsafe {
     public static final ByteOrder NATIVE_BYTE_ORDER = ByteOrder.nativeOrder();
 
     /** Unsafe. */
-    private static final Unsafe UNSAFE = unsafe();
+    static final Unsafe UNSAFE = unsafe();
 
     /** Page size. */
     private static final int PAGE_SIZE = UNSAFE.pageSize();
@@ -107,79 +100,6 @@ public abstract class GridUnsafe {
     /** {@link java.nio.Buffer#address} field offset. */
     private static final long DIRECT_BUF_ADDR_OFF = bufferAddressOffset();
 
-    /**
-     * Implementation used to wrap a region if an unmanaged memory in a {@link ByteBuffer}.
-     */
-    private static final PointerWrapping POINTER_WRAPPING;
-
-    static {
-        Object nioAccessObj = null;
-
-        MethodHandle directBufMtd = null;
-        MethodHandle directBufCtorWithIntLen = null;
-        MethodHandle directBufCtorWithLongLen = null;
-
-        if (majorJavaVersion(jdkVersion()) < 12) {
-            // for old java prefer Java NIO & Shared Secrets object init way
-            try {
-                nioAccessObj = javaNioAccessObject();
-                directBufMtd = newDirectBufferMethodHandle(nioAccessObj);
-            } catch (Exception e) {
-                nioAccessObj = null;
-                directBufMtd = null;
-
-                try {
-                    directBufCtorWithIntLen = createAndTestNewDirectBufferCtor(int.class);
-                } catch (Exception exFallback) {
-                    //noinspection CallToPrintStackTrace
-                    exFallback.printStackTrace(); // NOPMD
-
-                    e.addSuppressed(exFallback);
-
-                    throw e; // Fallback was not successful.
-                }
-
-                if (directBufCtorWithIntLen == null) {
-                    throw e;
-                }
-            }
-        } else {
-            try {
-                directBufCtorWithIntLen = createAndTestNewDirectBufferCtor(int.class);
-            } catch (Exception e) {
-                try {
-                    directBufCtorWithLongLen = createAndTestNewDirectBufferCtor(long.class);
-                } catch (Exception e2) {
-                    try {
-                        nioAccessObj = javaNioAccessObject();
-                        directBufMtd = newDirectBufferMethodHandle(nioAccessObj);
-                    } catch (Exception exFallback) {
-                        //noinspection CallToPrintStackTrace
-                        exFallback.printStackTrace(); // NOPMD
-
-                        e.addSuppressed(exFallback);
-
-                        throw e; // Fallback to shared secrets failed.
-                    }
-
-                    if (nioAccessObj == null || directBufMtd == null) {
-                        throw e;
-                    }
-                }
-            }
-        }
-
-        if (directBufMtd != null && nioAccessObj != null) {
-            POINTER_WRAPPING = new JavaNioPointerWrapping(directBufMtd, nioAccessObj);
-        } else if (directBufCtorWithIntLen != null) {
-            POINTER_WRAPPING = new WrapWithIntDirectBufferConstructor(directBufCtorWithIntLen);
-        } else if (directBufCtorWithLongLen != null) {
-            POINTER_WRAPPING = new WrapWithLongDirectBufferConstructor(directBufCtorWithLongLen);
-        } else {
-            POINTER_WRAPPING = new BrokenPointerWrapping();
-        }
-    }
-
     /**
      * Ensure singleton.
      */
@@ -195,46 +115,9 @@ public abstract class GridUnsafe {
      * @return Byte buffer wrapping the given memory.
      */
     public static ByteBuffer wrapPointer(long ptr, int len) {
-        return POINTER_WRAPPING.wrapPointer(ptr, len);
-    }
-
-    /**
-     * Wraps a pointer to unmanaged memory into a direct byte buffer. Uses the constructor of the 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.
-     */
-    static ByteBuffer wrapPointerDirectBufferConstructor(long ptr, int len, MethodHandle constructor) {
-        try {
-            ByteBuffer newDirectBuf = (ByteBuffer) constructor.invokeExact(ptr, len);
-
-            return newDirectBuf.order(NATIVE_BYTE_ORDER);
-        } catch (Throwable e) {
-            throw new RuntimeException("DirectByteBuffer#constructor is unavailable."
-                    + FeatureChecker.JAVA_STARTUP_PARAMS_WARN, e);
-        }
+        return PointerWrapping.wrapPointer(ptr, len);
     }
 
-    /**
-     * Wraps a pointer to unmanaged memory into a direct byte buffer. Uses the constructor of the 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.
-     */
-    static ByteBuffer wrapPointerDirectBufferConstructor(long ptr, long len, MethodHandle constructor) {
-        try {
-            ByteBuffer newDirectBuf = (ByteBuffer) constructor.invokeExact(ptr, len);
-
-            return newDirectBuf.order(NATIVE_BYTE_ORDER);
-        } catch (Throwable e) {
-            throw new RuntimeException("DirectByteBuffer#constructor is unavailable."
-                    + FeatureChecker.JAVA_STARTUP_PARAMS_WARN, e);
-        }
-    }
 
     /**
      * Returns allocated direct buffer.
@@ -1602,134 +1485,6 @@ public abstract class GridUnsafe {
         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 = accessPackage();
-
-        try {
-            Class<?> cls = Class.forName(pkgName + ".SharedSecrets");
-
-            Method mth = cls.getMethod("getJavaNioAccess");
-
-            return mth.invoke(null);
-        } catch (ReflectiveOperationException e) {
-            throw new RuntimeException(pkgName + ".JavaNioAccess class is unavailable."
-                    + FeatureChecker.JAVA_STARTUP_PARAMS_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 MethodHandle newDirectBufferMethodHandle(Object nioAccessObj) {
-        try {
-            Class<?> cls = nioAccessObj.getClass();
-
-            Method mtd = cls.getMethod("newDirectByteBuffer", long.class, int.class, Object.class);
-
-            AccessController.doPrivileged((PrivilegedExceptionAction<?>) () -> {
-                mtd.setAccessible(true);
-
-                return null;
-            });
-
-            MethodType mtdType = MethodType.methodType(
-                    ByteBuffer.class,
-                    Object.class,
-                    long.class,
-                    int.class,
-                    Object.class
-            );
-
-            return MethodHandles.lookup()
-                    .unreflect(mtd)
-                    .asType(mtdType);
-        } catch (ReflectiveOperationException | PrivilegedActionException e) {
-            throw new RuntimeException(accessPackage() + ".JavaNioAccess#newDirectByteBuffer() method is unavailable."
-                    + FeatureChecker.JAVA_STARTUP_PARAMS_WARN, e);
-        }
-    }
-
-    /**
-     * Returns access package name.
-     *
-     * @return Access package name.
-     */
-    private static String accessPackage() {
-        return "jdk.internal.access";
-    }
-
-
-    /**
-     * Creates and tests contructor for Direct ByteBuffer. Test is wrapping one-byte unsafe memory into a buffer.
-     *
-     * @param lengthType Type of the length parameter.
-     * @return constructor for creating direct ByteBuffers.
-     */
-    private static MethodHandle createAndTestNewDirectBufferCtor(Class<?> lengthType) {
-        assert lengthType == int.class || lengthType == long.class : "Unsupported type of length: " + lengthType;
-
-        MethodHandle ctorCandidate = createNewDirectBufferCtor(lengthType);
-
-        int l = 1;
-        long ptr = UNSAFE.allocateMemory(l);
-
-        try {
-            ByteBuffer buf = lengthType == int.class ? wrapPointerDirectBufferConstructor(ptr, l, ctorCandidate)
-                    : wrapPointerDirectBufferConstructor(ptr, (long) l, ctorCandidate);
-
-            if (!buf.isDirect()) {
-                throw new IllegalArgumentException("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.
-     *
-     * @param lengthType Type of the length parameter.
-     * @return constructor for creating direct ByteBuffers.
-     */
-    private static MethodHandle createNewDirectBufferCtor(Class<?> lengthType) {
-        try {
-            ByteBuffer buf = ByteBuffer.allocateDirect(1).order(NATIVE_BYTE_ORDER);
-
-            Constructor<?> ctor = buf.getClass().getDeclaredConstructor(long.class, lengthType);
-
-            AccessController.doPrivileged((PrivilegedExceptionAction<?>) () -> {
-                ctor.setAccessible(true);
-
-                return null;
-            });
-
-            MethodType mtdType = MethodType.methodType(
-                    ByteBuffer.class,
-                    long.class,
-                    lengthType
-            );
-
-            return MethodHandles.lookup()
-                    .unreflectConstructor(ctor)
-                    .asType(mtdType);
-        } catch (ReflectiveOperationException | PrivilegedActionException e) {
-            throw new RuntimeException("Unable to set up byte buffer creation using reflection :" + e.getMessage(), e);
-        }
-    }
-
     /**
      * Returns {@code short} value.
      *
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/JavaNioPointerWrapping.java b/modules/core/src/main/java/org/apache/ignite/internal/util/JavaNioPointerWrapping.java
deleted file mode 100644
index 049978f8708..00000000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/JavaNioPointerWrapping.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.internal.util;
-
-import java.lang.invoke.MethodHandle;
-import java.nio.ByteBuffer;
-
-/**
- * Uses the JavaNioAccess object to wraps a pointer to unmanaged memory into a direct byte buffer.
- */
-class JavaNioPointerWrapping implements PointerWrapping {
-    /** Null object. */
-    private static final Object NULL_OBJ = null;
-
-    private final MethodHandle newDirectBufMh;
-    private final Object javaNioAccessObj;
-
-    JavaNioPointerWrapping(MethodHandle newDirectBufMh, Object javaNioAccessObj) {
-        this.newDirectBufMh = newDirectBufMh;
-        this.javaNioAccessObj = javaNioAccessObj;
-    }
-
-    @Override
-    public ByteBuffer wrapPointer(long ptr, int len) {
-        try {
-            ByteBuffer buf = (ByteBuffer) newDirectBufMh.invokeExact(javaNioAccessObj, ptr, len, NULL_OBJ);
-
-            assert buf.isDirect() : "ptr=" + ptr + ", len=" + len;
-
-            buf.order(GridUnsafe.NATIVE_BYTE_ORDER);
-
-            return buf;
-        } catch (Throwable e) {
-            throw new RuntimeException("JavaNioAccess#newDirectByteBuffer() method is unavailable."
-                    + FeatureChecker.JAVA_STARTUP_PARAMS_WARN, e);
-        }
-    }
-}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/PointerWrapping.java b/modules/core/src/main/java/org/apache/ignite/internal/util/PointerWrapping.java
index 860fe41bcfa..a0b5da593d4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/PointerWrapping.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/PointerWrapping.java
@@ -17,13 +17,73 @@
 
 package org.apache.ignite.internal.util;
 
+import static org.apache.ignite.internal.util.GridUnsafe.NATIVE_BYTE_ORDER;
+import static org.apache.ignite.internal.util.GridUnsafe.UNSAFE;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
 import java.nio.ByteBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 
 /**
  * Wraps a pointer to unmanaged memory into a direct byte buffer.
  */
-@SuppressWarnings("InterfaceMayBeAnnotatedFunctional")
-interface PointerWrapping {
+abstract class PointerWrapping {
+    /** Null object. */
+    private static final Object NULL_OBJ = null;
+
+    /** Handle for {@code JavaNioAccess#newDirectByteBuffer(long addr, int cap, Object ob)}. */
+    private static final MethodHandle DIRECT_BUF_MTD;
+
+    /** Handle for {@code DirectByteBuffer#DirectByteBuffer(long addr, int cap)}. */
+    private static final MethodHandle DIRECT_BUF_CTOR_INT;
+
+    /** Handle for {@code DirectByteBuffer#DirectByteBuffer(long addr, long cap)}. */
+    private static final MethodHandle DIRECT_BUF_CTOR_LONG;
+
+    /** Instance of {@code JavaNioAccess} retrieved from {@code SharedSecrets#getJavaNioAccess()}. */
+    private static final Object JAVA_NIO_ACCESS_OBJ;
+
+    static {
+        Object nioAccessObj = null;
+
+        MethodHandle directBufMtd = null;
+        MethodHandle directBufCtorWithIntLen = null;
+        MethodHandle directBufCtorWithLongLen = null;
+
+        try {
+            directBufCtorWithIntLen = createAndTestNewDirectBufferCtor(int.class);
+        } catch (Throwable e) {
+            try {
+                directBufCtorWithLongLen = createAndTestNewDirectBufferCtor(long.class);
+            } catch (Throwable e1) {
+                e.addSuppressed(e1);
+
+                try {
+                    nioAccessObj = javaNioAccessObject();
+                    directBufMtd = newDirectBufferMethodHandle(nioAccessObj);
+                } catch (Throwable e2) {
+                    e.addSuppressed(e2);
+                }
+
+                if (nioAccessObj == null || directBufMtd == null) {
+                    throw e;
+                }
+            }
+        }
+
+        DIRECT_BUF_MTD = directBufMtd;
+        DIRECT_BUF_CTOR_INT = directBufCtorWithIntLen;
+        DIRECT_BUF_CTOR_LONG = directBufCtorWithLongLen;
+
+        JAVA_NIO_ACCESS_OBJ = nioAccessObj;
+    }
+
     /**
      * Wraps a pointer to unmanaged memory into a direct byte buffer.
      *
@@ -31,5 +91,202 @@ interface PointerWrapping {
      * @param len Memory location length.
      * @return Byte buffer wrapping the given memory.
      */
-    ByteBuffer wrapPointer(long ptr, int len);
+    static ByteBuffer wrapPointer(long ptr, int len) {
+        // Direct usage of "static final" method handle instances allows JIT to inline them into a compiled code. Such an approach produces
+        // the most optimal results.
+        // Usage of conditional branching here is not a problem, because they only refer to "static final" values too, which means that
+        // eventually JIT will inline them and perform a dead branch elimination.
+        // Please be aware of that if you want to refactor this code. Don't do it without having benchmarks and guaranteeing that
+        // performance won't suffer.
+        if (DIRECT_BUF_MTD != null && JAVA_NIO_ACCESS_OBJ != null) {
+            return wrapPointerJavaNio(ptr, len);
+        } else if (DIRECT_BUF_CTOR_INT != null) {
+            return wrapPointerDirectBufferConstructor(ptr, len);
+        } else if (DIRECT_BUF_CTOR_LONG != null) {
+            return wrapPointerDirectBufferConstructor(ptr, (long) len);
+        } else {
+            throw new AssertionError(
+                    "All alternatives for a new DirectByteBuffer() creation failed: " + FeatureChecker.JAVA_STARTUP_PARAMS_WARN);
+        }
+    }
+
+    /**
+     * Returns {@code JavaNioAccess} instance from private API for corresponding Java version.
+     *
+     * @return {@code JavaNioAccess} instance for corresponding Java version.
+     * @throws AssertionError If getting access to the private API is failed.
+     */
+    private static Object javaNioAccessObject() {
+        Class<?> cls;
+        try {
+            cls = Class.forName("jdk.internal.access.SharedSecrets");
+        } catch (ClassNotFoundException e) {
+            try {
+                cls = Class.forName("jdk.internal.misc.SharedSecrets");
+            } catch (ClassNotFoundException e1) {
+                throw new AssertionError("Neither jdk.internal.access.SharedSecrets nor jdk.internal.misc.SharedSecrets are unavailable."
+                        + FeatureChecker.JAVA_STARTUP_PARAMS_WARN, e);
+            }
+        }
+
+        try {
+            Method mth = cls.getMethod("getJavaNioAccess");
+
+            return mth.invoke(null);
+        } catch (ReflectiveOperationException e) {
+            throw new AssertionError(cls.getName() + " class is unavailable."
+                    + FeatureChecker.JAVA_STARTUP_PARAMS_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 AssertionError If getting access to the private API is failed.
+     */
+    private static MethodHandle newDirectBufferMethodHandle(Object nioAccessObj) {
+        try {
+            Class<?> cls = nioAccessObj.getClass();
+
+            Method mtd = cls.getMethod("newDirectByteBuffer", long.class, int.class, Object.class);
+
+            AccessController.doPrivileged((PrivilegedExceptionAction<?>) () -> {
+                mtd.setAccessible(true);
+
+                return null;
+            });
+
+            MethodType mtdType = MethodType.methodType(
+                    ByteBuffer.class,
+                    Object.class,
+                    long.class,
+                    int.class,
+                    Object.class
+            );
+
+            return MethodHandles.lookup()
+                    .unreflect(mtd)
+                    .asType(mtdType);
+        } catch (ReflectiveOperationException | PrivilegedActionException e) {
+            throw new AssertionError(nioAccessObj.getClass().getName() + "#newDirectByteBuffer() method is unavailable."
+                    + FeatureChecker.JAVA_STARTUP_PARAMS_WARN, e);
+        }
+    }
+
+
+    /**
+     * Creates and tests constructor for Direct ByteBuffer. Test is wrapping one-byte unsafe memory into a buffer.
+     *
+     * @param lengthType Type of the length parameter.
+     * @return constructor for creating direct ByteBuffers.
+     */
+    private static MethodHandle createAndTestNewDirectBufferCtor(Class<?> lengthType) {
+        assert lengthType == int.class || lengthType == long.class : "Unsupported type of length: " + lengthType;
+
+        MethodHandle ctorCandidate = createNewDirectBufferCtor(lengthType);
+
+        int l = 1;
+        long ptr = UNSAFE.allocateMemory(l);
+
+        try {
+            ByteBuffer buf = lengthType == int.class
+                    ? (ByteBuffer) ctorCandidate.invokeExact(ptr, l)
+                    : (ByteBuffer) ctorCandidate.invokeExact(ptr, (long) l);
+
+            if (!buf.isDirect()) {
+                throw new IllegalArgumentException("Buffer expected to be direct, internal error during #wrapPointerDirectBufCtor()");
+            }
+        } catch (Throwable t) {
+            throw new AssertionError(t);
+        } finally {
+            UNSAFE.freeMemory(ptr);
+        }
+
+        return ctorCandidate;
+    }
+
+    /**
+     * Simply create some instance of direct Byte Buffer and try to get it's class declared constructor.
+     *
+     * @param lengthType Type of the length parameter.
+     * @return constructor for creating direct ByteBuffers.
+     */
+    private static MethodHandle createNewDirectBufferCtor(Class<?> lengthType) {
+        try {
+            ByteBuffer buf = ByteBuffer.allocateDirect(1).order(NATIVE_BYTE_ORDER);
+
+            Constructor<?> ctor = buf.getClass().getDeclaredConstructor(long.class, lengthType);
+
+            AccessController.doPrivileged((PrivilegedExceptionAction<?>) () -> {
+                ctor.setAccessible(true);
+
+                return null;
+            });
+
+            MethodType mtdType = MethodType.methodType(
+                    ByteBuffer.class,
+                    long.class,
+                    lengthType
+            );
+
+            return MethodHandles.lookup()
+                    .unreflectConstructor(ctor)
+                    .asType(mtdType);
+        } catch (ReflectiveOperationException | PrivilegedActionException e) {
+            throw new AssertionError("Unable to set up byte buffer creation using reflection :" + e.getMessage(), e);
+        }
+    }
+
+    private static ByteBuffer wrapPointerJavaNio(long ptr, int len) {
+        try {
+            ByteBuffer buf = (ByteBuffer) DIRECT_BUF_MTD.invokeExact(JAVA_NIO_ACCESS_OBJ, ptr, len, NULL_OBJ);
+
+            assert buf.isDirect() : "ptr=" + ptr + ", len=" + len;
+
+            buf.order(NATIVE_BYTE_ORDER);
+
+            return buf;
+        } catch (Throwable e) {
+            throw new AssertionError("JavaNioAccess#newDirectByteBuffer() method is unavailable."
+                    + FeatureChecker.JAVA_STARTUP_PARAMS_WARN, e);
+        }
+    }
+
+    /**
+     * Wraps a pointer to unmanaged memory into a direct byte buffer. Uses the constructor of the direct byte buffer.
+     *
+     * @param ptr Pointer to wrap.
+     * @param len Memory location length.
+     * @return Byte buffer wrapping the given memory.
+     */
+    private static ByteBuffer wrapPointerDirectBufferConstructor(long ptr, int len) {
+        try {
+            ByteBuffer newDirectBuf = (ByteBuffer) DIRECT_BUF_CTOR_INT.invokeExact(ptr, len);
+
+            return newDirectBuf.order(NATIVE_BYTE_ORDER);
+        } catch (Throwable e) {
+            throw new AssertionError("DirectByteBuffer#constructor is unavailable."
+                    + FeatureChecker.JAVA_STARTUP_PARAMS_WARN, e);
+        }
+    }
+
+    /**
+     * Wraps a pointer to unmanaged memory into a direct byte buffer. Uses the constructor of the direct byte buffer.
+     *
+     * @param ptr Pointer to wrap.
+     * @param len Memory location length.
+     * @return Byte buffer wrapping the given memory.
+     */
+    private static ByteBuffer wrapPointerDirectBufferConstructor(long ptr, long len) {
+        try {
+            ByteBuffer newDirectBuf = (ByteBuffer) DIRECT_BUF_CTOR_LONG.invokeExact(ptr, len);
+
+            return newDirectBuf.order(NATIVE_BYTE_ORDER);
+        } catch (Throwable e) {
+            throw new AssertionError("DirectByteBuffer#constructor is unavailable."
+                    + FeatureChecker.JAVA_STARTUP_PARAMS_WARN, e);
+        }
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/WrapWithIntDirectBufferConstructor.java b/modules/core/src/main/java/org/apache/ignite/internal/util/WrapWithIntDirectBufferConstructor.java
deleted file mode 100644
index 50193902bf2..00000000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/WrapWithIntDirectBufferConstructor.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.internal.util;
-
-import java.lang.invoke.MethodHandle;
-import java.nio.ByteBuffer;
-
-/**
- * Uses constructor of the direct byte buffer with 'length' parameter of type {@code int} to wrap a pointer to unmanaged memory into a
- * direct byte buffer.
- */
-class WrapWithIntDirectBufferConstructor implements PointerWrapping {
-    private final MethodHandle constructor;
-
-    WrapWithIntDirectBufferConstructor(MethodHandle constructor) {
-        this.constructor = constructor;
-    }
-
-    @Override
-    public ByteBuffer wrapPointer(long ptr, int len) {
-        return GridUnsafe.wrapPointerDirectBufferConstructor(ptr, len, constructor);
-    }
-}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/WrapWithLongDirectBufferConstructor.java b/modules/core/src/main/java/org/apache/ignite/internal/util/WrapWithLongDirectBufferConstructor.java
deleted file mode 100644
index e3c41c00a54..00000000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/WrapWithLongDirectBufferConstructor.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.internal.util;
-
-import java.lang.invoke.MethodHandle;
-import java.nio.ByteBuffer;
-
-/**
- * Uses constructor of the direct byte buffer with 'length' parameter of type {@code long} to wrap a pointer to unmanaged memory into a
- * direct byte buffer.
- */
-class WrapWithLongDirectBufferConstructor implements PointerWrapping {
-    private final MethodHandle constructor;
-
-    WrapWithLongDirectBufferConstructor(MethodHandle constructor) {
-        this.constructor = constructor;
-    }
-
-    @Override
-    public ByteBuffer wrapPointer(long ptr, int len) {
-        return GridUnsafe.wrapPointerDirectBufferConstructor(ptr, (long) len, constructor);
-    }
-}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/WrapPointerBenchmark.java b/modules/core/src/test/java/org/apache/ignite/internal/util/WrapPointerBenchmark.java
new file mode 100644
index 00000000000..ded8d85dc20
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/WrapPointerBenchmark.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.internal.util;
+
+import java.nio.ByteBuffer;
+import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+/**
+ * Benchmark for {@link GridUnsafe#wrapPointer(long, int)}.
+ */
+@State(Scope.Benchmark)
+@Fork(1)
+@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@BenchmarkMode(Mode.Throughput)
+@OutputTimeUnit(TimeUnit.MICROSECONDS)
+public class WrapPointerBenchmark {
+    private static final int SIZE = 1024;
+
+    private long addr;
+
+    @Setup
+    public void setup() {
+        addr = GridUnsafe.allocateMemory(SIZE);
+    }
+
+    @Benchmark
+    public ByteBuffer benchmarkWrapPointer() {
+        return GridUnsafe.wrapPointer(addr, SIZE);
+    }
+
+    /**
+     * Benchmark's entry point.
+     */
+    public static void main(String[] args) throws RunnerException {
+        Options opt = new OptionsBuilder()
+                .include(".*" + WrapPointerBenchmark.class.getSimpleName() + ".*")
+                .build();
+
+        new Runner(opt).run();
+    }
+}