Eliminate noisy logging when using sun.misc.Unsafe and running on pre Java9
Motivation: We should only try to load jdk.internal.misc.Unsafe if we run on Java9+ to eliminate noise in the log. Modifications: - Move javaVersion() and related methods to PlatformDependent0 to be able to use these in the static initializer without creating a cycle. - Only try to load jdk.internal.misc.Unsafe when running in Java9+ Result: Less noise in the log when running pre java9.
This commit is contained in:
parent
827c409656
commit
0ee49e6d66
@ -67,12 +67,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*$");
|
||||
|
||||
private static final boolean IS_ANDROID = isAndroid0();
|
||||
private static final boolean IS_WINDOWS = isWindows0();
|
||||
private static final boolean MAYBE_SUPER_USER;
|
||||
|
||||
private static final int JAVA_VERSION = javaVersion0();
|
||||
|
||||
private static final boolean CAN_ENABLE_TCP_NODELAY_BY_DEFAULT = !isAndroid();
|
||||
|
||||
private static final boolean HAS_UNSAFE = hasUnsafe0();
|
||||
@ -197,7 +194,7 @@ public final class PlatformDependent {
|
||||
* Returns {@code true} if and only if the current platform is Android
|
||||
*/
|
||||
public static boolean isAndroid() {
|
||||
return IS_ANDROID;
|
||||
return PlatformDependent0.isAndroid();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -219,7 +216,7 @@ public final class PlatformDependent {
|
||||
* Return the version of Java under which this library is used.
|
||||
*/
|
||||
public static int javaVersion() {
|
||||
return JAVA_VERSION;
|
||||
return PlatformDependent0.javaVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -913,22 +910,6 @@ public final class PlatformDependent {
|
||||
return RANDOM_PROVIDER.current();
|
||||
}
|
||||
|
||||
private static boolean isAndroid0() {
|
||||
boolean android;
|
||||
try {
|
||||
Class.forName("android.app.Application", false, getSystemClassLoader());
|
||||
android = true;
|
||||
} catch (Throwable ignored) {
|
||||
// Failed to load the class uniquely available in Android.
|
||||
android = false;
|
||||
}
|
||||
|
||||
if (android) {
|
||||
logger.debug("Platform: Android");
|
||||
}
|
||||
return android;
|
||||
}
|
||||
|
||||
private static boolean isWindows0() {
|
||||
boolean windows = SystemPropertyUtil.get("os.name", "").toLowerCase(Locale.US).contains("win");
|
||||
if (windows) {
|
||||
@ -946,39 +927,6 @@ public final class PlatformDependent {
|
||||
return "root".equals(username) || "toor".equals(username);
|
||||
}
|
||||
|
||||
private static int javaVersion0() {
|
||||
final int majorVersion;
|
||||
|
||||
if (isAndroid()) {
|
||||
majorVersion = 6;
|
||||
} else {
|
||||
majorVersion = majorVersionFromJavaSpecificationVersion();
|
||||
}
|
||||
|
||||
logger.debug("Java version: {}", majorVersion);
|
||||
|
||||
return majorVersion;
|
||||
}
|
||||
|
||||
static int majorVersionFromJavaSpecificationVersion() {
|
||||
return majorVersion(SystemPropertyUtil.get("java.specification.version", "1.6"));
|
||||
}
|
||||
|
||||
static int majorVersion(final String javaSpecVersion) {
|
||||
final String[] components = javaSpecVersion.split("\\.");
|
||||
final int[] version = new int[components.length];
|
||||
for (int i = 0; i < components.length; i++) {
|
||||
version[i] = Integer.parseInt(components[i]);
|
||||
}
|
||||
|
||||
if (version[0] == 1) {
|
||||
assert version[1] >= 6;
|
||||
return version[1];
|
||||
} else {
|
||||
return version[0];
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasUnsafe0() {
|
||||
if (isAndroid()) {
|
||||
logger.debug("sun.misc.Unsafe: unavailable (Android)");
|
||||
|
@ -41,6 +41,8 @@ final class PlatformDependent0 {
|
||||
private static final Constructor<?> DIRECT_BUFFER_CONSTRUCTOR;
|
||||
private static final boolean IS_EXPLICIT_NO_UNSAFE = explicitNoUnsafe0();
|
||||
private static final Method ALLOCATE_ARRAY_METHOD;
|
||||
private static final int JAVA_VERSION = javaVersion0();
|
||||
private static final boolean IS_ANDROID = isAndroid0();
|
||||
|
||||
private static final Object INTERNAL_UNSAFE;
|
||||
static final Unsafe UNSAFE;
|
||||
@ -285,60 +287,63 @@ final class PlatformDependent0 {
|
||||
|
||||
UNALIGNED = unaligned;
|
||||
|
||||
Object maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
@Override
|
||||
public Object run() {
|
||||
try {
|
||||
// Java9 has jdk.internal.misc.Unsafe and not all methods are propagated to
|
||||
// sun.misc.Unsafe
|
||||
Class<?> internalUnsafeClass = getClassLoader(PlatformDependent0.class)
|
||||
.loadClass("jdk.internal.misc.Unsafe");
|
||||
Method method = internalUnsafeClass.getDeclaredMethod("getUnsafe");
|
||||
return method.invoke(null);
|
||||
} catch (Throwable e) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!(maybeException instanceof Throwable)) {
|
||||
internalUnsafe = maybeException;
|
||||
final Object finalInternalUnsafe = internalUnsafe;
|
||||
maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
if (javaVersion() >= 9) {
|
||||
Object maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
@Override
|
||||
public Object run() {
|
||||
try {
|
||||
return finalInternalUnsafe.getClass().getDeclaredMethod(
|
||||
"allocateUninitializedArray", Class.class, int.class);
|
||||
} catch (NoSuchMethodException e) {
|
||||
return e;
|
||||
} catch (SecurityException e) {
|
||||
// Java9 has jdk.internal.misc.Unsafe and not all methods are propagated to
|
||||
// sun.misc.Unsafe
|
||||
Class<?> internalUnsafeClass = getClassLoader(PlatformDependent0.class)
|
||||
.loadClass("jdk.internal.misc.Unsafe");
|
||||
Method method = internalUnsafeClass.getDeclaredMethod("getUnsafe");
|
||||
return method.invoke(null);
|
||||
} catch (Throwable e) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!(maybeException instanceof Throwable)) {
|
||||
internalUnsafe = maybeException;
|
||||
final Object finalInternalUnsafe = internalUnsafe;
|
||||
maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
@Override
|
||||
public Object run() {
|
||||
try {
|
||||
return finalInternalUnsafe.getClass().getDeclaredMethod(
|
||||
"allocateUninitializedArray", Class.class, int.class);
|
||||
} catch (NoSuchMethodException e) {
|
||||
return e;
|
||||
} catch (SecurityException e) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (maybeException instanceof Method) {
|
||||
try {
|
||||
Method m = (Method) maybeException;
|
||||
byte[] bytes = (byte[]) m.invoke(finalInternalUnsafe, byte.class, 8);
|
||||
assert bytes.length == 8;
|
||||
allocateArrayMethod = m;
|
||||
} catch (IllegalAccessException e) {
|
||||
maybeException = e;
|
||||
} catch (InvocationTargetException e) {
|
||||
maybeException = e;
|
||||
if (maybeException instanceof Method) {
|
||||
try {
|
||||
Method m = (Method) maybeException;
|
||||
byte[] bytes = (byte[]) m.invoke(finalInternalUnsafe, byte.class, 8);
|
||||
assert bytes.length == 8;
|
||||
allocateArrayMethod = m;
|
||||
} catch (IllegalAccessException e) {
|
||||
maybeException = e;
|
||||
} catch (InvocationTargetException e) {
|
||||
maybeException = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (maybeException instanceof Throwable) {
|
||||
logger.debug("jdk.internal.misc.Unsafe.allocateUninitializedArray(int): unavailable",
|
||||
(Throwable) maybeException);
|
||||
} else {
|
||||
logger.debug("jdk.internal.misc.Unsafe.allocateUninitializedArray(int): available");
|
||||
}
|
||||
} else {
|
||||
logger.debug("jdk.internal.misc.Unsafe.allocateUninitializedArray(int): unavailable prior to Java9");
|
||||
}
|
||||
ALLOCATE_ARRAY_METHOD = allocateArrayMethod;
|
||||
|
||||
if (maybeException instanceof Throwable) {
|
||||
logger.debug("jdk.internal.misc.Unsafe.allocateUninitializedArray(int): unavailable",
|
||||
(Throwable) maybeException);
|
||||
} else {
|
||||
logger.debug("jdk.internal.misc.Unsafe.allocateUninitializedArray(int): available");
|
||||
}
|
||||
}
|
||||
|
||||
INTERNAL_UNSAFE = internalUnsafe;
|
||||
@ -756,6 +761,65 @@ final class PlatformDependent0 {
|
||||
return UNSAFE.reallocateMemory(address, newSize);
|
||||
}
|
||||
|
||||
static boolean isAndroid() {
|
||||
return IS_ANDROID;
|
||||
}
|
||||
|
||||
private static boolean isAndroid0() {
|
||||
boolean android;
|
||||
try {
|
||||
Class.forName("android.app.Application", false, getSystemClassLoader());
|
||||
android = true;
|
||||
} catch (Throwable ignored) {
|
||||
// Failed to load the class uniquely available in Android.
|
||||
android = false;
|
||||
}
|
||||
|
||||
if (android) {
|
||||
logger.debug("Platform: Android");
|
||||
}
|
||||
return android;
|
||||
}
|
||||
|
||||
static int javaVersion() {
|
||||
return JAVA_VERSION;
|
||||
}
|
||||
|
||||
private static int javaVersion0() {
|
||||
final int majorVersion;
|
||||
|
||||
if (isAndroid0()) {
|
||||
majorVersion = 6;
|
||||
} else {
|
||||
majorVersion = majorVersionFromJavaSpecificationVersion();
|
||||
}
|
||||
|
||||
logger.debug("Java version: {}", majorVersion);
|
||||
|
||||
return majorVersion;
|
||||
}
|
||||
|
||||
// Package-private for testing only
|
||||
static int majorVersionFromJavaSpecificationVersion() {
|
||||
return majorVersion(SystemPropertyUtil.get("java.specification.version", "1.6"));
|
||||
}
|
||||
|
||||
// Package-private for testing only
|
||||
static int majorVersion(final String javaSpecVersion) {
|
||||
final String[] components = javaSpecVersion.split("\\.");
|
||||
final int[] version = new int[components.length];
|
||||
for (int i = 0; i < components.length; i++) {
|
||||
version[i] = Integer.parseInt(components[i]);
|
||||
}
|
||||
|
||||
if (version[0] == 1) {
|
||||
assert version[1] >= 6;
|
||||
return version[1];
|
||||
} else {
|
||||
return version[0];
|
||||
}
|
||||
}
|
||||
|
||||
private PlatformDependent0() {
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.Permission;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
@ -54,4 +55,40 @@ public class PlatformDependent0Test {
|
||||
assertEquals(address, PlatformDependent0.directBufferAddress(buffer));
|
||||
assertEquals(capacity, buffer.capacity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMajorVersionFromJavaSpecificationVersion() {
|
||||
final SecurityManager current = System.getSecurityManager();
|
||||
|
||||
try {
|
||||
System.setSecurityManager(new SecurityManager() {
|
||||
@Override
|
||||
public void checkPropertyAccess(String key) {
|
||||
if (key.equals("java.specification.version")) {
|
||||
// deny
|
||||
throw new SecurityException(key);
|
||||
}
|
||||
}
|
||||
|
||||
// so we can restore the security manager
|
||||
@Override
|
||||
public void checkPermission(Permission perm) {
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(6, PlatformDependent0.majorVersionFromJavaSpecificationVersion());
|
||||
} finally {
|
||||
System.setSecurityManager(current);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMajorVersion() {
|
||||
assertEquals(6, PlatformDependent0.majorVersion("1.6"));
|
||||
assertEquals(7, PlatformDependent0.majorVersion("1.7"));
|
||||
assertEquals(8, PlatformDependent0.majorVersion("1.8"));
|
||||
assertEquals(8, PlatformDependent0.majorVersion("8"));
|
||||
assertEquals(9, PlatformDependent0.majorVersion("1.9")); // early version of JDK 9 before Project Verona
|
||||
assertEquals(9, PlatformDependent0.majorVersion("9"));
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ package io.netty.util.internal;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.security.Permission;
|
||||
import java.util.Random;
|
||||
|
||||
import static io.netty.util.internal.PlatformDependent.hashCodeAscii;
|
||||
@ -147,40 +146,4 @@ public class PlatformDependentTest {
|
||||
hashCodeAscii(string));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMajorVersionFromJavaSpecificationVersion() {
|
||||
final SecurityManager current = System.getSecurityManager();
|
||||
|
||||
try {
|
||||
System.setSecurityManager(new SecurityManager() {
|
||||
@Override
|
||||
public void checkPropertyAccess(String key) {
|
||||
if (key.equals("java.specification.version")) {
|
||||
// deny
|
||||
throw new SecurityException(key);
|
||||
}
|
||||
}
|
||||
|
||||
// so we can restore the security manager
|
||||
@Override
|
||||
public void checkPermission(Permission perm) {
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(6, PlatformDependent.majorVersionFromJavaSpecificationVersion());
|
||||
} finally {
|
||||
System.setSecurityManager(current);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMajorVersion() {
|
||||
assertEquals(6, PlatformDependent.majorVersion("1.6"));
|
||||
assertEquals(7, PlatformDependent.majorVersion("1.7"));
|
||||
assertEquals(8, PlatformDependent.majorVersion("1.8"));
|
||||
assertEquals(8, PlatformDependent.majorVersion("8"));
|
||||
assertEquals(9, PlatformDependent.majorVersion("1.9")); // early version of JDK 9 before Project Verona
|
||||
assertEquals(9, PlatformDependent.majorVersion("9"));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user