I am trying to set up JNA to talk to a custom DLL i have but to no avail
It keeps saying it is looking in the resource path in the lcoation /target/classes/
I was wondering is it possible to add a resource location where it can pick up my DLL?
My code is as follows
System.setProperty("jna.debug_load", "true");
System.setProperty("jna.debug_load.jna", "true");
System.setProperty("jna.platform.library.path", "C:\\Development\\dll\\");
Native.loadLibrary("customDLL", CustomDLL.class);
If I manually add the dll to the folder /target/classes/, the DLL loads as expected
I am using Eclipse Luna 32bit
JDK 1.7.0_65 32 bit
JNA 4.1.0
Any help is greatly appreciated
Thanks
Damien
JNA looks in the location specified by the system property jna.library.path, falling back to whatever path is in java.library.path otherwise (which is mostly set based on PATH from the environment).
You should make sure that eclipse copies the DLL to wherever the application will eventually expect to find it, and also ensure the eclipse properly sets jna.library.path to that location when launching your JVM.
Note also that any dependent libraries must either by on PATH or in the same directory as your target DLL.
See the JavaDoc for NativeLibrary for other variations on where JNA can load your native library.
Related
I am using MinGW to create a shared library that is dynamically linked and loaded using the LoadLibrary function. My shared library is dependent on a dll that can be found in two different places on the path. These two are different (two different versions) and at the time of loading the library, it picks the wrong dll. How can I explicitly specify which dll to pick?
To be more specific these are the commands I am using:
Compilation
g++ -m64 -O3 -c my_file.cpp -o myfile.o
Creating shared library
g++ -m64 -shared myfile.o -o myfile.dll
I have tried many things including -L option but have not yet been able to figure out how to do this. I also have searched online for a couple of hours but it turn out to be of no use.
Any help is much appreciated.
Thanks in advance
It turns out that the dll I don't want to load is indeed at "The directory where the executable module for the current process is located." The other dll, with the same name is on the path but not where windows looks first. From what this document says, LoadLibrary will always pick the dll from the directory where the executable module for the current process is located, if the dll exists there, no matter what. Is there a way around this? Moving the dlls is really not an option as this is a third party program that we are building on
The chronological order of, how windows looks for DLLs is explained here step by step
https://msdn.microsoft.com/en-us/library/7d83bc18.aspx
After all steps in above link, when it comes to PATH environment variable, windows looks through each directory listed in PATH variable, from left to right.
First try if you can place the correct DLL in any of the locations as listed in the above link. Because path environment variable is the last thing that gets looked into.
If the above step is not possible, then ensure the correct DLL path is on the left of the wrong DLL path in PATH environment variable.
The following article gives some guidance for effecting alternate DLL search strategies using the SetDllDirectory and LoadLibraryEx API calls, assuming those are options (you mentioned LoadLibrary is currently used).
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682586(v=vs.85).aspx
It turns out that there is another windows function called LoadLibraryEx that allows to explicitly specify a path where the libraries will get loaded. You can learn more about it here:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms684179(v=vs.85).aspx
Specifically, as the docment mentions:
If this value is used and lpFileName specifies an absolute path, the
system uses the alternate file search strategy discussed in the
Remarks section to find associated executable modules that the
specified module causes to be loaded.
and
If lpFileName specifies an absolute path and dwFlags is set to
LOAD_WITH_ALTERED_SEARCH_PATH, LoadLibraryEx uses the altered search
path.
I'm trying to specify the library load path for JNA on linux for a C++ library.
From the java doc I used -Djna.library.path when calling my program but JNA fails to load the library.
This is how I call the program:
java -jar -Djna.library.path=/home/lib program.jar
When I use -Djna.debug_load=true I can see the library path and JNA trying to find the library, the path is correct and the library name is also correct, but it doesn't load. JNA continues to search the resource path for the library and then fails to find it.
When I put the library in the current directory (same level as program.jar) JNA is happy and the library is loaded without issue.
When I use:
java -cp program.jar:/home/lib package.program
JNA also loads the correct library.
Does anyone here know why -Djna.library.path does not work? Is it because I'm using a jar application file with a manifest?
Anyone with a similar problem?
Please note that once you leave JVM, jna.library.path or java.library.path is no longer taken into account.
Make sure to set LD_LIBRARY_PATH such way it points to locations where libshared.so is located.
Update:
Take a look here to check how using code from shared lib works:
https://github.com/mkowsiak/jnicookbook/blob/master/recipes/recipeNo023
After doing some research, some people say I can add the following VM Argument in my project Run Configuration. In run time, JVM will search these directories to find DDLs.
-Djava.library.path="${workspace_loc}/GunCalibration/myLib/DLLs;${env_var:PATH}"
GunCalibration is my Java project folder in my workspace.
DLLs folder contains all my DLLs which are defined with my JNI specification.
As a result, I get this error:
Exception in thread "main" java.lang.UnsatisfiedLinkError: D:\Software
x64\eclipse3.7\Kai\workspace_RealW\GunCalibration\myLib\DLLs\sixense.dll:
Can't find dependent libraries
However, if I copy some specific dll files to JAVA_HOME\jre6\bin, my code works correctly. (I do add this path into my system environment PATH.)
Could anyone explain why the first approach by using java.library.path doesn't work? How can I know which ddl is required to place in JAVA_HOME\jre6\bin?
Thank you a lot~
JAVA_HOME\jre6\bin is effectively in the system PATH (since it's the same directory as the java.exe program which is being run), which makes any DLLs there loadable by the system. java.library.path is mostly derived from the value of PATH, but it only affects where the VM looks for native libraries, not the system itself.
The VM can load any file explicitly based on the paths in java.library.path, but it cannot affect how the system looks up any dependent DLLs (other than telling the system to include the path to the initial DLL in its search -- see MSDN for LoadLibrary[Ex])
One alternative to copying the DLLs is to add the path to the DLLs to the PATH environment variable.
I'm getting the following error when trying to interface with a Magtek 32-bit DLL.
Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: Unable to load library 'MCPAPI': The specified module could not be found.
I have no problem interfacing with user32.dll in the same code (just tweaking the DLL name and interface). Seems to indicate that the DLL can't be found, but it's most definitely in my jna.library.path. I've even gone as far as dumping it into the Windows system directory, next to user32, without success.
What am I missing here?
jna.library.path will only influence loading of libraries directly referenced. Dependent libraries must be found either in the same directory as the explicitly loaded one, or in PATH.
For your example to work, MCPAPI must be in either jna.library.path or PATH, and its dependent libraries must be either in the same directory or in PATH.
If you run a 64bit jvm you cannot load 32bit dll's. If thats the case, install 32bit jvm
try using System.load(path\to\library) instead System.loadLibrary().
I've been integrating simple java modules into the MATLAB environment on Windows with some success. Recently I encountered a problem with a third-party library which attempts to load a dll.
The java ClassLoader throws the UnsatisfiedLinkError when the load is attempted:
java.lang.UnsatisfiedLinkError: no <libname> in java.library.path
at java.lang.ClassLoader.loadLibrary(Unknown Source)
at java.lang.Runtime.loadLibrary0(Unknown Source)
at java.lang.System.loadLibrary(Unknown Source)
The exception is reporting that my 'libname' is not in the java.library.path property. I have verified that the property does indeed have the correct path in it, and that the libname.dll file exists on that path.
I verified java.library.path in two ways. First, I simply checked that value returned on the MATLAB command line:
>> java.lang.System.getProperty('java.library.path')
Then, I modified the java method in question to print that value just before the call into the failing third-party function:
System.out.println(System.getProperty('java.library.path'));
Both confirmed that my path value was set as expected.
I've also tried manually loading the library from the command line, and it fails with the same results.
Is this something that is not possible in MATLAB, or am I missing something here? Unfortunately I'm not administrator on this machine so I can't try the old trick of moving the dll into a directory with dlls that do work.
I welcome any suggestions for things to try if there is no absolute answer.
Platform:
Windows XP
MATLAB R2009a
Java 1.6
Are you familiar with Process Monitor? (If not you will easily get how it works).
Download it. Run it. Just enable "Show File System Activity" (little icons on right under menu-bar), disable the others.
Then fire up whatever causes the library to try to load the dll. After the UnsatisfiedLinkError occured, stop the event capturing in Process Monitor.
Now do a CTRL+F and search for the name of the dll it should load. Check the (probably multiple) entry which say "Not Found" or "Name not found" in the result column and with the dll-name in the path column.
Now check where it really looks for the dll. Maybe it appends some additional path or similar and thus can't find it.
Just found this in the MATLAB docs:
Specifying the Search Path for Sun Java Native Method DLLs
The mechanism that MATLAB uses to locate native method libraries that are required by Java has changed. MATLAB no longer uses system environment variables to define the paths to these libraries.
Compatibility Considerations
If you presently rely on the PATH (for Windows) or LD_LIBRARY_PATH (for UNIX) environment variables for this purpose, you will need to use the file librarypath.txt, as described below, in its place.
Specifying the Java Library Path
Java classes can dynamically load native methods using the Java method java.lang.System.loadLibrary("LibFile"). In order for the JVM software to locate the specified library file, the directory containing it must be on the Java Library Path. This path is established when MATLAB launches the JVM software at startup, and is based on the contents of the file
$matlab/toolbox/local/librarypath.txt
(where $matlab is the MATLAB root directory represented by the MATLAB keyword matlabroot).
You can augment the search path for native method libraries by editing the librarypath.txt file. Follow these guidelines when editing this file:
Specify each new directory on a line by itself.
Specify only the directory names, not the names of the DLL files. The LoadLibrary call does this for you.
To simplify the specification of directories in cross-platform environments, you can use any of these macros: $matlabroot, $arch, and $jre_home.
Put the DLL that you try to load using java.lang.System.loadLibrary into the following directory:
$matlabroot\sys\java\jre\win??\jre\bin\
Does your library depend on other dlls? It could be that the dll java is loading as a result of its loadLibrary() call requires other dlls. On Windows, I believe it will look on %PATH% to try to find these dlls.
This isn't strictly a java thing; it's more to do with the native library you are loading.
Java is told where to find the dll via java.library.path (or whatever other mechanism Matlab uses), and the libname.dll will use %PATH% to find any dlls it depends on.
As you say that the missing dll is in your java.library.path, perhaps you could try appending the java.library.path value to %PATH% and trying again?