Java cannot open shared object file [duplicate] - java

This exception is arising when I am running my program for smart card reading. My device is not connected. Please help me.

This means it could not load a shared library you need. This could be because.
The library is not in your library path.
The library does not have the right name e.g. LIBRARY must be libLIBRARY.so on Unix
The library is not executable by you.
The library is not for the OS or bit size of your JVM. e.g. a 64-bit JVM will not load a 32-bit library.
Your JRE is not installed correctly and it is failing to load one of its own libraries.
You are using a shared library which needs another shared library you don't have.
The DLL wasn't build as a JNI library or used from JNA.

I got this when using System.loadLibrary which will use the java.libary.path resource.
Since absolute path isn't allowed by loadLibrary, you can use the absolute path and load method.
System.load(HelloWorld.class.getResource("/dlls/HelloWorld.dll")
.getPath());

Related

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 do you use JNA + native libaries with JNLP web launch [on a Mac]?

I am attempting to launch a Java application using JNLP; the app includes a 3rd party library (Lab Streaming Layer) that relies on native libraries loaded with JNA.
As far as I understand, I have followed all of the appropriate steps to make this work:
All of the native libraries are in JAR files, separated by OS and architecture.
All of the native library JAR files are on the server, accessible from the codebase URL.
The JNLP file contains a <resources> element with os and arch specified with a <nativelib> element inside it with the correct href attribute.
The JNLP file is not malformed and launches normally.
When I go to run my application, I get a java.lang.UnsatisifiedLinkError that reports "Unable to load library 'liblsl32.dylib': Can't obtain InputStream for darwin/liblsl32.dylib". This happens after the program has started up, the first time it tries to make use of the library with the native lib dependency. I have corrected this exact error with this library with a separate, non-web-launch application by putting the dylib in the correct place. I have also tried renaming all the dylibs to be jnilibs, per this information: http://permalink.gmane.org/gmane.comp.java.jna.user/3328, but everything happens identically.
It looks like I should be able to specify jna.library.path in the JNLP file, but I have no idea what this would be, if it would change from launch-to-launch, or how I would find out what it should be.
Native.getWebStartLibraryPath(name) should give you what you need to help JNA find the native library.
You can either construct an absolute pathname or just pass the path to NativeLibrary.addSearchPath(libName, path).
EDITED
You'll also need to name your bundled OS X shared library with a .jnilib suffix in order for web start to recognize it as a native library. This is a naming issue peculiar to OS X.
Edit the advice about using libo to get a single library to support multiple architectures (32 & 64bit) simultaneously, but the underlying issue is 1.6 related while I develop & use 1.8.
The root issue is really that OSX uses the extension .jnilib for libraries that it's going load, rather than .dylib. This means that if you're making a native jar, you should make sure that the extension for the library that you want to load is .jnilib rather than .dylib. Once you make a resource jar containing that .jnilib then it will be found by the JNLP classloader; otherwise JNA uses some heuristics to find it.
So, when creating your jar containing the library, you should make sure that it has a .jnilib extension, and is at the root of the .jar, so for example if we're dealing with liblsl32.dylib, we would do something akin to:
ln -fs liblsl32.dylib liblsl32.jnilib
jar cf lsl32.jar liblsl32.jnilib
This lsl32.jar is the resource that we're going to reference in our .jnlp file. We need to sign it; so I do this using the keystore keystore with the password password using the myself identity.
jarsigner -storepass password -keystore keystore lsl32.jar myself
For the resources I had to put the reference into the resource stanza of the jnlp file for Mac:
<resources os="Mac">
<nativelib href="darwin.jar"/>
<nativelib href="lsl32.jar"/>
</resources>
The references to darwin.jar is needed to load the core JNA library, and lsl32.jar is needed to load the liblsl32.jnilib library.
Instance referencing the library using:
Native.loadLibrary("lsl32", MyClass.class);
should successfully load it.
When signing the .jar files, I made sure that all of them have the relevant Codebase/Permissions attributes on-board, in a file called file.manifest. This file contains:
Permissions: all-permissions
Codebase: http://localhost/demo
... making sure that Codebase matches your own codebase, and you update the jar using:
jar cfm lsl32.jar file.manifest
For debug purposes, if you use lsof of the java process that the jnlp is running within, you can determine if it's using the JNLP loaded library or the JNA loaded library by the presence of the file in the list of loaded files, if it's using JNLPs mechanism, then there will be references to liblsl32.jnilib in the list of items, if it's using JNAs mechanism, then there will be no mention of the file as it's extracted to a temporary file.
In the 1.6 VM case, if you're not architecture compatible with the VM, and you're loading via JNA's load-mechanism, you'll get the error:
no matching architecture in universal wrapper
in amongst the noise.
If you're running across multiple modes (32bit/64bit) you could merge both the 32bit and 64bit libraries into one library, and reference that, or you could just install the 64 bit library.
To put the two together, you would do something like:
lipo -create liblsl.jnilib liblsl32.dylib liblsl64.dylib
then reference liblsl, not liblsl32.
I tend to stick with the newer VM, even with all the security issues. gatekeeper prevents me from loading self-signed apps on the 1.6 VM without turning it off, which makes for an unstable testing environment.
The only webstart issues I've ever had with JNA have been caused by the enhanced security of newer JRE versions.
I can't really call this an answer, but I did finally get this working via brute force. I modified the library I am using to request .jnilib (instead of its original .dylib), then created a native library called darwin.jar that contains the following structure:
/META-INF/MANIFEST.MF
/META-INF/INTERAC.DSA
/META-INF/INTERAC.SF
/liblsl32.jnilib
/liblsl32.dylib
/liblsl64.jnilib
/liblsl64.dylib
/darwin/liblsl32.jnilib
/darwin/liblsl32.dylib
/darwin/liblsl64.jnilib
/darwin/liblsl64.dylib
Unclear what about that works, but apparently this combination contains some permutation of things I had not otherwise tried. I am out of time or energy to troubleshoot further and find an exact answer. I suspect the .dylib versions of the files are not needed, since I explicitly changed the code to look for .jnilib, but they are in there for completeness sake.

