Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Xamarin.Android.Build.Tasks] fix proguard rules for R8 compat (#2735)
Fixes: #2684 Context: https://www.guardsquare.com/en/products/proguard/manual/usage#keepoptionmodifiers Context: https://www.guardsquare.com/en/products/proguard/manual/examples Using R8 on a pre-Android 8.0 device was crashing with: Unhandled Exception: Java.Lang.LinkageError: no non-static method "Landroid/runtime/UncaughtExceptionHandler;.<init>()V" at Java.Interop.JniEnvironment+InstanceMethods.GetMethodID (Java.Interop.JniObjectReference type, System.String name, System.String signature) [0x0005b] in <7d7bcc9ee9cc460db8abcdb9a9622733>:0 at Java.Interop.JniType.GetConstructor (System.String signature) [0x0000c] in <7d7bcc9ee9cc460db8abcdb9a9622733>:0 at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructor (System.String signature) [0x00035] in <7d7bcc9ee9cc460db8abcdb9a9622733>:0 at Java.Interop.JniPeerMembers+JniInstanceMethods.FinishCreateInstance (System.String constructorSignature, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x00036] in <7d7bcc9ee9cc460db8abcdb9a9622733>:0 at Java.Lang.Object..ctor () [0x00054] in <d77389624c8c4948a12589c4bd4500eb>:0 at Android.Runtime.UncaughtExceptionHandler..ctor (Java.Lang.Thread+IUncaughtExceptionHandler defaultHandler) [0x00000] in <d77389624c8c4948a12589c4bd4500eb>:0 at Android.Runtime.JNIEnv.Initialize (Android.Runtime.JnienvInitializeArgs* args) [0x00202] in <d77389624c8c4948a12589c4bd4500eb>:0 --- End of managed Java.Lang.LinkageError stack trace --- java.lang.NoSuchMethodError: no non-static method "Landroid/runtime/UncaughtExceptionHandler;.<init>()V" at mono.android.Runtime.init(Native Method) at mono.MonoPackageManager.LoadApplication(:21) at mono.MonoRuntimeProvider.attachInfo(:1) at android.app.ActivityThread.installProvider(ActivityThread.java:5853) at android.app.ActivityThread.installContentProviders(ActivityThread.java:5445) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5384) at android.app.ActivityThread.-wrap2(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1545) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6119) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) Looking into it, the following method was present when using ProGuard, but not R8: #1 : (in Landroid/runtime/UncaughtExceptionHandler;) name : '<init>' type : '()V' access : 0x10001 (PUBLIC CONSTRUCTOR) code - registers : 4 ins : 1 outs : 4 insns size : 22 16-bit code units catches : (none) positions : 0x0000 line=22 0x0003 line=23 0x0010 line=24 locals : 0x0000 - 0x0016 reg=3 this Landroid/runtime/UncaughtExceptionHandler; I looked at `proguard_xamarin.cfg`, and noticed something strange: -keep class android.runtime.** { <init>(***); } It seemed this rule was being ignored? All the other *working* rules were using `<init>(...);` to refer to the instance constructor. I reviewed [ProGuard's documented syntax/grammar][0]: [@annotationtype] [[!]public|final|abstract|@ ...] [!]interface|class|enum classname [extends|implements [@annotationtype] classname] [{ [@annotationtype] [[!]public|private|protected|static|volatile|transient ...] <fields> | (fieldtype fieldname); [@annotationtype] [[!]public|private|protected|static|synchronized|native|abstract|strictfp ...] <methods> | <init>(argumenttype,...) | classname(argumenttype,...) | (returntype methodname(argumenttype,...)); [@annotationtype] [[!]public|private|protected|static ... ] *; ... }] It seems `(...)` is the proper way to specify a match against any set of arguments. Looking through ProGuard's examples, I can't find any usage of `(***)`. It must *happened* to work, but is undocumented. R8 does not appear to accept the `(***)` syntax at all. Update `proguard_xamarin.cfg` so that it uses `(...)`, not `(***)`, allowing R8 to properly process `proguard_xamarin.cfg`. ~~ Other changes ~~ I expanded upon the `DexUtils` class so it can look for methods within classes. I also adjusted one test to verify this problem is solved. [0]: https://www.guardsquare.com/en/products/proguard/manual/usage#classspecification
- Loading branch information