fb64 commented on code in PR #1334:
URL: https://github.com/apache/arrow-java/pull/1334#discussion_r4283718990


##########
memory/memory-core/src/main/java/org/apache/arrow/memory/util/MemoryUtil.java:
##########
@@ -16,149 +16,97 @@
  */
 package org.apache.arrow.memory.util;
 
-import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
-import java.lang.reflect.InaccessibleObjectException;
-import java.lang.reflect.InvocationTargetException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import org.checkerframework.checker.nullness.qual.Nullable;
-import sun.misc.Unsafe;
+import org.apache.arrow.memory.DefaultAllocationManagerOption;
+import org.apache.arrow.util.VisibleForTesting;
 
 /** Utilities for memory related operations. */
 public class MemoryUtil {
-  private static final org.slf4j.Logger logger =
-      org.slf4j.LoggerFactory.getLogger(MemoryUtil.class);
-
-  private static final @Nullable Constructor<?> DIRECT_BUFFER_CONSTRUCTOR;
-
-  /** The unsafe object from which to access the off-heap memory. */
-  private static final Unsafe UNSAFE;
-
-  /** The start offset of array data relative to the start address of the 
array object. */
-  private static final long BYTE_ARRAY_BASE_OFFSET;
-
-  /** The offset of the address field with the {@link java.nio.ByteBuffer} 
object. */
-  private static final long BYTE_BUFFER_ADDRESS_OFFSET;
 
   /** If the native byte order is little-endian. */
   public static final boolean LITTLE_ENDIAN = ByteOrder.nativeOrder() == 
ByteOrder.LITTLE_ENDIAN;
 
-  // Java 1.8, 9, 11, 17, 21 becomes 1, 9, 11, 17, and 21.
-  @SuppressWarnings("StringSplitter")
-  private static final int majorVersion =
-      
Integer.parseInt(System.getProperty("java.specification.version").split("\\D+")[0]);
+  /**
+   * The system property used to select the {@link MemoryUtilAccessor} 
implementation. When unset,
+   * this defaults to FFM if {@link
+   * DefaultAllocationManagerOption#ALLOCATION_MANAGER_TYPE_PROPERTY_NAME} (or 
its environment
+   * variable) is set to {@code FFM}, so that selecting the FFM allocation 
manager avoids {@code
+   * sun.misc.Unsafe} entirely unless this property overrides it.
+   */
+  public static final String MEMORY_ACCESSOR_TYPE_PROPERTY_NAME = 
"arrow.memory.accessor.type";
 
-  static {
-    try {
-      // try to get the unsafe object
-      final Object maybeUnsafe =
-          AccessController.doPrivileged(
-              new PrivilegedAction<Object>() {
-                @Override
-                @SuppressWarnings({"nullness:argument", "nullness:return"})
-                // incompatible argument for parameter obj of Field.get
-                // incompatible types in return
-                public Object run() {
-                  try {
-                    final Field unsafeField = 
Unsafe.class.getDeclaredField("theUnsafe");
-                    unsafeField.setAccessible(true);
-                    return unsafeField.get(null);
-                  } catch (Throwable e) {
-                    return e;
-                  }
-                }
-              });
+  private static final org.slf4j.Logger logger =
+      org.slf4j.LoggerFactory.getLogger(MemoryUtil.class);
 
-      if (maybeUnsafe instanceof Throwable) {
-        throw (Throwable) maybeUnsafe;
-      }
+  private static final MemoryUtilAccessor ACCESSOR = resolveAccessor();
 
-      UNSAFE = (Unsafe) maybeUnsafe;
+  private MemoryUtil() {}
 
-      // get the offset of the data inside a byte array object
-      BYTE_ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset(byte[].class);
+  /** Returns the fully qualified class name of the {@link MemoryUtilAccessor} 
in use. */
+  @VisibleForTesting
+  public static String getAccessorClassName() {
+    return ACCESSOR.getClass().getName();
+  }
 
-      // get the offset of the address field in a java.nio.Buffer object
-      long maybeOffset;
-      Field addressField = java.nio.Buffer.class.getDeclaredField("address");
+  private static MemoryUtilAccessor resolveAccessor() {
+    String type = System.getProperty(MEMORY_ACCESSOR_TYPE_PROPERTY_NAME, "");
+    if ("FFM".equals(type)) {
+      logger.info(
+          "{}=FFM, loading org.apache.arrow.memory.ffm.FfmMemoryAccessor",
+          MEMORY_ACCESSOR_TYPE_PROPERTY_NAME);
+      return loadFfmAccessor();
+    }
+    if (type.isEmpty()
+        && DefaultAllocationManagerOption.getDefaultAllocationManagerType()
+            == DefaultAllocationManagerOption.AllocationManagerType.FFM) {
       try {
-        addressField.setAccessible(true);
-        maybeOffset = UNSAFE.objectFieldOffset(addressField);
-      } catch (InaccessibleObjectException e) {
-        maybeOffset = -1;
-        logger.debug(
-            "Cannot access the address field of java.nio.Buffer. DirectBuffer 
operations wont be available",
+        MemoryUtilAccessor accessor = loadFfmAccessor();
+        logger.info(
+            "{}=FFM, also loading 
org.apache.arrow.memory.ffm.FfmMemoryAccessor to avoid"
+                + " sun.misc.Unsafe (override with {}=Unsafe if this is not 
wanted)",
+            
DefaultAllocationManagerOption.ALLOCATION_MANAGER_TYPE_PROPERTY_NAME,
+            MEMORY_ACCESSOR_TYPE_PROPERTY_NAME);
+        return accessor;
+      } catch (RuntimeException e) {
+        // Unlike an explicit arrow.memory.accessor.type=FFM request, this 
preference is only

Review Comment:
   Done: the inferred-FFM fallback now catches `RuntimeException | 
LinkageError`, with tests for `UnsupportedClassVersionError` and 
`ExceptionInInitializerError` in `TestMemoryUtilInferredFfmAccessorFallback`.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to