From cff4a17ae0e1fdad0dfbfb6ea6c8395515bb74fd Mon Sep 17 00:00:00 2001 From: Kristoffer Sjogren Date: Tue, 20 Jan 2015 18:05:29 +0100 Subject: [PATCH] do not use unsafe on android --- .../org/fusesource/lmdbjni/NativeBuffer.java | 12 +++++- .../java/org/fusesource/lmdbjni/Unsafe.java | 38 ++++++++++--------- .../java/org/fusesource/lmdbjni/Util.java | 9 +++++ .../java/org/fusesource/lmdbjni/Value.java | 6 ++- 4 files changed, 45 insertions(+), 20 deletions(-) diff --git a/lmdbjni/src/main/java/org/fusesource/lmdbjni/NativeBuffer.java b/lmdbjni/src/main/java/org/fusesource/lmdbjni/NativeBuffer.java index 387fe30..709bf85 100644 --- a/lmdbjni/src/main/java/org/fusesource/lmdbjni/NativeBuffer.java +++ b/lmdbjni/src/main/java/org/fusesource/lmdbjni/NativeBuffer.java @@ -177,7 +177,11 @@ public void write(long at, byte []source, int offset, int length) { if( at < 0 ) throw new IllegalArgumentException("at cannot be negative"); if( at+length > capacity ) throw new ArrayIndexOutOfBoundsException("at + length exceeds the capacity of this object"); if( offset+length > source.length) throw new ArrayIndexOutOfBoundsException("offset + length exceed the length of the source buffer"); - Unsafe.UNSAFE.copyMemory(source, Unsafe.ARRAY_BASE_OFFSET, null, self + at, length); + if (Unsafe.UNSAFE != null) { + Unsafe.UNSAFE.copyMemory(source, Unsafe.ARRAY_BASE_OFFSET, null, self + at, length); + } else { + JNI.buffer_copy(source, offset, self, at, length); + } } public void read(long at, byte []target, int offset, int length) { @@ -187,7 +191,11 @@ public void read(long at, byte []target, int offset, int length) { if( at < 0 ) throw new IllegalArgumentException("at cannot be negative"); if( at+length > capacity ) throw new ArrayIndexOutOfBoundsException("at + length exceeds the capacity of this object"); if( offset+length > target.length) throw new ArrayIndexOutOfBoundsException("offset + length exceed the length of the target buffer"); - Unsafe.UNSAFE.copyMemory(null, self + at, target, Unsafe.ARRAY_BASE_OFFSET, length); + if (Unsafe.UNSAFE != null) { + Unsafe.UNSAFE.copyMemory(null, self + at, target, Unsafe.ARRAY_BASE_OFFSET, length); + } else { + JNI.buffer_copy(self, at, target, offset, length); + } } public byte[] toByteArray() { diff --git a/lmdbjni/src/main/java/org/fusesource/lmdbjni/Unsafe.java b/lmdbjni/src/main/java/org/fusesource/lmdbjni/Unsafe.java index a29574c..34c62ba 100644 --- a/lmdbjni/src/main/java/org/fusesource/lmdbjni/Unsafe.java +++ b/lmdbjni/src/main/java/org/fusesource/lmdbjni/Unsafe.java @@ -3,28 +3,32 @@ import java.lang.reflect.Field; import java.security.AccessController; import java.security.PrivilegedExceptionAction; +import java.util.Optional; class Unsafe { - public static final sun.misc.Unsafe UNSAFE; - public static final int ADDRESS_SIZE; - public static final long ARRAY_BASE_OFFSET; + /** unsafe may be null on android devices */ + public static sun.misc.Unsafe UNSAFE; + public static int ADDRESS_SIZE; + public static long ARRAY_BASE_OFFSET; static { - try { - final PrivilegedExceptionAction action = new PrivilegedExceptionAction() { - public sun.misc.Unsafe run() throws Exception { - final Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe"); - field.setAccessible(true); - return (sun.misc.Unsafe) field.get(null); - } - }; - - UNSAFE = AccessController.doPrivileged(action); - } catch (final Exception ex) { - throw new RuntimeException(ex); + if (!Util.isAndroid) { + try { + final PrivilegedExceptionAction action = new PrivilegedExceptionAction() { + public sun.misc.Unsafe run() throws Exception { + final Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe"); + field.setAccessible(true); + return (sun.misc.Unsafe) field.get(null); + } + }; + + UNSAFE = AccessController.doPrivileged(action); + ADDRESS_SIZE = UNSAFE.addressSize(); + ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset(byte[].class); + } catch (final Exception ex) { + throw new RuntimeException(ex); + } } - ADDRESS_SIZE = UNSAFE.addressSize(); - ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset(byte[].class); } public static long getAddress(long address, int offset) { diff --git a/lmdbjni/src/main/java/org/fusesource/lmdbjni/Util.java b/lmdbjni/src/main/java/org/fusesource/lmdbjni/Util.java index 850dcd5..08e32bd 100644 --- a/lmdbjni/src/main/java/org/fusesource/lmdbjni/Util.java +++ b/lmdbjni/src/main/java/org/fusesource/lmdbjni/Util.java @@ -27,6 +27,7 @@ * @author Hiram Chirino */ class Util { + public static final boolean isAndroid = isAndroid(); public static String string(long ptr) { if( ptr == 0 ) @@ -47,4 +48,12 @@ public static void checkArgNotNull(Object value, String name) { } } + private static boolean isAndroid() { + try { + Class.forName("android.os.Process"); + return true; + } catch (Throwable ignored) { + return false; + } + } } diff --git a/lmdbjni/src/main/java/org/fusesource/lmdbjni/Value.java b/lmdbjni/src/main/java/org/fusesource/lmdbjni/Value.java index 29ee743..85ccf50 100644 --- a/lmdbjni/src/main/java/org/fusesource/lmdbjni/Value.java +++ b/lmdbjni/src/main/java/org/fusesource/lmdbjni/Value.java @@ -51,7 +51,11 @@ public byte[] toByteArray() { throw new ArrayIndexOutOfBoundsException("Native slice is larger than the maximum Java array"); } byte[] rc = new byte[(int) mv_size]; - Unsafe.getBytes(mv_data, 0, rc); + if (Unsafe.UNSAFE != null) { + Unsafe.getBytes(mv_data, 0, rc); + } else { + JNI.buffer_copy(mv_data, 0, rc, 0, rc.length); + } return rc; }