Include more detail why Unsafe is not available
Motivation: PD and PD0 Both try to find and use Unsafe. If unavailable, they try to log why and continue on. However, it is not always east to enable this logging. Chaining exceptions together is much easier to reach, and the original exception is relevant when Unsafe is needed. Modifications: * Make PD log why PD0 could not be loaded with a trace level log * Make PD0 remember why Unsafe wasn't available * Expose unavailability cause through PD for higher level use. * Make Epoll and KQueue include the reason when failing Result: Easier debugging in hard to reconfigure environments
This commit is contained in:
parent
f5bea11ee4
commit
c891c9c13f
@ -246,6 +246,13 @@ public final class PlatformDependent {
|
||||
return HAS_UNSAFE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the reason (if any) why {@code sun.misc.Unsafe} was not available.
|
||||
*/
|
||||
public static Throwable getUnsafeUnavailabilityCause() {
|
||||
return PlatformDependent0.getUnsafeUnavailabilityCause();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code true} if and only if the platform supports unaligned access.
|
||||
*
|
||||
@ -966,7 +973,8 @@ public final class PlatformDependent {
|
||||
boolean hasUnsafe = PlatformDependent0.hasUnsafe();
|
||||
logger.debug("sun.misc.Unsafe: {}", hasUnsafe ? "available" : "unavailable");
|
||||
return hasUnsafe;
|
||||
} catch (Throwable ignored) {
|
||||
} catch (Throwable t) {
|
||||
logger.trace("Could not determine if Unsafe is available", t);
|
||||
// Probably failed to initialize PlatformDependent0.
|
||||
return false;
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ final class PlatformDependent0 {
|
||||
private static final int JAVA_VERSION = javaVersion0();
|
||||
private static final boolean IS_ANDROID = isAndroid0();
|
||||
|
||||
private static final Throwable UNSAFE_UNAVAILABILITY_CAUSE;
|
||||
private static final Object INTERNAL_UNSAFE;
|
||||
static final Unsafe UNSAFE;
|
||||
|
||||
@ -64,12 +65,14 @@ final class PlatformDependent0 {
|
||||
final ByteBuffer direct;
|
||||
Field addressField = null;
|
||||
Method allocateArrayMethod = null;
|
||||
Throwable unsafeUnavailabilityCause = null;
|
||||
Unsafe unsafe;
|
||||
Object internalUnsafe = null;
|
||||
|
||||
if (isExplicitNoUnsafe()) {
|
||||
direct = null;
|
||||
addressField = null;
|
||||
unsafeUnavailabilityCause = new UnsupportedOperationException("Unsafe explicitly disabled");
|
||||
unsafe = null;
|
||||
internalUnsafe = null;
|
||||
} else {
|
||||
@ -101,9 +104,10 @@ final class PlatformDependent0 {
|
||||
// is an instanceof Unsafe and reversing the if and else blocks; this is because an
|
||||
// instanceof check against Unsafe will trigger a class load and we might not have
|
||||
// the runtime permission accessClassInPackage.sun.misc
|
||||
if (maybeUnsafe instanceof Exception) {
|
||||
if (maybeUnsafe instanceof Throwable) {
|
||||
unsafe = null;
|
||||
logger.debug("sun.misc.Unsafe.theUnsafe: unavailable", (Exception) maybeUnsafe);
|
||||
unsafeUnavailabilityCause = (Throwable) maybeUnsafe;
|
||||
logger.debug("sun.misc.Unsafe.theUnsafe: unavailable", (Throwable) maybeUnsafe);
|
||||
} else {
|
||||
unsafe = (Unsafe) maybeUnsafe;
|
||||
logger.debug("sun.misc.Unsafe.theUnsafe: available");
|
||||
@ -134,6 +138,7 @@ final class PlatformDependent0 {
|
||||
} else {
|
||||
// Unsafe.copyMemory(Object, long, Object, long, long) unavailable.
|
||||
unsafe = null;
|
||||
unsafeUnavailabilityCause = (Throwable) maybeException;
|
||||
logger.debug("sun.misc.Unsafe.copyMemory: unavailable", (Throwable) maybeException);
|
||||
}
|
||||
}
|
||||
@ -169,6 +174,7 @@ final class PlatformDependent0 {
|
||||
addressField = (Field) maybeAddressField;
|
||||
logger.debug("java.nio.Buffer.address: available");
|
||||
} else {
|
||||
unsafeUnavailabilityCause = (Throwable) maybeAddressField;
|
||||
logger.debug("java.nio.Buffer.address: unavailable", (Throwable) maybeAddressField);
|
||||
|
||||
// If we cannot access the address of a direct buffer, there's no point of using unsafe.
|
||||
@ -183,10 +189,12 @@ final class PlatformDependent0 {
|
||||
long byteArrayIndexScale = unsafe.arrayIndexScale(byte[].class);
|
||||
if (byteArrayIndexScale != 1) {
|
||||
logger.debug("unsafe.arrayIndexScale is {} (expected: 1). Not using unsafe.", byteArrayIndexScale);
|
||||
unsafeUnavailabilityCause = new UnsupportedOperationException("Unexpected unsafe.arrayIndexScale");
|
||||
unsafe = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
UNSAFE_UNAVAILABILITY_CAUSE = unsafeUnavailabilityCause;
|
||||
UNSAFE = unsafe;
|
||||
|
||||
if (unsafe == null) {
|
||||
@ -389,6 +397,10 @@ final class PlatformDependent0 {
|
||||
return UNSAFE != null;
|
||||
}
|
||||
|
||||
static Throwable getUnsafeUnavailabilityCause() {
|
||||
return UNSAFE_UNAVAILABILITY_CAUSE;
|
||||
}
|
||||
|
||||
static boolean unalignedAccess() {
|
||||
return UNALIGNED;
|
||||
}
|
||||
|
@ -54,8 +54,11 @@ public final class Epoll {
|
||||
if (cause != null) {
|
||||
UNAVAILABILITY_CAUSE = cause;
|
||||
} else {
|
||||
UNAVAILABILITY_CAUSE = PlatformDependent.hasUnsafe() ? null :
|
||||
new IllegalStateException("sun.misc.Unsafe not available");
|
||||
UNAVAILABILITY_CAUSE = PlatformDependent.hasUnsafe()
|
||||
? null
|
||||
: new IllegalStateException(
|
||||
"sun.misc.Unsafe not available",
|
||||
PlatformDependent.getUnsafeUnavailabilityCause());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,8 +46,11 @@ public final class KQueue {
|
||||
if (cause != null) {
|
||||
UNAVAILABILITY_CAUSE = cause;
|
||||
} else {
|
||||
UNAVAILABILITY_CAUSE = PlatformDependent.hasUnsafe() ? null :
|
||||
new IllegalStateException("sun.misc.Unsafe not available");
|
||||
UNAVAILABILITY_CAUSE = PlatformDependent.hasUnsafe()
|
||||
? null
|
||||
: new IllegalStateException(
|
||||
"sun.misc.Unsafe not available",
|
||||
PlatformDependent.getUnsafeUnavailabilityCause());
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user