From d4d27248b4a21f89488fc74de067f874c1ce9048 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Wed, 25 Jun 2014 15:01:57 +0200 Subject: [PATCH] [#2599] Not use sun.nio.ch.DirectBuffer as it not exists on android Motivation: During some refactoring we changed PlatformDependend0 to use sun.nio.ch.DirectBuffer for release direct buffers. This broke support for android as the class does not exist there and so an exception is thrown. Modification: Use again the fieldoffset to get access to Cleaner for release direct buffers. Result: Netty can be used on android again --- .../util/internal/PlatformDependent0.java | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/common/src/main/java/io/netty/util/internal/PlatformDependent0.java b/common/src/main/java/io/netty/util/internal/PlatformDependent0.java index effed4c2c5..f50451ae9b 100644 --- a/common/src/main/java/io/netty/util/internal/PlatformDependent0.java +++ b/common/src/main/java/io/netty/util/internal/PlatformDependent0.java @@ -19,7 +19,6 @@ import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; import sun.misc.Cleaner; import sun.misc.Unsafe; -import sun.nio.ch.DirectBuffer; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -41,6 +40,7 @@ final class PlatformDependent0 { private static final Unsafe UNSAFE; private static final boolean BIG_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; private static final long ADDRESS_FIELD_OFFSET; + private static final long CLEANER_FIELD_OFFSET; /** * Limits the number of bytes to copy per {@link Unsafe#copyMemory(long, long, long)} to allow safepoint polling @@ -56,17 +56,19 @@ final class PlatformDependent0 { private static final boolean UNALIGNED; static { - boolean directBufferFreeable = false; + ByteBuffer direct = ByteBuffer.allocateDirect(1); + Field cleanerField; try { - Class cls = Class.forName("sun.nio.ch.DirectBuffer", false, getClassLoader(PlatformDependent0.class)); - Method method = cls.getMethod("cleaner"); - if ("sun.misc.Cleaner".equals(method.getReturnType().getName())) { - directBufferFreeable = true; - } + cleanerField = direct.getClass().getDeclaredField("cleaner"); + cleanerField.setAccessible(true); + Cleaner cleaner = (Cleaner) cleanerField.get(direct); + cleaner.clean(); } catch (Throwable t) { - // We don't have sun.nio.ch.DirectBuffer.cleaner(). + // We don't have ByteBuffer.cleaner(). + cleanerField = null; } - logger.debug("sun.nio.ch.DirectBuffer.cleaner(): {}", directBufferFreeable? "available" : "unavailable"); + + logger.debug("java.nio.ByteBuffer.cleaner(): {}", cleanerField != null? "available" : "unavailable"); Field addressField; try { @@ -76,7 +78,6 @@ final class PlatformDependent0 { // A heap buffer must have 0 address. addressField = null; } else { - ByteBuffer direct = ByteBuffer.allocateDirect(1); if (addressField.getLong(direct) == 0) { // A direct buffer must have non-zero address. addressField = null; @@ -89,7 +90,7 @@ final class PlatformDependent0 { logger.debug("java.nio.Buffer.address: {}", addressField != null? "available" : "unavailable"); Unsafe unsafe; - if (addressField != null && directBufferFreeable) { + if (addressField != null && cleanerField != null) { try { Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); unsafeField.setAccessible(true); @@ -126,9 +127,11 @@ final class PlatformDependent0 { if (unsafe == null) { ADDRESS_FIELD_OFFSET = -1; + CLEANER_FIELD_OFFSET = -1; UNALIGNED = false; } else { ADDRESS_FIELD_OFFSET = objectFieldOffset(addressField); + CLEANER_FIELD_OFFSET = objectFieldOffset(cleanerField); boolean unaligned; try { Class bitsClass = Class.forName("java.nio.Bits", false, ClassLoader.getSystemClassLoader()); @@ -145,6 +148,9 @@ final class PlatformDependent0 { UNALIGNED = unaligned; logger.debug("java.nio.Bits.unaligned: {}", UNALIGNED); } + + // free temporary buffer if possible + freeDirectBuffer(direct); } static boolean hasUnsafe() { @@ -156,11 +162,11 @@ final class PlatformDependent0 { } static void freeDirectBuffer(ByteBuffer buffer) { - if (!(buffer instanceof DirectBuffer)) { + if (CLEANER_FIELD_OFFSET == -1 || !buffer.isDirect()) { return; } try { - Cleaner cleaner = ((DirectBuffer) buffer).cleaner(); + Cleaner cleaner = (Cleaner) getObject(buffer, CLEANER_FIELD_OFFSET); if (cleaner != null) { cleaner.clean(); }