dependency of a JNI DLL which internally calls another dll - java

I have created a JNI library with visual studio to use in java application and internally this dll calls another DLL (openssl). Now when i load this library with eclipse I get an error saying "Can't find dependent libraries" unless I put the path of the other DLL on the PATH variable.
in thread "main" java.lang.UnsatisfiedLinkError: C:\*****\jniDLL.dll: Can't find dependent libraries
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 iwinAlgTest.test.<clinit>(test.java:7)
And I've already tried adding it to -Djava.library.path and to the classpath, and i also included all of my dll and openssl dll and lib files like libeay32.lib but neither worked. Is there a way to do this?
I tried to use Dependency Walker to check if there are any files required by my jniDLL.dll
but i get interesting thing:
what i really do to create my jniDLL:
(jniDLL --> calls myDLL.dll) ==> (myDLL.dll --> calls openssl library)
but Dependency Walker says that
(jniDLL --> depends on myDLL.exe) not myDLL.dll
Note : at first it was a win32 application( which output myDLL.exe) but i changed the project setting to output myDLL.dll then i create another project to create a JNI dll from myDLL.dll which i wrote in c++

One way to bypass this is to load your openssl.dll prior to loading myDLL, so myDLL will find the symbols loaded when it tries to initiate .
Other ways to go around this :
add the openssl.dll to PATH (you already mentioned this)
copy openssl in system32 at install time
put openssl in the same folder as your executable path
This however will only work on Windows.
In linux, you will have to change the rpath inside the .so (but I believe this is out of scope).

Related

Can't obtain static method fromNative(Method, Object) from class com.sun.jna.Native

I'm using the JNA's com.sun.jna.NativeLibrary class in order to load the VLCJ native library. I'm working on an armv8(aarch x64)-based linux device. Below is my code, note that i am using the latest JNA version jna-4.5.2:
NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), Constants.DEPLIB_OUTPUT_DIRECTORY);
Native.loadLibrary(RuntimeUtil.getLibVlcLibraryName(), LibVlc.class);
LibXUtil.initialise();
First i was getting this error:
java.lang.UnsatisfiedLinkError: JNA native support (com/sun/jna/linux-aarch64/libjnidispatch.so) not found in resource path
After a quick search i found that i must copy the jna native lib directory from inside the jar into the jvm lib path, where the jna jar library has pre-built libraries for almost all known systems as shown in the image below:
jna-4.5.2 internal content.jpeg
After doing that, the above exception disappeared but another one came up:
java.lang.UnsatisfiedLinkError: Can't obtain static method fromNative(Method, Object) from class com.sun.jna.Native
the exception is saying that it couldn't find the method fromNative(Method, Object) in the class com.sun.jna.Native however after decompiling this class i found that the method already exists.
I'm out of ideas know, any help would be highly appreiated, thanks!.
solve by:
undo this step:
After a quick search i found that i must copy the jna native lib
directory from inside the jar into the jvm lib path...
remove all jna modules (jars) from my project
download and link the following jars into my project:
jna.jar
jna-platform.jar
linux-aarch64.jar
If the jar files: jna-5.11.0.jar and jna-platform-5.11.0.jar (or whatever version number you are using) if in you lib path (build path in Eclipse), the java command option:
-Djna.nosys=true
may solve the problem. When first started, JNA is loads its own native access library and it wasn't finding it. jna.nosys=true allows JNA to look in the jna-X.XX.X.jar file for what it needs. The error message confused my because JNA seemed to be found and loaded, but it was complaining about not finding 'fromNative'.
From JNA documentation:
Loading JNA
JNA includes a small, platform-specific shared library which enables all
native access. When the Native class is first accessed, JNA will first
attempt to load this library from the directories specified in
jna.boot.library.path. If that fails and jna.nosys=false is set, it will
fall back to loading from the system library paths. Finally it will attempt
to extract the stub library from from the JNA jar file, and load it.
The jna.boot.library.path property is mainly to support jna.jar being
included in -Xbootclasspath, where java.library.path and LD_LIBRARY_PATH are
ignored. It is also useful for designating a version of the library to use
in preference to any which may already be installed on the system.
...

