From 64ae8b6a37249d099b5043ca39dc37c626e993ee Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Fri, 11 Jan 2013 14:03:27 +0900 Subject: [PATCH] Replace and merge DetectionUtil and DirectByteBufUtil into PlatformDependent and PlatformDependent0 PlatformDependent delegates the operations requires sun.misc.* to PlatformDependent0 to avoid runtime errors due to missing sun.misc.* classes. --- .../netty/buffer/DefaultCompositeByteBuf.java | 4 +- .../main/java/io/netty/buffer/PoolArena.java | 3 +- .../buffer/UnpooledByteBufAllocator.java | 4 +- .../netty/buffer/UnpooledDirectByteBuf.java | 15 +- .../codec/spdy/SpdyHeaderBlockCompressor.java | 4 +- .../codec/compression/ZlibCodecFactory.java | 16 +- .../java/io/netty/util/HashedWheelTimer.java | 4 +- .../util/internal/DirectByteBufUtil.java | 73 ----- ...ectionUtil.java => PlatformDependent.java} | 254 ++++++++++-------- .../util/internal/PlatformDependent0.java | 102 +++++++ .../java/io/netty/handler/ssl/SslHandler.java | 4 +- .../io/netty/channel/AbstractChannel.java | 4 +- .../socket/DefaultDatagramChannelConfig.java | 4 +- .../channel/socket/aio/AioEventLoopGroup.java | 4 +- .../socket/aio/UnsafeAioChannelFinder.java | 25 +- .../socket/nio/NioDatagramChannel.java | 10 +- .../socket/nio/NioDatagramChannelConfig.java | 6 +- 17 files changed, 285 insertions(+), 251 deletions(-) delete mode 100644 common/src/main/java/io/netty/util/internal/DirectByteBufUtil.java rename common/src/main/java/io/netty/util/internal/{DetectionUtil.java => PlatformDependent.java} (62%) create mode 100644 common/src/main/java/io/netty/util/internal/PlatformDependent0.java diff --git a/buffer/src/main/java/io/netty/buffer/DefaultCompositeByteBuf.java b/buffer/src/main/java/io/netty/buffer/DefaultCompositeByteBuf.java index 46640c5164..488374dae8 100644 --- a/buffer/src/main/java/io/netty/buffer/DefaultCompositeByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/DefaultCompositeByteBuf.java @@ -15,7 +15,7 @@ */ package io.netty.buffer; -import io.netty.util.internal.DetectionUtil; +import io.netty.util.internal.PlatformDependent; import java.io.IOException; import java.io.InputStream; @@ -699,7 +699,7 @@ public class DefaultCompositeByteBuf extends AbstractByteBuf implements Composit @Override public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { - if (DetectionUtil.javaVersion() < 7) { + if (PlatformDependent.javaVersion() < 7) { // XXX Gathering write is not supported because of a known issue. // See http://bugs.sun.com/view_bug.do?bug_id=6210541 return out.write(copiedNioBuffer(index, length)); diff --git a/buffer/src/main/java/io/netty/buffer/PoolArena.java b/buffer/src/main/java/io/netty/buffer/PoolArena.java index b8c9e01b00..8a5c30c483 100644 --- a/buffer/src/main/java/io/netty/buffer/PoolArena.java +++ b/buffer/src/main/java/io/netty/buffer/PoolArena.java @@ -16,6 +16,7 @@ package io.netty.buffer; +import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.StringUtil; import java.nio.ByteBuffer; @@ -370,7 +371,7 @@ abstract class PoolArena { @Override protected void destroyChunk(PoolChunk chunk) { - UnpooledDirectByteBuf.freeDirect(chunk.memory); + PlatformDependent.freeDirectBuffer(chunk.memory); } @Override diff --git a/buffer/src/main/java/io/netty/buffer/UnpooledByteBufAllocator.java b/buffer/src/main/java/io/netty/buffer/UnpooledByteBufAllocator.java index 2ec014f679..1bdd116557 100644 --- a/buffer/src/main/java/io/netty/buffer/UnpooledByteBufAllocator.java +++ b/buffer/src/main/java/io/netty/buffer/UnpooledByteBufAllocator.java @@ -15,7 +15,7 @@ */ package io.netty.buffer; -import io.netty.util.internal.DetectionUtil; +import io.netty.util.internal.PlatformDependent; /** * Simplistic {@link ByteBufAllocator} implementation that does not pool anything. @@ -41,7 +41,7 @@ public final class UnpooledByteBufAllocator extends AbstractByteBufAllocator { @Override public ByteBuf ioBuffer() { - if (DetectionUtil.canFreeDirectBuffer()) { + if (PlatformDependent.canFreeDirectBuffer()) { return directBuffer(0); } diff --git a/buffer/src/main/java/io/netty/buffer/UnpooledDirectByteBuf.java b/buffer/src/main/java/io/netty/buffer/UnpooledDirectByteBuf.java index a741c26142..232b45247c 100644 --- a/buffer/src/main/java/io/netty/buffer/UnpooledDirectByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/UnpooledDirectByteBuf.java @@ -15,8 +15,7 @@ */ package io.netty.buffer; -import io.netty.util.internal.DetectionUtil; -import io.netty.util.internal.DirectByteBufUtil; +import io.netty.util.internal.PlatformDependent; import java.io.IOException; import java.io.InputStream; @@ -109,7 +108,7 @@ final class UnpooledDirectByteBuf extends AbstractByteBuf { doNotFree = false; } else { if (suspendedDeallocations == null) { - freeDirect(oldBuffer); + PlatformDependent.freeDirectBuffer(oldBuffer); } else { suspendedDeallocations.add(oldBuffer); } @@ -471,7 +470,7 @@ final class UnpooledDirectByteBuf extends AbstractByteBuf { } resumeIntermediaryDeallocations(); - freeDirect(buffer); + PlatformDependent.freeDirectBuffer(buffer); } @Override @@ -492,7 +491,7 @@ final class UnpooledDirectByteBuf extends AbstractByteBuf { this.suspendedDeallocations = null; for (ByteBuffer buf: suspendedDeallocations) { - freeDirect(buf); + PlatformDependent.freeDirectBuffer(buf); } return this; } @@ -501,10 +500,4 @@ final class UnpooledDirectByteBuf extends AbstractByteBuf { public ByteBuf unwrap() { return null; } - - static void freeDirect(ByteBuffer buffer) { - if (DetectionUtil.canFreeDirectBuffer()) { - DirectByteBufUtil.freeDirect(buffer); - } - } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockCompressor.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockCompressor.java index 15a1729bb9..12deaab15c 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockCompressor.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockCompressor.java @@ -16,14 +16,14 @@ package io.netty.handler.codec.spdy; import io.netty.buffer.ByteBuf; -import io.netty.util.internal.DetectionUtil; +import io.netty.util.internal.PlatformDependent; abstract class SpdyHeaderBlockCompressor { static SpdyHeaderBlockCompressor newInstance( int version, int compressionLevel, int windowBits, int memLevel) { - if (DetectionUtil.javaVersion() >= 7) { + if (PlatformDependent.javaVersion() >= 7) { return new SpdyHeaderBlockZlibCompressor( version, compressionLevel); } else { diff --git a/codec/src/main/java/io/netty/handler/codec/compression/ZlibCodecFactory.java b/codec/src/main/java/io/netty/handler/codec/compression/ZlibCodecFactory.java index 5d8609ce0a..979a124694 100644 --- a/codec/src/main/java/io/netty/handler/codec/compression/ZlibCodecFactory.java +++ b/codec/src/main/java/io/netty/handler/codec/compression/ZlibCodecFactory.java @@ -15,7 +15,7 @@ */ package io.netty.handler.codec.compression; -import io.netty.util.internal.DetectionUtil; +import io.netty.util.internal.PlatformDependent; /** * Creates a new {@link ZlibEncoder} and a new {@link ZlibDecoder}. @@ -23,7 +23,7 @@ import io.netty.util.internal.DetectionUtil; public final class ZlibCodecFactory { public static ZlibEncoder newZlibEncoder(int compressionLevel) { - if (DetectionUtil.javaVersion() < 7) { + if (PlatformDependent.javaVersion() < 7) { return new JZlibEncoder(compressionLevel); } else { return new JdkZlibEncoder(compressionLevel); @@ -31,7 +31,7 @@ public final class ZlibCodecFactory { } public static ZlibEncoder newZlibEncoder(ZlibWrapper wrapper) { - if (DetectionUtil.javaVersion() < 7) { + if (PlatformDependent.javaVersion() < 7) { return new JZlibEncoder(wrapper); } else { return new JdkZlibEncoder(wrapper); @@ -39,7 +39,7 @@ public final class ZlibCodecFactory { } public static ZlibEncoder newZlibEncoder(ZlibWrapper wrapper, int compressionLevel) { - if (DetectionUtil.javaVersion() < 7) { + if (PlatformDependent.javaVersion() < 7) { return new JZlibEncoder(wrapper, compressionLevel); } else { return new JdkZlibEncoder(wrapper, compressionLevel); @@ -47,7 +47,7 @@ public final class ZlibCodecFactory { } public static ZlibEncoder newZlibEncoder(ZlibWrapper wrapper, int compressionLevel, int windowBits, int memLevel) { - if (DetectionUtil.javaVersion() < 7) { + if (PlatformDependent.javaVersion() < 7) { return new JZlibEncoder(wrapper, compressionLevel, windowBits, memLevel); } else { return new JdkZlibEncoder(wrapper, compressionLevel); @@ -55,7 +55,7 @@ public final class ZlibCodecFactory { } public static ZlibEncoder newZlibEncoder(byte[] dictionary) { - if (DetectionUtil.javaVersion() < 7) { + if (PlatformDependent.javaVersion() < 7) { return new JZlibEncoder(dictionary); } else { return new JdkZlibEncoder(dictionary); @@ -63,7 +63,7 @@ public final class ZlibCodecFactory { } public static ZlibEncoder newZlibEncoder(int compressionLevel, byte[] dictionary) { - if (DetectionUtil.javaVersion() < 7) { + if (PlatformDependent.javaVersion() < 7) { return new JZlibEncoder(compressionLevel, dictionary); } else { return new JdkZlibEncoder(compressionLevel, dictionary); @@ -71,7 +71,7 @@ public final class ZlibCodecFactory { } public static ZlibEncoder newZlibEncoder(int compressionLevel, int windowBits, int memLevel, byte[] dictionary) { - if (DetectionUtil.javaVersion() < 7) { + if (PlatformDependent.javaVersion() < 7) { return new JZlibEncoder(compressionLevel, windowBits, memLevel, dictionary); } else { return new JdkZlibEncoder(compressionLevel, dictionary); diff --git a/common/src/main/java/io/netty/util/HashedWheelTimer.java b/common/src/main/java/io/netty/util/HashedWheelTimer.java index 943e45f448..7513ccc99c 100644 --- a/common/src/main/java/io/netty/util/HashedWheelTimer.java +++ b/common/src/main/java/io/netty/util/HashedWheelTimer.java @@ -21,7 +21,7 @@ import io.netty.monitor.EventRateMonitor; import io.netty.monitor.MonitorName; import io.netty.monitor.MonitorRegistry; import io.netty.monitor.ValueDistributionMonitor; -import io.netty.util.internal.DetectionUtil; +import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.SharedResourceMisuseDetector; import java.util.ArrayList; @@ -548,7 +548,7 @@ public class HashedWheelTimer implements Timer { // the JVM if it runs on windows. // // See https://github.com/netty/netty/issues/356 - if (DetectionUtil.isWindows()) { + if (PlatformDependent.isWindows()) { sleepTime = sleepTime / 10 * 10; } diff --git a/common/src/main/java/io/netty/util/internal/DirectByteBufUtil.java b/common/src/main/java/io/netty/util/internal/DirectByteBufUtil.java deleted file mode 100644 index b7f8ad6f09..0000000000 --- a/common/src/main/java/io/netty/util/internal/DirectByteBufUtil.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2013 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.netty.util.internal; - -import sun.misc.Cleaner; - -import java.lang.reflect.Field; -import java.nio.ByteBuffer; - -// This resist in common because otherwise we would produce a cycle dependency between common and buffer. -public final class DirectByteBufUtil { - - private static final Field CLEANER_FIELD; - - static { - ByteBuffer direct = ByteBuffer.allocateDirect(1); - Field cleanerField; - try { - cleanerField = direct.getClass().getDeclaredField("cleaner"); - cleanerField.setAccessible(true); - Cleaner cleaner = (Cleaner) cleanerField.get(direct); - cleaner.clean(); - } catch (Throwable t) { - cleanerField = null; - } - CLEANER_FIELD = cleanerField; - } - - /** - * Try to clean a direct {@link ByteBuffer}. - * - * Only try to access this method when {@link DetectionUtil#canFreeDirectBuffer()} returns - * {@code true} - * - */ - public static void freeDirect(ByteBuffer buffer) { - if (!buffer.isDirect()) { - return; - } - if (CLEANER_FIELD == null) { - // Doomed to wait for GC. - return; - } - - Cleaner cleaner; - try { - cleaner = (Cleaner) CLEANER_FIELD.get(buffer); - cleaner.clean(); - } catch (Throwable t) { - // Nothing we can do here. - } - } - - static boolean canFreeDirect() { - return CLEANER_FIELD != null; - } - - private DirectByteBufUtil() { - } -} diff --git a/common/src/main/java/io/netty/util/internal/DetectionUtil.java b/common/src/main/java/io/netty/util/internal/PlatformDependent.java similarity index 62% rename from common/src/main/java/io/netty/util/internal/DetectionUtil.java rename to common/src/main/java/io/netty/util/internal/PlatformDependent.java index 4a5a1c7fb9..5071909b8e 100644 --- a/common/src/main/java/io/netty/util/internal/DetectionUtil.java +++ b/common/src/main/java/io/netty/util/internal/PlatformDependent.java @@ -15,14 +15,12 @@ */ package io.netty.util.internal; +import java.lang.reflect.Field; import java.net.InetSocketAddress; import java.net.ServerSocket; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; +import java.nio.ByteBuffer; import java.util.Locale; import java.util.concurrent.BlockingQueue; -import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Pattern; @@ -34,22 +32,108 @@ import java.util.regex.Pattern; * You can disable the use of {@code sun.misc.Unsafe} if you specify * the system property io.netty.noUnsafe. */ -public final class DetectionUtil { +public final class PlatformDependent { + + private static final ClassLoader LOADER = ClassLoader.getSystemClassLoader(); + + private static final boolean IS_ANDROID = isAndroid0(); + private static final boolean IS_WINDOWS = isWindows0(); + private static final boolean IS_ROOT = isRoot0(); private static final int JAVA_VERSION = javaVersion0(); - private static final boolean HAS_UNSAFE = hasUnsafe(AtomicInteger.class.getClassLoader()); - private static final boolean CAN_FREE_DIRECT_BUFFER; - private static final boolean IS_WINDOWS; - private static final boolean IS_ROOT; - static { + private static final boolean HAS_UNSAFE = hasUnsafe0(); + private static final boolean CAN_FREE_DIRECT_BUFFER = canFreeDirectBuffer0(); + private static final boolean IS_UNALIGNED = isUnaligned0(); + + /** + * Returns {@code true} if and only if the current platform is Android + */ + public static boolean isAndroid() { + return IS_ANDROID; + } + + /** + * Return {@code true} if the JVM is running on Windows + */ + public static boolean isWindows() { + return IS_WINDOWS; + } + + /** + * Return {@code true} if the current user is root. Note that this method returns + * {@code false} if on Windows. + */ + public static boolean isRoot() { + return IS_ROOT; + } + + /** + * Return the version of Java under which this library is used. + */ + public static int javaVersion() { + return JAVA_VERSION; + } + + /** + * Return {@code true} if {@code sun.misc.Unsafe} was found on the classpath and can be used. + */ + public static boolean hasUnsafe() { + return HAS_UNSAFE; + } + + /** + * Return {@code true} if direct buffers can be freed using an optimized way and so memory footprint will be very + * small. + */ + public static boolean canFreeDirectBuffer() { + return CAN_FREE_DIRECT_BUFFER; + } + + /** + * Returns {@code true} if and only if {@code java.nio.Bits.unaligned()} is true. + */ + public static boolean isUnaligned() { + return IS_UNALIGNED; + } + + /** + * Try to deallocate the specified direct {@link ByteBuffer}. Please note this method does nothing if + * the current platform does not support this operation or the specified buffer is not a direct buffer. + */ + public static void freeDirectBuffer(ByteBuffer buffer) { + if (canFreeDirectBuffer() && buffer.isDirect()) { + PlatformDependent0.freeDirectBuffer(buffer); + } + } + + public static Object getObject(Object object, long fieldOffset) { + return PlatformDependent0.getObject(object, fieldOffset); + } + + public static long objectFieldOffset(Field field) { + return PlatformDependent0.objectFieldOffset(field); + } + + private static boolean isAndroid0() { + boolean android; + try { + Class.forName("android.app.Application", false, LOADER); + android = true; + } catch (Exception e) { + android = false; + } + return android; + } + + private static boolean isWindows0() { + return SystemPropertyUtil.get("os.name", "").toLowerCase(Locale.US).contains("win"); + } + + private static boolean isRoot0() { Pattern PERMISSION_DENIED = Pattern.compile(".*permission.*denied.*"); - String os = SystemPropertyUtil.get("os.name", "").toLowerCase(Locale.UK); - // windows - IS_WINDOWS = os.contains("win"); - boolean root = false; - if (!IS_WINDOWS) { + if (!isWindows()) { for (int i = 1023; i > 0; i --) { ServerSocket ss = null; try { @@ -80,97 +164,7 @@ public final class DetectionUtil { } } } - - IS_ROOT = root; - - boolean canFreeDirectBuffer = false; - - // Only try to use DirectByteBufUtil if it is not android as otherwise it will give errors because - // it try to access sun.misc.Cleaner - if (!isAndroid()) { - try { - canFreeDirectBuffer = DirectByteBufUtil.canFreeDirect(); - } catch (Throwable t) { - // Ignore. - } - } - - CAN_FREE_DIRECT_BUFFER = canFreeDirectBuffer; - } - - /** - * Return {@code true} if the JVM is running on Windows - */ - public static boolean isWindows() { - return IS_WINDOWS; - } - - /** - * Return {@code true} if the current user is root. Note that this method returns - * {@code false} if on Windows. - */ - public static boolean isRoot() { - return IS_ROOT; - } - - /** - * Return {@code true} if {@link sun.misc.Unsafe} was found on the classpath and can be used. - */ - public static boolean hasUnsafe() { - return HAS_UNSAFE; - } - - /** - * Return the version of Java under which this library is used. - */ - public static int javaVersion() { - return JAVA_VERSION; - } - - /** - * Return {@code true} if direct buffers can be freed using an optimized way and so memory footprint will be very - * small. - */ - public static boolean canFreeDirectBuffer() { - return CAN_FREE_DIRECT_BUFFER; - } - - private static boolean hasUnsafe(ClassLoader loader) { - boolean noUnsafe = SystemPropertyUtil.getBoolean("io.netty.noUnsafe", false); - if (noUnsafe) { - return false; - } - - // Legacy properties - boolean tryUnsafe; - if (SystemPropertyUtil.contains("io.netty.tryUnsafe")) { - tryUnsafe = SystemPropertyUtil.getBoolean("io.netty.tryUnsafe", true); - } else { - tryUnsafe = SystemPropertyUtil.getBoolean("org.jboss.netty.tryUnsafe", true); - } - - if (!tryUnsafe) { - return false; - } - - try { - Class unsafeClazz = Class.forName("sun.misc.Unsafe", true, loader); - return hasUnsafeField(unsafeClazz); - } catch (Exception e) { - // Ignore - } - - return false; - } - - private static boolean hasUnsafeField(final Class unsafeClass) throws PrivilegedActionException { - return AccessController.doPrivileged(new PrivilegedExceptionAction() { - @Override - public Boolean run() throws Exception { - unsafeClass.getDeclaredField("theUnsafe"); - return true; - } - }); + return root; } private static int javaVersion0() { @@ -191,18 +185,48 @@ public final class DetectionUtil { return 6; } - private static boolean isAndroid() { - // Android - try { - Class.forName("android.app.Application", false, ClassLoader.getSystemClassLoader()); - return true; - } catch (Exception e) { - // Ignore + private static boolean hasUnsafe0() { + if (isAndroid()) { + return false; } - return false; + + boolean noUnsafe = SystemPropertyUtil.getBoolean("io.netty.noUnsafe", false); + if (noUnsafe) { + return false; + } + + // Legacy properties + boolean tryUnsafe; + if (SystemPropertyUtil.contains("io.netty.tryUnsafe")) { + tryUnsafe = SystemPropertyUtil.getBoolean("io.netty.tryUnsafe", true); + } else { + tryUnsafe = SystemPropertyUtil.getBoolean("org.jboss.netty.tryUnsafe", true); + } + + if (!tryUnsafe) { + return false; + } + + return PlatformDependent0.hasUnsafe(); } - private DetectionUtil() { + private static boolean canFreeDirectBuffer0() { + if (isAndroid()) { + return false; + } + + return PlatformDependent0.canFreeDirectBuffer(); + } + + private static boolean isUnaligned0() { + if (!hasUnsafe()) { + return false; + } + + return PlatformDependent0.isUnaligned(); + } + + private PlatformDependent() { // only static method supported } } diff --git a/common/src/main/java/io/netty/util/internal/PlatformDependent0.java b/common/src/main/java/io/netty/util/internal/PlatformDependent0.java new file mode 100644 index 0000000000..37d097981b --- /dev/null +++ b/common/src/main/java/io/netty/util/internal/PlatformDependent0.java @@ -0,0 +1,102 @@ +/* + * Copyright 2013 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.util.internal; + +import sun.misc.Cleaner; +import sun.misc.Unsafe; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.nio.ByteBuffer; + +/** + * The {@link PlatformDependent} operations which requires access to {@code sun.misc.*}. + */ +final class PlatformDependent0 { + + private static final Unsafe UNSAFE; + private static final Field CLEANER_FIELD; + private static final boolean UNALIGNED; + + static { + Unsafe unsafe; + try { + Field singleoneInstanceField = Unsafe.class.getDeclaredField("theUnsafe"); + singleoneInstanceField.setAccessible(true); + unsafe = (Unsafe) singleoneInstanceField.get(null); + } catch (Throwable cause) { + unsafe = null; + } + UNSAFE = unsafe; + + ByteBuffer direct = ByteBuffer.allocateDirect(1); + Field cleanerField; + try { + cleanerField = direct.getClass().getDeclaredField("cleaner"); + cleanerField.setAccessible(true); + Cleaner cleaner = (Cleaner) cleanerField.get(direct); + cleaner.clean(); + } catch (Throwable t) { + cleanerField = null; + } + CLEANER_FIELD = cleanerField; + + boolean unaligned; + try { + Class bitsClass = Class.forName("java.nio.Bits", false, ClassLoader.getSystemClassLoader()); + Method unalignedMethod = bitsClass.getDeclaredMethod("unaligned"); + unalignedMethod.setAccessible(true); + unaligned = Boolean.TRUE.equals(unalignedMethod.invoke(null)); + } catch (Throwable t) { + unaligned = false; + } + UNALIGNED = unaligned; + } + + static boolean hasUnsafe() { + return UNSAFE != null; + } + + static boolean canFreeDirectBuffer() { + return CLEANER_FIELD != null; + } + + static void freeDirectBuffer(ByteBuffer buffer) { + Cleaner cleaner; + try { + cleaner = (Cleaner) CLEANER_FIELD.get(buffer); + cleaner.clean(); + } catch (Throwable t) { + // Nothing we can do here. + } + } + + static boolean isUnaligned() { + return UNALIGNED; + } + + static Object getObject(Object object, long fieldOffset) { + return UNSAFE.getObject(object, fieldOffset); + } + + static long objectFieldOffset(Field field) { + return UNSAFE.objectFieldOffset(field); + } + + + private PlatformDependent0() { + } +} diff --git a/handler/src/main/java/io/netty/handler/ssl/SslHandler.java b/handler/src/main/java/io/netty/handler/ssl/SslHandler.java index 561001e354..6126b42a2b 100644 --- a/handler/src/main/java/io/netty/handler/ssl/SslHandler.java +++ b/handler/src/main/java/io/netty/handler/ssl/SslHandler.java @@ -30,7 +30,7 @@ import io.netty.channel.ChannelPromise; import io.netty.channel.DefaultChannelPromise; import io.netty.logging.InternalLogger; import io.netty.logging.InternalLoggerFactory; -import io.netty.util.internal.DetectionUtil; +import io.netty.util.internal.PlatformDependent; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; @@ -659,7 +659,7 @@ public class SslHandler } // also match against SctpChannel via String matching as it may not present. - if (DetectionUtil.javaVersion() >= 7 + if (PlatformDependent.javaVersion() >= 7 && "com.sun.nio.sctp.SctpChannel".equals(clazz.getSuperclass().getName())) { return true; } diff --git a/transport/src/main/java/io/netty/channel/AbstractChannel.java b/transport/src/main/java/io/netty/channel/AbstractChannel.java index 6157e48c51..8f084d970d 100644 --- a/transport/src/main/java/io/netty/channel/AbstractChannel.java +++ b/transport/src/main/java/io/netty/channel/AbstractChannel.java @@ -21,7 +21,7 @@ import io.netty.buffer.MessageBuf; import io.netty.logging.InternalLogger; import io.netty.logging.InternalLoggerFactory; import io.netty.util.DefaultAttributeMap; -import io.netty.util.internal.DetectionUtil; +import io.netty.util.internal.PlatformDependent; import java.io.EOFException; import java.io.IOException; @@ -631,7 +631,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha boolean wasActive = isActive(); // See: https://github.com/netty/netty/issues/576 - if (!DetectionUtil.isWindows() && !DetectionUtil.isRoot() && + if (!PlatformDependent.isWindows() && !PlatformDependent.isRoot() && Boolean.TRUE.equals(config().getOption(ChannelOption.SO_BROADCAST)) && localAddress instanceof InetSocketAddress && !((InetSocketAddress) localAddress).getAddress().isAnyLocalAddress()) { diff --git a/transport/src/main/java/io/netty/channel/socket/DefaultDatagramChannelConfig.java b/transport/src/main/java/io/netty/channel/socket/DefaultDatagramChannelConfig.java index 324e847a70..eb9c2b0adb 100644 --- a/transport/src/main/java/io/netty/channel/socket/DefaultDatagramChannelConfig.java +++ b/transport/src/main/java/io/netty/channel/socket/DefaultDatagramChannelConfig.java @@ -21,7 +21,7 @@ import io.netty.channel.ChannelOption; import io.netty.channel.DefaultChannelConfig; import io.netty.logging.InternalLogger; import io.netty.logging.InternalLoggerFactory; -import io.netty.util.internal.DetectionUtil; +import io.netty.util.internal.PlatformDependent; import java.io.IOException; import java.net.DatagramSocket; @@ -146,7 +146,7 @@ public class DefaultDatagramChannelConfig extends DefaultChannelConfig implement try { // See: https://github.com/netty/netty/issues/576 if (broadcast && - !DetectionUtil.isWindows() && !DetectionUtil.isRoot() && + !PlatformDependent.isWindows() && !PlatformDependent.isRoot() && !javaSocket.getLocalAddress().isAnyLocalAddress()) { // Warn a user about the fact that a non-root user can't receive a // broadcast packet on *nix if the socket is bound on non-wildcard address. diff --git a/transport/src/main/java/io/netty/channel/socket/aio/AioEventLoopGroup.java b/transport/src/main/java/io/netty/channel/socket/aio/AioEventLoopGroup.java index f9fad5fb7e..3bb2e2d48f 100644 --- a/transport/src/main/java/io/netty/channel/socket/aio/AioEventLoopGroup.java +++ b/transport/src/main/java/io/netty/channel/socket/aio/AioEventLoopGroup.java @@ -22,7 +22,7 @@ import io.netty.channel.EventLoopException; import io.netty.channel.MultithreadEventLoopGroup; import io.netty.logging.InternalLogger; import io.netty.logging.InternalLoggerFactory; -import io.netty.util.internal.DetectionUtil; +import io.netty.util.internal.PlatformDependent; import java.io.IOException; import java.nio.channels.AsynchronousChannelGroup; @@ -44,7 +44,7 @@ public class AioEventLoopGroup extends MultithreadEventLoopGroup { static { AioChannelFinder finder; try { - if (DetectionUtil.hasUnsafe()) { + if (PlatformDependent.hasUnsafe()) { finder = new UnsafeAioChannelFinder(); } else { finder = new ReflectiveAioChannelFinder(); diff --git a/transport/src/main/java/io/netty/channel/socket/aio/UnsafeAioChannelFinder.java b/transport/src/main/java/io/netty/channel/socket/aio/UnsafeAioChannelFinder.java index 2d361a498b..58d0a2ece3 100644 --- a/transport/src/main/java/io/netty/channel/socket/aio/UnsafeAioChannelFinder.java +++ b/transport/src/main/java/io/netty/channel/socket/aio/UnsafeAioChannelFinder.java @@ -15,19 +15,16 @@ */ package io.netty.channel.socket.aio; +import io.netty.util.internal.PlatformDependent; + import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; -import sun.misc.Unsafe; - /** - * {@link AioChannelFinder} implementation which will use {@link Unsafe}. + * {@link AioChannelFinder} implementation which uses {@code sun.misc.Unsafe}. */ -@SuppressWarnings("restriction") final class UnsafeAioChannelFinder implements AioChannelFinder { - private static final Unsafe UNSAFE = getUnsafe(); - private static volatile Map, Long> offsetCache = new HashMap, Long>(); @Override @@ -38,7 +35,7 @@ final class UnsafeAioChannelFinder implements AioChannelFinder { if (offset == null) { return null; } - Object next = UNSAFE.getObject(command, offset); + Object next = PlatformDependent.getObject(command, offset); if (next instanceof AbstractAioChannel) { return (AbstractAioChannel) next; } @@ -56,7 +53,7 @@ final class UnsafeAioChannelFinder implements AioChannelFinder { for (Field f: commandType.getDeclaredFields()) { if (f.getType() == Runnable.class) { - res = UNSAFE.objectFieldOffset(f); + res = PlatformDependent.objectFieldOffset(f); put(offsetCache, commandType, res); return res; } @@ -65,7 +62,7 @@ final class UnsafeAioChannelFinder implements AioChannelFinder { f.setAccessible(true); Object candidate = f.get(command); if (candidate instanceof AbstractAioChannel) { - res = UNSAFE.objectFieldOffset(f); + res = PlatformDependent.objectFieldOffset(f); put(offsetCache, commandType, res); return res; } @@ -80,14 +77,4 @@ final class UnsafeAioChannelFinder implements AioChannelFinder { newCache.put(key, value); offsetCache = newCache; } - - private static Unsafe getUnsafe() { - try { - Field singleoneInstanceField = Unsafe.class.getDeclaredField("theUnsafe"); - singleoneInstanceField.setAccessible(true); - return (Unsafe) singleoneInstanceField.get(null); - } catch (Throwable cause) { - throw new RuntimeException("Error while obtaining sun.misc.Unsafe", cause); - } - } } diff --git a/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java b/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java index 5ac79d6121..8ce572c640 100755 --- a/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java +++ b/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannel.java @@ -25,7 +25,7 @@ import io.netty.channel.ChannelPromise; import io.netty.channel.socket.DatagramChannelConfig; import io.netty.channel.socket.DatagramPacket; import io.netty.channel.socket.InternetProtocolFamily; -import io.netty.util.internal.DetectionUtil; +import io.netty.util.internal.PlatformDependent; import java.io.IOException; import java.net.InetAddress; @@ -69,7 +69,7 @@ public final class NioDatagramChannel return newSocket(); } - if (DetectionUtil.javaVersion() < 7) { + if (PlatformDependent.javaVersion() < 7) { throw new UnsupportedOperationException(); } @@ -309,7 +309,7 @@ public final class NioDatagramChannel public ChannelFuture joinGroup( InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source, ChannelPromise promise) { - if (DetectionUtil.javaVersion() >= 7) { + if (PlatformDependent.javaVersion() >= 7) { if (multicastAddress == null) { throw new NullPointerException("multicastAddress"); } @@ -384,7 +384,7 @@ public final class NioDatagramChannel public ChannelFuture leaveGroup( InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress source, ChannelPromise promise) { - if (DetectionUtil.javaVersion() < 7) { + if (PlatformDependent.javaVersion() < 7) { throw new UnsupportedOperationException(); } if (multicastAddress == null) { @@ -438,7 +438,7 @@ public final class NioDatagramChannel public ChannelFuture block( InetAddress multicastAddress, NetworkInterface networkInterface, InetAddress sourceToBlock, ChannelPromise promise) { - if (DetectionUtil.javaVersion() < 7) { + if (PlatformDependent.javaVersion() < 7) { throw new UnsupportedOperationException(); } else { if (multicastAddress == null) { diff --git a/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannelConfig.java b/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannelConfig.java index f15dcb6810..349dcbf235 100644 --- a/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannelConfig.java +++ b/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannelConfig.java @@ -18,7 +18,7 @@ package io.netty.channel.socket.nio; import io.netty.channel.ChannelException; import io.netty.channel.socket.DatagramChannelConfig; import io.netty.channel.socket.DefaultDatagramChannelConfig; -import io.netty.util.internal.DetectionUtil; +import io.netty.util.internal.PlatformDependent; import java.lang.reflect.Method; import java.net.InetAddress; @@ -162,7 +162,7 @@ class NioDatagramChannelConfig extends DefaultDatagramChannelConfig { } private Object getOption0(Object option) { - if (DetectionUtil.javaVersion() < 7) { + if (PlatformDependent.javaVersion() < 7) { throw new UnsupportedOperationException(); } else { try { @@ -174,7 +174,7 @@ class NioDatagramChannelConfig extends DefaultDatagramChannelConfig { } private void setOption0(Object option, Object value) { - if (DetectionUtil.javaVersion() < 7) { + if (PlatformDependent.javaVersion() < 7) { throw new UnsupportedOperationException(); } else { try {