Determine path of native library (dll / so) - java

The System.loadLibrary("Something") will load libSomething.so or Something.dll depending on platform. It will search for it in a list of directories (java.library.path) and will load the first it finds (I think).
I would like to know the full path of the loaded .so / .dll. There is ClassLoader.findLibrary(String libname) which does exactly what I want, but it is protected.
A workaround option could be to use System.mapLibraryName(String) to make platform specific file name from the library name and then to split and iterate through the java.library.path system property. I suppose it would give the same result as ClassLoader.finLibrary for most cases, but would it for all cases?
Is there any best practice for this task?

Related

Java, Load native library inside classpath

I have the following distribution
.__bin
| |__start.sh
|
|__lib
|__Main.jar
|__Utility.jar
|__lib.so
Main.jar contains main method, in which I would like to access native functions provided by the lib.so bundled in the distribution. start.sh simply sets the classpath and bootstraps java.
What is the best approach to load the lib.so library inside the application? I am aware of two methods:
System.load(absolute path)
System.loadLibrary(name)
Former requires the absolute path of the library in the file system, latter requires setting the application specific java.library.path JVM argument. Which is better solution in this case? Would setting the library path in the start.sh script possibly break something? How could I get the absolute file system path of the library for the former solution?
Assuming I am not missing anything, isn't setting System.load the best approach? Your lib.so is not going to change since you have it in your structure. If you would want to give control to the end user to load the native/shared library from elsewhere have an optional parameter in start.sh. Else use the System.load().Just make sure to check the type of OS, since you will be having the different formats for file paths.
The load() method requires the complete path name of the library as an argument. For example, on a Solaris system you might write:
System.load("/home/me/libs/libmylib.so");
to load the libmylib.so library in the /home/me/libs directory.
Using the load() method is system-dependent because it uses a pathname to load the library and pathnames are usually system-dependent. Thus, loadLibrary() is sometimes a better choice. However, dynamically loadable libraries are system-dependent in nature so the use of load() may not compromise system-independence any more than the act of loading the library itself.
The loadLibrary() method requires just the name of a to load:
System.loadLibrary("mylib");
The loadLibrary() method searches for the library. The search performed by loadLibrary() depends on the system you are running on, but typically, it searches the directories listed in one of your environment variables set up to that purpose.
You can explicitly specify your absolute path.
Apart from system independence, there are no real differences security wise.
References :
1) https://security.stackexchange.com/questions/35724/security-implications-of-javas-system-load-vs-system-loadlibrary
2) https://www.chilkatsoft.com/java-loadLibrary-Linux.asp

JNA can't find shared library on Mac OS

I am writing an interface in Java which uses underneath library in "C".
Now, when I try to load the library specifying relative path, it cannot find the library.
If I give the absolute path, it works fine.
I want to know, is there something to do with relative and absolute path on MAc OS. Because same code works well on linux(even though I specify relative path on that).
Please Help.
Defining the system property jna.debug_load (pass -Djna.debug_load=true to your JVM) will result in console output indicating where JNA is looking for your native library.
Keep in mind you need to define jna.library.path to be the directory where JNA can find your library. That value should be an absolute path. If you're using something like myapp/libs then your operation is going to be dependent on whatever the process's current directory is set to.

How to use a JNI lib, with associated libs, at an arbitrary location?

