Сбой лямбда-выражений с IncompatibleClassChangeError в Android при использовании jack

Я использую Java 8 в моем проекте Android. У меня есть настройки как Джек (в модуле приложения Android) и Retrolambda (в других модулях).

Проблема, с которой я столкнулся, заключается в том, что мои лямбда-выражения аварийно завершают работу в одном конкретном сценарии, когда я пытаюсь заставить его использовать переменную класса (и я могу воспроизвести его в любом модуле), во всех других ситуациях это работает, как и ожидалось. Может быть, это стандартное поведение 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 ответ

Google больше не поддерживает Android-джек.

Jack больше не поддерживается, и вы должны сначала отключить Jack, чтобы использовать поддержку Java 8, встроенную в набор инструментов по умолчанию

Android Studio 3.0 и более поздние версии поддерживают выражения Lambdas. Настройте файл build.gradle:

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
 }
}

Примечание. Если Android Studio обнаруживает, что в вашем проекте используется Jack, Retrolambda или DexGuard, в среде IDE вместо этого используется поддержка Java 8, предоставляемая этими инструментами. Однако рассмотрите возможность перехода на набор инструментов по умолчанию.

Другие вопросы по тегам