Android 5上来自Kotlin的java依赖关系中的外部java依赖关系中的java.lang.NoSuchMethodError

我从存储库中实现了外部 JAVA -dependency,该存储库包含来自Kotlin上android应用程序的另一个外部依赖项( retro stream ),导致崩溃在 android 5 上由 java.lang.NoSuchMethodError:没有静态方法根据 JAVA -库中的跟踪(跟踪附加在下面) 。该问题发生在复古流库的 Stream 类中(方法“ ”)。我检查了该库是否存在于外部依赖关系中,并且所有类和方法都可以从代码中看到,并且最有趣的是,它在 android> = 7 设备上不会崩溃。

我尝试从 kotlin 代码中明确调用方法-一切正常。

Versions: 
Kotlin                   1.3.50 
Gradle plugin            3.4.2
Gradle                   5.4.1
Android studio           3.5

问题代码:

    EmptyUtils.getLastNotNullGotvalue(Supplier { "" })
  

E / AndroidRuntime(5699):致命异常:主E / AndroidRuntime(   5699):流程:com.jetruby.kotlindslgradleexample,PID:5699   E / AndroidRuntime(5699):java.lang.NoSuchMethodError:没有静态方法   ([Ljava / lang / Object;)Ljava9 / util / stream / Stream;的在班上   Ljava9 / util / stream / Stream;或其超类(声明为   'java9.util.stream.Stream'出现在   /data/app/com.jetruby.kotlindslgradleexample-2/base.apk)   E / AndroidRuntime(5699):在   ru.m4bank.mpos.service.network.utils.EmptyUtils.getLastNotNullGotvalueOrDefault(EmptyUtils.java:40)   E / AndroidRuntime(5699):在   ru.m4bank.mpos.service.network.utils.EmptyUtils.getLastNotNullGotvalue(EmptyUtils.java:51)   E / AndroidRuntime(5699):在   com.jetruby.kotlindslgradleexample.Mainactivity.onCreate(Mainactivity.kt:33)   E / AndroidRuntime(5699):在   android.app.activity.performCreate(activity.java:5990)   E / AndroidRuntime(5699):在   android.app.Instrumentation.callactivityOnCreate(Instrumentation.java:1106)   E / AndroidRuntime(5699):在   android.app.activityThread.performLaunchactivity(activityThread.java:2278)   E / AndroidRuntime(5699):在   android.app.activityThread.handleLaunchactivity(activityThread.java:2387)   E / AndroidRuntime(5699):在   android.app.activityThread.access $ 800(activityThread.java:151)   E / AndroidRuntime(5699):在   android.app.activityThread $ H.handleMessage(activityThread.java:1303)   E / AndroidRuntime(5699):在   android.os.Handler.dispatchMessage(Handler.java:102)E / AndroidRuntime(   5699):位于android.os.Looper.loop(Looper.java:135)E / AndroidRuntime(   5699):位于android.app.activityThread.main(activityThread.java:5254)   E / AndroidRuntime(5699):at java.lang.reflect.Method.invoke(本机   方法)E / AndroidRuntime(5699):at   java.lang.reflect.Method.invoke(Method.java:372)E / AndroidRuntime(   5699):在   com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:903)   E / AndroidRuntime(5699):在   com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

尝试了各种组装选项,我发现如果您在本地实现 JAVA -依赖性(通过文件),则在第5个android上不会崩溃! / strong>。另外,如果使用 JAVA 而不是 kotlin 进行编译,则不会发生跌落。而且它仅取决于接口中的静态方法

在下面的图片中有2个依赖项变体(当我拉出第二个依赖项并将其本地实现为 file 时,我从 gradle 缓存中复制了第一个依赖项),第二个从存储库中拉出)。

Implementation variants

结果:

On android <7:  1-st variant - all ok,2-nd variant - crashes.
On android >=7 - 1,2 variants - ok

我已经对应用程序进行了反编译,并注意到来自kotlin 来自接口的静态方法收集在一个单独的类中(辅助内部类 Classname.CC 已创建,并在其中放置了静态方法)。因此,当从存储库中实现依赖项时,反编译的外部类将引用原始类和原始方法,而从本地源实现 >(从拉出的存储库复制到libs文件夹),它是指辅助 XX.CC 。有一种怀疑是 java.lang.NoSuchMethodError崩溃的原因:没有静态方法

Decompiled classes of the problem class

