Where to put DLL file? - java

I am calling C++ method using DLL file in my Java project. Right now, I have hard coded the path.
The application will be deployed on many machines and it also run on multiple machine. Where should I put my DLL file so that I can load it and call it on any machine?

I've seen applications that put the DLL into the JAR file. At run-time, they extract the DLL from the JAR into a temporary directory and then access it there.
It's not the most efficient approach but the easiest from a deployment perspective.

You have to make sure your DLL is in the classpath.
One such way to do so is to put the path to the DLL in PATH environment variable.
Other option is to add it to the VM arguments in the variable LD_LIBRARY_PATH, like this:
java -Djava.library.path=/path/to/my/dll -cp /my/classpath/goes/here MainClass
If you are developing a complex application, that has to be stable you have to ensure that the DLL you need is put somewhere, where the OS is going to look for it, probably think of an installer script/program.

C:\WINDOWS\system32 (assuming C is the drive where windows is installed, probably you can get it from registry)
I used to use windows long time ago & not an expert, so I made a google search for you and find the link http://vlaurie.com/computers2/Articles/dll.htm
See the last topic in the link (the one starting with headline Using Regsvr32.exe to Register DLLs)

Related

Why 2 Path for load Library JNA

Hello This is my code :
if (isWindows()) {
//System.setProperty("jna.library.path", getClass().getResource("/resources/win32-x86").getPath());//netbeans WinOs
System.setProperty("jna.library.path", System.getProperty("user.dir").toString()+File.separator+"Desktop");//compiler WinOs
} else if (isMac()) {
//System.setProperty("jna.library.path", getClass().getResource("/resources").getPath());//netbeans MacOs
System.setProperty("jna.library.path", System.getProperty("user.dir").toString()+File.separator+"Desktop");//compiler MacOs
} else {
System.out.println("Your OS is not support!!");
}
Why I have 2 PATH (don't understand because for add an image i have only one Path) by OS, one for use with IDE and another for use with .JAR ?
I just realized, that when I'm use windows and I run the project (from netbeans) the "Library" load and I get the information, but when I compile and I launch my .jar I get error :
Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: %1 is not a valid Win32 application.
My Structure
It is correct?
On mac only work with this command : java -jar "/System/Volumes/Data/Users/hugoclo/NetBeansProjects/Prezauto/dist/Prezauto.jar"since Terminal. If click on jar i have message error : Not Found .....
Sorry about my English,
There can be two reasons for the "why". While Java is cross-platform, JNA (which relies on some native code) must necessarily behave differently on different operating systems. Particularly in the case of loading DLLs (Windows) or dynamic libraries (OSX), you don't want to mix and match. Because it might be possible to have a dll with the same name compiled for different operating systems, JNA's Getting Started page identifies standard locations for these libraries:
Make your target library available to your Java program. There are several ways to do this:
The preferred method is to set the jna.library.path system property to the path to your target library. This property is similar to java.library.path, but only applies to libraries loaded by JNA.
Change the appropriate library access environment variable before launching the VM. This is PATH on Windows, LD_LIBRARY_PATH on Linux, and DYLD_LIBRARY_PATH on OSX.
Make your native library available on your classpath, under the path {OS}-{ARCH}/{LIBRARY}, where {OS}-{ARCH} is JNA's canonical prefix for native libraries (e.g. win32-x86, linux-amd64, or darwin). If the resource is within a jar file it will be automatically extracted when loaded.
In your code, you appear to be trying to do the first option (setting the jna.library.path) to include the user's desktop. That's fine for testing, not good for production, and likely the reason your compiled jar can't find it. Furthermore, by setting this variable, you are overwriting any previous (default) location for it. If you want to go this route, you should copy the saved location and then append your own additional path to it.
However, for code you'll distribute to users, you don't want to have to rely on an absolute file path. It's far better to put the library in a standard relative path location: a resources path (src/main/resources if using Maven) that will be available on your (or any user's) classpath when executing. This seems to align with the commented-out Windows branch of your code, which will look in the win32-x86 subdirectory of your resources folder.
You may have told your IDE to add something to the classpath (so it works there) but if it's not in a standard location, it may fail in a jar.
I'm not sure why the macOS branch of your code does not put the resources in the darwin subdirectory but it probably should.

Exporting a runnable jar, opening it returns an UnsatisfiedLinkError

