Android 8.0+未校验java.lang.invoke.Transformers中MethodHandle调用类型问题
关于Android 8.0及以上版本MethodHandle类型校验异常的原因分析
问题现象
Android 8.0及以上版本中,java.lang.invoke.Transformers存在未校验调用的MethodHandle类型的问题,允许调用类型不匹配的方法,具体表现为两种异常场景:
场景1:类型不匹配的方法调用未触发校验错误
代码示例:
static void test(Integer v) { System.out.println("test " + (Object)v); } MethodHandle test = MethodHandles.lookup().findStatic(/*当前类*/, "test", MethodType.methodType(void.class, Integer.class)); MethodHandle i1 = MethodHandles.invoker(MethodType.methodType(void.class, Integer.class)); MethodHandle i2 = MethodHandles.invoker(MethodType.methodType(void.class, MethodHandle.class, String.class)); i2.invoke(i1, test, "string");
执行后输出test string,并未触发预期的参数类型不匹配错误。
场景2:返回值类型转换结果与预期不符
代码示例:
MethodHandle test = MethodHandles.identity(String.class); MethodHandle i1 = MethodHandles.invoker(MethodType.methodType(String.class, String.class)); MethodHandle i2 = MethodHandles.invoker(MethodType.methodType(Integer.class, MethodHandle.class, String.class)); Integer tmp = (Integer) i2.invokeExact(i1, test, "string"); System.out.println(tmp);
执行后输出string,与预期的Integer类型转换结果不符,且未抛出类型转换异常。
异常原因
该异常行为的核心原因是Android 8.0及以上版本的ART(Android Runtime)在实现java.lang.invoke相关逻辑时存在缺陷:
- 当使用嵌套的
MethodHandles.invoker()生成的调用器MethodHandle执行目标方法时,Transformers类在处理MethodHandle的类型适配过程中,遗漏了对最终目标方法的参数类型、返回值类型的严格校验。 - 按照Java规范,
invokeExact()要求调用的参数类型、返回值类型必须与MethodHandle的MethodType完全匹配,但Android的实现跳过了嵌套invoker调用链中的最终类型校验步骤,导致类型不匹配的调用得以直接执行。 - 这种实现上的疏漏,使得原本应该被拦截的类型不匹配调用(包括参数类型、返回值类型)绕过了校验,从而出现示例中的异常输出。
内容的提问来源于stack exchange,提问作者Vladimir
相关产品推荐
相关产品推荐

