I am trying to use the MethodHandle
on Android for a project. At the moment, I'm converting some existing Java code to be compatible with Android, but I've run into a problem.
In plain Java 7/8, the following compiles and prints "Jim":
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
public class Example {
public static void main(String[] args) throws Throwable {
MethodHandle arrayReader = MethodHandles.arrayElementGetter(String[].class);
Object array = new String[]{"Hi", "there", "Jim"};
Object item = arrayReader.invoke(array, 2);
System.out.println(item);
}
}
The same code compiles for Android, but an exception is thrown at runtime:
java.lang.NoSuchMethodError: No virtual method invoke(Ljava/lang/Object;I)Ljava/lang/Object; in class Ljava/lang/invoke/MethodHandle; or its super classes (declaration of 'java.lang.invoke.MethodHandle' appears in /system/framework/core-oj.jar)
MethodHandle.invoke exists and uses the varargs feature to pass any number of Object
arguments, yet at runtime it tries to find a method with arity 2 with parameter types Object
and int
.
I have tried replacing the invoke
call with an array parameter: arrayReader.invoke(new Object[]{array, 2})
, but this just creates another problem:
java.lang.UnsupportedOperationException: MethodHandle.invoke cannot be invoked reflectively.
I wouldn't have expected this to work anyway, since the MethodHandle
produced by the MethodHandles.arrayElementGetter
call takes two arguments (the array and the index), but I thought it was worth a shot.
I am running an Android emulator with API level 26. This is a portion of the build.gradle
file:
android {
compileSdkVersion 26
buildToolsVersion "26.0.1"
defaultConfig {
minSdkVersion 26
targetSdkVersion 26
versionCode 1
versionName "1.0"
...
Is there any way to fix this, or an alternative method to achieve the same result?