2010-06-06 52 views
3

我有一個非常簡單的編譯項目,但無法在模擬器上啓動。問題是用這種方法:具有帶註釋參數的私有方法的Android java.lang.VerifyError

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 

任何想法有什麼不對原始的方法?這是一個達爾維克錯誤,還是?

如果有人喜歡對子級的代碼去嘗試,那就是:

Test.java:

public class Test { 

    private void bar(@Some String a) {} 

    public void foo() { 
     bar(null); 
    } 
} 

Some.java:

public @interface Some {} 

MainActivity.java:

public class MainActivity extends Activity { 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     new Test().foo(); 
    } 
} 

S粘跡:

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 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123) 
ERROR/AndroidRuntime(1358):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2231) 
ERROR/AndroidRuntime(1358):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2284) 
ERROR/AndroidRuntime(1358):  at android.app.ActivityThread.access$1800(ActivityThread.java:112) 
ERROR/AndroidRuntime(1358):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1692) 
ERROR/AndroidRuntime(1358):  at android.os.Handler.dispatchMessage(Handler.java:99) 
ERROR/AndroidRuntime(1358):  at android.os.Looper.loop(Looper.java:123) 
ERROR/AndroidRuntime(1358):  at android.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.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:782) 
ERROR/AndroidRuntime(1358):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:540) 
ERROR/AndroidRuntime(1358):  at dalvik.system.NativeStart.main(Native Method) 

回答

0

我的猜測是,「私人無效欄(字符串){}」被標記由編譯器完全inlineable並沒有真正建立。正是爲什麼foo()中的引用發生(vs內聯)很難說,但是註釋可能會使編譯器的記賬失效。

(這裏的線索是「私」 - 私有方法幾乎都是內聯很好的候選人,尤其是無效的身體的。)

3

這實際上就是Eclipse 3.5的編譯器(Bug 289576)的錯誤,這改變了private帶有帶註釋參數的方法的修飾符,以便方法變成「包 - 私有」方法。所以你:

private void bar(@Some String a) {…} 
的.class文件成爲

void bar(@Some String a) {…} 

更改的方法,但是仍然被invokespecial JVM指令,它僅用於私有方法調用(也可用於調用一些其他非方法的東西),但令人驚訝的是也適用於Sun/Oracle JVM上的「包 - 私有」方法。
期間的Android 的.class => .DEX翻譯invokespecial JVM指令被轉換爲調用直接的Dalvik指令,這隻能調用私有方法和構造函數。由於bar()方法已成爲包可見方法,invoke-direct無法找到它並拋出NoSuchMethodError

解決方案是使用Eclipse 3.6+或javac編譯器(通過build.xml ant腳本)。

+0

我也發現這也發生在Android Studio中。但是,它沒有任何註釋。我將訪問修飾符從private改爲public,並且像魅力一樣工作。很奇怪。 – 2014-09-04 17:37:24

相關問題