Set java.library.path inside a jar file

1.6k Views Asked by At

I am trying to create an executable jar file for a project which has a java library resource folder as dependency within the project itself. I want to deploy that jar without the need for the user to download that dependency separately. So I added that java library as a resource to my project and built it. Inside the project source-code, I have the following code to try and set "java.library.path" to include that resource.

Here is what my code looks like:

URL url = Staple.class.getResource("/path/to/java_library_name");
String stringUrl = url.toString();
System.setProperty( "java.library.path", stringUrl );  
Field fieldSysPath = ClassLoader.class.getDeclaredField( "sys_paths" );  
fieldSysPath.setAccessible( true );  
fieldSysPath.set( null, null ); 

However, when building the code and trying to execute the jar itself, this doesn't work and I am getting the following error:

no java_library_name in java.library.path: [jar, file, /path/to/project/target/jar_name-0.0.1-SNAPSHOT-jar-with-dependencies.jar!/path/to/java_library_name]
at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2660)
at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:829)
at java.base/java.lang.System.loadLibrary(System.java:1867)
.....

What is the problem with the above code? It looks like it got the whole path wrong and composed something like /path/to/project/target/jar_name-0.0.1-SNAPSHOT-jar-with-dependencies.jar!/path/to/java_library_name
How otherwise can I programmatically retrieve the path which includes the java library folder after jar is created, and during runtime?

1

There are 1 best solutions below

3
On BEST ANSWER

native resources (the ones you are trying to load with loadLibrary) need to be FILES, and the resources returned by MyClass.class.getResource are URLs; on purpose, as they need not be files. In fact, they usually aren't, as is the case right here: Your resource isn't a file. It's a zip entry in a jar file, which is not a file.

There's no way around this; OS restriction.

I know, I know. Sucks. But you gotta do it: Unpack the DLL into a temporary location (you CAN do this; use getResourceAsStream instead, and copy it to a file using the new Files API; it's a one-liner these days (Files.write), then load that.

Of course, writing executable code into a temp dir and then executing it is very security sensitive; I have no solutions for that dilemma.