Android java。带注释参数的私有方法的lang.VerifyError
我有一个非常简单的编译项目,但无法在Emulator上启动。此方法的问题在于:
private void bar(@Some String a) {} // java.lang.VerifyError
如果删除注释,则可以避免此问题
private void bar(String a) {} // OK
或者方法可见性已更改:
void bar(@Some String a) {} // OK
public void bar(@Some String a) {} // OK
protected void bar(@Some String a) {} // OK
你知道原来的方法有什么问题吗?这是dalvik臭虫,还是
如果有人想尝试代码,这里是:
测试。爪哇:
public class Test {
private void bar(@Some String a) {}
public void foo() {
bar(null);
}
}
一些。爪哇:
public @interface Some {}
主要活动。爪哇:
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new Test().foo();
}
}
堆栈跟踪:
ERROR/dalvikvm(1358): Could not find method com.my.Test.bar, referenced from method com.my.Test.foo
WARN/dalvikvm(1358): VFY: unable to resolve direct method 11: Lcom/my/Test;.bar (Ljava/lang/String;)V
WARN/dalvikvm(1358): VFY: rejecting opcode 0x70 at 0x0001
WARN/dalvikvm(1358): VFY: rejected Lcom/my/Test;.foo ()V
WARN/dalvikvm(1358): Verifier rejected class Lcom/my/Test;
DEBUG/AndroidRuntime(1358): Shutting down VM
WARN/dalvikvm(1358): threadid=3: thread exiting with uncaught exception (group=0x4000fe70)
ERROR/AndroidRuntime(1358): Uncaught handler: thread main exiting due to uncaught exception
ERROR/AndroidRuntime(1358): java.lang.VerifyError: com.my.Test
ERROR/AndroidRuntime(1358): at com.my.MainActivity.onCreate(MainActivity.java:13)
ERROR/AndroidRuntime(1358): at 安卓.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
ERROR/AndroidRuntime(1358): at 安卓.app.ActivityThread.performLaunchActivity(ActivityThread.java:2231)
ERROR/AndroidRuntime(1358): at 安卓.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2284)
ERROR/AndroidRuntime(1358): at 安卓.app.ActivityThread.access$1800(ActivityThread.java:112)
ERROR/AndroidRuntime(1358): at 安卓.app.ActivityThread$H.handleMessage(ActivityThread.java:1692)
ERROR/AndroidRuntime(1358): at 安卓.os.Handler.dispatchMessage(Handler.java:99)
ERROR/AndroidRuntime(1358): at 安卓.os.Looper.loop(Looper.java:123)
ERROR/AndroidRuntime(1358): at 安卓.app.ActivityThread.main(ActivityThread.java:3948)
ERROR/AndroidRuntime(1358): at java.lang.reflect.Method.invokeNative(Native Method)
ERROR/AndroidRuntime(1358): at java.lang.reflect.Method.invoke(Method.java:521)
ERROR/AndroidRuntime(1358): at com.安卓.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:782)
ERROR/AndroidRuntime(1358): at com.安卓.internal.os.ZygoteInit.main(ZygoteInit.java:540)
ERROR/AndroidRuntime(1358): at dalvik.system.NativeStart.main(Native Method)
# 1 楼答案
我的猜测是,“私有void bar(String){}”被编译器标记为完全可内联,并且从未实际创建过。很难说foo()中引用出现的确切原因(vs inlining),但注释可能会使编译器的簿记工作出错
(这里的线索是,“私有”私有方法几乎总是很好的内联候选方法,尤其是带有空体的方法。)
# 2 楼答案
这实际上是Eclipse3.5编译器(Bug 289576)的一个bug,它使用带注释的参数更改方法的
private
修饰符,使该方法成为“包私有”方法。因此,你的:在中。类文件变为:
但是,更改后的方法仍然由invokespecialJVM指令调用,该指令仅用于私有方法调用(也用于其他一些非方法内容),但令人惊讶的是,它也适用于Sun/Oracle JVM上的“包私有”方法
在Android期间。类=>。dextranslationinvokespecialJVM指令被转换为invoke directDalvik指令,该指令只能调用私有方法和构造函数。由于
bar()
方法已成为包可见的方法,invoke direct无法找到它并抛出NoSuchMethodError
解决方案是使用Eclipse3.6+或javac编译器(通过
build.xml
ant脚本)