JNI Unable to load native library - java

I'm using JNI as mean to connect my java code and C code.
The code compiles fine and the screen GUI application opens and then closes which means that there is nothing wrong with that part of the code which is pure C.
However when I run the program the output console immediately tells me:
Error occurred during initialization of VM
Unable to load native library: Can't find dependent libraries
and returns 1 as error code. I got the jvm.dll in the same folder of the exe and I think JDK PATH is correctly set up. I have no clue for what the problem may be.
I searched for the error but couldn't fix it.

That error means that the Java VM is finding and attempting to load your .dll, but additional .dlls that your .dll depends on cannot be found. One option is to make sure that those extra dependencies are in the PATH, but that can be tricky because it depends on setting up environment variables during installation, setting them at runtime, or placing additional .dlls into the same folder.
Another way to fix it is to use the -static linker flag when linking your .dll (note that this is not mutually exclusive with the -shared option, which tells the linker to package your code into a .dll). This means that the additional dependencies will be statically linked into your .dll, instead of needing to be located at runtime.

Related

tomcat on ubuntu jnetpcap native library *.so unable to load [duplicate]

How can I load a custom dll file in my web application? I've tried the following:
Copied all required dlls in system32 folder and tried to load one of them in Servlet constructor System.loadLibrary
Copied required dlls into tomcat_home/shared/lib and tomcat_home/common/lib
All these dlls are in WEB-INF/lib of the web-application
In order for System.loadLibrary() to work, the library (on Windows, a DLL) must be in a directory somewhere on your PATH or on a path listed in the java.library.path system property (so you can launch Java like java -Djava.library.path=/path/to/dir).
Additionally, for loadLibrary(), you specify the base name of the library, without the .dll at the end. So, for /path/to/something.dll, you would just use System.loadLibrary("something").
You also need to look at the exact UnsatisfiedLinkError that you are getting. If it says something like:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no foo in java.library.path
then it can't find the foo library (foo.dll) in your PATH or java.library.path. If it says something like:
Exception in thread "main" java.lang.UnsatisfiedLinkError: com.example.program.ClassName.foo()V
then something is wrong with the library itself in the sense that Java is not able to map a native Java function in your application to its actual native counterpart.
To start with, I would put some logging around your System.loadLibrary() call to see if that executes properly. If it throws an exception or is not in a code path that is actually executed, then you will always get the latter type of UnsatisfiedLinkError explained above.
As a sidenote, most people put their loadLibrary() calls into a static initializer block in the class with the native methods, to ensure that it is always executed exactly once:
class Foo {
static {
System.loadLibrary('foo');
}
public Foo() {
}
}
Changing 'java.library.path' variable at runtime is not enough because it is read only once by JVM. You have to reset it like:
System.setProperty("java.library.path", path);
//set sys_paths to null
final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
sysPathsField.setAccessible(true);
sysPathsField.set(null, null);
Please, take a loot at: Changing Java Library Path at Runtime.
The original answer by Adam Batkin will lead you to a solution, but if you redeploy your webapp (without restarting your web container), you should run into the following error:
java.lang.UnsatisfiedLinkError: Native Library "foo" already loaded in another classloader
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1715)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1646)
at java.lang.Runtime.load0(Runtime.java:787)
at java.lang.System.load(System.java:1022)
This happens because the ClassLoader that originally loaded your DLL still references this DLL. However, your webapp is now running with a new ClassLoader, and because the same JVM is running and a JVM won't allow 2 references to the same DLL, you can't reload it. Thus, your webapp can't access the existing DLL and can't load a new one. So.... you're stuck.
Tomcat's ClassLoader documentation outlines why your reloaded webapp runs in a new isolated ClassLoader and how you can work around this limitation (at a very high level).
The solution is to extend Adam Batkin's solution a little:
package awesome;
public class Foo {
static {
System.loadLibrary('foo');
}
// required to work with JDK 6 and JDK 7
public static void main(String[] args) {
}
}
Then placing a jar containing JUST this compiled class into the TOMCAT_HOME/lib folder.
Now, within your webapp, you just have to force Tomcat to reference this class, which can be done as simply as this:
Class.forName("awesome.Foo");
Now your DLL should be loaded in the common classloader, and can be referenced from your webapp even after being redeployed.
Make sense?
A working reference copy can be found on google code, static-dll-bootstrapper .
You can use System.load() to provide an absolute path which is what you want, rather than a file in the standard library folder for the respective OS.
If you want native applications that already exist, use System.loadLibrary(String filename). If you want to provide your own you're probably better with load().
You should also be able to use loadLibrary with the java.library.path set correctly. See ClassLoader.java for implementation source showing both paths being checked (OpenJDK)
In the case where the problem is that System.loadLibrary cannot find the DLL in question, one common misconception (reinforced by Java's error message) is that the system property java.library.path is the answer. If you set the system property java.library.path to the directory where your DLL is located, then System.loadLibrary will indeed find your DLL. However, if your DLL in turn depends on other DLLs, as is often the case, then java.library.path cannot help, because the loading of the dependent DLLs is managed entirely by the operating system, which knows nothing of java.library.path. Thus, it is almost always better to bypass java.library.path and simply add your DLL's directory to LD_LIBRARY_PATH (Linux), DYLD_LIBRARY_PATH (MacOS), or Path (Windows) prior to starting the JVM.
(Note: I am using the term "DLL" in the generic sense of DLL or shared library.)
If you need to load a file that's relative to some directory where you already are (like in the current directory), here's an easy solution:
File f;
if (System.getProperty("sun.arch.data.model").equals("32")) {
// 32-bit JVM
f = new File("mylibfile32.so");
} else {
// 64-bit JVM
f = new File("mylibfile64.so");
}
System.load(f.getAbsolutePath());
For those who are looking for java.lang.UnsatisfiedLinkError: no pdf_java in java.library.path
I was facing same exception; I tried everything and important things to make it work are:
Correct version of pdf lib.jar ( In my case it was wrong version jar kept in server runtime )
Make a folder and keep the pdflib jar in it and add the folder in your PATH variable
It worked with tomcat 6.
If you believe that you added a path of native lib to %PATH%, try testing with:
System.out.println(System.getProperty("java.library.path"))
It should show you actually if your dll is on %PATH%
Restart the IDE Idea, which appeared to work for me after I setup the env variable by adding it to the %PATH%
The issue for me was naming:
The library name should begin with "lib..." such as libnative.dll.
So you might think you need to load "libnative": System.loadLibrary("libnative")
But you actually need to load "native": System.loadLibrary("native")
Poor me ! spent a whole day behind this.Writing it down here if any body replicates this issue.
I was trying to load as Adam suggested but then got caught with AMD64 vs IA 32 exception.If in any case after working as per Adam's(no doubt the best pick) walkthrough,try to have a 64 bit version of latest jre.Make sure your JRE AND JDK are 64 bit and you have correctly added it to your classpath.
My working example goes here:unstatisfied link error
I'm using Mac OS X Yosemite and Netbeans 8.02, I got the same error and the simple solution I have found is like above, this is useful when you need to include native library in the project. So do the next for Netbeans:
1.- Right click on the Project
2.- Properties
3.- Click on RUN
4.- VM Options: java -Djava.library.path="your_path"
5.- for example in my case: java -Djava.library.path=</Users/Lexynux/NetBeansProjects/NAO/libs>
6.- Ok
I hope it could be useful for someone.
The link where I found the solution is here:
java.library.path – What is it and how to use
It is simple just write java -XshowSettings:properties on your command line in windows and then paste all the files in the path shown by the java.library.path.
I had the same problem and the error was due to a rename of the dll.
It could happen that the library name is also written somewhere inside the dll.
When I put back its original name I was able to load using System.loadLibrary
First, you'll want to ensure the directory to your native library is on the java.library.path. See how to do that here. Then, you can call System.loadLibrary(nativeLibraryNameWithoutExtension) - making sure to not include the file extension in the name of your library.

UnsatisfiedLinkError, but library is in path

I'm a little confused by this error. I'm new to Java and the error seems pretty self explanatory, but I've checked my paths (even defined my own) and it still fails to find this library. Is there something I'm doing wrong? See directory screenshot and error screenshot below:
UPDATE
UPDATE 2
If I create a new NetBeans project this works fine. Same code and everything. If I create new IntelliJ project I get this error above. I must be missing something in IntelliJ
UPDATE 3
Found the solution. Adding dependencies is a bit different in IntelliJ. Thanks all for the help.
http://www.jetbrains.com/idea/webhelp/configuring-module-dependencies-and-libraries.html
Obidisc4j is a .jar file. You just dont see its extension in the explorer.
Regular jar files are not loaded by System.loadLibrary. They are automatically loaded by the JVM's classLoader.
You are using a native library. It doen't matter if that library is in the classpath. There are 4 ways you can make the Java runtime load your shared library at runtime:
Call System.load to load the .so from an explicitly specified absolute path.
Copy the shared library to one of the paths already listed in java.library.path
Modify the LD_LIBRARY_PATH environment variable to include the directory where the shared library is located.
Specify the java.library.path on the command line by using the -D option.
Seems like your application is trying to find out a obidisc4j.dll (for Windows) or obidisc4j.so (for Linux). The file must be present on the PATH (but not the classpath). If you are not sure what PATH is your Java application searching in, you can write the following statement, before the point where the exception takes place, to find out the PATH.
System.out.println(System.getProperty("java.library.path"));
This will tell you about the paths where your DLL or SO file should be placed. You just need to place the file in ONE of those N-paths.

Java not able to load library in Eclipse project

I'm trying to load a .dll into my java/c++ project in eclipse. I've created the .dll in order for my Java project to use it with the JNI, but when I try to load the library, I get this message: "java.lang.UnsatisfiedLinkError: no hpaprogram in java.library.path". My main class is located in a different directory than the dll, but I used the flag -Djava.library.path=jni in VM Arguments. I have no idea what could be going wrong, and I've been debugging this for hours.
Here's my git repo: https://github.com/zalbhathena/Thesis-Test-Application
Also I'm using OS X if that matters.
EDIT: Here's a post I found. it states that I need a jnilib, not a dll. I've made the changes yet I still get the same error. I'm doing exactly what he is but in eclipse, so I'm not sure what's wrong.
Check if this helps:
How to set the java.library.path from Eclipse
Also, maybe we can try this another way, if not already tried.
a) Create your java class having the native methods defined.
b) Use javah to generate the required header and c files (http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javah.html).
c) Put in your code in the C file generated and use gcc to create a library of the same.

