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.
This commit is contained in:
Jason Tedor 2016-11-28 17:25:24 -05:00 committed by Norman Maurer
parent b9959c869b
commit 7dac4fdd25
2 changed files with 44 additions and 29 deletions

View File

@ -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);

View File

@ -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<Object>() {
@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<Object>() {
@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.<init>(long, int): {}",
DIRECT_BUFFER_CONSTRUCTOR != null ? "available" : "unavailable");
freeDirectBuffer(direct);
if (direct != null) {
freeDirectBuffer(direct);
}
}
static boolean isUnaligned() {