在使用方法引用的 proguard 之后因 NoSuchMethodError 崩溃
crash with NoSuchMethodError after proguard with method references
编译前的源码&proguard :
public class IntentSession extends BaseIntentSession {
@Override
public void onResume() {
super.onResume();
mExecutor.exec(getIntent(), this::finish);
}
}
compile&proguard后的反编译代码:(用CFR反编译0_118)
public class a extends superA {
public void e() {
super.e();
this.c.a(this.j(), b.a((a)this)); // the problematic code here
}
}
现在是compile&proguard后的关键代码,b
class的反编译代码:
final class b implements c.a {
private a a;
b (a a1) {
this.a = a1;
}
static /* synthetic */ b a(final a a) {
return new b(a);
}
@LambdaForm.Hidden
public void a() {
this.a.finish();
}
}
它仍然引用了 finish()
方法,该方法已经被 proguard 混淆为 m()
。
我希望参考 finish() 方法被混淆为 m(),但这不是正在发生的事情,这是我的问题。
Proguard 没有警告我,它只会在遇到错误代码时在运行时以 NoSuchMethodError
崩溃。所以不要告诉我添加像 -dontwarn java.lang.invoke.* 这样的 proguard 配置,我试过了但没有用。
可能是混淆时涉及的classes的处理顺序错了,谁知道?
我不想在 finish() 方法上添加 @Keep
注释,这是一个糟糕的解决方案,我不得不担心它并在将来谨慎使用方法引用,所以我'我正在寻找最佳解决方案。
以下是我的 gradle 配置:
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'me.tatarka:gradle-retrolambda:3.4.0'
classpath "com.fernandocejas.frodo:frodo-plugin:0.8.3"
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
下面是我的proguard-rules.pro
:
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-ignorewarnings
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-dontwarn java.util.**
-keep class java.util.** {*; }
-dontwarn com.android.**
-keep class com.android.** { *; }
-dontwarn android.support.**
-keep class android.support.** { *; }
-keepattributes SourceFile, LineNumberTable
# end common config
##---------------Begin: proguard configuration for Gson ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }
-dontwarn com.google.gson.**
-keep class com.google.gson.** { *; }
-dontwarn com.baidu.util.audiocore.**
-keep class com.baidu.util.audiocore.** { *; }
# Application classes that will be serialized/deserialized over Gson
##---------------End: proguard configuration for Gson ----------
# Explicitly preserve all serialization members. The Serializable interface
# is only a marker interface, so it wouldn't save them.
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
-keep public class * implements java.io.Serializable {*;}
# end Serializable
# ----------------------------
-dontnote
-dontwarn com.xiaomi.push.service.XMPushService
#for speech sdk
-keep class com.orion.speech.** {*;}
-keep class com.orion.speech.audio.** {*;}
#end for speech sdk
#for xiaomi
-keep class PushReceiver {*;}
-keep class com.xiaomi.push.**{*;}
#end for xiaomi
#for retrofit
-dontwarn sun.misc.Unsafe
-dontwarn okio.**
# Platform calls Class.forName on types which do not exist on Android to determine platform.
-dontnote retrofit2.Platform
# Platform used when running on RoboVM on iOS. Will not be used at runtime.
-dontnote retrofit2.Platform$IOS$MainThreadExecutor
# Platform used when running on Java 8 VMs. Will not be used at runtime.
-dontwarn retrofit2.Platform$Java8
# Retain generic type information for use by reflection by converters and adapters.
-keepattributes Signature
# Retain declared checked exceptions for use by a Proxy instance.
-keepattributes Exceptions
#end for retrofit
#for lambda
-dontwarn java.lang.invoke.*
#end for lambda
#for okhttp
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-dontwarn okhttp3.**
#end for okhttp
#for RxJava
-keep class rx.schedulers.Schedulers {
public static <methods>;
}
-keep class rx.schedulers.ImmediateScheduler {
public <methods>;
}
-keep class rx.schedulers.TestScheduler {
public <methods>;
}
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
long producerIndex;
long consumerIndex;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
rx.internal.util.atomic.LinkedQueueNode producerNode;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
rx.internal.util.atomic.LinkedQueueNode consumerNode;
}
# end for RxJava
#for bugly
-dontwarn com.tencent.bugly.**
-keep public class com.tencent.bugly.**{*;}
#end for bugly
#----------------android
# this indicate the case of using APIs higher than minSDK (API 8)
-dontwarn android.**
# ---------------------------------------
# TODO: can be reduce if we have more understanding about Service and AIDL
-keep public class android.service.notification.** {*;}
-keepattributes *Annotation*,EnclosingMethod
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepattributes *Annotation*,EnclosingMethod,Signature
-keep interface android.content.pm.**{*;}
-keep class android.content.pm.**{*;}
-keep class android.os.Process{*;}
-dontwarn com.android.internal.os.*
-keep class android.support.v4.os.**{*;}
-keepclassmembers class * {
@android.support.v4 *;
}
# cmcm support
-keep class com.cmcm.support.jni.** { *; }
大多数时候,您的库的 website/github 会提供必要的混淆规则,例如 retrolamda:
-dontwarn java.lang.invoke.*
-dontwarn **$$Lambda$*
Proguarding 是一个跟踪错误的故事。检查您的日志记录以查看哪个库、class 或组件导致了问题并将它们 小心地 添加到规则 :).
你的错误 NoSuchMethod 具体来说:
Your code is probably calling something like myClass.getMethod, trying
to find some method dynamically. Since ProGuard can't always detect
this automatically, you have to keep the missing method in using the
appropriate -keep option:
-keepclassmembers class mypackage.MyClass { void myMethod(); }
解决这些 -keep
没有修复的错误是 真正的 痛苦,我在这些问题上取得进展的唯一方法就是遵循这个策略:
- 找出错误是在混淆器周期的哪个阶段引入的(缩小、优化或混淆)
- Add/remove 该步骤的例外情况,从最广泛的排除范围到最窄的排除范围,直到问题再次出现
验证这是否是优化问题
- 添加
-dontoptimize
而不是 -optimizations
字符串重建和测试
- 如果崩溃得到缓解,则通过最高级别 class 的优化排除向后工作
!method/*, !code/*, !class/*, !field/*
直到您确定哪个排除使问题消失
- 确定排除的 class 中的最小排除是什么(假设它是
!method/*
,从它到 !method/marking/*
然后如果它也有效,请尝试 !method/marking/final
. 如果可行,那么你已经找到了最小排除)
这很可能是 Proguard 规则中的错误 您正在使用的库之一或 您正在使用的 Proguard 版本中的错误本身(我都看过)所以也尝试更新它们。
当 class 在运行时通过反射寻找或直接调用给定参数的方法时会发生这种情况。 Proguard 无法对此发出警告,因为在编译时混淆的 class 和消费者 class 之间没有 link。你可以有类似
public class AbstractbaseSomething{
public abstract void doStuff();
}
public class iDoStuff{
public void letsGo(Object o){
Method method = o.getClass().getDeclaredMethod("doStuff");
// do stuff with the method
}
}
由于引用该方法时使用了带有名称的字符串,proguard 不会检测到它,并且在运行时会发生崩溃。唯一的解决办法是,假设你不能修改代码,是为了避免混淆方法和 class.
(你可以在Ormlite中查看更真实的例子-Android)
仔细检查后,我断定这可能不是proguard的错误,只是gradle。
首先,我让源代码使用通用接口编码风格:
mExecutor.exec(getIntent(), new MyInterface() {
@Override
public void execute() {
finish();
}
});
然后我清理构建缓存并重建 :
./gradlew clean
./gradlew :app:assembleRelease
我执行了输出发布应用程序并使其到达有问题的代码,它没有崩溃。
这次我转向方法参考:
mExecutor.exec(getIntent(), this::finish);
但我在重新构建之前没有清理构建缓存:
./gradlew :app:assembleRelease
现在在崩溃发生时重新执行:
05-22 11:35:33.870 D/AndroidRuntime( 631): Shutting down VM
05-22 11:35:37.470 E/AndroidRuntime( 631): FATAL EXCEPTION: main
05-22 11:35:37.470 E/AndroidRuntime( 631): Process: com.cmrobot.assistant, PID: 631
05-22 11:35:37.470 E/AndroidRuntime( 631): java.lang.NoSuchMethodError: com.session.a.finish
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.b.executeDone(Unknown Source)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.base.a.a(BaseIntentExecutor.java:99)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.base.a.e(BaseIntentExecutor.java:76)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.base.a.a(BaseIntentExecutor.java:67)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.cmd.general.volume.VolumeChangeExecutor.b(VolumeChangeExecutor.java:28)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.cmd.general.volume.a.a(LowerVolumeExecutor.java:63)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.base.a.d(BaseIntentExecutor.java:44)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.base.b.run(Unknown Source)
05-22 11:35:37.470 E/AndroidRuntime( 631): at android.os.Handler.handleCallback(Handler.java:733)
05-22 11:35:37.470 E/AndroidRuntime( 631): at android.os.Handler.dispatchMessage(Handler.java:95)
05-22 11:35:37.470 E/AndroidRuntime( 631): at android.os.Looper.loop(Looper.java:136)
05-22 11:35:37.470 E/AndroidRuntime( 631): at android.app.ActivityThread.main(ActivityThread.java:5001)
05-22 11:35:37.470 E/AndroidRuntime( 631): at java.lang.reflect.Method.invokeNative(Native Method)
05-22 11:35:37.470 E/AndroidRuntime( 631): at java.lang.reflect.Method.invoke(Method.java:515)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:829)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:645)
05-22 11:35:37.470 E/AndroidRuntime( 631): at dalvik.system.NativeStart.main(Native Method)
为了确认这是构建缓存的原因,我 clean 然后 re-build 基本上改变了代码:
./gradlew clean
./gradlew :app:assembleRelease
后记应用程序中的崩溃消失了。
我试图创建一个演示项目来证明这个问题,但该项目不会弹出崩溃,仅在我的生产项目中。
编译前的源码&proguard :
public class IntentSession extends BaseIntentSession {
@Override
public void onResume() {
super.onResume();
mExecutor.exec(getIntent(), this::finish);
}
}
compile&proguard后的反编译代码:(用CFR反编译0_118)
public class a extends superA {
public void e() {
super.e();
this.c.a(this.j(), b.a((a)this)); // the problematic code here
}
}
现在是compile&proguard后的关键代码,b
class的反编译代码:
final class b implements c.a {
private a a;
b (a a1) {
this.a = a1;
}
static /* synthetic */ b a(final a a) {
return new b(a);
}
@LambdaForm.Hidden
public void a() {
this.a.finish();
}
}
它仍然引用了 finish()
方法,该方法已经被 proguard 混淆为 m()
。
我希望参考 finish() 方法被混淆为 m(),但这不是正在发生的事情,这是我的问题。
Proguard 没有警告我,它只会在遇到错误代码时在运行时以 NoSuchMethodError
崩溃。所以不要告诉我添加像 -dontwarn java.lang.invoke.* 这样的 proguard 配置,我试过了但没有用。
可能是混淆时涉及的classes的处理顺序错了,谁知道?
我不想在 finish() 方法上添加 @Keep
注释,这是一个糟糕的解决方案,我不得不担心它并在将来谨慎使用方法引用,所以我'我正在寻找最佳解决方案。
以下是我的 gradle 配置:
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'me.tatarka:gradle-retrolambda:3.4.0'
classpath "com.fernandocejas.frodo:frodo-plugin:0.8.3"
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
下面是我的proguard-rules.pro
:
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-ignorewarnings
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-dontwarn java.util.**
-keep class java.util.** {*; }
-dontwarn com.android.**
-keep class com.android.** { *; }
-dontwarn android.support.**
-keep class android.support.** { *; }
-keepattributes SourceFile, LineNumberTable
# end common config
##---------------Begin: proguard configuration for Gson ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }
-dontwarn com.google.gson.**
-keep class com.google.gson.** { *; }
-dontwarn com.baidu.util.audiocore.**
-keep class com.baidu.util.audiocore.** { *; }
# Application classes that will be serialized/deserialized over Gson
##---------------End: proguard configuration for Gson ----------
# Explicitly preserve all serialization members. The Serializable interface
# is only a marker interface, so it wouldn't save them.
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
-keep public class * implements java.io.Serializable {*;}
# end Serializable
# ----------------------------
-dontnote
-dontwarn com.xiaomi.push.service.XMPushService
#for speech sdk
-keep class com.orion.speech.** {*;}
-keep class com.orion.speech.audio.** {*;}
#end for speech sdk
#for xiaomi
-keep class PushReceiver {*;}
-keep class com.xiaomi.push.**{*;}
#end for xiaomi
#for retrofit
-dontwarn sun.misc.Unsafe
-dontwarn okio.**
# Platform calls Class.forName on types which do not exist on Android to determine platform.
-dontnote retrofit2.Platform
# Platform used when running on RoboVM on iOS. Will not be used at runtime.
-dontnote retrofit2.Platform$IOS$MainThreadExecutor
# Platform used when running on Java 8 VMs. Will not be used at runtime.
-dontwarn retrofit2.Platform$Java8
# Retain generic type information for use by reflection by converters and adapters.
-keepattributes Signature
# Retain declared checked exceptions for use by a Proxy instance.
-keepattributes Exceptions
#end for retrofit
#for lambda
-dontwarn java.lang.invoke.*
#end for lambda
#for okhttp
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-dontwarn okhttp3.**
#end for okhttp
#for RxJava
-keep class rx.schedulers.Schedulers {
public static <methods>;
}
-keep class rx.schedulers.ImmediateScheduler {
public <methods>;
}
-keep class rx.schedulers.TestScheduler {
public <methods>;
}
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
long producerIndex;
long consumerIndex;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
rx.internal.util.atomic.LinkedQueueNode producerNode;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
rx.internal.util.atomic.LinkedQueueNode consumerNode;
}
# end for RxJava
#for bugly
-dontwarn com.tencent.bugly.**
-keep public class com.tencent.bugly.**{*;}
#end for bugly
#----------------android
# this indicate the case of using APIs higher than minSDK (API 8)
-dontwarn android.**
# ---------------------------------------
# TODO: can be reduce if we have more understanding about Service and AIDL
-keep public class android.service.notification.** {*;}
-keepattributes *Annotation*,EnclosingMethod
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepattributes *Annotation*,EnclosingMethod,Signature
-keep interface android.content.pm.**{*;}
-keep class android.content.pm.**{*;}
-keep class android.os.Process{*;}
-dontwarn com.android.internal.os.*
-keep class android.support.v4.os.**{*;}
-keepclassmembers class * {
@android.support.v4 *;
}
# cmcm support
-keep class com.cmcm.support.jni.** { *; }
大多数时候,您的库的 website/github 会提供必要的混淆规则,例如 retrolamda:
-dontwarn java.lang.invoke.*
-dontwarn **$$Lambda$*
Proguarding 是一个跟踪错误的故事。检查您的日志记录以查看哪个库、class 或组件导致了问题并将它们 小心地 添加到规则 :).
你的错误 NoSuchMethod 具体来说:
Your code is probably calling something like myClass.getMethod, trying to find some method dynamically. Since ProGuard can't always detect this automatically, you have to keep the missing method in using the appropriate -keep option:
-keepclassmembers class mypackage.MyClass { void myMethod(); }
解决这些 -keep
没有修复的错误是 真正的 痛苦,我在这些问题上取得进展的唯一方法就是遵循这个策略:
- 找出错误是在混淆器周期的哪个阶段引入的(缩小、优化或混淆)
- Add/remove 该步骤的例外情况,从最广泛的排除范围到最窄的排除范围,直到问题再次出现
验证这是否是优化问题
- 添加
-dontoptimize
而不是-optimizations
字符串重建和测试 - 如果崩溃得到缓解,则通过最高级别 class 的优化排除向后工作
!method/*, !code/*, !class/*, !field/*
直到您确定哪个排除使问题消失 - 确定排除的 class 中的最小排除是什么(假设它是
!method/*
,从它到!method/marking/*
然后如果它也有效,请尝试!method/marking/final
. 如果可行,那么你已经找到了最小排除)
这很可能是 Proguard 规则中的错误 您正在使用的库之一或 您正在使用的 Proguard 版本中的错误本身(我都看过)所以也尝试更新它们。
当 class 在运行时通过反射寻找或直接调用给定参数的方法时会发生这种情况。 Proguard 无法对此发出警告,因为在编译时混淆的 class 和消费者 class 之间没有 link。你可以有类似
public class AbstractbaseSomething{
public abstract void doStuff();
}
public class iDoStuff{
public void letsGo(Object o){
Method method = o.getClass().getDeclaredMethod("doStuff");
// do stuff with the method
}
}
由于引用该方法时使用了带有名称的字符串,proguard 不会检测到它,并且在运行时会发生崩溃。唯一的解决办法是,假设你不能修改代码,是为了避免混淆方法和 class.
(你可以在Ormlite中查看更真实的例子-Android)
仔细检查后,我断定这可能不是proguard的错误,只是gradle。
首先,我让源代码使用通用接口编码风格:
mExecutor.exec(getIntent(), new MyInterface() {
@Override
public void execute() {
finish();
}
});
然后我清理构建缓存并重建 :
./gradlew clean
./gradlew :app:assembleRelease
我执行了输出发布应用程序并使其到达有问题的代码,它没有崩溃。
这次我转向方法参考:
mExecutor.exec(getIntent(), this::finish);
但我在重新构建之前没有清理构建缓存:
./gradlew :app:assembleRelease
现在在崩溃发生时重新执行:
05-22 11:35:33.870 D/AndroidRuntime( 631): Shutting down VM
05-22 11:35:37.470 E/AndroidRuntime( 631): FATAL EXCEPTION: main
05-22 11:35:37.470 E/AndroidRuntime( 631): Process: com.cmrobot.assistant, PID: 631
05-22 11:35:37.470 E/AndroidRuntime( 631): java.lang.NoSuchMethodError: com.session.a.finish
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.b.executeDone(Unknown Source)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.base.a.a(BaseIntentExecutor.java:99)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.base.a.e(BaseIntentExecutor.java:76)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.base.a.a(BaseIntentExecutor.java:67)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.cmd.general.volume.VolumeChangeExecutor.b(VolumeChangeExecutor.java:28)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.cmd.general.volume.a.a(LowerVolumeExecutor.java:63)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.base.a.d(BaseIntentExecutor.java:44)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.newsessions.base.b.run(Unknown Source)
05-22 11:35:37.470 E/AndroidRuntime( 631): at android.os.Handler.handleCallback(Handler.java:733)
05-22 11:35:37.470 E/AndroidRuntime( 631): at android.os.Handler.dispatchMessage(Handler.java:95)
05-22 11:35:37.470 E/AndroidRuntime( 631): at android.os.Looper.loop(Looper.java:136)
05-22 11:35:37.470 E/AndroidRuntime( 631): at android.app.ActivityThread.main(ActivityThread.java:5001)
05-22 11:35:37.470 E/AndroidRuntime( 631): at java.lang.reflect.Method.invokeNative(Native Method)
05-22 11:35:37.470 E/AndroidRuntime( 631): at java.lang.reflect.Method.invoke(Method.java:515)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:829)
05-22 11:35:37.470 E/AndroidRuntime( 631): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:645)
05-22 11:35:37.470 E/AndroidRuntime( 631): at dalvik.system.NativeStart.main(Native Method)
为了确认这是构建缓存的原因,我 clean 然后 re-build 基本上改变了代码:
./gradlew clean
./gradlew :app:assembleRelease
后记应用程序中的崩溃消失了。
我试图创建一个演示项目来证明这个问题,但该项目不会弹出崩溃,仅在我的生产项目中。