I currently wrote a simple GUI in Eclipse which runs as intended. I was hoping to export it so I can share it with my friend (who doesn't need to install eclipse and the java libraries). I tried all 3 library handling method Eclipse provides and none of them works. I read a little online and saw something about a manifest file, but wasn't quite sure what to do with it. Is it going to help?
This is where I placed the folder that comes with the .dll file.
This is the result. Am I doing something wrong?
As indicated by the error messages in the first screenshot, what you are missing here is the native library - the software library written and compiled to native code specific to the operating system. What you will need to do is provide the libraries specific to the operating system on which your software will run, eg. dlls for 32 or 64 bit Windows. The manifest does not provide the capability to include those libraries.
When the program is run on Windows, Java will look for native libraries in the following locations:
The current directory
The directories in the PATH environment variable
The directories in java.library.path (if it's specified)
It may be easiest to simply put all files in the one directory. If you do this, you should be able to run the program in the same way as you do now.
The java.library.path option is only needed if you want to put your native library files in a directory separate to the one in which you run your program and not on your PATH. It is only in this case that you will need to add java.library.path, eg. by adding -Djava.library.path=c:\path\to\your\lib after java. Also note that you may use a relative path, ie. a path that is relative to the directory you are in when you execute the command.
I also see from your later error messages that you have another dependency, but on a java library LeapJava.jar. As running a jar with -jar will only work if you have a single jar, but because you have more than one (your own program plus the dependency), you'll instead need to use the -classpath (or -cp for short) argument and add your main class. The classpath argument is a semicolon-separated list of classpath locations, while the main class is the one containing your public static void main method, eg. your.package.name.YourMainClass. So assuming your UI.jar is still in C:\Users\Ian\Desktop\Leap Data UI, you should be able to navigate to that directory and execute with:
java -cp UI.jar;UI_lib\LeapJava.jar -Djava.library.path="UI_lib\x64" your.package.name.YourMainClass

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.

UnsatisfiedLinkError Exception [duplicate]

I am using Jacob jar file in my java application.
This Jacob jar file comes with a .dll file. I have added Jacob jar file to my classpath. But when I execute my application a runtime error occurs as
"couldn't load jacob-1.15-M3-x86.dll file"
How can I load this .dll file?
Edited:=================================================================================
I had set the "path" environment varaible to the dir that contains my .dll file and loading that .dll file as follows
static {
System.loadLibrary("jacob-1.15-M3-x86.dll");
}
but the following error occured
java.lang.UnsatisfiedLinkError: no jacob-1.15-M3-x86.dll in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1734)
at java.lang.Runtime.loadLibrary0(Runtime.java:823)
at java.lang.System.loadLibrary(System.java:1028)
at TemplateClass.TemplateClass.<clinit>(TemplateClass.java:14)
The 'jacob-1.15-M3-x86.dll' needs to be in a place where your the operating system can find it. You have a few options here:
You can place the .dll file in the directory you started your application from. If you have a batch script to start your application, it would be that directory. If you are starting in some sort of application server, it would typically be the 'bin' directory.
You can place the .dll file somewhere in the %PATH% environment variable. I may be easier to just update your PATH environment variable to include the directory that contains your .dll file.
Another option is to place your .dll into the %SystemRoot%\system32 directory. Usually this is 'C:\Windows\system32'. This option is not usually recommended unless it is a shared library like the MSCVRT runtime.
One other possible issue you might have. If the .dll is compiled as 32-bit, then you must be running in the 32-bit Java runtime. Likewise, if it is a 64-bit .dll it needs to be run in a 64-bit JRE.
Ah, that's not a compilation error but a runtime error.
My guess would be that your DLL needs to be on the PATH. Not CLASSPATH, but PATH, because that's where Windows looks for DLLs. Try either extending your PATH to include the location of your DLL, or do what many other people do: Dump the DLL into \Winnt\System\System32 or whatever the system directory is called on your box. Wherever all the other DLLs are, in other words.
Update
The error message you post, thankfully, is pointing out the exact problem. You can solve it by putting the directory containing your DLL into java.library.path This Sun forum thread shows a nice example: http://forums.sun.com/thread.jspa?threadID=627890
Actually, that's a lot less clean than it should be; this seems to be one of the "shadier" areas in Java. The thread wanders around a lot, I do advise you to read all the way through to see some problems and solutions. I think you'll be able to succeed with a little trial and error.
Other options :
set the property java.library.path to the directory containing the dll. Example :
java -Djava.library.path="path/to/directory/containing/the/dll" -jar appli.jar
in the code, load the dll explicitly, with System.load.
You need to set LD_LIBRARY_PATH. This will give you all the right steps to follow.
When you use System.loadLibrary() don't include the .dll at the end.
Also, if you are not setting java.library.path to point to the folder containing the DLL then the DLL should be in the directory where you launch your Java application from.
I had the same problem.
I see that the question is not "answered", so maybe none of the options above worked.
One of my last hypothesis was that the Jacob.dll is missing its dependency.
What I did was to get depend and check if all the dependence, used by Jacob are loaded.
Of course this works for Windows.
Cheers!

How to load a library that depends on another library, all from a jar file

I would like to ship my application as a self-contained jar file. The jar file should contain all the class files, as well as two shared libraries. One of these shared libraries is written for the JNI and is essentially an indirection to the other one (which is 100% C).
I have first tried running my jar file without the libraries, but having them accessible through the LD_LIBRARY_PATH environment variable. That worked fine.
I then put the JNI library into the jar file. I have read about loading libraries from jar files by copying them first to some temporary directory, and that worked well for me (note that the 100% C library was, I suppose, loaded as before).
Now I want to put both libraries into the jar, but I don't understand how I can make sure that they will both be loaded. Sure I can copy them both to a temporary directory, but when I load the "indirection" one, it always gives me:
java.lang.UnsatisfiedLinkError: /tmp/.../libindirect.so: /libpure.so: cannot open shared object file: No such file or directory
I've tried to force the JVM to load the "100% C" library first by explicitely calling System.load(...) on its temporary file, but that didn't work better. I suspect the system is looking for it when resolving the links in libindirect.so but doesn't care about what the JVM loaded.
Can anyone help me on that one?
Thanks
One way would be to spawn another Java process from the first, generating the appropriate invocation script.
The jar is invoked by the user
The libraries are extracted to a temp directory
A (bash) script is written to the temp directory
this sets/exports the necessary environment variables
this launches the second JRE instance
The code makes the script executable
The code invokes the script
I know, spawning two JRE instances to launch one app would not be my first choice either.
If you are using Eclipse IDE, then this answer might help you.
I had same problem in eclipse windows that I couldn't added dependant .class files from the JNI.
After searching for a while I came to know that "Its a known bug inside Eclipse", In order resolve the same, I ported all the code to NetBeans IDE.
Can not add all the classes files from the JNI folder in Eclipse (JAVA, Windows 7)

Categories