As far as I can tell, currently, System.loadLibrary() is mostly unusable for Java libraries because they cannot influence the library search path. If you want to transparently load a DSO, you need to use System.load() and hard-code the path. This probably means patching upstream sources.
Debian patches the default search path so that System.loadLibrary() searches /usr/lib/jni for DSOs with native code. This means that classes which call System.loadLibrary() just work, assuming that the Debian package installs its DSOs into /usr/lib/jni.
Can we do something similar in Fedora? We probably want /usr/lib/jni and /usr/lib64/jni, for consistency with the rest of the system.
The upstream default search path starts with "/usr/java/packages/lib/amd64" (and variants for other architectures), but this isn't mentioned in the Fedora guidelines. I'm also not sure if we want to use this file system location because it doesn't look particularly FHS-compliant. But the proprietary JDKs could install a symlink there so that /usr/lib{,64}/jni is searched as well.
On 07/29/2014 06:05 AM, Florian Weimer wrote:
As far as I can tell, currently, System.loadLibrary() is mostly unusable for Java libraries because they cannot influence the library search path. If you want to transparently load a DSO, you need to use System.load() and hard-code the path.
Here's a bit more information on native library loading which might be useful.
When loading a native library, the first thing that happens is that the system will identify the class loader of the class with the method that actually calls loadLibrary(). Then it will ask this class loader to map the name passed into loadLibrary (e.g. "tcnative") to a properly named absolute path on the filesystem (e.g. "/usr/local/lib/libtcnative.so"). The proper naming is usually done by a class loader by calling System.mapLibraryName() which translates e.g. "tcnative" to "libtcnative.so" (on Linux, and different mappings in different OSes).
So if you're dealing with an environment where the class loader is controlled, for example an application server, mostly the "right path" will be chosen - WildFly for example will look for native libraries along side the modules which load them.
However if this is a run-of-the-mill Java JAR trying to load some native stuff, the class loader will typically return "null" indicating that it has no mapping for the native library. In this case, the java.library.path system property is consulted and the paths contained therein are searched, one by one, using the standard name mapping scheme described above.
Only if no matches are found using this mechanism will it default to the compiled-in paths AFAIK.
Once the library is found, the normal ld.so linkage rules apply since AFAIK it's a plain dlopen().
The upstream default search path starts with "/usr/java/packages/lib/amd64" (and variants for other architectures), but this isn't mentioned in the Fedora guidelines. I'm also not sure if we want to use this file system location because it doesn't look particularly FHS-compliant. But the proprietary JDKs could install a symlink there so that /usr/lib{,64}/jni is searched as well.
Changing this default path seems like a sensible approach to me, FWIW.
On Tue, Jul 29, 2014 at 7:05 AM, Florian Weimer fweimer@redhat.com wrote:
As far as I can tell, currently, System.loadLibrary() is mostly unusable for Java libraries because they cannot influence the library search path. If you want to transparently load a DSO, you need to use System.load() and hard-code the path. This probably means patching upstream sources.
To be clear, you can use LD_LIBRARY_PATH, or -Djava.library.path to
influence the search path in any launch scripts, just like you'd control the bootstrap classpath in those same scripts. By choosing to use System.loadLibrary(), instead of System.load(), the developer has already decided to defer any influence over the search path to something external, like a script (or the system's ld cache), so I've not found this to be much of a limitation. I'm sure there are arguments against doing this, but it is imprecise to say that it's not possible.
Debian patches the default search path so that System.loadLibrary() searches /usr/lib/jni for DSOs with native code. This means that classes which call System.loadLibrary() just work, assuming that the Debian package installs its DSOs into /usr/lib/jni.
Forgive my ignorance, but what exactly is wrong with just using
/usr/lib[64], and how does putting them in a separate directory from other system shared libraries offer any greater degree of control? It seems to me that this solution is just as good as just putting the DSOs in /usr/lib[64]. What am I missing? What's the difference?
Can we do something similar in Fedora? We probably want /usr/lib/jni and
/usr/lib64/jni, for consistency with the rest of the system.
The upstream default search path starts with "/usr/java/packages/lib/amd64" (and variants for other architectures), but this isn't mentioned in the Fedora guidelines. I'm also not sure if we want to use this file system location because it doesn't look particularly FHS-compliant. But the proprietary JDKs could install a symlink there so that /usr/lib{,64}/jni is searched as well.
-- Florian Weimer / Red Hat Product Security -- java-devel mailing list java-devel@lists.fedoraproject.org https://admin.fedoraproject.org/mailman/listinfo/java-devel
On 29/07/14 12:05, Florian Weimer wrote:
As far as I can tell, currently, System.loadLibrary() is mostly unusable for Java libraries because they cannot influence the library search path. If you want to transparently load a DSO, you need to use System.load() and hard-code the path. This probably means patching upstream sources.
Debian patches the default search path so that System.loadLibrary() searches /usr/lib/jni for DSOs with native code. This means that classes which call System.loadLibrary() just work, assuming that the Debian package installs its DSOs into /usr/lib/jni.
Can we do something similar in Fedora? We probably want /usr/lib/jni and /usr/lib64/jni, for consistency with the rest of the system.
The upstream default search path starts with "/usr/java/packages/lib/amd64" (and variants for other architectures), but this isn't mentioned in the Fedora guidelines. I'm also not sure if we want to use this file system location because it doesn't look particularly FHS-compliant. But the proprietary JDKs could install a symlink there so that /usr/lib{,64}/jni is searched as well.
Ideally we'd want to have this discussion with Java upstream.
Depending on a Fedora-local patch to the search path means that if people build their own OpenJDK or install Oracle Java, their programs will stop working. So, we must not do that.
If a symlink at /usr/java/packages/lib/amd64 to wherever is allowable, and I see no reason why it should not be, then we don't need to patch OpenJDK. We could make /usr/java/packages/lib/amd64 a real directory, and populate it with symlinks to the packages or make it just a symlink to /usr/lib64/jni ; again, I don't think it matters.
Andrew.
On 07/30/2014 11:39 AM, Andrew Haley wrote:
Ideally we'd want to have this discussion with Java upstream.
Okay, I can bring it up there, but I'm not sure yet what Fedora's needs are, so I think it's premature to bring it up upstream.
Depending on a Fedora-local patch to the search path means that if people build their own OpenJDK or install Oracle Java, their programs will stop working. So, we must not do that.
I suspect that using a JDK not packaged by us needs a changed invocation of the launcher anyway, and throwing the appropriate -Djava.library.path= setting would only be a minor complication, compared to all the other things that aren't quite right by default.
If a symlink at /usr/java/packages/lib/amd64 to wherever is allowable, and I see no reason why it should not be, then we don't need to patch OpenJDK. We could make /usr/java/packages/lib/amd64 a real directory, and populate it with symlinks to the packages or make it just a symlink to /usr/lib64/jni ; again, I don't think it matters.
If there's consensus to introduce /usr/lib64/jni with compatiblity symlinks under /usr/java/packages/lib, then we don't need any upstream changes, just a java-filesystem package which installs the symbolic links, and a change to the Java packaging guidelines.
Debian uses (or will soon use) multiarch paths, and these seem difficult to compute outside of a Debian environment, which is why I believe that changing the upstream default to include appropriate /usr/lib/jni directories could be challenging. Maybe we could just use the non-multiarch directories, and Debian can keep patching the defaults, but that doesn't seem ideal to me, either.
On 08/04/2014 12:38 PM, Florian Weimer wrote:
On 07/30/2014 11:39 AM, Andrew Haley wrote:
Ideally we'd want to have this discussion with Java upstream.
Okay, I can bring it up there, but I'm not sure yet what Fedora's needs are, so I think it's premature to bring it up upstream.
I agree.
Depending on a Fedora-local patch to the search path means that if people build their own OpenJDK or install Oracle Java, their programs will stop working. So, we must not do that.
I suspect that using a JDK not packaged by us needs a changed invocation of the launcher anyway,
I don't see why it needs to, and IMO we should strive to ensure that it does not. JAVA_HOME is traditional but fugly, and doesn't work properly with alternatives.
and throwing the appropriate -Djava.library.path= setting would only be a minor complication, compared to all the other things that aren't quite right by default.
If a symlink at /usr/java/packages/lib/amd64 to wherever is allowable, and I see no reason why it should not be, then we don't need to patch OpenJDK. We could make /usr/java/packages/lib/amd64 a real directory, and populate it with symlinks to the packages or make it just a symlink to /usr/lib64/jni ; again, I don't think it matters.
If there's consensus to introduce /usr/lib64/jni with compatiblity symlinks under /usr/java/packages/lib, then we don't need any upstream changes, just a java-filesystem package which installs the symbolic links, and a change to the Java packaging guidelines.
Indeed. It's a simple solution that will work, not only with future JVMs but with existing ones.
Debian uses (or will soon use) multiarch paths, and these seem difficult to compute outside of a Debian environment, which is why I believe that changing the upstream default to include appropriate /usr/lib/jni directories could be challenging. Maybe we could just use the non-multiarch directories, and Debian can keep patching the defaults, but that doesn't seem ideal to me, either.
Debian's multiarch system is a can of worms, and whatever they do with it won't be ideal. They'll always need to patch, I think.
Andrew.
java-devel@lists.fedoraproject.org