UnsatisfiedLinkError for JNI library - java

I have the following Java class that invokes a native library on Linux (/usr/local/lib/libCAPJni.so):
public class MyClass {
private native float runCAP(String name, int[] data);
private static final String LD_LIBRARY_PATH = "/usr/local/lib";
static {
System.setProperty("java.library.path", LD_LIBRARY_PATH);
System.loadLibrary("CAPJni");
}
...
}
The native library libCAPJni.so is located in /usr/local/lib. I also set this lib path in my Eclipse's Build Path -> Native library location. However when I launched my application in Eclipse, I got the following error:
java.lang.UnsatisfiedLinkError: no CAPJni in java.library.path
This seems to be caused by that the native lib is not found in /usr/local/lib directory. But if I directly run the following in command line:
java -Djava.library.path=/usr/local/lib MyClass
It runs fine without any problem. Why can't my Tomcat web application find the native library?

Specifying the native library path in Eclipse should definitely work.
However, it does NOT work to specify the library path at runtime with setting the system property. The library path must be known and set when booting the jvm.
I haven't worked with tomcat yet but as you mentioned it, make sure that tomcat starts with this parameter as well which might be your problem here.
EDIT:
As stated here it might actually be possible to change the library path later on. But as this is a hack and messes with the classloader it is most likely not a good idea to use that in the tomcat environment.

Related

java.lang.UnsatisfiedLinkError: com.example.program.ClassName.foo()L