Java JNA load DLL

I have a problem when I try load a DLL like this:
String a = "C:\\Users\\ElteGps 022\\Documents\\NetBeansProjects\\JavaApplication1\\src\\lib\\EQ2008_Dll.dll";
String strDllFileName = m_strUserPath + "\\res\\EQ2008_Dll.dll";
String strEQ2008_Dll_Set_Path = m_strUserPath + "\\res\\EQ2008_Dll_Set.ini";
m_DllLibrary = (DllLibrary) Native.loadLibrary(a,DllLibrary.class);
I see this:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'C:\Users\ElteGps 022\Documents\NetBeansProjects\JavaApplication1\src\lib\EQ2008_Dll.dll': Nie mo¿na odnaleæ okrelonego modu³
at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:163)
at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:236)
at com.sun.jna.Library$Handler.<init>(Library.java:140)
at com.sun.jna.Native.loadLibrary(Native.java:379)
at com.sun.jna.Native.loadLibrary(Native.java:364)
at javaapplication1.Fun.main(Fun.java:280)
I read and I did this:
Can not add all the classes files from the JNI folder in Eclipse (JAVA, Windows 7)
giving 'java.library.path' in netbeans for .dll/.so files
From the JNA javadoc
Library Search Paths
A search for a given library will scan the following locations:
jna.library.path User-customizable path
jna.platform.library.path Platform-specific
paths On OSX, ~/Library/Frameworks,
/Library/Frameworks, and
/System/Library/Frameworks will be searched for a
framework with a name corresponding to that requested. Absolute
paths to frameworks are also accepted, either ending at the framework
name (sans ".framework") or the full path to the framework shared
library (e.g. CoreServices.framework/CoreServices).
Context class loader classpath. Deployed native libraries
may be installed on the classpath under
${os-prefix}/LIBRARY_FILENAME, where
${os-prefix} is the OS/Arch prefix returned by Platform.getNativeLibraryResourcePrefix().
If bundled in a jar file, the resource will be extracted to
jna.tmpdir for loading, and later removed (but only if
jna.nounpack is false or not set). You may
set the system property jna.debug_load=true to make JNA
print the steps of its library search to the console.
Native.loadLibrary doesn't work with a full path, try instead System.load
If you can't use that you could also specify the directory of the dll before the loading by setting the enviroment variable of java like this
System.setProperty("jna.library.path", "C:\\Users\\ElteGps 022\\Documents\\NetBeansProjects\\JavaApplication1\\src\\lib");
But this is higly not recommended since it will works only on your computer

JNA: Native Library dependencies and JAR extraction

