PatternConsulting/opencv

Loading Issues with Multiple Class Loaders

michaelahlers opened this issue · 5 comments

Particularly when working in hosted environments (like IDEs), where different class loaders may be used between one run and the next, developers will encounter errors like the following:

java.lang.UnsatisfiedLinkError: Native Library /private/var/folders/d1/3323g01s4bn3ntx1g_yzm_dc0000gn/T/1621396069368823549/nu/pattern/opencv/osx/x86_64/libopencv_java249.dylib already loaded in another classloader
    at java.lang.ClassLoader.loadLibrary0(test.sc5011658132463706269.tmp:1891)
    at java.lang.ClassLoader.loadLibrary(test.sc5011658132463706269.tmp:1843)
    at java.lang.Runtime.loadLibrary0(test.sc5011658132463706269.tmp:866)
    at java.lang.System.loadLibrary(test.sc5011658132463706269.tmp:1115)
    at nu.pattern.OpenCV$Loader.loadLibrary(test.sc5011658132463706269.tmp:221)
    at nu.pattern.OpenCV$Loader.access$100(test.sc5011658132463706269.tmp:156)
    at nu.pattern.OpenCV.loadLibrary(test.sc5011658132463706269.tmp:153)
    at #worksheet#.get$$instance$$res1(test.sc5011658132463706269.tmp:5)
    at #worksheet#.#worksheet#(test.sc5011658132463706269.tmp:27)

If sys_paths is not set to null, and the library is loaded by absolute path, this problem goes away. Comments by Holger Hoffstätte on a similar topic suggest stale class loaders are not garbage collected—possibly due to the reflection hack.

Ultimately, there are no good solutions—only partial workarounds. There are now two loader methods on nu.pattern.OpenCV. Both are now safe to call spuriously, and give developers a choice between adding the native binary to java.library.path at runtime and giving “shared” access, or forcibly loading a different copy of the library (which is not blocked by guards against the static ClassLoader.loadedLibraryNames collection).