如何解决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.
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_api
或 firebase.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 的字节码操作管道,这是一种更合乎逻辑的方法。
基本思想是:
- 更改 Kotlin 和 Java 编译输出目录。
- 将 Kotlin/Java 编译输出复制到一个目录。
- 编织组合的 Kotlin/Java 类。
- 注册为字节码生成器,以便 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 举报,一经查实,本站将立刻删除。