-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ability for static search locations #41
Comments
Thanks for the detailed writeup, @tresf! About the eager public static void loadLibrary(final String libName, final boolean trySystemFirst,
final String... searchPaths) throws IOException which lets the caller control whether to do a |
First I'd like to preface that often people don't exactly have control over the code that's executing. They might be hitting a bug on only one system and providing a code-less workaround can empower them to manipulate the environment to fix the issue without editing code (e.g. systems administrator or support tech trying to troubleshoot an app crashing). So I think it's a saner default behavior to mimic JNA's ordering (which native-lib-loader already does, mostly)
.. and match JNA by loading these conditional properties based on a user-editable System property. So the short solution in my opinion is to simply add a condition like: String nosys = System.getProperty("native-lib-loader.nosys");
if(nosys == null || !Boolean.parseBoolean(nosys)) {
// Check system path unless otherwise specified
System.loadLibrary(libName);
} This same condition can be applied to extraction as well, quoting JNA:
... so to mimic this behavior, something like Sorry to copy so much text and property names from JNA, I'm just rather pleased with how they offer System properties for this, since often I don't want to recompile a dependant library to control the native library structure (e.g. repackaging a third-party lib for compatibility with the AppStore). This allows something as simple (codeless) as: _JAVA_OPTIONS="-Dnative-lib-loader.nosys=true" ... or something that can be controlled 100% from within code: System.setProperty("native-lib-loader.nosys", "true"); It also will theoretically require no API changes to the project. |
To add to the above, if the opinion of System.setProperty("native-lib-loader.mylib.nosys", "true");
// ^----- additional namespace for granular control
NativeLoader.loadLibrary("mylib"); ... although to that point, I think the last entropy has very few (if any) use-cases and can probably be started as its own request if/when needed. |
Summary
The
native-lib-loader
should allow specifying a library in a static location for edge-case scenarios, usually imposed by security restrictions, constraints or sandboxing.Edit: Static locations may also offer slight performance benefits as well, eliminating the need for unzipping (CPU/disk) activity, see discussion here.
Details
Technically,
native-lib-loader
allows for static search locations, but it requires implementing theJniExtractor
class or overriding the behavior of theDefaultJniExractor
class, as -- by design -- they both intend to perform an extract operation prior to loading a native library. This extraction operation doesn't work in all environments.I'll quote a sister project -- JNA -- documentation, I think it words this problem well and explains as to why this can be needed...
The last bullet is the point I'd like to focus on since this same use-case exists for
native-lib-loader
. For example, if a native library is intended to be distributed with a Java application that's distributed from the Apple AppStore, sandboxing is a hard-requirement, and like the aforementioned SELinux use-case, sandboxing can prevent loading a library from arbitrary locations (such as $TEMP), quoting an Apple employee on the Apple Developer forums:Furthermore, the JNA portion "unless
jna.nosys=true
", I find to be increasingly important as client environments may have identically named libraries in search paths that the client has little or no control over. This is a separate issue, but may be tackled as part of the same enhancement.Workaround
Providing a stub extractor can handle this issue:
Click to see
DefaultJniExtractorStub.java
Usage:
+ NativeLoader.setJniExtractor(new DefaultJniExtractorStub(null, "/opt/libs")); NativeLoader.loadLibrary("mylibrary");
Caveats
Due to the library loading order in
native-lib-loader
, any System locations will be always be preferred, which can cause compatibility issues if the system was modified (probably warrants a separate bug report).native-lib-loader/src/main/java/org/scijava/nativelib/NativeLoader.java
Lines 134 to 142 in 56cdf62
The text was updated successfully, but these errors were encountered: