From 74738fbd08eec71dc6c8dd801f79e7f2e3e7f366 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Tue, 19 Feb 2013 12:21:08 +0100 Subject: [PATCH] [#1061] Add workaround to not use PooledUnsafeDirectByteBuf when running on latest OpenJDK6 because of missing Unsafe method --- .../main/java/io/netty/buffer/PoolArena.java | 4 ++-- .../buffer/PooledUnsafeDirectByteBuf.java | 1 - .../netty/util/internal/PlatformDependent.java | 15 +++++++++++++++ .../util/internal/PlatformDependent0.java | 18 ++++++++++++++++++ 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/buffer/src/main/java/io/netty/buffer/PoolArena.java b/buffer/src/main/java/io/netty/buffer/PoolArena.java index fa6ec557a2..ca848d16c0 100644 --- a/buffer/src/main/java/io/netty/buffer/PoolArena.java +++ b/buffer/src/main/java/io/netty/buffer/PoolArena.java @@ -376,7 +376,7 @@ abstract class PoolArena { @Override protected PooledByteBuf newByteBuf(int maxCapacity) { - if (PlatformDependent.isUnaligned()) { + if (PlatformDependent.isUnaligned() && PlatformDependent.unsafeHasCopyMethods()) { return new PooledUnsafeDirectByteBuf(maxCapacity); } else { return new PooledDirectByteBuf(maxCapacity); @@ -389,7 +389,7 @@ abstract class PoolArena { return; } - if (PlatformDependent.isUnaligned()) { + if (PlatformDependent.isUnaligned() && PlatformDependent.unsafeHasCopyMethods()) { PlatformDependent.copyMemory( PlatformDependent.directBufferAddress(src) + srcOffset, PlatformDependent.directBufferAddress(dst) + dstOffset, length); diff --git a/buffer/src/main/java/io/netty/buffer/PooledUnsafeDirectByteBuf.java b/buffer/src/main/java/io/netty/buffer/PooledUnsafeDirectByteBuf.java index 36838cc683..28a70c2118 100644 --- a/buffer/src/main/java/io/netty/buffer/PooledUnsafeDirectByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/PooledUnsafeDirectByteBuf.java @@ -30,7 +30,6 @@ import java.nio.channels.ScatteringByteChannel; final class PooledUnsafeDirectByteBuf extends PooledByteBuf { private static final boolean NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; - private long memoryAddress; PooledUnsafeDirectByteBuf(int maxCapacity) { diff --git a/common/src/main/java/io/netty/util/internal/PlatformDependent.java b/common/src/main/java/io/netty/util/internal/PlatformDependent.java index 6aad8ad32f..c679ed776d 100644 --- a/common/src/main/java/io/netty/util/internal/PlatformDependent.java +++ b/common/src/main/java/io/netty/util/internal/PlatformDependent.java @@ -46,6 +46,7 @@ public final class PlatformDependent { private static final boolean HAS_UNSAFE = hasUnsafe0(); private static final boolean CAN_FREE_DIRECT_BUFFER = canFreeDirectBuffer0(); + private static final boolean UNSAFE_HASE_COPY_METHODS = unsafeHasCopyMethods0(); private static final boolean IS_UNALIGNED = isUnaligned0(); private static final long ARRAY_BASE_OFFSET = arrayBaseOffset0(); @@ -109,6 +110,13 @@ public final class PlatformDependent { return IS_UNALIGNED; } + /** + * Returns {@code true} if unsafe has all needed copy methods which is not the case on latest openjdk6 atm. + */ + public static boolean unsafeHasCopyMethods() { + return UNSAFE_HASE_COPY_METHODS; + } + /** * Returns {@code true} if and only if Javassist is available. */ @@ -293,6 +301,13 @@ public final class PlatformDependent { return PlatformDependent0.isUnaligned(); } + private static boolean unsafeHasCopyMethods0() { + if (!hasUnsafe()) { + return false; + } + + return PlatformDependent0.hasCopyMethods(); + } private static long arrayBaseOffset0() { if (!hasUnsafe()) { return -1; 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 141a26b74c..bdbbb978cd 100644 --- a/common/src/main/java/io/netty/util/internal/PlatformDependent0.java +++ b/common/src/main/java/io/netty/util/internal/PlatformDependent0.java @@ -32,6 +32,7 @@ final class PlatformDependent0 { private static final long CLEANER_FIELD_OFFSET; private static final long ADDRESS_FIELD_OFFSET; private static final boolean UNALIGNED; + private static final boolean HAS_COPY_METHODS; static { Unsafe unsafe; @@ -48,6 +49,7 @@ final class PlatformDependent0 { CLEANER_FIELD_OFFSET = -1; ADDRESS_FIELD_OFFSET = -1; UNALIGNED = false; + HAS_COPY_METHODS = false; } else { ByteBuffer direct = ByteBuffer.allocateDirect(1); Field cleanerField; @@ -94,6 +96,18 @@ final class PlatformDependent0 { } UNALIGNED = unaligned; + boolean hasCopyMethods; + try { + // Unsafe does not shop all copy methods in latest openjdk update.. + // https://github.com/netty/netty/issues/1061 + // http://www.mail-archive.com/jdk6-dev@openjdk.java.net/msg00698.html + UNSAFE.getClass().getDeclaredMethod("copyMemory", + new Class[] { Object.class, long.class, Object.class, long.class, long.class }); + hasCopyMethods = true; + } catch (Throwable ignore) { + hasCopyMethods = false; + } + HAS_COPY_METHODS = hasCopyMethods; } } @@ -127,6 +141,10 @@ final class PlatformDependent0 { return UNALIGNED; } + static boolean hasCopyMethods() { + return HAS_COPY_METHODS; + } + static long arrayBaseOffset() { return UNSAFE.arrayBaseOffset(byte[].class); }