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.
This commit is contained in:
Carl Mastrangelo 2018-02-01 16:52:51 -08:00 committed by Norman Maurer
parent 501662a77f
commit 4ed961f4fe

View File

@ -786,19 +786,19 @@ final class PlatformDependent0 {
} }
private static boolean isAndroid0() { private static boolean isAndroid0() {
boolean android; // Idea: Sometimes java binaries include Android classes on the classpath, even if it isn't actually Android.
try { // Rather than check if certain classes are present, just check the VM, which is tied to the JDK.
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) { // 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"); logger.debug("Platform: Android");
} }
return android; return isAndroid;
} }
private static boolean explicitTryReflectionSetAccessible0() { private static boolean explicitTryReflectionSetAccessible0() {