I've been given a .jar that calls to a .dll to use in a project.
I can compile and run without problem if I do the following:
Add the folder containing the .dll to the Path environment varibale (Windows 10).
Add the .jar as a dependency on my gradle project.
That way the API works fine.
When I move the generated jar to another computer it cannot find the dll although I include it in the jar, so the software doesn't work.
How can I tell the generated jar that the dll it needs is in it?
I feel like the .jar they sent me just calls the functions of the dll and assumes you added the directory to the path variable. Is there any way to make this work without needing to change the path configuration to every PC I move the jar?
I´ve already tried the answers posted here (And they don't work):
Gradle how to add native dependency? [Libgdx]
Add native library to local jar in gradle build
The problem is the way the jar loads the dll. Usually it just calls System.loadLibrary(<libname>) which expects the native library to be in the library search path.
If you want to load it from somewhere else you have to extract the DLL from the JAR into e.g. a temp directory or somewhere else and the load it using
System.load(<absolute path to the dll file>);
Note: If you can't change the Classes in the JAR you can place the call to System.load(..) in a second class that is loaded before the code of the JAR is executed. AFAIR a library is only loaded once by Java, therefore if the dll of the same name is already loaded the call to System.loadLibrary() in the original JAR is simply ignored.
Related
I am working on a Java project in NetBeans using JNA. According to the JNA documentation, I can make my DLL:s available to Java by putting it in the jar:
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.
This is what I want to do, so I have included the DLL:s in the project under src/win32-x86-64. If I build a jar-file with netbeans, and then include the jar file in another project everything works fine and JNA finds my library without a problem. This is what I get with jna.debug_load on:
Looking in classpath from sun.misc.Launcher$AppClassLoader#15db9742 for /com/sun/jna/win32-x86-64/jnidispatch.dll
Found library resource at jar:file:/C:/MyNetBeansProject/dist/lib/jna-4.2.2.jar!/com/sun/jna/win32-x86-64/jnidispatch.dll
Looking for library 'MyLibrary'
Adding paths from jna.library.path: null
Trying MyLibrary.dll
Adding system paths: []
Trying MyLibrary.dll
Looking for lib- prefix
Trying libMyLibrary.dll
Looking in classpath from sun.misc.Launcher$AppClassLoader#15db9742 for MyLibrary
Found library resource at file:/C:/MyNetBeansProject/build/classes/win32-x86-64/MyLibrary.dll
Looking in C:/MyNetBeansProject/build\classes\win32-x86-64\MyLibrary.dll
Found library 'MyLibrary' at C:/MyNetBeansProject/build\classes\win32-x86-64\MyLibrary.dll
Apparently the DLL from the jar is not used. Instead the DLL from the build folder is used.
Now, if I move the jar-file to another folder and include it in my project, I get a UnsatisfiedLinkError. JNA gives the following output:
Looking in classpath from sun.misc.Launcher$AppClassLoader#70dea4e for /com/sun/jna/win32-x86-64/jnidispatch.dll
Found library resource at jar:file:/C:/SomeFolder/lib/jna-4.2.2.jar!/com/sun/jna/win32-x86-64/jnidispatch.dll
Looking for library 'MyLibrary'
Adding paths from jna.library.path: null
Trying MyLibrary.dll
Adding system paths: []
Trying MyLibrary.dll
Looking for lib- prefix
Trying libMyLibrary.dll
Looking in classpath from sun.misc.Launcher$AppClassLoader#70dea4e for MyLibrary
Found library resource at jar:file:/C:/SomeFolder/MyNetBeansProject.jar!/win32-x86-64/MyLibrary.dll
It looks like JNA finds the DLL in the jar, but it does not try to extract it. I can not find it in my temp folder (where JNA extracts it's own internal DLL).
What is the problem here? Why doesn't JNA extract the file? How can I fix this?
(I don't know if this is relevant, but I should mention that my DLL depends on multiple other DLL files that are in the same folder in the jar. Not sure if JNA will extract them automatically for me, but so far it seems JNA isn't even extracting the DLL I am actually using.)
EDIT: There seems to be no problem locating jnidispatch.dll. According to the output when jna.debug_load.jna is set to true the file is found in the JAR and extracted to the temp folder.
JNA show error "UnsatisfiedLinkError" when dll couldn't be loaded. If your DLL needs another custom DLLs not present in the system path it will fail, as JNA doesn't extract this dll automatically.
JNA as a Java library doesn't know the dependencies of the system library, so it can't extract from the jar. The solution is to specify all the dependencies in the JNA Java interfaces.
You can see an example here Load multiple dependent libraries with JNA
What is happening behind the scenes of the Operating System
At the end, the libraries are loaded by the operating system as requested by the main executable. In this case the main executable is java.exe or (jvm.dll). If the system can't find a library in the path it fails and java generates an exception.
Another related and solved question is Registering multiple .dll libraries into a single java class using JNA
I inherited a working large Java8 project that needs to be re-architected. It builds a jar, but also includes an example main (not included in the jar) and a deep tree of libs including some .dll files deep in the libs/ tree (dll's also NOT included in the jar).
At some point, the code in the jar calls Native.loadLibrary("fti2x.dll", fti2xWrapper.class, [Map< String, Integer>] options) on the simple file name "fti2x.dll" -- with no path components -- and the load succeeds. This .dll is only located deep in the libs/ directory on my computer. How did the jar, running under eclipse, figure out this was in /libs/client/usb/CommLib/amd64/fti2x.dll without specifying the path to it?
If I copy just the jar, the example main, and the libs/ directory to a new project, how do I configure it in Eclipse(Mars) to find the .dll for the Native.loadLibrary call? (Just simply doing so fails, so I am missing some config.)
How do I do execute the main.class outside of Eclipse and have it find the .dll?
Is there possibly some Java code I am missing that sets this path? If so, what do I look for?
There is a system property that is used to specify the path that JNA uses to search for native libraries: jna.library.path. Try printing out its value just after the library loads successfully in the old project to see if it is being set.
This answer explains how to set a system property in an Eclipse run configuration. Outside of Eclipse, specify a value for it using the -D command-line switch to the JVM, e.g.
java -Djna.library.path=<some path> YourMainClass
I am new to Java and am using Eclipse to write Java code.
I've added lots of library (.jar) files as referenced libraries. I've also exported my project as a JAR file. My question is if I run this file on a computer where the referenced libraries are not at the same place as in my computer, will it run successfully?
I also made a runnable JAR file, whose size was much larger (~29 MB) as compared to the previous file (~24 KB).
My question is if I run this file on a computer where the referenced libraries are not at the same place as in my computer, will it run successfully?
No. You need to package the referenced JARs alongside your program JAR. It would be inconvenient for the end-user to have to download all the libraries that your program depends on. A couple of options, both possible using the Eclipse Export function.
Unpack all your dependent JARs and package them together with your code into one single executable JAR.
Specify in your program JAR manifest the classpath, which will contain relative paths to the location of your dependent JARs. These could be for example in a lib folder. The location of the lib folder relative to your program JAR would need to be the same for all your end-users, so it would make sense to package it all together.
It depends on the way you package jars with the runnable jar app. if you do it inside the jar or outside it then you should make a classpath entry to your manifest.mf.
you can even bundle the reference library in the same jar. So as you reduced the size to that extent i assume you removed those from the jar, which is not good approach in most cases. It is not recommended not to include referenced jar, unless you are 100% (not even 99.9%) sure those library WILL be in the system you would want to run.
EDIT:
to include the referenced jar in eclipse, you need to goto
project-properties>java-build-path>order-and-export
here check whatever libraries you want.
I've made a jar library and places it inside jdk and jre's ext directory to check for installed extension scenario in Java.
Now when I a trying to create a Java project in eclipse and try to use the jar files classes or use the library, I am not able to access but those jar files are visible under Java PRoject jre system library in ECLIPSE.
Are the extension classes loaded when you run something outside of Eclipse? For example you can try the following command in a terminal to check if a class from the extension can be found:
javap name.of.ExtensionClass
When you run your program from Eclipse, are you sure that you use the JRE that has the extension installed?
You probably will have to specifically reference the jar in Eclipse. The colleciton of JARs that come with the JRE are also included in the manifest file so that the runtime knows which files to request be loaded. Since your jar is not in the manifest, it will not be loaded automatically.
An alternative might be to repackage a JRE with an updated manifest that refers to your extension jar.
After adding to JAVA_HOME/lib/ext file or java.ext.dirs system property,
Don't Run the jar file ,it won't.
but Run the class with package name ,it will.
My application relies on two external libraries, I have both in jar format and have added them to my classpath, making it possible to run my application within NetBeans.
However, I would like to package my application in an easy to use jar file. When I tried the automatic method of jar creation provided by NetBeans (where it auto generates a jarfile in dist/) and ran it on another computer, I got lots of ClassNotFound (or similar) exceptions for classes that I could tell were supposed to be provided by my other libraries.
Is there a way I can include the other jarfiles I have into my own jar? I've never created an application which relies on other libraries before so this is a first for me.
You can add a "Class-path" line to your jar's manifest. The drawback is that you have to hard code the paths to a file system (not jar) location in the manifest. If you put them all in the same directory or a consistent relative directory, it should be manageable.
See: http://docs.oracle.com/javase/tutorial/deployment/jar/downman.html
Alternately you can try something line One-JAR: http://one-jar.sourceforge.net/