微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

AspectJ - 添加 firebase 依赖项后的 Android IllegalStateException

如何解决AspectJ - 添加 firebase 依赖项后的 Android IllegalStateException

使用 Ibotta,一个适用于 android 的 AOP gradle 插件,在添加以下依赖项后似乎不起作用

implementation 'com.google.firebase:firebase-auth:20.0.3'

实际结果:

构建成功,似乎没有创建所有 dex

运行时错误

Application class not found in dex path list.

AOP 日志显示以下错误

java.lang.IllegalStateException: Expecting .,<,or ;,but found - while unpacking <MessageType:Lcom/google/android/gms/internal/firebase-auth-api/zzaaa<TMessageType;TBuilderType;>;BuilderType:Lcom/google/android/gms/internal/firebase-auth-api/zzzw<TMessageType;TBuilderType;>;>Lcom/google/android/gms/internal/firebase-auth-api/zzyj<TMessageType;TBuilderType;>;
    at org.aspectj.util.GenericSignatureParser.parseClasstypeSignature(GenericSignatureParser.java:204)
    at org.aspectj.util.GenericSignatureParser.parseFieldTypeSignature(GenericSignatureParser.java:155)
    at org.aspectj.util.GenericSignatureParser.parseFormalTypeParameter(GenericSignatureParser.java:130)
    at org.aspectj.util.GenericSignatureParser.parseAsClassSignature(GenericSignatureParser.java:51)
    at org.aspectj.weaver.UnresolvedType.forGenericTypeSignature(UnresolvedType.java:275)
    at org.aspectj.weaver.bcel.bcelWorld.addSourceObjectType(bcelWorld.java:479)
    at org.aspectj.weaver.bcel.bcelWorld.addSourceObjectType(bcelWorld.java:453)
    at org.aspectj.weaver.bcel.bcelweaver.addAspectsFromJarFile(bcelweaver.java:265)
    at org.aspectj.weaver.bcel.bcelweaver.addLibraryJarFile(bcelweaver.java:238)

下面添加了重现此所需的代码

gradle-wrapper.properties

distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip

项目 build.gradle

 repositories {
        maven { url "https://plugins.gradle.org/m2/" }
    }

    dependencies {
        classpath "com.ibotta:plugin:1.1.0"
    }

app build.gradle

apply plugin: "com.ibotta.gradle.aop"

dependencies {
        //AspectJ
        implementation "org.aspectj:aspectjrt:1.9.6"
        implementation 'com.google.firebase:firebase-auth:20.0.3'
    }

AspectLogging 类

@Aspect
class AOPLog {

    @pointcut("within(com.example.aopdemo..*) && execution(* *(..))")
    fun allMethods() {
    }

    @Around("allMethods()")
    @Throws(Throwable::class)
    open fun onMethodAdvice(joinPoint: JoinPoint?): Any? {
        val methodSignature = joinPoint!!.signature as MethodSignature
        val methodName = methodSignature.name
        val startTime = System.currentTimeMillis();
        val result = (joinPoint as ProceedingJoinPoint).proceed()
        val endTime = System.currentTimeMillis() - startTime
        Log.e("LoggingVM","$methodName ---> $endTime")
        return result
    }
}

注意:Firebase 依赖项是刚刚添加的,并未在演示应用中的任何地方使用。

com.example.aopdemo 包只有一个启动器活动,并在 onCreate 方法调用一些方法。它在添加 firebase 之前跟踪所有方法添加后,出现以上错误

解决方法

使用 Ibotta,一个适用于 android 的 AOP 库

它不是一个 AOP 库,而是一个 Gradle 插件,适用于希望将 AspectJ 方面编织到他们的 Android 目标应用程序或库中的人,请参阅 here

您的错误消息中让我感到奇怪的是包名称 com/google/android/gms/internal/firebase-auth-api/zzaaa - 请注意连字符。实际上,包名称中的连字符 ("-") 字符是非法的,请参阅 Java naming conventions

