Bug 27866 - UnsatisfiedLinkError: Native method not found: mono.android.Runtime.register
Summary: UnsatisfiedLinkError: Native method not found: mono.android.Runtime.register
Status: NEEDINFO
Alias: None
Product: Android
Classification: Xamarin
Component: General (show other bugs)
Version: 4.20.0
Hardware: PC Windows
: Normal normal
Target Milestone: ---
Assignee: Jonathan Pryor
URL:
Depends on:
Blocks:
 
Reported: 2015-03-11 04:29 UTC by Roman Cervenak
Modified: 2016-12-13 09:22 UTC (History)
4 users (show)

See Also:
Tags:
Is this bug a regression?: ---
Last known good build:


Attachments

Description Roman Cervenak 2015-03-11 04:29:38 UTC
In the google developer console I can see several occurences per week of following error. I never seen it personally on my device, so I cant supply full log unfortunately. The error is present on many devices (Xperia, Galaxy S3, Moto E, Moto G, LG Optimus, some Alcatels, etc.) and on all Android versions 4.0.3 - 4.4.

java.lang.UnsatisfiedLinkError: Native method not found: mono.android.Runtime.register:(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;)V
at mono.android.Runtime.register(Native Method)
at speedcamapp.SpeedcamApplication.onCreate(SpeedcamApplication.java:18)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1008)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4506)
at android.app.ActivityThread.access$1500(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1306)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5196)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
at dalvik.system.NativeStart.main(Native Method)

Line numbers in java classes differ for different error report instances, so for example also:

java.lang.UnsatisfiedLinkError: Native method not found: mono.android.Runtime.register:(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;)V
at mono.android.Runtime.register(Native Method)
at speedcamapp.SpeedcamApplication.onCreate(SpeedcamApplication.java:24)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:999)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4185)
at android.app.ActivityThread.access$1300(ActivityThread.java:133)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1258)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:4786)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
at dalvik.system.NativeStart.main(Native Method)
Comment 1 Jonathan Pryor 2015-03-11 10:43:57 UTC
The problem is this:

> at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1008)
                 ^^^^^^^^^^^^^^^

Xamarin.Android's startup code works by registering a <provider/> with a very high initialization order (so it runs first), so that we can use Context to determine various filesystem locations during app startup (e.g. the app's files dir, cache dir, where native libraries are stored, etc.) as part of initializing the Xamarin.Android runtime.

The problem you're seeing is that the app, for some reason, is being launched within the context of instrumentation, which screws with the normal process startup mechanics -- the provider *isn't* created and executed early enough to initialize Xamarin.Android properly, which results in the "Native method not found" error.

Thus, the question: why are these apps being instrumented? Instrumentation (afaik) is usually done on an individual app basis, not for everything running on the device. Why is your app being run within instrumentation when you're not the one doing so?

If you *do* want to use instrumentation, it's possible but requires that your Instrumentation code perform the Xamarin.Android initialization, as your Instrumentation class will execute before we have an opportunity to.
Comment 2 Roman Cervenak 2015-03-11 10:57:27 UTC
Thanks for the clarification. We are NOT using instrumentation. These errors are real-world, from google developer console. So you are basically telling me, that somebody is "playing hacker" with our app, and we should not be concerned about our app crashing for regular users? :)
Comment 3 Jonathan Pryor 2015-03-11 12:30:26 UTC
> So you are basically telling me,
> that somebody is "playing hacker" with our app, and we should not be concerned
> about our app crashing for regular users?

Yes.

At least until someone can provide a "proper" reason android.app.Instrumentation would be in the callstack that *doesn't* involve someone "playing hacker"...

