2010-06-06 2 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 

Любой идея, что случилось с оригинальным методом ? Это ошибка далвика, или?

Если кто-то один whould поэкспериментировать с кодом, здесь:

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

Я думаю, что «частная пустота бар (String) {}» помечен полностью inlineable компилятором и никогда не создан. Именно поэтому ссылка в foo() затем встречается (vs inlining), сказать сложно, но, скорее всего, аннотация добавляет в бухгалтерию компилятора.

(Ключ здесь «частный» - частные методы почти всегда хорошими кандидатами на встраивание, особенно те, с ничтожных тел.)

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 преобразуются в Invoke-прямой инструкции Dalvik, которая может вызывать только частные методы и конструктор. Поскольку метод bar() стал видимым в пакете способом, invoke-direct не может найти его и выбрасывает NoSuchMethodError.

Решение заключается в использовании Eclipse 3.6+ или javac-компилятора (через build.xml ant script).

+0

Я также нашел, что это произошло в Android Studio. Однако это было без каких-либо аннотаций.Я изменил модификатор доступа от частного к публичному и работал как шарм. Очень странно. –

Смежные вопросы