You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by dp...@apache.org on 2019/04/01 17:50:39 UTC

[ignite] branch ignite-11600-12 updated: IGNITE-11600 Selective prioritized approaches to allocate a direct buffer

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

dpavlov pushed a commit to branch ignite-11600-12
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/ignite-11600-12 by this push:
     new 3289628  IGNITE-11600 Selective prioritized approaches to allocate a direct buffer
3289628 is described below

commit 3289628238ec204d3ea688e4fa28165798544bd6
Author: Dmitriy Pavlov <dp...@apache.org>
AuthorDate: Mon Apr 1 20:50:13 2019 +0300

    IGNITE-11600 Selective prioritized approaches to allocate a direct buffer
---
 .../apache/ignite/internal/util/GridUnsafe.java    | 155 +++++++++++++++------
 1 file changed, 115 insertions(+), 40 deletions(-)

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 2c8533d..6145295 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
@@ -29,10 +29,10 @@ import java.security.PrivilegedAction;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import org.apache.ignite.IgniteSystemProperties;
+import org.apache.ignite.internal.util.typedef.internal.A;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import sun.misc.Unsafe;
-import sun.nio.ch.DirectBuffer;
 
 import static org.apache.ignite.internal.util.IgniteUtils.jdkVersion;
 import static org.apache.ignite.internal.util.IgniteUtils.majorJavaVersion;
@@ -111,57 +111,76 @@ public abstract class GridUnsafe {
             ? new ReflectiveDirectBufferCleaner()
             : new UnsafeDirectBufferCleaner();
 
-    /** JavaNioAccess object. */
+    /** 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. */
+    /** JavaNioAccess#newDirectByteBuffer method. Ususally {@code null} if {@link #JAVA_NIO_ACCESS_OBJ} is null. */
     @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 ba not null.
+     */
     @Nullable private static final Constructor<?> NEW_DIRECT_BUF_CONSTRUCTOR;
 
     static {
-        NEW_DIRECT_BUF_CONSTRUCTOR = newDirectBufferCtor();
-
         Object nioAccessObj = null;
         Method directBufMtd = null;
-        try {
-            nioAccessObj = javaNioAccessObject();
 
-            directBufMtd = newDirectBufferMethod(nioAccessObj);
-        }
-        catch (Exception e) {
-            nioAccessObj = null;
-            directBufMtd = null;
+        Constructor<?> directBufCtor = null;
 
-            if (majorJavaVersion(jdkVersion()) > 11) {
-                Constructor<?> constructor = newDirectBufferCtor();
+        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
-                throw e;
-        }
-        finally {
-            JAVA_NIO_ACCESS_OBJ = nioAccessObj;
-            NEW_DIRECT_BUF_MTD = directBufMtd;
         }
-    }
+        else {
+            try {
+                directBufCtor = createAndTestNewDirectBufferCtor();
+            }
+            catch (Exception e) {
+                directBufCtor = null;
 
-    private static Constructor<?> newDirectBufferCtor() {
-        try {
-            ByteBuffer direct = ByteBuffer.allocateDirect(1).order(NATIVE_BYTE_ORDER);
+                try {
+                    nioAccessObj = javaNioAccessObject();
+                    directBufMtd = newDirectBufferMethod(nioAccessObj);
+                }
+                catch (Exception eFallback) {
+                    eFallback.printStackTrace();
 
-            final Constructor<?> constructor =
-                direct.getClass().getDeclaredConstructor(long.class, int.class);
+                    e.addSuppressed(eFallback);
 
-            constructor.setAccessible(true);
+                    throw e; //fallback to shared secrets failed.
+                }
 
-            return constructor;
-        } catch (NoSuchMethodException e) {
-            return null;
-        } catch (SecurityException e) {
-            return null;
+                if (nioAccessObj == null || directBufCtor == null)
+                    throw e;
+            }
         }
+
+        JAVA_NIO_ACCESS_OBJ = nioAccessObj;
+        NEW_DIRECT_BUF_MTD = directBufMtd;
+        NEW_DIRECT_BUF_CONSTRUCTOR = directBufCtor;
     }
 
     /**
@@ -177,17 +196,29 @@ public abstract class GridUnsafe {
      * @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);
+        else if (NEW_DIRECT_BUF_CONSTRUCTOR != null)
+            return wrapPointerDirectBufCtor(ptr, len, NEW_DIRECT_BUF_CONSTRUCTOR);
+        else
+            throw new RuntimeException("All cases of newDirectByteBuffer() creation failed" + FeatureChecker.JAVA_VER_SPECIFIC_WARN);
+    }
+
+    /**
+     * @param ptr Pointer to wrap.
+     * @param len Memory location length.
+     * @param constructor Constructor to use.
+     * @return Byte buffer wrapping the given memory.
+     */
+    @NotNull private static ByteBuffer wrapPointerDirectBufCtor(long ptr, int len, Constructor<?> constructor) {
         try {
-            Object newDirectBuf = NEW_DIRECT_BUF_CONSTRUCTOR.newInstance(ptr, len);
+            Object newDirectBuf = constructor.newInstance(ptr, len);
 
             return ((ByteBuffer)newDirectBuf).order(NATIVE_BYTE_ORDER);
         }
-        catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
-            new RuntimeException("JavaNioAccess#newDirectByteBuffer() method is unavailable."
+        catch (ReflectiveOperationException e) {
+            throw new RuntimeException("DirectByteBuffer#constructor is unavailable."
                 + FeatureChecker.JAVA_VER_SPECIFIC_WARN, e);
-            //todo check presence
-
-            return wrapPointer2(ptr, len);
         }
     }
 
@@ -196,7 +227,7 @@ public abstract class GridUnsafe {
      * @param len Memory location length.
      * @return Byte buffer wrapping the given memory.
      */
-    @NotNull private static ByteBuffer wrapPointer2(long ptr, int len) {
+    @NotNull private static ByteBuffer wrapPointerJavaNio(long ptr, int len) {
         try {
             ByteBuffer buf = (ByteBuffer)NEW_DIRECT_BUF_MTD.invoke(JAVA_NIO_ACCESS_OBJ, ptr, len, null);
 
@@ -1559,6 +1590,50 @@ public abstract class GridUnsafe {
         return javaVer < 9 ? "sun" : "jdk.internal";
     }
 
+
+    /**
+     * Create and test contructor for DirectByteBuffer. Test is simple wrap of one object
+     */
+    @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 declared constructor.
+     */
+    @NotNull
+    private static Constructor<?> createNewDirectBufferCtor() {
+        try {
+            ByteBuffer direct = ByteBuffer.allocateDirect(1).order(NATIVE_BYTE_ORDER);
+
+            Constructor<?> constructor = direct.getClass().getDeclaredConstructor(long.class, int.class);
+
+            constructor.setAccessible(true);
+
+            return constructor;
+        }
+        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.