Welcome! Please see the About page for a little more info on how this works.

0 votes
in Clojure by

Similar to CLJ-843, one cannot invoke (System/load "/tmp/a.so") since it successfully loads the so file to the wrong classloader (thanks SUN!)

While trying to make a simple way to load shared-objects embedded in uberjars (using https://github.com/adamheinrich/native-utils/blob/master/src/main/java/cz/adamh/utils/NativeUtils.java), I found that it is not possible to do due to the classloader issue.

Any thoughts?

3 Answers

0 votes
by

Comment made by: alexmiller

That linked jira had a patch and was committed, so it seems this already exists as (clojure.lang.RT/loadLibrary "/tmp/a.so") ?

0 votes
by

Comment made by: shlomi

Alex,
Sorry for not being clear enough:

(clojure.lang.RT/loadLibrary "/tmp/a.so") - does not work, loadLibrary is expecting properly named library files existing within a path pointed to by either LD_LIBRARY_PATH or java.library.path. For example, if you have the file liba.so existing somewhere on LD_LIBRARY_PATH than (clojure.lang.RT/loadLibrary "a") would work.

For use cases where you dont want to rely on environment settings or preexistence of the .so files, you could use System/load instead of System/loadLibrary. For instance if you want to download the proper .so files for some platform from within the running clojure program, or have the .so files exists inside your jar. In these cases you would want to download or extract them from the jar respectively, place them in some temp folder (which is not in LD_LIBRARY_PATH) and load them using their full path, to be used in the running program (i.e. no special scripts or preparation tasks).

If I was to write a patch to src/jvm/clojure/lang/RT.java, it would be:

// Load a library in the System ClassLoader instead of Clojure's own, from anywhere
public static void loadObject(String libFullPath){

System.load(libFullPath);

}

0 votes
by
Reference: https://clojure.atlassian.net/browse/CLJ-2243 (reported by alex+import)
...