ReLinker: Cannot load library if library failed to load previously

After switching to ReLinker, I recently recently received this report from one my users. It seems like if a previous call to System.load() fails for a given library, then the library does not load in subsequent calls?

java.lang.UnsatisfiedLinkError: Cannot load library: find_library(linker.cpp:901): "/data/data/com.LearnImmersive.Lingoland/app_lib/libLingolandNativeActivity.so" failed to load previously
    at java.lang.Runtime.load(Runtime.java:341)
    at java.lang.System.load(System.java:500)
    at com.getkeepsafe.relinker.SystemLibraryLoader.loadPath(SystemLibraryLoader.java:29)
    at com.getkeepsafe.relinker.ReLinkerInstance.loadLibraryInternal(ReLinkerInstance.java:198)
    at com.getkeepsafe.relinker.ReLinkerInstance.loadLibrary(ReLinkerInstance.java:139)
    at com.getkeepsafe.relinker.ReLinkerInstance.loadLibrary(ReLinkerInstance.java:95)
    at com.LearnImmersive.Lingoland.LingolandApplication.onCreate(LingolandApplication.java:71)
    at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1003)
    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)

I am not sure how to diagnose this one further than this. I noticed some log statements inside your library that I will be sure to remotely propagate over rsyslog in a future release.

If it helps, I also received the following information:

Android version: Android 4.2
Device: ONE TOUCH 4015X (Yaris35_GSM) 1
Manufacturer: TCT Mobile Limited (Alcatel)
Android version: Android 4.2
RAM: (MB) 512
Screen size: 320 × 480
Screen density (dpi): 160
OpenGL ES: version 2.0
Native platform: armeabi-v7a
CPU make: Mediatek
CPU model: MT6572M

Chances are I can obtain additional information from this user, but his technical knowledge is definitely average.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 15

Most upvoted comments

Thank you for the gift! I’m glad to hear that building with NDK r9d worked out!

To know why r9d worked vs anything above it, you can refer to this issue.

What compiler are you using btw? Try GCC with a higher optimization level, it seems like it might inline the function in your code removing the dependency on an external library. More info can be found here

You can try statically linking your dependencies… which might result in a gigantic binary, but it should work fine everywhere. You might also be able to get away with defining __isnanf in your own code, but that will probably wont be maintainable for the future.

Additionally, you could compile API specific binaries, where API < 20 devices are served binaries compiled with r9d and devices > API 20 are served binaries compiled with the latest toolchain. This would be terrible to manage, I’d imagine, but should work theoretically… And if you choose to do this, you wont get the benefit of ReLinker since we strictly look for /abi/lib.so in your APK

If you’re feeling adventurous, Google actually has a alternative “crazy” linker you can include with your App that might solve your issues.

However, all in all it seems like this is a problem with the system / configuration rather than loading / linking libraries. The left over tidbit that is interesting for ReLinker is the viability of including “crazy linker” in the library and unconditionally utilizing it instead of relying on the system’s linker. Of course, if you choose to try out “crazy linker”, any feedback you could provide on that would be very helpful.

I’m going to go ahead and close this issue. Please open another issue if you choose to investigate crazy linker and have information to share, or if you encounter any other issues while using ReLinker!

https://github.com/KeepSafe/ReLinker/commit/090d85722063c518f4f83284147b1c3e9061819f

ReLinker will now log the actual stacktrace. This should tell us why libLingolandNativeActivity.so is a problem.

It would be cool if you can try unloading the library in your own native code, if that works then we can put it inside of ReLinker. It only becomes a chicken and egg sort of problem though when devices fail to load ReLinker’s bundled .so file 😃

If you want to unload a library, it seems like you want to link libdl and call dlclose(1), as described here http://osxr.org:8080/android/source/bionic/linker/dlfcn.c#0159 . Here’s some sample code using it http://osxr.org:8080/android/source/development/ndk/platforms/android-4/samples/san-angeles/jni/importgl.c#0165

So, to see if this would help, you would try / catch your last library load function, if an exception is thrown, you would unload the problem library and try again. Doing this would get past the “failed to load previously” message.

By wanting to support api >= 16, you will run into this issue since this misconfiguration in Bionic was fixed in API 18. I definitely would love to have ReLinker fix it for you, but I’m still unsure as to what is going wrong in the linking process. It seems like the reason a library can “fail to load” is pretty broad, ranging from not having an intra-library dependency present to corrupt offsets within the ELF format, etc.

Thanks for putting forth the effort to try it out! I really appreciate it 😃