I can't run methods of a library.
My library is in my PATH and also getting loaded without errors by following code:
System.loadLibrary("FTDIInterface");
But the functions are not working.
I get the following exception:
Caused by: java.lang.UnsatisfiedLinkError: Messgeraet.src.net.sf.yad2xx.FTDIInterface.getDevices()[LMessgeraet/src/net/sf/yad2xx/Device;
at Messgeraet.src.net.sf.yad2xx.FTDIInterface.getDevices(Native Method)
at Messgeraet.src.Emu.EmuConnection.<init>(EmuConnection.java:22)
at Messgeraet.src.Emu.EmuModel.connect(EmuModel.java:27)
at Messgeraet.src.JavaFX.FXController.connect(FXController.java:112)
... 62 more
I am using eclipse. In IntelliJ it is working fine and I also got another eclipse project that includes the library without any problems.
Why it can't run my method FTDIInterface.getDevices?
Your package seems off; Messgereat.src sounds like you have a project dir named Messgereat, within you have a folder named 'src' with your java sources, and you've misconfigured your build tooling; the right package name sounds like it should be: package net.sf.yad2xx;, but due to a misconfigured build it wasn't working and you decided to fix the problem by updating your package statements, but that broke your JNI bindings.
The solution would then be to undo all the changes you've made to your package statements, and fix your build script instead.
Alternatively, if you really do intend to use that bizarre package, then make sure you have executed javah with the exact same build setup and use that as a basis for your JNI code. If you've done that, include the exported symbols in the library as the comment by #user2543253 suggested.
NB: It's a bit odd that your loadLibrary call works at all; PATH has nothing to do with it, but presuambly then your library so happens to be located in a place that is listed on your librarypath, which is the system property (of the VM, not of your OS) named 'java.library.path'; you set it with e.g.:
java -Djava.library.path=/path1:/path2 -cp /path/to/dep1.jar:/path/to/dep2.jar com.foo.Main
because of this confusion it is also possible that some different native lib file also named FTDIInterface is being loaded instead of the one you think is being loaded. If you want to be certain of what is being loaded, run System.load("/absolute/path/to/the/dll-jnilib-or-so-libraryfile.so"); - then you know for sure.

JNI - Specify the own executable as source for native methods

I have started a Java VM with JNI_CreateJavaVM. I want my java classes to be able to use native methods exported from the executable that started JNI_CreateJavaVM.
All around google results, people tell you to use System.loadLibrary to specify what library to import native methods from. However, doing
public class someclass
{
static { System.loadLibrary("myExeName.exe"); }
}
will fail FindClass with
java.lang.UnsatisfiedLinkError: no myExeName. in java.library.path
(I added -Djava.library.path=. as a JavaVMOption)
It seems Java cuts off the extension, which is a bummer as win32 LoadLibrary("myExeName.exe"); works when having the extension. (But it might bite me when I try to port to another OS)
Anyway, my question is if there are other/better ways specify which module to import the natives from.
P.S I am aware there is RegisterNatives, but I'm hoping there to be a more automatic way.
You can give the full path of your executable (not hard to guess on any OS) into System.load() function, but RegisterNatives is not too much code to write.

"Unable to load library: JNA native support not found in resource path" on trying to load JNA library on Mac OS X

I have a JNA library stub like this:
public interface FREngine extends Library {
NativeLibrary JNA_NATIVE_LIB = NativeLibrary.getInstance("FREngine");
FREngine INSTANCE = (FREngine) Native.loadLibrary("FREngine", FREngine.class);
}
If I try to use this library in any way, I get a really confusing error:
java.lang.UnsatisfiedLinkError: Unable to load library 'FREngine':
JNA native support (darwin/libFREngine.jnilib) not found in resource path
(...entire classpath here...)
Why this is confusing to me:
.jnilib is the file extension for JNI libraries. Since I'm using JNA, I wouldn't expect JNA to be using any JNI library other than its own one, "jnidispatch".
JNA is looking on the classpath for this file, but there is no way in hell it will be there because it's just some random library I'm trying to import. Shouldn't it be looking on DYLD_FRAMEWORK_PATH?
Other native libraries which are initialised in exactly the same way work fine. For instance, CoreFoundation can be resolved. Its code for loading the library is the same aside from the name of the library being different.
I tried looking at the frameworks themselves and can only see minor differences:
FREngine.framework is in /Library, CoreFoundation.framework is in /System/Library
FREngine.framework/Versions contains a directory with a longer and more complex name than CoreFoundation.framework, which only has one version called A.
FREngine.framework/Versions/[ver] contains Headers and Libraries
The version of JNA in use is 3.5.2. We can't upgrade to 4.x because there is some other bug which causes an exception as soon as we try to load our native library.
The reason why FREngine library does not work in this case in a wrong Engine load method. FREngine is expected to be loaded via com.abbyy.FREngine only.

UnsatisfiedLinkError: The library loads but I still get a link error

I have two Eclipse plugins:
plugin-1: provides a package in .jar to other plugins. (a Java Wrapper for a C++ library) This plugin was created by clicking File->New->Other->Plug-in from Existing JAR Archives.
plugin-2: has the native library .so for plugin-1 (Bundle-NativeCode directive is in MANIFEST.MF) and instantiates a class from plugin-1
(I actually tried putting the .so in plugin-1, but I cannot seem to load the library, even with the Bundle-NativeCode directive in the plugin-1 MANIFEST.MF, outside of the plugin project that contains the .so, so I guess I have to bundle the .so with any plugin that uses plugin-1.)
I am running a JUnit tests from plugin-2 which instantiates MyClass from plugin-2 which, in turn, instantiates MyLibraryClass from plugin-1. MyClass successfully loads the native library and instantiates MyLibraryClass without an UnsatisfiedLinkError or other exception being thrown from either the loading of the native library or from instantiating MyLibraryClass. I am not running a plugin in this case -- just the JUnit tests.
When I run plugin-2 (using a product configuration) and instantiate MyClass, the native library loads fine but I get an UnsatisifiedLinkError when MyClass instantiates MyLibraryClass. In this case, I believe the library is being loaded based on the output I get from using the class described in the posting How do I get a list of JNI libraries which are loaded?
NOTE: I'm using Eclipse 3.6.1.
Here is a code sample that shows the essence of what I'm trying to do:
package com.mylibrary;
import com.external_library.MyLibraryClass;
public class MyClass {
public static void loadLibrary() {
// Without Bundle-NativeCode in MANIFEST.MF I get
// "java.lang.UnsatisfiedLinkError: no mylibrary_java in java.library.path"
System.loadLibrary("mylibrary_java"); // Loads libmylibrary_java.so.
// Works fine from JUnit Test
// When I run the plugin, I get an UnsatisfiedLinkError:
// "java.lang.UnsatisfiedLinkError:
// com.external_library.MyLibrary_javaJNI.new_MyLibraryClass__SWIG_3()J"
MyLibraryClass instance = new MyLibraryClass();
}
}
I have replicated your setup and I get the same exception.
The problem could be solved by:
add the native library to plugin-1
add the Bundle-NativeCode directive to plugin-1's Manifest
load the library in the static constructor of plugins-1's Activator (you can write one and add it to the plugin)
Some other possible sources of errors:
Be aware that the package path, the class name and the method signatures should never be changed for any class with native bindings. Otherwise JNI would not be able to find the native counterpart and you get an UnsatisfiedLinkError. In your import directive you specified the following classname com.external_library.MyLibraryClass, but your error message has a different classname com.external_library.MyLibrary_javaJNI. Check for these sources of errors.
Some additional explanations:
A JUnit test in contrast to an JUnit plugin test starts no OSGi environment. Therefore you have a plain Java application with an ordinary JUnit test. If your native lib and your application are contained in the same folder (top level) the native lib will be automatically found on windows. If that is also true on UNIX systems, this would be an explanation why your JUnit test is successful. If it lies in a different folder, you have to specify the Java Library Path for an ordinary Java application.
EDIT by MrMas:
Modify plugin-2 so it doesn't depend on plugin-1 by adding the .jar file to plugin-2.
Copy the .jar file into plugin-2. I put it in the same directory as the .so.
Add the jar to the project via: Project->Properties->Libraries->Add Jar
Add the jar to the class path via plugin.xml->Runtime->ClassPath section->Add
Export the packages from the Jar (if they're needed by downstream plugins)
Remove the dependence of plugin-1 from the plugin.xml->dependencies tab
Now you can load the library with a System.loadLibrary and use the classes from within the plugin and from another plugin.
I chose not to modify plugin-1 because it was created as a plugin from an existing jar to which I couldn't discover how to add an Activator. I instead chose the path of adding the .jar to plugin-2. See Adding jars to a Eclipse PlugIn for additional discussion.
Bundle-NativeCode is an OSGI-tag. This means only OSGI classloaders are using it. In my case, I had an E4-RCP application. One plugin contained the Java class. The native code, however, I put into a fragment.
When loading and looking for a library, the OSGI classloader has a list of fragments (according to the naming of the structure involved) and examines their Bundle-NativeCode using the class NativeCodeFinder. If one has troubles, try to add breakpoints at the relevant functions. getNativePath() returns the entries as read by the OSGIpart.

Loading DLL in Java - Eclipse - JNI

I am trying to load a dll in java using the following code
System.loadLibrary("mydll");
The project is placed in D:\development\project\ and i have placed the dll on D:. I then gave following VM argument in eclipse configuration
-Djava.library.path=D:/
But when i run i get UnsatisifiedLinkerError. After googling a bit, I used
System.load("D:\mydll.dll");
but again getting the same problem, could someone can help?
Where you specify the DLL filename in the library path, omit that. Additionally, your System.loadLibrary call should just be 'mydll'. I can tell you (from experience) that if you put the DLL in the root of your project in Eclipse (i.e., D:\Eclipse Workspace\Proj), it should work. Any further linker errors could be from dependency problems with finding other DLLs. The exception is the same. Use something like Dependency Walker (http://www.dependencywalker.com/) to see if your DLL relies on anything else not on the system library path.
Edit: UnsatisfiedLinkError: Thrown if the Java Virtual Machine cannot find an appropriate native-language definition of a method declared native -- it seems like you are using a JNI function which does not exist.
One problem you have is:
System.load("D:\mydll.dll");
should be
System.load("D:\\mydll.dll");
or
System.load("D:/mydll.dll");
I have had more success with System.load, but loadlibrary is better designed for multiplatform.
It figures out the extension for you.
Check out how to properly set up the native dependencies here. Additionally, make sure you use the correct JVM: in my case, the DLL was not found because it was a 32 bit DLL, but I used the x64 JVM!
Using System.loadLibrary("mydll") works fine, you can also use that one. If you used javah and you think with your DLL everything is fine, there are two possibilies:
The JVM does not find your DLL: In this case, your java library path is not correct (which I doubt) and you should probably set it to . and place your DLL in the current working dir.
The JVM does not find a DLL your DLL depends on: If you have any dependent libraries in your DLL, they are NOT searched by the JVM, but by Windows itself. And Windows does not know the java.library.path, so it will look in the system PATH variable for those. If you have the possibility, you can set the system PATH variable to the location of your DLLs before starting the JVM and everything will be fine. Or you can load all your DLLs using the JVM like this
System.loadLibrary("dll_1");
System.loadLibrary("dll_2");
System.loadLibrary("dll_3");
where dll_3.dll depends on dll_2.dll, which depends on dll_1.dll.
Hope that helps.
System.loadLibrary loads the DLL from the JVM path (JDK bin path).
If you want to load an explicit file with a path, use System.load()
See also: Difference between System.load() and System.loadLibrary in Java
public class MyClass
{
static
{
System.load("MyJNI.dll");
}
}
Put your Almafa.dll into the C:/Java/jre7/lib or /bin sorry, I can`t remember exactly. After you have done no more configuration needed, just say
static{
System.LoadLibrary("Almafa");
}
in the class, where you want to load it. It is works only in Java project, in Android like project you need to use JNI. I had posted now the result of 3 days no sleeping :)
I got my error resolved by using the following:
static {
try {
System.loadLibrary("myDLL");
} catch (Exception e) {
e.printStackTrace();
}
}
Instead of using System.load("myDLL.dll")
#alee- You can just copy and the paste the dll files in system32 folder of your windows and try to call the library through the System.loadLibrary("mydll")... i guess it may work...
Give the library path in your project as native library location,seems to be solved.

Categories