如果 Firebase 本身或者某种代码转换器或混淆器使用 firebase-auth-api 而不是 firebase_auth_apifirebase.auth.api 之类的东西(取决于它在原始代码库中的样子),它使 AspectJ 签名解析器脱轨也就不足为奇了。我想知道现在哪个编译器甚至允许这样做。

修复包名,那么我猜AspectJ问题也会消失。 AspectJ 报告的错误是有效的,问题在 AspectJ 之外。


更新:我查看了您添加到类路径中的 AAR 文件,它确实包含一个带有混淆类的非法包名称,可能是有意为之,以使其更难以使用和操作这些类:

$ unzip firebase-auth-20.0.3.aar -d firebase-auth
Archive:  firebase-auth-20.0.3.aar
  inflating: firebase-auth/AndroidManifest.xml
  inflating: firebase-auth/R.txt
  inflating: firebase-auth/classes.jar
  inflating: firebase-auth/proguard.txt
  inflating: firebase-auth/third_party_licenses.json
  inflating: firebase-auth/third_party_licenses.txt

$ unzip -l firebase-auth/classes.jar | grep firebase-auth-api | head -n 10
     1209  2021-02-26 09:54   com/google/android/gms/internal/firebase-auth-api/zza.class
     1032  2021-02-26 09:54   com/google/android/gms/internal/firebase-auth-api/zzaa.class
    10997  2021-02-26 09:54   com/google/android/gms/internal/firebase-auth-api/zzaaa.class
     4291  2021-02-26 09:54   com/google/android/gms/internal/firebase-auth-api/zzaab.class
      172  2021-02-26 09:54   com/google/android/gms/internal/firebase-auth-api/zzaac.class
      275  2021-02-26 09:54   com/google/android/gms/internal/firebase-auth-api/zzaad.class
      192  2021-02-26 09:54   com/google/android/gms/internal/firebase-auth-api/zzaae.class
      525  2021-02-26 09:54   com/google/android/gms/internal/firebase-auth-api/zzaaf.class
     2430  2021-02-26 09:54   com/google/android/gms/internal/firebase-auth-api/zzaag.class
      373  2021-02-26 09:54   com/google/android/gms/internal/firebase-auth-api/zzaah.class

不幸的是,这也会使合法用例停止工作。在使用 AspectJ 时,您可能想要 raise an issue 或确保排除 Firebase 或至少它的内部包,例如通过!within(com.google.android.gms.internal..*)。或者您的方面是否真的想要修改 Firebase 中的任何内容?


更新 2:在 Ibotta 内部,有一个 source code comment 如下:

使用 Gradle 代表推荐的技术执行 AOP 编织的 Gradle 插件。它利用了 Android 的字节码操作管道,这是一种更合乎逻辑的方法。

基本思想是:

  1. 更改 Kotlin 和 Java 编译输出目录。
  2. 将 Kotlin/Java 编译输出复制到一个目录。
  3. 编织组合的 Kotlin/Java 类。
  4. 注册为字节码生成器,以便 Android 将自定义 AOP 编织识别为构建管道中的正式步骤。

也许在使用这种方法而不是调用独立的 AspectJ 编译器时,字节码编织器必须以某种方式加载并查看所有类,即使是普通的 AspectJ 编译器由于 within(com.example.aopdemo..*) 而忽略的类示例方面或我建议的安全保护 !within(com.google.android.gms.internal..*)。无论哪种方式,它在您更改 Gradle 构建插件后都可以工作,这告诉我您应该为 Ibotta 项目(而不是像我最初认为的那样针对 Firebase)提出问题。实际上,您似乎已经这样做了,请参阅issue #5


更新 3:不久前,Ibotta maintainer said 您应该使用该工具自己的过滤功能并使用类似的东西

aopWeave {
    filter = "com/example/aopdemo"
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。