(I can't think of such a reason...)

It would be interesting to ask the customer what they're doing, but I don't think that the developer console allows you to actually contact those individuals...
Comment 4 Roman Cervenak 2015-03-17 05:46:57 UTC
Yes, it would be interesting, but I cant contact those users. 
However, I have my doubts about this "wannabe hacker" theory, because there are quite a few of these, from many different devices, and some of them have message from user attached - like "it stopped working" etc.

I am thinking about possibility of some "chinese" android OS using instrumentation by default for some reason, or something like that..
Comment 5 Roman Cervenak 2015-03-19 07:15:56 UTC
I asked on StackOverflow about this, and they pointed out in source code, that instrumentation in this step is normal. So maybe it is not causing this issue?

http://stackoverflow.com/questions/29140889/when-is-instrumentation-involved-in-app-start
Comment 6 Jonathan Pryor 2015-03-20 17:26:58 UTC
> So maybe it is not causing this issue?

Indeed, they are correct. My mistake.

Unfortunately, that doesn't help.

> java.lang.UnsatisfiedLinkError: Native method not found: mono.android.Runtime.register:(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;)V
> at mono.android.Runtime.register(Native Method)

Because the message is *not* "findLbirary returned null", we can be reasonably sure that the native library was installed and found.

If the library couldn't be loaded (e.g. dlopen(3) failed), there would still be an UnsatisfiedLinkError but it would come from dlerror(3); it wouldn't read "Native method not found".

Consequently, we can infer that the library was both found and loaded.

What's failing is dlsym(handle, "Java_mono_android_Runtime_register"). This doesn't make any sense to me. Furthermore, as far as I can tell, dlerror() is not preserved after the failing dlsym(3) call:

https://github.com/android/platform_dalvik/blob/kitkat-release/vm/Native.cpp#L721
Comment 7 Jonathan Pryor 2015-03-20 17:48:49 UTC
Although...

Maybe the problem is something else. "Native method not found" is thrown if the method can't be found after probing all loaded native libraries.

What if libmonodroid.so was never loaded? What if this is happening before System.loadLibrary("monodroid") is invoked, which is done in obj/$(Configuration)/android/src/mono/MonoPackageManager.java, which in turn is invoked from obj/$(Configuration)/android/src/mono/MonoRuntimeProvider.java, which is a ContentProvider which should be loaded during process startup via a <provider/> within AndroidManifest.xml.

...which is why "normal" use of Instrumentation breaks things, as it causes the <provider/> to be executed "too late" to cause anything to be properly initialized.

To reiterate: if the MonoRuntimeProvider hasn't had a chance to run, then System.loadLibrary("monodroid") won't have executed, and thus libmonodroid.so! Java_mono_android_Runtime_register won't be probed, which would explain why you get the exception you do.

But how/why would MonoRuntimeProvider not have had a chance to execute?

MonoRuntimeProvider should be initialized within installProvider():

https://github.com/android/platform_frameworks_base/blob/kitkat-release/core/java/android/app/ActivityThread.java#L4771

Which is called by installContentProviders(), which is called by handleBindApplication():

https://github.com/android/platform_frameworks_base/blob/kitkat-release/core/java/android/app/ActivityThread.java#L4306

As per the callstack, we're *in* handleBindApplication(), and if we knew which Android versions your stack traces came from, we could plausibly get useful line numbers...

That said, we can try to deduce things. Your stack trace has handleBindApplication() calling callApplicationOnCreate(). For the kitkat-release branch, that would be:

https://github.com/android/platform_frameworks_base/blob/kitkat-release/core/java/android/app/ActivityThread.java#L4325

Notice that this is *after* the installContentProviders() call, and thus MonoRuntimeProvider.attachInfo() *should* have been invoked, meaning System.loadLibrary("monodroid") should have been executed, meaning Java_mono_android_Runtime_register should have been found.

...and it wasn't. :-(
Comment 8 Jonathan Pryor 2015-03-20 17:58:04 UTC
How many ABIs are included in your .apk? Just armeabi? armeabi-v7a? Both?

Does your app include any other native libraries?

i.e. what's the output of:

    $ unzip -l your.apk | grep .so$
Comment 9 Roman Cervenak 2015-03-25 03:48:24 UTC
There are 3 ABIs included: armeabi, armeabi-v7a, x86. All of them containing 2 files: libmonodroid.so, libmonosgen-2.0.so. No other .so files in lib folder.
Comment 10 Roman Cervenak 2015-03-25 04:35:50 UTC
I can provide few stacks with line numbers for different android versions:

Android 4.1 (Z740):

java.lang.UnsatisfiedLinkError: Native method not found: mono.android.Runtime.register:(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;)V
at mono.android.Runtime.register(Native Method)
at speedcamapp.SpeedcamApplication.onCreate(SpeedcamApplication.java:24)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:999)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4185)
at android.app.ActivityThread.access$1300(ActivityThread.java:133)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1258)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:4786)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
at dalvik.system.NativeStart.main(Native Method)

