From 4ed961f4fee1884f58118896c542b4a33803d47e Mon Sep 17 00:00:00 2001 From: Carl Mastrangelo Date: Thu, 1 Feb 2018 16:52:51 -0800 Subject: [PATCH] To detect Android, check the VM property rather than the classpath Motivation: Some java binaries include android classes on their classpath, even if they aren't actually android. When this is true, `Unsafe` no longer works, disabling the Epoll functionality. A sample case is for binaries that use the j2objc library. Modifications: Check the `java.vm.name` instead of the classpath. Numerous Google-internal Android libraries / binaries check this property rather than the class path. It is believed this is safe and works with bother ART and Dalvik VMs, safe for Robolectric, and j2objc. Results: Unusually built java server binaries can still use Netty Epoll. --- .../util/internal/PlatformDependent0.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/common/src/main/java/io/netty/util/internal/PlatformDependent0.java b/common/src/main/java/io/netty/util/internal/PlatformDependent0.java index f56a1a9ca3..820de8bdfb 100644 --- a/common/src/main/java/io/netty/util/internal/PlatformDependent0.java +++ b/common/src/main/java/io/netty/util/internal/PlatformDependent0.java @@ -786,19 +786,19 @@ final class PlatformDependent0 { } 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; - } + // Idea: Sometimes java binaries include Android classes on the classpath, even if it isn't actually Android. + // Rather than check if certain classes are present, just check the VM, which is tied to the JDK. - if (android) { + // Optional improvement: check if `android.os.Build.VERSION` is >= 24. On later versions of Android, the + // OpenJDK is used, which means `Unsafe` will actually work as expected. + + // Android sets this property to Dalvik, regardless of whether it actually is. + String vmName = SystemPropertyUtil.get("java.vm.name"); + boolean isAndroid = vmName.equals("Dalvik"); + if (isAndroid) { logger.debug("Platform: Android"); } - return android; + return isAndroid; } private static boolean explicitTryReflectionSetAccessible0() {