下面的代码是方法“缺失”的“ helper”类的反编译代码。成功和失败的构建都是相同的:

    .class public final synthetic Ljava9/util/stream/Stream$-CC;
        .super Ljava/lang/Object;
        .source "Stream.java"


        # direct methods
        .method public static $default$dropWhile(Ljava9/util/stream/Stream;Ljava9/util/function/Predicate;)Ljava9/util/stream/Stream;
            .locals 3
            .param p0,"_this"    # Ljava9/util/stream/Stream;
            .annotation system Ldalvik/annotation/Signature;
                value = {
                    "(","Ljava9/util/function/Predicate<","-TT;>;)","Ljava9/util/stream/Stream<","TT;>;"
                }
            .end annotation

            .line 630
            .local p0,"this":Ljava9/util/stream/Stream;,"Ljava9/util/stream/Stream<TT;>;"
            .local p1,"predicate":Ljava9/util/function/Predicate;,"Ljava9/util/function/Predicate<-TT;>;"
            invoke-static {p1},Ljava9/util/Objects;->requireNonNull(Ljava/lang/Object;)Ljava/lang/Object;

            .line 633
            new-instance v0,Ljava9/util/stream/WhileOps$UnorderedWhileSpliterator$OfRef$Dropping;

            .line 634
            invoke-interface {p0},Ljava9/util/stream/Stream;->spliterator()Ljava9/util/Spliterator;

            move-result-object v1

            const/4 v2,0x1

            invoke-direct {v0,v1,v2,p1},Ljava9/util/stream/WhileOps$UnorderedWhileSpliterator$OfRef$Dropping;-><init>(Ljava9/util/Spliterator;ZLjava9/util/function/Predicate;)V

            .line 635
            invoke-interface {p0},Ljava9/util/stream/Stream;->isParallel()Z

            move-result v1

            .line 633
            invoke-static {v0,v1},Ljava9/util/stream/StreamSupport;->stream(Ljava9/util/Spliterator;Z)Ljava9/util/stream/Stream;

            move-result-object v0

            .line 635
            invoke-static {p0},Ljava9/util/stream/StreamSupport;->closeHandler(Ljava9/util/stream/BaseStream;)Ljava/lang/Runnable;

            move-result-object v1

            invoke-interface {v0,Ljava9/util/stream/Stream;->onClose(Ljava/lang/Runnable;)Ljava9/util/stream/BaseStream;

            move-result-object v0

            check-cast v0,Ljava9/util/stream/Stream;

            return-object v0
        .end method

        .method public static $default$takeWhile(Ljava9/util/stream/Stream;Ljava9/util/function/Predicate;)Ljava9/util/stream/Stream;
            .locals 3
            .param p0,"TT;>;"
                }
            .end annotation

            .line 564
            .local p0,Ljava9/util/Objects;->requireNonNull(Ljava/lang/Object;)Ljava/lang/Object;

            .line 567
            new-instance v0,Ljava9/util/stream/WhileOps$UnorderedWhileSpliterator$OfRef$Taking;

            .line 568
            invoke-interface {p0},Ljava9/util/stream/WhileOps$UnorderedWhileSpliterator$OfRef$Taking;-><init>(Ljava9/util/Spliterator;ZLjava9/util/function/Predicate;)V

            .line 569
            invoke-interface {p0},Ljava9/util/stream/Stream;->isParallel()Z

            move-result v1

            .line 567
            invoke-static {v0,Ljava9/util/stream/StreamSupport;->stream(Ljava9/util/Spliterator;Z)Ljava9/util/stream/Stream;

            move-result-object v0

            .line 569
            invoke-static {p0},Ljava9/util/stream/Stream;

            return-object v0
        .end method

        .method public static builder()Ljava9/util/stream/Stream$Builder;
            .locals 1
            .annotation system Ldalvik/annotation/Signature;
                value = {
                    "<T:","Ljava/lang/Object;",">()","Ljava9/util/stream/Stream$Builder<","TT;>;"
                }
            .end annotation

            .line 1148
            new-instance v0,Ljava9/util/stream/Streams$StreamBuilderImpl;

            invoke-direct {v0},Ljava9/util/stream/Streams$StreamBuilderImpl;-><init>()V

            return-object v0
        .end method

        .method public static concat(Ljava9/util/stream/Stream;Ljava9/util/stream/Stream;)Ljava9/util/stream/Stream;
            .locals 3
            .annotation system Ldalvik/annotation/Signature;
                value = {
                    "<T:",">(","+TT;>;","+TT;>;)","TT;>;"
                }
            .end annotation

            .line 1387
            .local p0,"a":Ljava9/util/stream/Stream;,"Ljava9/util/stream/Stream<+TT;>;"
            .local p1,"b":Ljava9/util/stream/Stream;,"Ljava9/util/stream/Stream<+TT;>;"
            invoke-static {p0},Ljava9/util/Objects;->requireNonNull(Ljava/lang/Object;)Ljava/lang/Object;

            .line 1388
            invoke-static {p1},Ljava9/util/Objects;->requireNonNull(Ljava/lang/Object;)Ljava/lang/Object;

            .line 1391
            new-instance v0,Ljava9/util/stream/Streams$concatSpliterator$OfRef;

            .line 1392
            invoke-interface {p0},Ljava9/util/stream/Stream;->spliterator()Ljava9/util/Spliterator;

            move-result-object v1

            invoke-interface {p1},Ljava9/util/stream/Stream;->spliterator()Ljava9/util/Spliterator;

            move-result-object v2

            invoke-direct {v0,v2},Ljava9/util/stream/Streams$concatSpliterator$OfRef;-><init>(Ljava9/util/Spliterator;Ljava9/util/Spliterator;)V

            .line 1393
            .local v0,"split":Ljava9/util/Spliterator;,"Ljava9/util/Spliterator<TT;>;"
            invoke-interface {p0},Ljava9/util/stream/Stream;->isParallel()Z

            move-result v1

            if-nez v1,:cond_1

            invoke-interface {p1},Ljava9/util/stream/Stream;->isParallel()Z

            move-result v1

            if-eqz v1,:cond_0

            goto :goto_0

            :cond_0
            const/4 v1,0x0

            goto :goto_1

            :cond_1
            :goto_0
            const/4 v1,0x1

            :goto_1
            invoke-static {v0,Ljava9/util/stream/StreamSupport;->stream(Ljava9/util/Spliterator;Z)Ljava9/util/stream/Stream;

            move-result-object v1

            .line 1394
            .local v1,"stream":Ljava9/util/stream/Stream;,"Ljava9/util/stream/Stream<TT;>;"
            invoke-static {p0,Ljava9/util/stream/Streams;->composedClose(Ljava9/util/stream/BaseStream;Ljava9/util/stream/BaseStream;)Ljava/lang/Runnable;

            move-result-object v2

            invoke-interface {v1,Ljava9/util/stream/Stream;->onClose(Ljava/lang/Runnable;)Ljava9/util/stream/BaseStream;

            move-result-object v2

            check-cast v2,Ljava9/util/stream/Stream;

            return-object v2
        .end method

        .method public static empty()Ljava9/util/stream/Stream;
            .locals 2
            .annotation system Ldalvik/annotation/Signature;
                value = {
                    "<T:","TT;>;"
                }
            .end annotation

            .line 1158
            invoke-static {},Ljava9/util/Spliterators;->emptySpliterator()Ljava9/util/Spliterator;

            move-result-object v0

            const/4 v1,0x0

            invoke-static {v0,Ljava9/util/stream/StreamSupport;->stream(Ljava9/util/Spliterator;Z)Ljava9/util/stream/Stream;

            move-result-object v0

            return-object v0
        .end method

        .method public static generate(Ljava9/util/function/Supplier;)Ljava9/util/stream/Stream;
            .locals 3
            .annotation system Ldalvik/annotation/Signature;
                value = {
                    "<T:","Ljava9/util/function/Supplier<","TT;>;"
                }
            .end annotation

            .line 1345
            .local p0,"s":Ljava9/util/function/Supplier;,"Ljava9/util/function/Supplier<+TT;>;"
            invoke-static {p0},Ljava9/util/Objects;->requireNonNull(Ljava/lang/Object;)Ljava/lang/Object;

            .line 1346
            new-instance v0,Ljava9/util/stream/StreamSpliterators$InfiniteSupplyingSpliterator$OfRef;

            const-wide v1,0x7fffffffffffffffL

            invoke-direct {v0,p0},Ljava9/util/stream/StreamSpliterators$InfiniteSupplyingSpliterator$OfRef;-><init>(JLjava9/util/function/Supplier;)V

            const/4 v1,Ljava9/util/stream/StreamSupport;->stream(Ljava9/util/Spliterator;Z)Ljava9/util/stream/Stream;

            move-result-object v0

            return-object v0
        .end method

        .method public static iterate(Ljava/lang/Object;Ljava9/util/function/Predicate;Ljava9/util/function/UnaryOperator;)Ljava9/util/stream/Stream;
            .locals 8
            .annotation system Ldalvik/annotation/Signature;
                value = {
                    "<T:","S:TT;>(TS;","TS;>;","Ljava9/util/function/UnaryOperator<","TS;>;)","TT;>;"
                }
            .end annotation

            .line 1287
            .local p0,"seed":Ljava/lang/Object;,"TS;"
            .local p1,"hasnext":Ljava9/util/function/Predicate;,"Ljava9/util/function/Predicate<TS;>;"
            .local p2,"next":Ljava9/util/function/UnaryOperator;,"Ljava9/util/function/UnaryOperator<TS;>;"
            invoke-static {p2},Ljava9/util/Objects;->requireNonNull(Ljava/lang/Object;)Ljava/lang/Object;

            .line 1288
            invoke-static {p1},Ljava9/util/Objects;->requireNonNull(Ljava/lang/Object;)Ljava/lang/Object;

            .line 1289
            new-instance v7,Ljava9/util/stream/Stream$2;

            const-wide v1,0x7fffffffffffffffL

            const/16 v3,0x410

            move-object v0,v7

            move-object v4,p2

            move-object v5,p0

            move-object v6,p1

            invoke-direct/range {v0 .. v6},Ljava9/util/stream/Stream$2;-><init>(JILjava9/util/function/UnaryOperator;Ljava/lang/Object;Ljava9/util/function/Predicate;)V

            .line 1331
            .local v0,"spliterator":Ljava9/util/Spliterator;,"Ljava9/util/Spliterator<TT;>;"
            const/4 v1,Ljava9/util/stream/StreamSupport;->stream(Ljava9/util/Spliterator;Z)Ljava9/util/stream/Stream;

            move-result-object v1

            return-object v1
        .end method

        .method public static iterate(Ljava/lang/Object;Ljava9/util/function/UnaryOperator;)Ljava9/util/stream/Stream;
            .locals 7
            .annotation system Ldalvik/annotation/Signature;
                value = {
                    "<T:","TT;>;"
                }
            .end annotation

            .line 1224
            .local p0,"f":Ljava9/util/function/UnaryOperator;,"Ljava9/util/function/UnaryOperator<TS;>;"
            invoke-static {p1},Ljava9/util/Objects;->requireNonNull(Ljava/lang/Object;)Ljava/lang/Object;

            .line 1225
            new-instance v6,Ljava9/util/stream/Stream$1;

            const-wide v1,v6

            move-object v4,p1

            move-object v5,p0

            invoke-direct/range {v0 .. v5},Ljava9/util/stream/Stream$1;-><init>(JILjava9/util/function/UnaryOperator;Ljava/lang/Object;)V

            .line 1244
            .local v0,Ljava9/util/stream/StreamSupport;->stream(Ljava9/util/Spliterator;Z)Ljava9/util/stream/Stream;

            move-result-object v1

            return-object v1
        .end method

        .method public static of(Ljava/lang/Object;)Ljava9/util/stream/Stream;
            .locals 2
            .annotation system Ldalvik/annotation/Signature;
                value = {
                    "<T:",">(TT;)","TT;>;"
                }
            .end annotation

            .line 1169
            .local p0,"t":Ljava/lang/Object;,"TT;"
            new-instance v0,Ljava9/util/stream/Streams$StreamBuilderImpl;

            invoke-direct {v0,Ljava9/util/stream/Streams$StreamBuilderImpl;-><init>(Ljava/lang/Object;)V

            const/4 v1,Ljava9/util/stream/StreamSupport;->stream(Ljava9/util/Spliterator;Z)Ljava9/util/stream/Stream;

            move-result-object v0

            return-object v0
        .end method

        .method public static varargs of([Ljava/lang/Object;)Ljava9/util/stream/Stream;
            .locals 1
            .annotation system Ldalvik/annotation/Signature;
                value = {
                    "<T:",">([TT;)","TT;>;"
                }
            .end annotation

            .line 1196
            .local p0,"values":[Ljava/lang/Object;,"[TT;"
            invoke-static {p0},Ljava9/util/J8Arrays;->stream([Ljava/lang/Object;)Ljava9/util/stream/Stream;

            move-result-object v0

            return-object v0
        .end method

        .method public static ofNullable(Ljava/lang/Object;)Ljava9/util/stream/Stream;
            .locals 2
            .annotation system Ldalvik/annotation/Signature;
                value = {
                    "<T:","TT;>;"
                }
            .end annotation

            .line 1183
            .local p0,"TT;"
            if-nez p0,:cond_0

            invoke-static {},Ljava9/util/stream/Stream$-CC;->empty()Ljava9/util/stream/Stream;

            move-result-object v0

            goto :goto_0

            :cond_0
            new-instance v0,0x0

            .line 1184
            invoke-static {v0,Ljava9/util/stream/StreamSupport;->stream(Ljava9/util/Spliterator;Z)Ljava9/util/stream/Stream;

            move-result-object v0

            :goto_0
            return-object v0
        .end method

JAVA 库的反编译方法,其中缺少的方法称为(崩溃崩溃):

    .method public static varargs getLastNotNullValue([Ljava/lang/Object;)Ljava/lang/Object;
        .locals 2
        .annotation system Ldalvik/annotation/Signature;
            value = {
                "<T:",">([TT;)TT;"
            }
        .end annotation

        .annotation runtime Ljava/lang/SafeVarargs;
        .end annotation

        .line 56
        .local p0,"[TT;"
        invoke-static {p0},Ljava9/util/stream/Stream;->of([Ljava/lang/Object;)Ljava9/util/stream/Stream;

        move-result-object v0

        sget-object v1,Lru/m4bank/mpos/service/network/utils/-$$Lambda$h24iVvNNOyPAWTyqI3I8dzCunHY;->INSTANCE:Lru/m4bank/mpos/service/network/utils/-$$Lambda$h24iVvNNOyPAWTyqI3I8dzCunHY;

        invoke-interface {v0,Ljava9/util/stream/Stream;->filter(Ljava9/util/function/Predicate;)Ljava9/util/stream/Stream;

        move-result-object v0

        invoke-interface {v0},Ljava9/util/stream/Stream;->findFirst()Ljava9/util/Optional;

        move-result-object v0

        sget-object v1,Lru/m4bank/mpos/service/network/utils/-$$Lambda$EmptyUtils$2lJJnncNhWO5-cW1nB8g96aMo4M;->INSTANCE:Lru/m4bank/mpos/service/network/utils/-$$Lambda$EmptyUtils$2lJJnncNhWO5-cW1nB8g96aMo4M;

        invoke-virtual {v0,Ljava9/util/Optional;->orElseGet(Ljava9/util/function/Supplier;)Ljava/lang/Object;

        move-result-object v0

        return-object v0
    .end method

相同的反编译方法(无崩溃构建):

    .method public static varargs getLastNotNullValue([Ljava/lang/Object;)Ljava/lang/Object;
        .locals 2
        .annotation system Ldalvik/annotation/Signature;
            value = {
                "<T:",Ljava9/util/stream/Stream$-CC;->of([Ljava/lang/Object;)Ljava9/util/stream/Stream;

        move-result-object v0

        sget-object v1,Ljava9/util/Optional;->orElseGet(Ljava9/util/function/Supplier;)Ljava/lang/Object;

        move-result-object v0

        return-object v0
    .end method

问题:是 kotlin 错误还是我做错了什么?我该如何使用存储库中的 JAVA -库 (在内部包含具有静态方法的接口)在 android 上并且不会崩溃?

ipqydp 回答:Android 5上来自Kotlin的java依赖关系中的外部java依赖关系中的java.lang.NoSuchMethodError

您正在尝试在Android API级别 Java Stream Api。

根据Android API级别here检查您可以使用和不能使用的内容

,

我再次遇到了这个问题(将 Android Gradle Plugin 版本升级到 4+ 后),不得不自己解决。

经过调查我发现问题出在哪里:

  1. 我所有的依赖项都是工件 -> 它没有元数据。
  2. Android Studio 组装 apk 的方式与控制台不同(它在组装过程中通过运行按钮添加了 API 级别的选项以加快速度)-> android 7+ 设备仅工作,因为目标 API24+ 并且没有对接口中的静态方法进行脱糖。
  3. Java 版本由于不同的脱糖和依赖缓存机制而有效(在将 Android Gradle 插件 更新到 4+ 后停止工作)。
  4. 关于本地依赖:我认为它可以工作,因为 gradle 没有缓存它并且必须重新编译。

解决方案 我在我的依赖项中添加了一个适当的元数据(pom.xml.module 文件),它明确地标记了二进制文件依赖关系图,现在 R8 使适当的脱糖,现在一切正常。

P. S. 如果所有依赖项都在本地实现,它会起作用,但它看起来更像是一种解决方法。

本文链接:https://www.f2er.com/3149344.html

大家都在问