Closed petebankhead closed 1 year ago
@petebankhead Thanks for dig into this issue. I think your workaround looks good to me. Do you mind raise a PR?
The non-hacky way of doing that would be to set the "org.bytedeco.javacpp.pathsFirst" system property to "true", which makes JavaCPP look in priority at the paths inside "java.library.path" as per System.loadLibrary(), which is used by "standard JNI", so we can add the desired paths there. That's what essentially gets done on Android where we basically have to use System.loadLibrary(). @frankfliu If that doesn't work for DJL, let's do someting about it. Please let me know why that doesn't work for you guys.
"org.bytedeco.javacpp.pathsFirst" doesn't work for us. We are actually calling Loader directly.
Here is what we did for TensorFlow:
If Loader.loadProperties()
get called before we set org.bytedeco.javacpp.platform.preloadpath
, then we are in trouble. I think the hack is OK in our case. Maybe you can expose an API: Loader.loadProperties(boolean refresh)
so we don't have to use reflection.
Right, I understand you're trying to hack JavaCPP, but I don't understand why. What doesn't work exactly when you set "org.bytedeco.javacpp.pathsFirst"? Something like the following does work and does exactly what you need, if I understand correctly your needs:
For the same reason, usr_paths
variable get initialized before I can set "java.library.path". Once ClassLoader is initialized, updated system properties won't take effect.
JavaCPP does reload "java.library.path" in "pathsFirst" mode, so that should still work.
@saudet
pathsFirst
itself is cached, if Loader.loadProperties()
is called before DJL code, setting org.bytedeco.javacpp.pathsFirst
in DJL code takes no effect.
I tested with the follow code, it still fails to load the library:
Loader.loadProperties();
System.setProperty("org.bytedeco.javacpp.pathsFirst", "true");
System.setProperty("java.library.path", path);
Well, we can easily change that. Is that all that is missing?
a little bit concern about setting java.library.path
, it impacts other native libraries. It that possible we set org.bytedeco.javacpp.platform.preloadpath
instead of java.library.path
?
That's not exactly what it's meant for, but if you're not having any issues with it, I guess that's fine. I've added a Loader.loadProperties(boolean forceReload)
method in commit https://github.com/bytedeco/javacpp/commit/232dcb0abf431330f70548c9920c8ae259d9d1f9 that we can call to keep doing it like this without having to use reflection.
JavaCPP 1.5.9 has been released! Please upgrade to get that new Loader.loadProperties(boolean forceReload)
method.
Description
Attempting to load TensorFlow after another JavaCPP dependency (e.g. OpenCV) fails with an
UnsatisfiedLinkError
. This can make it hard to use Deep Java Library + TensorFlow in an application that uses any other JavaCPP presets.(Loading TensorFlow before OpenCV works fine)
Expected Behavior
TensorFlow can be loaded, even if other JavaCPP presets are used - irrespective of the order.
Error Message
How to Reproduce?
I've created a minimal repo that reproduces the issue, and included instructions for running it in the ReadMe: https://github.com/petebankhead/djl-tensorflow-javacpp
What have you tried to solve it?
The problem seems to arise between
LibUtils.loadLibrary
and JavaCPPLoader
. The former usesBut if
Loader.loadProperties()
has already been called, then the properties are cached and setting the system property won't have any effect.It's possible to overcome this via reflection, using something like:
Code demonstrating that is here but I don't know if it's too messy a solution for DJL - and maybe there's a better way @saudet