Vin*_*ing 8 android gradle android-proguard
compile&proguard之前的源代码:
public class IntentSession extends BaseIntentSession {
@Override
public void onResume() {
super.onResume();
mExecutor.exec(getIntent(), this::finish);
}
}
Run Code Online (Sandbox Code Playgroud)
编译和编译后的反编译代码:(用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
}
}
Run Code Online (Sandbox Code Playgroud)
现在是编译&proguard之后的关键代码,b该类的反编译代码:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
它仍然引用了finish()已经m()被proguard 混淆的方法.
我希望引用finish()方法被混淆为m(),但这不是正在发生的事情,这是我的问题.
Proguard没有警告我,只有NoSuchMethodError在遇到错误的代码时它才会在运行时崩溃.所以不要告诉我添加像-dontwarn java.lang.invoke.*这样的proguard配置,我试过但它没有用.
也许在混淆过程中涉及的类的处理顺序是错误的,谁知道呢?
我不想@Keep在finish()方法上添加注释,这是一个糟糕的解决方案,我将不得不担心它并在未来仔细使用方法引用,所以我正在寻找最佳解决方案.
下面是我的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'
}
Run Code Online (Sandbox Code Playgroud)
以下是我的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.** { *; }
Run Code Online (Sandbox Code Playgroud)
仔细检查后,我得出结论,这可能不是 proguard 的 bug,只是 gradle 的 bug。
首先,我让源代码使用通用接口编码风格:
mExecutor.exec(getIntent(), new MyInterface() {
@Override
public void execute() {
finish();
}
});
Run Code Online (Sandbox Code Playgroud)
然后我清理构建缓存并重建:
./gradlew clean
./gradlew :app:assembleRelease
Run Code Online (Sandbox Code Playgroud)
我执行输出发布应用程序并使其到达有问题的代码,它可以正常工作而不会崩溃。
这次我转向方法参考:
mExecutor.exec(getIntent(), this::finish);
Run Code Online (Sandbox Code Playgroud)
但我在重新构建之前没有清理构建缓存:
./gradlew :app:assembleRelease
Run Code Online (Sandbox Code Playgroud)
现在重新执行崩溃发生的情况:
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)
Run Code Online (Sandbox Code Playgroud)
为了确认这是构建缓存的原因,我清理然后重新构建基本上已更改的代码:
./gradlew clean
./gradlew :app:assembleRelease
Run Code Online (Sandbox Code Playgroud)
那次崩溃在后记应用程序中消失了。
我尝试创建一个演示项目来证明这个问题,但该项目不会弹出崩溃,仅在我的生产项目中出现。
| 归档时间: |
|
| 查看次数: |
1400 次 |
| 最近记录: |