What does "Native library location" entry do in Eclipse?

If adding user-defined library in Eclipse, one has an ability to set "Native library location". This field allows to enter some directory path.
When does this path plays a part?
Eclipse uses this information to build the java.library.path when it launches a Java program.
Background: Some Java frameworks depend on native code. This code usually comes in the form of a native shared library (*.so, *.dll). In Java, you can see methods with the attribute native. The code will load the shared library using System.loadLibrary().
In order to make the code independent of absolute paths, you just pass the name of the shared library to System.loadLibrary(). The System property java.library.path is then used to determine in which directories the VM should look to locate the file.
Together with Eclipse's feature to define user libraries, you can easily add Java libraries that depend on native code to your projects.
Are you referring to the Java Build Path configuration?
You may need this location if your project uses JNI or JNA. This directory is the location of native code (e.g. a Windows DLL written in C.)
I don't think this information is actually required until you try to run the code. You could provide this information via the Run Configuration for example.

Configuring libmediainfo to work with Java project without installation across all platforms (OSes)

I am using mediainfo (http://mediainfo.sourceforge.net/en) to extract information from audio and video files using Java code.
My java project runs over all platforms (osx, win & linux). So far I have only tested mediainfo over osx where the procedure is simple: just put libmediainfo.dylib in the target folder and access it using a native library and you're good to go. And the solution works flawlessly...
I am now looking to expand this functionality to the other OSs, starting with Linux. However, it is proving to be more of a challenge than I thought.
At first I kept getting this:
"java.lang.UnsatisfiedLinkError: Unable to load library 'mediainfo': libmediainfo.so: cannot open shared object file: No such file or directory"
and this was expected as it was looking in /usr/lib
but this was solved by installing the suitable libmediainfo0 & libzen0 ".deb from http://mediainfo.sourceforge.net/en/Download/Ubuntu
Still, my solution needs to be portable, meaning, I want all necessary resources to be included with the java project package without requiring any further installations.
I also need to know if it's possible to change mediainfo to look for the resources in my java package instead of a system location.
For your reference, I am using Java Native Access (jna) to interact with the library. Also using the MediaInfo.java & MediaInfoLibrary.java classes that the website suggests.
Let me know if you need other details.
any wisdom is highly appreciated
thanks!!
The latest release of JNA (3.5.2) will automatically unpack native libraries bundled as resources (whether file- or jar-based).
If you include you shared library for linux/amd64 as /linux-x86-64/libmylibrary.so in one of your jar files, JNA will extract it and load it automatically when you call Native.loadLibrary("my library"). Older versions of JNA require that you make the library available on LD_LIBRARY_PATH (envariable) or jna.library.path (system property).

How can I Java webstart multiple, dependent, native libraries?

Example: I have two shared objects (same should apply to .dlls). The first shared object is from a third-party library, we'll call it libA.so. I have wrapped some of this with JNI and created my own library, libB.so. Now libB depends on libA.
When webstarting, both libraries are places in some webstart working area. My java code attempts to load libB. At this point the system loader will attempt to load libA which is not in the system library path (java.library.path won't help this). The end result is that libB has an unsatisfied link and cannot be used.
I have tried loading libA before libB, but that still does not work. Seems the OS wants to do that loading for me. Is there any way I can make this work other than statically compiling?
I'm not sure if this would be handled exactly the same way for webstart, but we ran into this situation in a desktop application when dealing with a set of native libraries (dlls in our case).
Loading libA before libB should work, unless one of those libraries has a dependency that is unaccounted for and not in the path. My understanding is that once it gets to a system loadLibrary call (i.e. Java has found the library in its java.library.path and is now telling the OS to load it) - it is completely dependent on the operating system to find any dependent libraries, because at that point it is the operating system that is loading the library for the process, and the OS only knows how to look in the system path. That seems hard to set in the case of a Webstart app, but there is a way around this that does not involve static compiling. You may be able to shuffle where your libraries are - I am unsure
If you use a custom classloader, you can override loadLibrary and findLibrary so that it can locate your libraries from within a jar in your classpath, and if you also make it aware of your native library dependencies (i.e. libB depends on libA depends on libX, then when loading libB you can catch yourself and ensure you load libA first, and in checking that notice and load libX first. Then the OS doesn't try to find a library that isn't in your path. It's klunky and a bit painful, but ensuring Java finds them and loads them all in the correct order can work.
Static compilation proved to be the only way to webstart multiple dependent native libraries.
Are both native libraries packaged into a signed jar which is listed as
<nativelib ...>
In the JNLP file?

Categories