I will access the MSP430.dll (see here) via JNA. But this library has a dependency to other native library, which cames bundled with the MSP430.dll. This dependend native library is called HIL.dll. With use of jna.library.path all does work perfect. Now I would bundle the native librarys to my own .jar package. Then I would use the automatic native library loading from jar of the JNA framework. But this makes problems with native librarys that have dependencies. If I package the MSP430.dll and HIL.dll to my .jar package then I get following error: "JNA java.lang.UnsatisfiedLinkError and The specified module could not be found". This means, it was not possible to resolve the dependencies of the MSP430.dll to the HIL.dll. In the debug outputs of JNA i can see, only the MSP430.dll will extract from .jar package. In this context the error is understandable. In the next trail, I load the HIL.dll explicit and I can see the extraction of HIL.dll then of the MSP430.dll. But I get still the module error from JNA.
I have looked to the JNA code of the extraction method. I see JNA extracts the native librarys to system temp directory and creates an own temp directory in their. But now I think the problem is, JNA creats temp files for the native librarys wit "jna" prefix and a unique generated numeric value. Here the output of JNA:
Found library 'HIL.dll' at C:\Users\RD3\AppData\Local\Temp\jna-80961\jna1305152974718331988.dll
I think the MSP430.dll needs the HIL.dll unrenamed for finding it. I have testet with direct loading of the HIL.dll with following as first call in the application
System.loadLibrary(C:\\absolutepath\\HIL.dll);
Then loads only MSP430.dll via JNA from .jar package, this works without problems. After that I rename the HIL.dll to lol.dll and use this call:
System.loadLibrary(C:\\absolutepath\\lol.dll);
then I gets the module error again from JNA. The MSP430.dll was not able to resolve the renamed HIL.dll.
It is anyway possible to package a native library with dependencies to .jar package and loading with JNA?
Here the JNA debug output with explicit loading of HIL.dll via JNA:
C:\Users\RD3\Desktop>call "C:\Program Files (x86)\Java\jre1.8.0_25\bin\java.exe"
-Djna.debug_load=true -jar C:\Data\Workspace\NetBeans\MspApiTest\target\MspApiTest-1.0.0-SNAPSHOT-jar-with-dependencies.jar
Looking in classpath from sun.misc.Launcher$AppClassLoader#1f96302 for /com/sun/jna/win32-x86/jnidispatch.dll
Found library resource at jar:file:/C:/Data/mstandfuss/Workspace/NetBeans/MspApiTest/target/MspApiTest-1.0.0-SNAPSHOT-jar-with-dependencies.jar!/com/sun/jna/win32-x86/jnidispatch.dll
Looking for library 'HIL.dll'
Adding paths from jna.library.path: null
Trying HIL.dll
Adding system paths: []
Trying HIL.dll
Looking for lib- prefix
Trying libHIL.dll
Looking in classpath from sun.misc.Launcher$AppClassLoader#1f96302 for HIL.dll
Found library resource at jar:file:/C:/Data/mstandfuss/Workspace/NetBeans/MspApiTest/target/MspApiTest-1.0.0-SNAPSHOT-jar-with-dependencies.jar!/win32-x86/HIL.dll
Found library 'HIL.dll' at C:\Users\RD3\AppData\Local\Temp\jna-80961\jna1305152974718331988.dll
Looking for library 'MSP430.dll'
Adding paths from jna.library.path: null
Trying MSP430.dll
Adding system paths: []
Trying MSP430.dll
Looking for lib- prefix
Trying libMSP430.dll
Looking in classpath from sun.misc.Launcher$AppClassLoader#1f96302 for MSP430.dll
Found library resource at jar:file:/C:/Data/mstandfuss/Workspace/NetBeans/MspApi
Test/target/MspApiTest-1.0.0-SNAPSHOT-jar-with-dependencies.jar!/win32-x86/MSP430.dll
Exception in thread "main" java.lang.UnsatisfiedLinkError: Das angegebene Modul wurde nicht gefunden.
at com.sun.jna.Native.open(Native Method)
at com.sun.jna.Native.open(Native.java:1759)
at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:260)
at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:398)
at com.sun.jna.Library$Handler.<init>(Library.java:147)
at com.sun.jna.Native.loadLibrary(Native.java:412)
at com.sun.jna.Native.loadLibrary(Native.java:391)
at de.sitec.jmspflash.Msp430Native.<clinit>(Msp430Native.java:22)
at de.sitec.jmspflash.Msp430Impl.init(Msp430Impl.java:50)
at de.sitec.jmspflash.Msp430Impl.createMsp430Impl(Msp430Impl.java:36)
at de.sitec.mspapitest.App.main(App.java:34)
C:\Users\RD3\Desktop>
Best regards
Assuming that the only issue you're having is the name of the dependent library, see Native.extractFromResourcePath(). You can use that to extract your non-explicit dependencies and use File.rename() to ensure the library has the name you want.

Problem in accessing dll file from a Java program through JNA

