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(
|
private static final Pattern MAX_DIRECT_MEMORY_SIZE_ARG_PATTERN = Pattern.compile(
|
||||||
"\\s*-XX:MaxDirectMemorySize\\s*=\\s*([0-9]+)\\s*([kKmMgG]?)\\s*$");
|
"\\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 IS_WINDOWS = isWindows0();
|
||||||
private static final boolean MAYBE_SUPER_USER;
|
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 CAN_ENABLE_TCP_NODELAY_BY_DEFAULT = !isAndroid();
|
||||||
|
|
||||||
private static final boolean HAS_UNSAFE = hasUnsafe0();
|
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
|
* Returns {@code true} if and only if the current platform is Android
|
||||||
*/
|
*/
|
||||||
public static boolean isAndroid() {
|
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.
|
* Return the version of Java under which this library is used.
|
||||||
*/
|
*/
|
||||||
public static int javaVersion() {
|
public static int javaVersion() {
|
||||||
return JAVA_VERSION;
|
return PlatformDependent0.javaVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -913,22 +910,6 @@ public final class PlatformDependent {
|
|||||||
return RANDOM_PROVIDER.current();
|
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() {
|
private static boolean isWindows0() {
|
||||||
boolean windows = SystemPropertyUtil.get("os.name", "").toLowerCase(Locale.US).contains("win");
|
boolean windows = SystemPropertyUtil.get("os.name", "").toLowerCase(Locale.US).contains("win");
|
||||||
if (windows) {
|
if (windows) {
|
||||||
@ -946,39 +927,6 @@ public final class PlatformDependent {
|
|||||||
return "root".equals(username) || "toor".equals(username);
|
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() {
|
private static boolean hasUnsafe0() {
|
||||||
if (isAndroid()) {
|
if (isAndroid()) {
|
||||||
logger.debug("sun.misc.Unsafe: unavailable (Android)");
|
logger.debug("sun.misc.Unsafe: unavailable (Android)");
|
||||||
|
@ -41,6 +41,8 @@ final class PlatformDependent0 {
|
|||||||
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 boolean IS_EXPLICIT_NO_UNSAFE = explicitNoUnsafe0();
|
||||||
private static final Method ALLOCATE_ARRAY_METHOD;
|
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;
|
private static final Object INTERNAL_UNSAFE;
|
||||||
static final Unsafe UNSAFE;
|
static final Unsafe UNSAFE;
|
||||||
@ -285,60 +287,63 @@ final class PlatformDependent0 {
|
|||||||
|
|
||||||
UNALIGNED = unaligned;
|
UNALIGNED = unaligned;
|
||||||
|
|
||||||
Object maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
if (javaVersion() >= 9) {
|
||||||
@Override
|
Object maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||||
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>() {
|
|
||||||
@Override
|
@Override
|
||||||
public Object run() {
|
public Object run() {
|
||||||
try {
|
try {
|
||||||
return finalInternalUnsafe.getClass().getDeclaredMethod(
|
// Java9 has jdk.internal.misc.Unsafe and not all methods are propagated to
|
||||||
"allocateUninitializedArray", Class.class, int.class);
|
// sun.misc.Unsafe
|
||||||
} catch (NoSuchMethodException e) {
|
Class<?> internalUnsafeClass = getClassLoader(PlatformDependent0.class)
|
||||||
return e;
|
.loadClass("jdk.internal.misc.Unsafe");
|
||||||
} catch (SecurityException e) {
|
Method method = internalUnsafeClass.getDeclaredMethod("getUnsafe");
|
||||||
|
return method.invoke(null);
|
||||||
|
} catch (Throwable e) {
|
||||||
return 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) {
|
if (maybeException instanceof Method) {
|
||||||
try {
|
try {
|
||||||
Method m = (Method) maybeException;
|
Method m = (Method) maybeException;
|
||||||
byte[] bytes = (byte[]) m.invoke(finalInternalUnsafe, byte.class, 8);
|
byte[] bytes = (byte[]) m.invoke(finalInternalUnsafe, byte.class, 8);
|
||||||
assert bytes.length == 8;
|
assert bytes.length == 8;
|
||||||
allocateArrayMethod = m;
|
allocateArrayMethod = m;
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
maybeException = e;
|
maybeException = e;
|
||||||
} catch (InvocationTargetException e) {
|
} catch (InvocationTargetException e) {
|
||||||
maybeException = 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;
|
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;
|
INTERNAL_UNSAFE = internalUnsafe;
|
||||||
@ -756,6 +761,65 @@ final class PlatformDependent0 {
|
|||||||
return UNSAFE.reallocateMemory(address, newSize);
|
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() {
|
private PlatformDependent0() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import org.junit.BeforeClass;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.security.Permission;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assume.assumeTrue;
|
import static org.junit.Assume.assumeTrue;
|
||||||
@ -54,4 +55,40 @@ public class PlatformDependent0Test {
|
|||||||
assertEquals(address, PlatformDependent0.directBufferAddress(buffer));
|
assertEquals(address, PlatformDependent0.directBufferAddress(buffer));
|
||||||
assertEquals(capacity, buffer.capacity());
|
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 org.junit.Test;
|
||||||
|
|
||||||
import java.security.Permission;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import static io.netty.util.internal.PlatformDependent.hashCodeAscii;
|
import static io.netty.util.internal.PlatformDependent.hashCodeAscii;
|
||||||
@ -147,40 +146,4 @@ public class PlatformDependentTest {
|
|||||||
hashCodeAscii(string));
|
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