2016-08-20 8 views
14

AndroidプロジェクトでJava 8を使用しています。私はジャック(アンドロイドアプリケーションモジュールで)とRetrolambda(他のモジュールで)の両方をセットアップしました。ジャックを使用しているときにAndroidのIncompatibleClassChangeErrorでラムダ式がクラッシュする

問題は、ラムダ式がクラス変数を使用するようにしようとすると(ある特定のシナリオで)ラムダ式がクラッシュして、他のすべての状況で予想どおりに動作することです。たぶんこれは標準的なJavaの動作ですが、私は今まで説明を見つけることができませんでした。誰が問題がどこにあるか知っていますか? 私のクラスと下のクラッシュ:

public class LambdaBugTest { 

    private final String parentClassVariableString = "parentClassVariableString"; 

    public void testLambdas() { 

     // ----------- THESE WORK OK -------------- 
     final Functional simpleLambdaWorks = text -> System.out.print(text); 
     final Functional methodReferenceWorks = System.out::print; 
     final Functional interfaceWithClassParamWorks = new Functional() { 
      @Override 
      public void doSomething(String text) { 
       System.out.print(text + " " + parentClassVariableString); 
      } 
     }; 
     // ----------------------------------------- 

     // ----------- THIS ONE CRASHES ------------ 
     final Functional lambdaWithClassParamCrashes = text -> System.out.print(text + " " + parentClassVariableString); 
     // ----------------------------------------- 

     simpleLambdaWorks.doSomething("Text from simpleLambdaWorks"); 
     methodReferenceWorks.doSomething("Text from methodReferenceWorks"); 
     interfaceWithClassParamWorks.doSomething("Text from interfaceWithClassParamWorks"); 
     lambdaWithClassParamCrashes.doSomething("Text from lambdaWithClassParamCrashes"); 
    } 

    private interface Functional { 
     void doSomething(String text); 
    } 
} 

クラッシュログ:

08-21 00:27:41.564 25752-25752/debug E/AndroidRuntime: FATAL EXCEPTION: main 
     Process: debug, PID: 25752 
     java.lang.IncompatibleClassChangeError: The method 'void data.api.mapper.LambdaBugTest.data_api_mapper_LambdaBugTest_lambda$testLambdas$1(java.lang.String)' was expected to be of type direct but instead was found to be of type virtual (declaration of 'java.lang.reflect.ArtMethod' appears in /system/framework/core-libart.jar) 
     at data.api.mapper.LambdaBugTest.access$lambda$1(LambdaBugTest.java) 
     at data.api.mapper.LambdaBugTest$$Lambda$5.doSomething(Unknown) 
     at data.api.mapper.LambdaBugTest.testLambdas(LambdaBugTest.java:27) 
     at home.presentation.HomeActivity.onCreate(HomeActivity.java:47) 
     at android.app.Activity.performCreate(Activity.java:5990) 
     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106) 
     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278) 
     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387) 
     at android.app.ActivityThread.access$800(ActivityThread.java:151) 
     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303) 
     at android.os.Handler.dispatchMessage(Handler.java:102) 
     at android.os.Looper.loop(Looper.java:135) 
     at android.app.ActivityThread.main(ActivityThread.java:5254) 
     at java.lang.reflect.Method.invoke(Native Method) 
     at java.lang.reflect.Method.invoke(Method.java:372) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) 
+1

ジャックコンパイラとの対戦でretrolambdaを使用していますか? 2人を一緒に使うべきか?私は、ジャックコンパイラがJava 8 apiのサポート(lambdas、すべてのretrolambdaが行う)をもたらすと思った。私は間違っているかもしれません、ちょうどあなたがそれについて知っていて、それがここであなたの問題を引き起こす可能性があるかどうか不思議です。 – anthonymonori

+1

Jackと同じ問題と例外メッセージがありますが、私はRetrolambdaを使用していません。ジャックが '() - > instanceVariable = localVariable'のようなインスタンス変数を代入して式ラムダを好きではないようだ。 – fast3r

+0

ジャックコンパイラだけでなく、レトロラムダを使ってこの問題も起こっている – IcedDante

答えて

1

GoogleがAndroidのジャックをサポートされなくなりました。

ジャックは、もはやサポートされません、あなたは最初にデフォルトのツールチェーン

のAndroidメーカー3.0に組み込まれたJava 8のサポートを使用するようにジャックを無効にし、後にラムダ式をサポートしていなければなりません。

android { 
... 
// Configure only for each module that uses Java 8 
// language features (either in its source code or 
// through dependencies). 
compileOptions { 
    sourceCompatibility JavaVersion.VERSION_1_8 
    targetCompatibility JavaVersion.VERSION_1_8 
} 
} 

注:build.gradleファイルを設定してAndroidのメーカーは、あなたのプロジェクトがジャック、Retrolambda、またはDexGuardを使用していることを検出すると、IDEではなく、これらのツールによって提供されているJava 8のサポートを使用しています。ただし、デフォルトのツールチェーンに移行することを検討してください。

関連する問題