running from console is ok, from Eclipse error

I'm going crazzy with Eclipse. I writing simple test class which uses external jar. which uses native library .dll
When I Running from Eclipse, command Run.
Here my stack trace:
Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\Program Files\YAZ\bin\yaz4j.dll: The specified procedure could not be found
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary1(ClassLoader.java:1939)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1864)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1854)
at java.lang.Runtime.loadLibrary0(Runtime.java:845)
at java.lang.System.loadLibrary(System.java:1084)
at org.yaz4j.Connection.<clinit>(Connection.java:56)
at ru.Test.testConnection(Test.java:20)
at ru.Test.main(Test.java:15)
But when I run this code from console like this
java -cp "bin;C:\Program Files\YAZ\java\yaz4j.jar" ru.Test
Everything works perfect!
It's the same code. How is it works in console and not works in Eclipse?
here how I plugin this referenced jar to my project in Eclipse:
The messages you get when native methods fail to link are dreadful. I can think of several root causes that might give this message:
The DLL isn't loading some other dependent DLL when loaded from Eclipse. This is governed by the Windows PATH environment variable, which could be different when you're running in Eclipse.
It's a 32-bit DLL, and you're running with a 64-bit JVM under Eclipse, but 32-bit from the command line (or vice versa.)
I have been struggling with exactly the same problem for some days now trying to use the YAZ toolkit in my project. The thing was that native libraries get loaded correctly on various test computers, but not on my personal PC.
In short: the cause of the problem is that the JVM loads the incorrect libxml2.dll and libxslt.dll dependent libraries.
When I launch the JVM from the IDE, it starts looking in the following places for the native libraries:
(jdk_home_dir)\jre\bin. Somehow this step is skipped on all other test computers when loading dependent libraries (other than the main yaz4j.dll). This way the test computers don't load the wrong dll's.
(jdk_home_dir)\bin
if you set the -Djava.library.path parameter, it will look in that dir at this step
%SystemRoot%\system32
%SystemRoot%
The working directory set for the project, if any. This step is skipped on my personal PC, for unknown reasons, but works on all other test computers.
the %path%
I have figured out this by using Process Monitor. Note that steps 1 and 2 may be interchanged.
The YAZ toolkit main DLL named yaz4j.dll makes secondary calls to other dll's in the toolkit: libxml2.dll and libxslt.dll (among others).
My JVM finds them in the (jdk_home)\jre\bin directory. They seem to be bundled with Java and they are obviously different from the ones in the YAZ toolkit.
That means that procedures that are being called by yaz4j.dll could not be found in those dll's. This way the UnsatisfiedLinkException is thrown.
My JVM seems to be always searching firstly for native libraries in (jdk_home)\jre\bin regardless of the environment %path% variable or the -Djava.library.path switch.
Replacing the dll's in that dir may break some JVM native functionality so I wouldn't recommend that.
So the last step that needs to be done is to figure out how to make the JVM load the correct libxml2.dll and libxslt.dll libraries.
Recompiling yaz4.dll to make it point to renamed libxml2.dll and libxslt.dll might be a potential solution.
I had same problem, you need to have JDK not JRE build path library