Android 4.2 (ONE TOUCH 4033X):

java.lang.UnsatisfiedLinkError: Native method not found: mono.android.Runtime.register:(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;)V
at mono.android.Runtime.register(Native Method)
at speedcamapp.SpeedcamApplication.onCreate(SpeedcamApplication.java:18)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1000)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4661)
at android.app.ActivityThread.access$1300(ActivityThread.java:162)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1424)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5400)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:837)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:604)
at dalvik.system.NativeStart.main(Native Method)

Android 4.4 (Xperia M2):

java.lang.UnsatisfiedLinkError: Native method not found: mono.android.Runtime.register:(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;)V
at mono.android.Runtime.register(Native Method)
at speedcamapp.SpeedcamApplication.onCreate(SpeedcamApplication.java:18)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1008)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4506)
at android.app.ActivityThread.access$1500(ActivityThread.java:144)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1306)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5196)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
at dalvik.system.NativeStart.main(Native Method)
Comment 14 joeperkins 2016-12-13 09:22:32 UTC
I just started getting the same error from Google play crash reports.

java.lang.UnsatisfiedLinkError: Native method not found: mono.android.Runtime.register:(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;)

Project Settings (Release):
    <AndroidLinkMode>Full</AndroidLinkMode>
    <EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
    <BundleAssemblies>False</BundleAssemblies>
    <AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
    <AndroidSupportedAbis>armeabi;armeabi-v7a;x86;x86_64;arm64-v8a</AndroidSupportedAbis>
    <Debugger>Xamarin</Debugger>
    <AotAssemblies>False</AotAssemblies>
    <EnableLLVM>False</EnableLLVM>
    <AndroidEnableMultiDex>False</AndroidEnableMultiDex>
    <EnableProguard>False</EnableProguard>
    <DebugSymbols>False</DebugSymbols>

Device Information:

Android 4.4
Device: Hydro VIBE (C6725) 
Manufacturer: Kyocera Corporation 
Device type: Phone 
Device language: English 
CPU make: Qualcomm 
CPU model: MSM8926 
Native platform: armeabi-v7a, armeabi 
RAM (MB): 1536 
Screen size: 540 × 960 
Screen density (dpi): 240 
OpenGL ES version: 3.0 

java.lang.UnsatisfiedLinkError: Native method not found: mono.android.Runtime.register:(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;)V
	at mono.android.Runtime.register(Native Method)
	at md5ebb1172dca24df6656d2275118d7fce9.ActivityBase.<clinit>(ActivityBase.java:19)
	at java.lang.Class.newInstanceImpl(Native Method)
	at java.lang.Class.newInstance(Class.java:1215)
	at android.app.Instrumentation.newActivity(Instrumentation.java:1061)
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2255)
	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
	at android.app.ActivityThread.access$800(ActivityThread.java:151)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1321)
	at android.os.Handler.dispatchMessage(Handler.java:110)
	at android.os.Looper.loop(Looper.java:193)
	at android.app.ActivityThread.main(ActivityThread.java:5292)
	at java.lang.reflect.Method.invokeNative(Native Method)
	at java.lang.reflect.Method.invoke(Method.java:515)
	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)
	at dalvik.system.NativeStart.main(Native Method)

Note You need to log in before you can comment on or make changes to this bug.