Propagate full Unsafe unavailability reason in PlatformDependent

Motivation:
It is not clear why Unsafe is unavailable when it is explicitly
disabled, or when Netty thinks it is running on Android.

Modification:
Change the "has" fields and methods to be causes.  A null cause
means Unsafe is present.  This catches all possible reason why
Unsafe might not be available.

Result:
Easier to debug Netty start up when logging cannot be turned on.
This commit is contained in:
Carl Mastrangelo 2018-02-16 10:43:06 -08:00 committed by Scott Mitchell
parent 268b901844
commit 15560530d4
2 changed files with 24 additions and 24 deletions

View File

@ -78,9 +78,9 @@ public final class PlatformDependent {
private static final boolean CAN_ENABLE_TCP_NODELAY_BY_DEFAULT = !isAndroid(); private static final boolean CAN_ENABLE_TCP_NODELAY_BY_DEFAULT = !isAndroid();
private static final boolean HAS_UNSAFE = hasUnsafe0(); private static final Throwable UNSAFE_UNAVAILABILITY_CAUSE = unsafeUnavailabilityCause0();
private static final boolean DIRECT_BUFFER_PREFERRED = private static final boolean DIRECT_BUFFER_PREFERRED =
HAS_UNSAFE && !SystemPropertyUtil.getBoolean("io.netty.noPreferDirect", false); UNSAFE_UNAVAILABILITY_CAUSE == null && !SystemPropertyUtil.getBoolean("io.netty.noPreferDirect", false);
private static final long MAX_DIRECT_MEMORY = maxDirectMemory0(); private static final long MAX_DIRECT_MEMORY = maxDirectMemory0();
private static final int MPSC_CHUNK_SIZE = 1024; private static final int MPSC_CHUNK_SIZE = 1024;
@ -249,14 +249,14 @@ public final class PlatformDependent {
* direct memory access. * direct memory access.
*/ */
public static boolean hasUnsafe() { public static boolean hasUnsafe() {
return HAS_UNSAFE; return UNSAFE_UNAVAILABILITY_CAUSE == null;
} }
/** /**
* Return the reason (if any) why {@code sun.misc.Unsafe} was not available. * Return the reason (if any) why {@code sun.misc.Unsafe} was not available.
*/ */
public static Throwable getUnsafeUnavailabilityCause() { public static Throwable getUnsafeUnavailabilityCause() {
return PlatformDependent0.getUnsafeUnavailabilityCause(); return UNSAFE_UNAVAILABILITY_CAUSE;
} }
/** /**
@ -965,24 +965,24 @@ public final class PlatformDependent {
return "root".equals(username) || "toor".equals(username); return "root".equals(username) || "toor".equals(username);
} }
private static boolean hasUnsafe0() { private static Throwable unsafeUnavailabilityCause0() {
if (isAndroid()) { if (isAndroid()) {
logger.debug("sun.misc.Unsafe: unavailable (Android)"); logger.debug("sun.misc.Unsafe: unavailable (Android)");
return false; return new UnsupportedOperationException("sun.misc.Unsafe: unavailable (Android)");
} }
Throwable cause = PlatformDependent0.getUnsafeUnavailabilityCause();
if (PlatformDependent0.isExplicitNoUnsafe()) { if (cause != null) {
return false; return cause;
} }
try { try {
boolean hasUnsafe = PlatformDependent0.hasUnsafe(); boolean hasUnsafe = PlatformDependent0.hasUnsafe();
logger.debug("sun.misc.Unsafe: {}", hasUnsafe ? "available" : "unavailable"); logger.debug("sun.misc.Unsafe: {}", hasUnsafe ? "available" : "unavailable");
return hasUnsafe; return hasUnsafe ? null : PlatformDependent0.getUnsafeUnavailabilityCause();
} catch (Throwable t) { } catch (Throwable t) {
logger.trace("Could not determine if Unsafe is available", t); logger.trace("Could not determine if Unsafe is available", t);
// Probably failed to initialize PlatformDependent0. // Probably failed to initialize PlatformDependent0.
return false; return new UnsupportedOperationException("Could not determine if Unsafe is available", t);
} }
} }

View File

@ -39,7 +39,7 @@ final class PlatformDependent0 {
private static final long ADDRESS_FIELD_OFFSET; private static final long ADDRESS_FIELD_OFFSET;
private static final long BYTE_ARRAY_BASE_OFFSET; private static final long BYTE_ARRAY_BASE_OFFSET;
private static final Constructor<?> DIRECT_BUFFER_CONSTRUCTOR; private static final Constructor<?> DIRECT_BUFFER_CONSTRUCTOR;
private static final boolean IS_EXPLICIT_NO_UNSAFE = explicitNoUnsafe0(); private static final Throwable EXPLICIT_NO_UNSAFE_CAUSE = explicitNoUnsafeCause0();
private static final Method ALLOCATE_ARRAY_METHOD; private static final Method ALLOCATE_ARRAY_METHOD;
private static final int JAVA_VERSION = javaVersion0(); private static final int JAVA_VERSION = javaVersion0();
private static final boolean IS_ANDROID = isAndroid0(); private static final boolean IS_ANDROID = isAndroid0();
@ -71,10 +71,9 @@ final class PlatformDependent0 {
Unsafe unsafe; Unsafe unsafe;
Object internalUnsafe = null; Object internalUnsafe = null;
if (isExplicitNoUnsafe()) { if ((unsafeUnavailabilityCause = EXPLICIT_NO_UNSAFE_CAUSE) != null) {
direct = null; direct = null;
addressField = null; addressField = null;
unsafeUnavailabilityCause = new UnsupportedOperationException("Unsafe explicitly disabled");
unsafe = null; unsafe = null;
internalUnsafe = null; internalUnsafe = null;
} else { } else {
@ -369,32 +368,33 @@ final class PlatformDependent0 {
} }
static boolean isExplicitNoUnsafe() { static boolean isExplicitNoUnsafe() {
return IS_EXPLICIT_NO_UNSAFE; return EXPLICIT_NO_UNSAFE_CAUSE == null;
} }
private static boolean explicitNoUnsafe0() { private static Throwable explicitNoUnsafeCause0() {
final boolean noUnsafe = SystemPropertyUtil.getBoolean("io.netty.noUnsafe", false); final boolean noUnsafe = SystemPropertyUtil.getBoolean("io.netty.noUnsafe", false);
logger.debug("-Dio.netty.noUnsafe: {}", noUnsafe); logger.debug("-Dio.netty.noUnsafe: {}", noUnsafe);
if (noUnsafe) { if (noUnsafe) {
logger.debug("sun.misc.Unsafe: unavailable (io.netty.noUnsafe)"); logger.debug("sun.misc.Unsafe: unavailable (io.netty.noUnsafe)");
return true; return new UnsupportedOperationException("sun.misc.Unsafe: unavailable (io.netty.noUnsafe)");
} }
// Legacy properties // Legacy properties
boolean tryUnsafe; String unsafePropName;
if (SystemPropertyUtil.contains("io.netty.tryUnsafe")) { if (SystemPropertyUtil.contains("io.netty.tryUnsafe")) {
tryUnsafe = SystemPropertyUtil.getBoolean("io.netty.tryUnsafe", true); unsafePropName = "io.netty.tryUnsafe";
} else { } else {
tryUnsafe = SystemPropertyUtil.getBoolean("org.jboss.netty.tryUnsafe", true); unsafePropName = "org.jboss.netty.tryUnsafe";
} }
if (!tryUnsafe) { if (!SystemPropertyUtil.getBoolean(unsafePropName, true)) {
logger.debug("sun.misc.Unsafe: unavailable (io.netty.tryUnsafe/org.jboss.netty.tryUnsafe)"); String msg = "sun.misc.Unsafe: unavailable (" + unsafePropName + ")";
return true; logger.debug(msg);
return new UnsupportedOperationException(msg);
} }
return false; return null;
} }
static boolean isUnaligned() { static boolean isUnaligned() {