Matlab Compiler MCC errors on imports for Java classes from dynamic Java classpath

How can I get mcc to recognize imports from user-provided Java libraries, or to simply ignore unresolvable imports?
I have a Matlab codebase that I'm building with the Matlab Compiler, but the build is breaking because mcc is erroring out when it encounters import statements for Java classes that were in JARs on Matlab's dynamic classpath. I am including all the JAR files on the classpath with the mcc -a option. The code works in the IDE, and I think it will work in the deployed app, if it will only allow me to build. (Works under R2009b, which ignores these imports in non-MCOS classes.)
Here's a simple repro. This file is in the same dir as guava-11.0.1.jar from Google Guava.
%file hello_world_with_import.m
function hello_world_with_import
import com.google.common.base.Stopwatch;
disp('Hello, world!');
end
Running it in Matlab works fine. But building it fails. (The javaaddpath here is not strictly necessary in the example, because bad imports by themselves are not an error in plain Matlab. Just showing how it works in practice, and how I wish mcc picked up on it.)
>> javaaddpath('guava-11.0.1.jar');
>> hello_world_with_import()
Hello, world!
>> mcc -m -a guava-11.0.1.jar hello_world_with_import
Error: File: C:\Temp\import_test\hello_world_with_import.m Line: 3 Column: 8
Arguments to IMPORT must either end with ".*"
or else specify a fully qualified class name: "com.google.common.base.Stopwatch" fails this test.
Unable to determine function name or input/output argument count for function
in MATLAB file "hello_world_with_import".
Please use MLINT to determine if this file contains errors.
Error using mcc
Error executing mcc, return status = 1 (0x1).
This is in Matlab R2011b on Windows.
Some background on my environment. My app has about 40 JARs on the dynamic classpath which are a mix of third party libraries and our own Java code. It's deployed to 50+ users on a mix of single-user and multi-user Windows machines. And there are other groups that may be deploying other MCR apps to the same users and machines. On any machine, different MCR apps may be run concurrently by the same or different users. We do weekly releases, and (mostly due to changes in our own Java code) at least one JAR file changes about every other release. I need a mechanism that will work in this environment.
Any suggestions? Anybody know a good way to get mcc to add stuff to its java classpath in the compilation step, or just ignore bogus imports? My fallback plan is to go through the codebase and remove all the imports for Java classes, which is kind of a pain.
UPDATE 12/2/2012: I heard from MathWorks that this is fixed in Matlab R2012b. (But I'm no longer using Matlab so can't personally verify it.)
UPDATE 12/09/2014: I'm using Matlab again (R2014b), and the Matlab Compiler now includes JARs that are on the dynamic classpath in the compiled program's dynamic classpath. It doesn't seem to automatically include the JAR files in the archive, though; you must manually include them using an mcc command line switch, or adding them as "additional included files" in the Matlab Compiler app.
The code executing in the MATLAB IDE works because the guava jar file has been added to the "dynamic" classpath via the javaaddpath method. However, when you use MCC to invoke the MATLAB Compiler, it does not rely on the dynamic java classpath, but the "static" java classpath which is defined in:
$MATLABROOT/toolbox/local/classpath.txt
If you add an entry for your JAR file here, then MCC will be able to resolve the IMPORT line in your M-File.
So to test this, I downloaded the guava jar file and tried the steps above. Works like a charm.
Also, If you read the "Troubleshooting" section for the MATLAB Compiler, this exact situation is documented:
http://www.mathworks.com/help/toolbox/compiler/brtm1xm-8.html
Quoting from the link: "The import statement is referencing a Java class () that MATLAB Compiler (if the error occurs at compile time) or the MCR (if the error occurs at run time) cannot find.
To work around this, ensure that the JAR file that contains the Java class is stored in a folder that is on the Java class path. (See matlabroot/toolbox/local/classpath.txt for the class path.) If the error occurs at run time, the classpath is stored in matlabroot/toolbox/local/classpath.txt when running on the development machine."
You just have to put import statements in a separate .m file.
so from:
javaaddpath 'c:\some.jar';
import com.something.Element;
...interesting stuff...
There will be a do_imports.m:
import com.something.Element;
And in original .m:
javaaddpath 'c:\some.jar';
do_imports
...interesting stuff...
And then it will compile and work. No need to mess around with system-wide classpaths.
Here is an extract from the link
http://blogs.mathworks.com/desktop/2009/07/06/calling-java-from-matlab/
MATLAB maintains a path for Java classes separate from the search path. That means even if you have a .class or .jar file on the MATLAB path, unless you use javaaddpath you will not be able to use it. To see what is currently on the path use javaclasspath. Running this command you will show you a long list of files that ship with matlab called the Static Class Path and then you'll see the Dynamic Class Path. The dynamic class path is where classes added to the path with javaaddpath will be placed. They can be removed with javarmpath and have to actively reloaded each session of matlab.

Categories