We have an app that sometimes is installed with an associated app. Both may be installed separately, at different times, and neither is usually in the OS Path environment setting.
IF both apps are installed, the one I'm working on needs to use a JNI library from the other app. This library uses a dozen or so other native libs. While I can FIND the JNI lib, I can't seem to find a way to use it without requiring the user to change their system setup.
I've found the (hacky) technique to add the JNI lib to the java.library.path, I've been unable to find any way of updating the native Path so the JNI lib can find it's associated libs.
The only things that have worked so far are to:
Add the folder that the JNI and associated files are in to the OS path before launching our app.
Launch our app so the Current Working Directory is the JNI lib folder.
Neither of which makes for a hassle-free user experience.
So, is there any way for a Java app to modify it's own environment Path so the JNI lib can find it's associated native libs? (currently testing on Win7, will also need to support OS/X)
This can not be done with an unknown location at run time. According to jni documentation
"To load your shared native library module in Java, simply use Java's System.loadLibrary method in a Java class:"
as well as
"Another common reason for the native library not loading is because it is not in your path. On Windows make sure the path environment variable contains the path to the native library. On Unix make sure that your LD_LIBRARY_PATH contains the path to the native library. Adding paths to LD_LIBRARY_PATH can slow down other programs on your system so you may want to consider alternative approaches. For example you could recompile your native library with extra path information using -rpath if you're using GNU, see the GNU linker documentation (ld man page). You could use a command such as ldconfig (Linux) or crle (Solaris) to add additional search paths to the default system configuration (this requires root access and you will need to read the man pages)."
So thus you need to know the location and must be in a path to be able to load the file. If the location is not known it can not be done due to how jni works and the jvm works.
One way to load a JNI lib with dependent libraries is to load each of the dependents then load the JNI library.
For example, if bar.so is dependent on foo.so and both libraries exist in /some/dir, do the following:
System.load("/some/dir/foo.so");
System.load("/some/dir/bar.so");
Use System.load() instead of System.loadLibrary() so you can specify the absolute path to the library.
You'll have to load all dependents of all loaded libraries unless they can be found in the java.library.path path.
Hope this helps.

How to unzip a library to a temporary directory, load it and all of its dependencies from that directory

Essentially I want to zip up collection of shared objects in a jar file, unzip them to a temporary directory at runtime, and load from there. Say for example I have the libraries:
libApp.so
libBasicPlugin.so => libApp.so
libPlugin1.so => libApp.so, libBasicPlugin.so, libPlugin2.so
libPlugin2.so => libApp.so, libBasicPlugin.so
Java unzips them to an arbitrary, unique temporary directory $USER_HOME/.my-app/2011_12_05_001/, and then loads libApp.so, which in turn uses dlopen to load libPlugin1 and libPlugin2 (libBasicPlugin isn't explicitly loaded). The problem is that libPlugin1 doesn't know where to find libBasicPlugin and libPlugin2.
Here are the various solutions I have tried/considered:
Putting the libraries in a known location and setting LD_LIBRARY_PATH in a sh file before invoking Java. This works but precludes packaging the libraries in a jar
Using Java's System.load to "preload" the dependencies. This is the approach I've seen suggested, but only seems to work if you know a priori what plugins are going to be loaded and know their dependencies. Unless you iterated over all the files in a directory, loading them until you stop getting UnsatisfiedLinkExceptions...
Somehow tell the shared object that its dependencies will be in the same directory (via DT_RPATH?). This is what I think I would like in an ideal world, but it seems the best you can do is set the library location relative to the executable, which in this case is /usr/lib/jvm/.../java.
Statically link each library with its dependencies. I'm worried this would result in two copies of libPlugin2 (a dynamic one and a static one) which has caused all sorts of problems for us in the past.
On Windows, calling SetDllDirectory before loading the plugins solves this nicely. Are there any solutions I am overlooking/misunderstanding? Am I going about this entirely the wrong way?
You could set the LD_LIBRARY_PATH env var from within the Java process itself.

Eclipse: find resource on classpath

Is there a way in eclipse to search the classpath for arbitrary resource file names (or patterns)?
I know I can use either
Navigate > Open Type
(which will scan the classpath for classes) or
Navigate > Open Resource,
which will search for any resource type, but only in my project folders. Is there any way to achieve a combination ob both, to do a resource search (something like *.xsd) that searches all jars on the classpath?
The classpath helper plugin is at least a starting point. Looks like it doesn't provide a search but it seems to list all entries on the classpath.
I don't know if your fit and willing to modify it but it should provide the basic code to add some filename-based search on top.
Which Version are you using?
Because when I open the search-menu (Java-Search), I could choose, which space should be searched, whether the hole workspace or including all JRE-Libraries. Think, it should work for you.

Categories