From 7dac4fdd250c5638e02511e00d22ddf2a6ecf4d1 Mon Sep 17 00:00:00 2001 From: Jason Tedor Date: Mon, 28 Nov 2016 17:25:24 -0500 Subject: [PATCH] Do not try to be unsafe when told not to be unsafe Motivation: Netty has a flag (io.netty.noUnsafe) for specifying to Netty to not be unsafe. Yet, when initializing PlatformDependent0, Netty still tries to be unsafe. For application that specify to Netty to not be unsafe and run under a security manager, this can lead to an obnoxious (debug level) stack trace. Since Netty was told not to be unsafe, Netty should not try to be unsafe. Modifications: The initialization logic in PlatformDependent0 should take into account that Netty was told not to be unsafe. This means that we need to initialize PlatformDependent#IS_EXPLICIT_NO_UNSAFE as soon as possible, before the static initializer for PlatformDependent0 has a chance to run. Thus the following modifications are made: - initialize PlatformDependent#IS_EXPLICIT_NO_UNSAFE before any other code in PlatformDependent causes PlatformDependent0 to initialize - expose the value of PlatformDependent#IS_EXPLICIT_NO_UNSAFE for reading in PlatformDependent0 - take the value of PlatformDependent#IS_EXPLICIT_NO_UNSAFE into account in PlatformDependent0 Result: Netty does not try to be unsafe when told not to be unsafe. --- .../util/internal/PlatformDependent.java | 8 ++- .../util/internal/PlatformDependent0.java | 65 +++++++++++-------- 2 files changed, 44 insertions(+), 29 deletions(-) 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 40785e4c92..d9f550de63 100644 --- a/common/src/main/java/io/netty/util/internal/PlatformDependent.java +++ b/common/src/main/java/io/netty/util/internal/PlatformDependent.java @@ -78,6 +78,9 @@ public final class PlatformDependent { private static final Pattern MAX_DIRECT_MEMORY_SIZE_ARG_PATTERN = Pattern.compile( "\\s*-XX:MaxDirectMemorySize\\s*=\\s*([0-9]+)\\s*([kKmMgG]?)\\s*$"); + // this must be initialized before any code below triggers initialization of PlatformDependent0 + private static final boolean IS_EXPLICIT_NO_UNSAFE = explicitNoUnsafe0(); + private static final boolean IS_ANDROID = isAndroid0(); private static final boolean IS_WINDOWS = isWindows0(); private static volatile Boolean IS_ROOT; @@ -86,7 +89,6 @@ public final class PlatformDependent { private static final boolean CAN_ENABLE_TCP_NODELAY_BY_DEFAULT = !isAndroid(); - private static final boolean IS_EXPLICIT_NO_UNSAFE = explicitNoUnsafe0(); private static final boolean HAS_UNSAFE = hasUnsafe0(); private static final boolean CAN_USE_CHM_V8 = HAS_UNSAFE && JAVA_VERSION < 8; private static final boolean DIRECT_BUFFER_PREFERRED = @@ -1116,6 +1118,10 @@ public final class PlatformDependent { } } + static boolean isExplicitNoUnsafe() { + return IS_EXPLICIT_NO_UNSAFE; + } + private static boolean explicitNoUnsafe0() { final boolean noUnsafe = SystemPropertyUtil.getBoolean("io.netty.noUnsafe", false); logger.debug("-Dio.netty.noUnsafe: {}", noUnsafe); 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 eb7cdb388d..6f86da9be4 100644 --- a/common/src/main/java/io/netty/util/internal/PlatformDependent0.java +++ b/common/src/main/java/io/netty/util/internal/PlatformDependent0.java @@ -58,36 +58,43 @@ final class PlatformDependent0 { private static final boolean UNALIGNED; static { - final ByteBuffer direct = ByteBuffer.allocateDirect(1); + final ByteBuffer direct; final Field addressField; - // attempt to access field Buffer#address - final Object maybeAddressField = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Object run() { - try { - final Field field = Buffer.class.getDeclaredField("address"); - field.setAccessible(true); - // if direct really is a direct buffer, address will be non-zero - if (field.getLong(direct) == 0) { - return null; - } - return field; - } catch (IllegalAccessException e) { - return e; - } catch (NoSuchFieldException e) { - return e; - } catch (SecurityException e) { - return e; - } - } - }); - if (maybeAddressField instanceof Field) { - addressField = (Field) maybeAddressField; - logger.debug("java.nio.Buffer.address: available"); - } else { - logger.debug("java.nio.Buffer.address: unavailable", (Exception) maybeAddressField); + if (PlatformDependent.isExplicitNoUnsafe()) { + direct = null; addressField = null; + } else { + direct = ByteBuffer.allocateDirect(1); + // attempt to access field Buffer#address + final Object maybeAddressField = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Object run() { + try { + final Field field = Buffer.class.getDeclaredField("address"); + field.setAccessible(true); + // if direct really is a direct buffer, address will be non-zero + if (field.getLong(direct) == 0) { + return null; + } + return field; + } catch (IllegalAccessException e) { + return e; + } catch (NoSuchFieldException e) { + return e; + } catch (SecurityException e) { + return e; + } + } + }); + + if (maybeAddressField instanceof Field) { + addressField = (Field) maybeAddressField; + logger.debug("java.nio.Buffer.address: available"); + } else { + logger.debug("java.nio.Buffer.address: unavailable", (Exception) maybeAddressField); + addressField = null; + } } Unsafe unsafe; @@ -247,7 +254,9 @@ final class PlatformDependent0 { logger.debug("java.nio.DirectByteBuffer.(long, int): {}", DIRECT_BUFFER_CONSTRUCTOR != null ? "available" : "unavailable"); - freeDirectBuffer(direct); + if (direct != null) { + freeDirectBuffer(direct); + } } static boolean isUnaligned() {