Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling System.loadLibrary twice for the same shared library

I have the situation when two jar libraries use the same shared library. In each library "the main interface" class loads the .so file with System.loadLibrary. My question is: if the user decides to use these two jar libraries in one project, would the second call to System.loadLibrary for the same .so file cause any exception? Or is it "somehowe handled" by the system to prevent shared libraries from being loaded twice? Or maybe there is a "commonly known pattern" to handle such situations?

The jni wrappers are targeted to be used on android. I am the author of both wrapper libs so answering you can assume full control on java sources.

like image 942
Tomasz Gawel Avatar asked Feb 19 '14 10:02

Tomasz Gawel


2 Answers

According to the apidocs it should not be a problem: "If this method is called more than once with the same library name, the second and subsequent calls are ignored."

like image 121
vanOekel Avatar answered Oct 22 '22 04:10

vanOekel


I've found one very narrow use case when this will be a problem.

If you are running Android system app, with android:sharedUserId="android.uid.system" in manifest, either pre-installed to the device, or signed with the platform certificate, and you are trying to call System.loadLibrary twice to load the same library (either by running the same app twice, or creating two separate system apps loading the same library), Android will reboot.

Invoking JNI method from this library, if it was not yet loaded, will not generate an exception when running inside android.uid.system process, as with normal Android app - it will reboot Android.

To prevent that, and find out if the library was already loaded, you can read file /proc/self/maps and search for your library name there. ClassLoader and reflection will not help here - they will show JNI methods as accessible even when the library is not yet loaded.

Note that you cannot do if (Runtime.getRuntime().exec("/system/bin/grep <library-name> /proc/self/maps").waitFor() == 0) - system process is forbidden from launching any external commands by SELinux, you will have to read the file from the Java code.

Another quirk is that the library must be preinstalled to device to the /system/lib directory - if you bundle the library with your app, and install the app to device, library will end up in /data/app/..../lib, and when you will try lo load it from /data partition, well you already guessed - Android will reboot.

like image 37
pelya Avatar answered Oct 22 '22 03:10

pelya