I have a dll file and I am trying to call functions of it through a Java program through JNA
But the problem is It is not able to locate my dll file and throwing the following exception:
java.lang.UnsatisfiedLinkError: Unable to load library 'UsbDll': The specified module could not be found.
at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:163)
at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:236)
at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:199)
at com.sun.jna.Native.register(Native.java:1018)
at com.MainClass.<clinit>(MainClass.java:15)
Exception in thread "main"
Below is my program:
package com;
import com.sun.jna.Native
public class MainClass {
static {
Native.register("UsbDll");
}
public native int method();
public static void main(String[] args) {
}
}
The name of my dll file is UsbDll.dll and my operating system is Windows.
============================ EDITED ================================
The location of my dll file is "c:\UsbDll.dll"
When I placed another dll file at the same location, JNA has located it so I think that the problem is with my "UsbDll.dll" file only.
When I tried to load both the dll files (UsbDll.dll and the another dll) with the following command
System.load("c:\\UsbDll.dll");
System.load("c:\\another.dll");
It loaded the "another.dll" successfully but for "UsbDll.dll", it throws the following exception:
java.lang.UnsatisfiedLinkError: C:\UsbDll.dll: Can't find dependent libraries
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1803)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1699)
at java.lang.Runtime.load0(Runtime.java:770)
at java.lang.System.load(System.java:1003)
at com.MainClass.<clinit>(MainClass.java:16)
Exception in thread "main"
Q1. It looks like it is not finding some dependent libraries. But as I am totally new to these dlls, Is there anything I am missing or I need to ask the vendor to provide me the dependent libraries.
OR
Is it depends on some standard libraries which I can download from internet? If it is, then how to find the libraries name on which it depends?
============================ EDITED #2 ================================
I ran the Dependency Walker on my UsbDll.dll file to find the missing dependencies and found the following missing dependencies.
WER.DLL (referred by library WINNM.DLL found in my c:\windows\system32)
IESHIMS.DLL (referred by library WINNM.DLL found in my c:\windows\system32)
WDAPI920.DLL (referred directly by my UsbDll.dll)
Q1. As WINNM.DLL was found in my system32 folder, it seems as the standard dll. And if this standard dll is referring to 2 missing dlls (WER.DLL & IESHIMS.DLL), then I suspect how other applications are working who are using this WINNM.DLL file?
Q2. I googled for WDAPI920.dll (that was referred my UsbDll.dll directly) and many search results appeared with the same dll name. So it also looks like some standard library. So how to fix these dependencies? From where to download them? After downloading, Can I place them in the same directory in which my main dll (UsbDll.dll) is or I need to do something extra to load my dll (UsbDll.dll) sucessfully?
From your edited code it is quite evident that the UsbDll.dll depends on some standard modules which are not there on your system (for example if it uses ATL and if you have don't have proper runtime then it is guaranteed to fail). To resolve this you will need proper runtime environment.
Also it is possible that the dll in concern depends on some vendor specific module. For you the best option is (and fastest option would be) to contact the vendor. Otherwise, try to install proper runtime from the microsoft site (but its more of hit-and-trial)
Update
Use the below links for finding more about DLL dependency:
How do I determine the dependencies of a .NET application?
http://msdn.microsoft.com/en-us/library/ms235265.aspx
Command line tool to find Dll dependencies
Update 2
See the below mentioned link for the missing dll details (but it is specific to the windows version)
Dependency Walker reports IESHIMS.DLL and WER.DLL missing?
http://social.msdn.microsoft.com/Forums/en/vsx/thread/6bb7dcaf-6385-4d24-b2c3-ce7e3547e68b
From few simple google queries, WDAPIXXX.dll appears to be some win driver related thing (although i am not too sure). Check this link, they have something to say about WDAPI http://www.jungo.com/st/support/tech_docs/td131.html.
The DLL must by in the Path specified by LD_LIBRARY_PATH (see your env), or, in the case of JNA, in the current directory.

java.lang.UnsatisfiedLinkError no *****.dll in java.library.path

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.

Categories

Resources