【问题标题】:AspectJ - Android IllegalStateException after adding firebase dependencyAspectJ - 添加 firebase 依赖项后的 Android IllegalStateException
【发布时间】:2021-03-05 13:28:39
【问题描述】:

使用 Android 的 AOP gradle 插件 Ibotta,添加以下依赖项后似乎无法正常工作

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

项目构建.gradle

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

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

应用构建.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 之前跟踪所有方法。添加后,出现上述错误。

【问题讨论】:

  • 你的MCVE在哪里?没有代码,没有构建配置,甚至没有这里提到的 AspectJ 版本。
  • “构建成功并且似乎没有创建所有 dex”是什么意思?什么不是你期望被创造的?

标签: android firebase aop aspectj


【解决方案1】:

使用 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

不幸的是,这也会阻止合法用例的工作。您可能想raise an issue 或者确保在使用 AspectJ 时排除 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"
}

【讨论】:

  • 感谢您对此进行调查。我已经用最少的代码更新了问题来重现这个。似乎也不是包命名约定问题,因为不同的 google-play-service 依赖项java.lang.IllegalStateException: Expecting .,&lt;, or ;, but found authapi while unpacking &lt;R::Lcom/google/android/gms/common/api/Result;&gt;Lcom/google/android/gms/common/api/internal/BaseImplementation$ApiMethodImpl&lt;TR;Lcom/google/android/gms/internal/auth-api/zzr;&gt;; at org.aspectj.util.GenericSignatureParser.parseClassTypeSignature(GenericSignatureParser.java:204) 出现类似错误
  • 当然com/google/android/gms/internal/auth-api/zzr是一样的→auth-api是非法包名,com.google.android.gms.internal甚至是同一个基础包。
  • 是的,你是对的..我尝试通过添加 !within 来排除这些包,但没有工作
  • 刚刚尝试使用不同的插件“io.freefair.gradle:android-gradle-plugins”,它正在工作
  • 请参阅 update 2,其中我解释了它与 Freefair 插件一起使用但与 Ibotta 插件不兼容的可能原因。
猜你喜欢
  • 1970-01-01
  • 2021-05-01
  • 2018-05-12
  • 2019-01-15
  • 1970-01-01
  • 2018-04-25
  • 1970-01-01
  • 2020-01-04
  • 1970-01-01
相关资源
最近更新 更多