Использование ConcurrentHashMap::newKeySet с Android coreLibraryDesugaring

#android #android-studio #gradle #android-gradle-plugin

#Android #android-studio #gradle #android-gradle-плагин

Вопрос:

Я пытаюсь использовать новые функции десугаринга в AGP, однако при попытке использования ConcurrentHashMap.newKeySet() в моем приложении я получаю следующую ошибку:

 10-23 21:17:49.471 5023-5023/uk.org.mattford.scoutlink E/AndroidRuntime: FATAL EXCEPTION: main
    Process: uk.org.mattford.scoutlink, PID: 5023
    java.lang.NoSuchMethodError: No static method newKeySet()Lj$/util/concurrent/ConcurrentHashMap$KeySetView; in class Lj$/util/concurrent/ConcurrentHashMap; or its super classes (declaration of 'j$.util.concurrent.ConcurrentHashMap' appears in /data/app/uk.org.mattford.scoutlink-1/base.apk:classes3.dex)
        at org.pircbotx.hooks.managers.ThreadedListenerManager.<init>(ThreadedListenerManager.java:49)
        at org.pircbotx.Configuration$Builder.getListenerManager(Configuration.java:884)
        at org.pircbotx.Configuration$Builder.addListener(Configuration.java:726)
        at uk.org.mattford.scoutlink.irc.IRCService.connect(IRCService.java:143)
        at uk.org.mattford.scoutlink.irc.IRCService.onStartCommand(IRCService.java:67)
        at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2864)
        at android.app.ActivityThread.access$2100(ActivityThread.java:144)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1376)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5221)
        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:899)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
  

На моем верхнем уровне у меня есть следующее build.gradle

 buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.0'
        classpath 'com.google.gms:google-services:4.3.4'
        classpath 'com.google.firebase:firebase-crashlytics-gradle:2.3.0'
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        maven {
            url 'https://oss.sonatype.org/content/repositories/snapshots'
        }
    }
}
  

и в моем модуле build-gradle :

 apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'

android {
    compileSdkVersion 29
    buildToolsVersion '29.0.3'
    defaultConfig {
        applicationId "uk.org.mattford.scoutlink"
        minSdkVersion 16
        targetSdkVersion 29
        multiDexEnabled true
    }
    buildTypes {
        release {}
    }
    packagingOptions {
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/license.txt'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/NOTICE.txt'
        exclude 'META-INF/notice.txt'
        exclude 'META-INF/ASL2.0'
    }
    compileOptions {
        coreLibraryDesugaringEnabled true
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    productFlavors {
    }
    buildFeatures {
        viewBinding = true
    }
}

dependencies {
    implementation 'org.slf4j:slf4j-android:1.7.30'
    implementation 'org.pircbotx:pircbotx:2.3-SNAPSHOT'
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.firebase:firebase-analytics:17.6.0'
    implementation 'com.google.firebase:firebase-crashlytics:17.2.2'
    implementation 'com.google.android.material:material:1.2.1'

    implementation "androidx.room:room-runtime:2.2.5"
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'androidx.recyclerview:recyclerview:1.1.0'
    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
    implementation "androidx.lifecycle:lifecycle-viewmodel:2.2.0"
    annotationProcessor "androidx.room:room-compiler:2.2.5"

    implementation 'androidx.multidex:multidex:2.0.1'
    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10'
}
  

Смотрю на анализатор APK. Я вижу, что j$.util.concurrent.ConcurrentHashMap это определено в classes3.dex , но не включает newKeySet метод. Однако j$.util.concurrent.ConcurrentHashMap он также определен в classes4.dex и имеет этот метод!

ConcurrentHashMap.newKeySet Вызов, который я пытаюсь обойти, находится в зависимости pircbotx. Однако я ввел вызов этого метода в onCreate метод моего приложения, и это также приводит к сбою приложения.

Заранее спасибо за любую помощь. Я занимался этим уже несколько часов, но безрезультатно.

Комментарии:

1. R8 может запутывать этот класс или метод.

2. @Martin Zeitler У меня не включена модификация, поэтому не думаю, что это сыграет здесь роль

3. Автокоррекция. Это должно было означать «минимизацию»

4. Спасибо за вопрос / отчет. Я из команды R8 / D8, и это похоже на ошибку. Я открыл b.corp.google.com/issues/171666278 , и надеюсь, что вы сможете последовать этому примеру. У меня есть несколько вопросов: 1) Имеют ли оба classes3.dex и classes4.dex только классы с j$ префиксом? 2) Что произойдет, если вы просто удалите classes3.dex (тот, в котором отсутствует метод) из apk ? 3) Можете ли вы поделиться проектом с этой проблемой или простым примером проекта с использованием зависимости pricboxt, демонстрирующим проблему? 4) можете ли вы поделиться apk с проблемой?

5. И если вы можете поделиться чем-то, чем не хотите делиться публично, вы можете поделиться этим с sgjesse@google.com и clementbera@google.com .

Ответ №1:

Это оказалось «ошибкой» в D8, оказывается, что, хотя в документах перечислены следующие 3 метода (https://developer.android.com/studio/write/java8-support-table ) как поддерживаемые, они на самом деле в настоящее время не поддерживаются.

Это был запрос на функцию, но, по словам команды D8, маловероятно, что они будут рассмотрены в этом квартале. (полное обсуждение проблемы здесь: https://issuetracker.google.com/171666278 )

 public ConcurrentHashMap.KeySetView keySet(Object mappedValue)
public static ConcurrentHashMap.KeySetView newKeySet()
public static ConcurrentHashMap.KeySetView newKeySet(int initialCapacity)
  

Ответ №2:

Эта проблема была решена путем обновления зависимости десугаринга до 1.2.0, как показано ниже:

 dependencies {
    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.0'
    // or
    // coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.0'

...
}
  

смотрите следующую информацию: