Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mono.Android-Tests crashes when r8 is enabled on Android devices versioned 7.1.1 and lower #2684

Closed
pjcollins opened this issue Feb 1, 2019 · 0 comments
Assignees
Labels
Area: App Runtime Issues in `libmonodroid.so`. Area: Unit Tests Issues with repo unit tests.
Milestone

Comments

@pjcollins
Copy link
Member

Steps to Reproduce

  1. Install Mono.Android-Tests in Release mode on an Android device running v7.1.1 or lower.
  2. Run the tests via instrumentation, and a crash occurs on startup:
02-01 14:39:30.427 I/ActivityManager( 4839): Start proc 16220:Mono.Android_Tests/u0a7060 for added application Mono.Android_Tests
02-01 14:39:30.495 W/monodroid(16220): Using runtime path: /data/app/Mono.Android_Tests-1/lib/arm64
02-01 14:39:30.495 W/monodroid(16220): Trying to load sgen from: /data/app/Mono.Android_Tests-1/lib/arm64/libmonosgen-2.0.so
02-01 14:39:30.541 W/monodroid-gc(16220): GREF GC Threshold: 46080
02-01 14:39:30.922 E/mono    (16220): 
02-01 14:39:30.922 E/mono    (16220): Unhandled Exception:
02-01 14:39:30.922 E/mono    (16220): Java.Lang.LinkageError: no non-static method "Landroid/runtime/UncaughtExceptionHandler;.<init>()V"
02-01 14:39:30.922 E/mono    (16220):   at Java.Interop.JniEnvironment+InstanceMethods.GetMethodID (Java.Interop.JniObjectReference type, System.String name, System.String signature) [0x0005b] in <7d7bcc9ee9cc460db8abcdb9a9622733>:0 
02-01 14:39:30.922 E/mono    (16220):   at Java.Interop.JniType.GetConstructor (System.String signature) [0x0000c] in <7d7bcc9ee9cc460db8abcdb9a9622733>:0 
02-01 14:39:30.922 E/mono    (16220):   at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructor (System.String signature) [0x00035] in <7d7bcc9ee9cc460db8abcdb9a9622733>:0 
02-01 14:39:30.922 E/mono    (16220):   at Java.Interop.JniPeerMembers+JniInstanceMethods.FinishCreateInstance (System.String constructorSignature, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x00036] in <7d7bcc9ee9cc460db8abcdb9a9622733>:0 
02-01 14:39:30.922 E/mono    (16220):   at Java.Lang.Object..ctor () [0x00054] in <d77389624c8c4948a12589c4bd4500eb>:0 
02-01 14:39:30.922 E/mono    (16220):   at Android.Runtime.UncaughtExceptionHandler..ctor (Java.Lang.Thread+IUncaughtExceptionHandler defaultHandler) [0x00000] in <d77389624c8c4948a12589c4bd4500eb>:0 
02-01 14:39:30.922 E/mono    (16220):   at Android.Runtime.JNIEnv.Initialize (Android.Runtime.JnienvInitializeArgs* args) [0x00202] in <d77389624c8c4948a12589c4bd4500eb>:0 
02-01 14:39:30.922 E/mono    (16220):   --- End of managed Java.Lang.LinkageError stack trace ---
02-01 14:39:30.922 E/mono    (16220): java.lang.NoSuchMethodError: no non-static method "Landroid/runtime/UncaughtExceptionHandler;.<init>()V"
02-01 14:39:30.922 E/mono    (16220): 	at mono.android.Runtime.init(Native Method)
02-01 14:39:30.922 E/mono    (16220): 	at mono.MonoPackageManager.LoadApplication(:21)
02-01 14:39:30.922 E/mono    (16220): 	at mono.MonoRuntimeProvider.attachInfo(:1)
02-01 14:39:30.922 E/mono    (16220): 	at android.app.ActivityThread.installProvider(ActivityThread.java:5853)
02-01 14:39:30.922 E/mono    (16220): 	at android.app.ActivityThread.installContentProviders(ActivityThread.java:5445)
02-01 14:39:30.922 E/mono    (16220): 	at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5384)
02-01 14:39:30.922 E/mono    (16220): 	at android.app.ActivityThread.-wrap2(ActivityThread.java)
02-01 14:39:30.922 E/mono    (16220): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1545)
02-01 14:39:30.922 E/mono    (16220): 	at android.os.Handler.dispatchMessage(Handler.java:102)
02-01 14:39:30.922 E/mono    (16220): 	at android.os.Looper.loop(Looper.java:154)
02-01 14:39:30.922 E/mono    (16220): 	at android.app.ActivityThread.main(ActivityThread.java:6119)
02-01 14:39:30.922 E/mono    (16220): 	at java.lang.reflect.Method.invoke(Native Method)
02-01 14:39:30.922 E/mono    (16220): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
02-01 14:39:30.922 E/mono    (16220): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

Version Information

https://gist.github.com/pjcollins/575235c0ed394b425ec79ae5f06886cb

Log File

http://xqa.blob.core.windows.net/gist/log-5aec55044cb9416eb9660ec10d983751.txt
binlog.zip

@pjcollins pjcollins added Area: App Runtime Issues in `libmonodroid.so`. Area: Unit Tests Issues with repo unit tests. labels Feb 1, 2019
@jonathanpeppers jonathanpeppers added this to the d16-1 milestone Feb 1, 2019
jonathanpeppers added a commit to jonathanpeppers/xamarin-android that referenced this issue Feb 14, 2019
Context: https://www.guardsquare.com/en/products/proguard/manual/usage#keepoptionmodifiers
Context: https://www.guardsquare.com/en/products/proguard/manual/examples
Fixes: dotnet#2684

Using R8 on a pre-Android 8.0 device was crashing with:

    E/mono    (16220): Unhandled Exception:
    E/mono    (16220): Java.Lang.LinkageError: no non-static method "Landroid/runtime/UncaughtExceptionHandler;.<init>()V"
    E/mono    (16220):   at Java.Interop.JniEnvironment+InstanceMethods.GetMethodID (Java.Interop.JniObjectReference type, System.String name, System.String signature) [0x0005b] in <7d7bcc9ee9cc460db8abcdb9a9622733>:0
    E/mono    (16220):   at Java.Interop.JniType.GetConstructor (System.String signature) [0x0000c] in <7d7bcc9ee9cc460db8abcdb9a9622733>:0
    E/mono    (16220):   at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructor (System.String signature) [0x00035] in <7d7bcc9ee9cc460db8abcdb9a9622733>:0
    E/mono    (16220):   at Java.Interop.JniPeerMembers+JniInstanceMethods.FinishCreateInstance (System.String constructorSignature, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x00036] in <7d7bcc9ee9cc460db8abcdb9a9622733>:0
    E/mono    (16220):   at Java.Lang.Object..ctor () [0x00054] in <d77389624c8c4948a12589c4bd4500eb>:0
    E/mono    (16220):   at Android.Runtime.UncaughtExceptionHandler..ctor (Java.Lang.Thread+IUncaughtExceptionHandler defaultHandler) [0x00000] in <d77389624c8c4948a12589c4bd4500eb>:0
    E/mono    (16220):   at Android.Runtime.JNIEnv.Initialize (Android.Runtime.JnienvInitializeArgs* args) [0x00202] in <d77389624c8c4948a12589c4bd4500eb>:0
    E/mono    (16220):   --- End of managed Java.Lang.LinkageError stack trace ---
    E/mono    (16220): java.lang.NoSuchMethodError: no non-static method "Landroid/runtime/UncaughtExceptionHandler;.<init>()V"
    E/mono    (16220): 	at mono.android.Runtime.init(Native Method)
    E/mono    (16220): 	at mono.MonoPackageManager.LoadApplication(:21)
    E/mono    (16220): 	at mono.MonoRuntimeProvider.attachInfo(:1)
    E/mono    (16220): 	at android.app.ActivityThread.installProvider(ActivityThread.java:5853)
    E/mono    (16220): 	at android.app.ActivityThread.installContentProviders(ActivityThread.java:5445)
    E/mono    (16220): 	at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5384)
    E/mono    (16220): 	at android.app.ActivityThread.-wrap2(ActivityThread.java)
    E/mono    (16220): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1545)
    E/mono    (16220): 	at android.os.Handler.dispatchMessage(Handler.java:102)
    E/mono    (16220): 	at android.os.Looper.loop(Looper.java:154)
    E/mono    (16220): 	at android.app.ActivityThread.main(ActivityThread.java:6119)
    E/mono    (16220): 	at java.lang.reflect.Method.invoke(Native Method)
    E/mono    (16220): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
    E/mono    (16220): 	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;

Then 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.

When I reviewed ProGuard's documented syntax/grammar:

    [@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 *happen* to work, but is undocumented.

R8 does not appear to accept the `(***)` syntax at all.

~~ 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.
jonpryor pushed a commit that referenced this issue Feb 14, 2019
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
@ghost ghost locked as resolved and limited conversation to collaborators Jun 6, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Area: App Runtime Issues in `libmonodroid.so`. Area: Unit Tests Issues with repo unit tests.
Projects
None yet
Development

No branches or pull requests

2 participants