adoptium / temurin-build

Eclipse Temurin™ build scripts - common across all releases/versions
Apache License 2.0
1.02k stars 249 forks source link

default `java.library.path` incorrect on Linux #3552

Open theofficialgman opened 10 months ago

theofficialgman commented 10 months ago

What are you trying to do? run a jar that expect the default library path to be set as it is in debian distributions of java

Expected behaviour: java.library.path evaluates to /usr/java/packages/lib:/usr/lib/aarch64-linux-gnu/jni:/lib/aarch64-linux-gnu:/usr/lib/aarch64-linux-gnu:/usr/lib/jni:/lib:/usr/lib which is the case on openjdk packages by debian

Observed behaviour: java.library.path evaluates to /usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib

Any other comments: this breaks software such as https://angryip.org/ which expects the /usr/lib/jni to be in the default java.library.path to load the debian package swt libraries. additionally, the architecture specific specifier is incorrect.

the paths can be obtained easily with -> https://stackoverflow.com/a/20498049

temurin 17 jre: /usr/lib/jvm/temurin-17-jre-arm64/bin/java GetSystemProperty java.library.path /usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib

openjdk 17 jre: /usr/lib/jvm/java-17-openjdk-arm64/bin/java GetSystemProperty java.library.path /usr/java/packages/lib:/usr/lib/aarch64-linux-gnu/jni:/lib/aarch64-linux-gnu:/usr/lib/aarch64-linux-gnu:/usr/lib/jni:/lib:/usr/lib

theofficialgman commented 10 months ago

refer to debian rules file configuration args that need to be added to correct this issue https://salsa.debian.org/openjdk-team/openjdk/-/blob/openjdk-17/debian/rules#L395

theofficialgman commented 10 months ago

@karianna I do not think this issue belongs under the installer repo. The configuration flags (referenced above) that need to be corrected/enabled are set at jdk/jre build time.

sxa commented 10 months ago

@theofficialgman To be clear, which openjdk 17 jre is it you used for the output above - was it the default openjdk17 package from the Debian repositories (Which potentially has been built with specific options they've added for their OS)?

theofficialgman commented 10 months ago

@theofficialgman To be clear, which openjdk 17 jre is it you used for the output above - was it the default openjdk17 package from the Debian repositories (Which potentially has been built with specific options they've added for their OS)?

yes, the debian/ubuntu openjdk jre from the debian/ubuntu apt repos. that was already answered above with the link to the debian repository openjdk-17 rules file. If you are to ship a debian package of temurin (which you do and is what I have installed) then you need to also build with these same configuration arguments. If you do not wish to build binaries specific to the distro which you are packaging for (which is what you should do but I can understand not wanting to do that) then you should make these configuration changes for all builds.

If you want a build that is compatible with many distros then you will need to add many locations to the search path. Looking at fedora, it does use /usr/lib64 even on arm64, so that should be left in. Looking at debian/ubuntu, they use /usr/lib/aarch64-linux-gnu and similar paths. Additionally, debian/ubuntu use /usr/lib/jni on all architectures for the placement of any jni java files, fedora does not and it appears that each jni library gets its own subfolder in the /usr/lib64 path (idk if that works with the current path or not since I don't use fedora, it would need to do a recursive search to find the libraries).

tellison commented 10 months ago

/cc: @pushkarnk

gnu-andrew commented 10 months ago

The values listed for Temurin are the default values in the OpenJDK source code [0] [1]. The build produced by Debian is overriding these values using the --with-jni-libpath configure option, which ends up as the value of OVERRIDE_LIBPATH.

As it is Debian that is using non-standard locations, this is their bug. They could have placed their libraries in /usr/java/packages/lib instead of /usr/lib/jni and they would have worked with any build of OpenJDK where the library path is left unmodified.

The absence of these values is not specific to Temurin and you will encounter the same with builds from other vendors, such as Red Hat or Oracle. If Debian want to use these values, they should be contributing them upstream rather than adding them solely to their own builds. Specifying them as a configure option is fragile and prone to problems if the default values within OpenJDK are altered.

When you say that the standard library path used by Temurin breaks software, I presume that you mean it doesn't find SWT libraries installed by Debian in /usr/lib/jni, not that the software has /usr/lib/jni hardcoded into it. Note that OpenJDK does honour the LD_LIBRARY_PATH environment variable, so either you or the distribution can include /usr/lib/jni there and have it prepended to the library path as an alternative workaround.

Incidentally, the property values can be obtained via java -XshowSettings:properties -version. There is no need to write a program to print these.

[0] https://github.com/openjdk/jdk17u/blob/b78a848cc7ae5787d9ec9ea0ce843cd63b06efec/src/hotspot/os/linux/os_linux.cpp#L421 [1] https://github.com/openjdk/jdk17u/blob/b78a848cc7ae5787d9ec9ea0ce843cd63b06efec/src/hotspot/os/linux/os_linux.cpp#L492

theofficialgman commented 10 months ago

The values listed for Temurin are the default values in the OpenJDK source code [0] [1]. The build produced by Debian is overriding these values using the --with-jni-libpath configure option, which ends up as the value of OVERRIDE_LIBPATH.

yes, I showed that in the above direct link to that line in the debian rules file in the second comment. thanks for reiterating.

As it is Debian that is using non-standard locations, this is their bug.

adoptium produce debian packages of temurin and advertise them as compatible with debian/ubuntu. that makes it adoptium's bug and not debian's. the configuration option is there so that distros, packagers, and implementers can best integrate java into their system as they best see fit. debian (and downstream distros like ubuntu) chose to use their own paths and as such temurin has to follow suite. You can see that prior to this debian had to actually patch the source every time to build with their desired library path locations https://salsa.debian.org/openjdk-team/openjdk/-/commit/07281144c2dd25ba4b8262120913ca70738a6fdf . Indeed the documentation at jdk implies that distros requested for there to be a "special shared directory" for jni libraries https://github.com/openjdk/jdk17u/commit/b2bf2d252b84cdb2ece6f957df82c4337bd77c75

They could have placed their libraries in /usr/java/packages/lib instead of /usr/lib/jni and they would have worked with any build of OpenJDK where the library path is left unmodified.

the /usr folder is strictly regulated and adding a java path directly in it would not be allowed as debian follows the FHS https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch04.html .Large software packages must not use a direct subdirectory under the /usr hierarchy. and any such java library could be a "large software package"

The absence of these values is not specific to Temurin and you will encounter the same with builds from other vendors, such as Red Hat or Oracle.

These third party debian packages are not compatible with debian's chosen distribution packaging system and the third party packages from red had and oracle should be corrected as well.

When you say that the standard library path used by Temurin breaks software, I presume that you mean it doesn't find SWT libraries installed by Debian in /usr/lib/jni, not that the software has /usr/lib/jni hardcoded into it.

yes

pushkarnk commented 10 months ago

Nice discussion. My two cents:

I'd be little careful before calling this out as a bug in either Temurin packages for Debian or the latter's own OpenJDK packages installed through APT.

The use of --with-jni-libpath by Debian seems, to me, like support added for Java application packages on Debian. For example, on my Ubuntu instance, I see shared libraries related to VisualVM installed under /usr/lib/jni.

I'd say such support is good to have. However, there is no evidence that the Debian OpenJDK maintainers or the users deemed this as an OpenJDK issue. So, there was never a question of "upstreaming" this change (i.e. proposing it in OpenJDK).

So, with Temurin, which is an OpenJDK distribution, whether to have this support included is the prerogative of it's maintainers. Again, it is good to have. But, choosing to not include it and expecting the user to handle this when their Java application uses third-party JNI libraries, is also a valid opinionated choice.

PcChip commented 10 months ago

Hello,

I use Ubuntu 22.04, and use OpenWebStart for ScreenConnect in order to remote into servers. Over the past year or two, there have been numerous updates with no issues, but now this latest update it just freezes and won't open. I'm wondering if it's related to this issue - how can I collect more detailed logs to track it down?

My sincere apologies if this issue is not related to adoptium/temurin , however I do remember seeing this name mentioned during the update process so that's why I assume it's related

If this is indeed related, could someone share how I could roll this back so I can resume work?

This is what I'm seeing in my system log: image

and this is what i'm getting if i try to run javaws -jnlp ScreenConnect.client-xxx.jnlp:

[ITW-CORE][2023-12-04 10:37:38.047 CST][ERROR][net.adoptopenjdk.icedteaweb.jdk89access.JarIndexAccess] jdk.internal.util.jar.JarIndex not found
Exception in thread "ScreenConnect Client" java.lang.RuntimeException: java.lang.ExceptionInInitializerError[ITW-CORE][2023-12-04 10:37:38.047 CST][ERROR][net.sourceforge.jnlp.Launcher]
General Throwable encountered:
java.lang.ExceptionInInitializerError
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.doActivateJars(JNLPClassLoader.java:1276)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.lambda$activateJars$3(JNLPClassLoader.java:1176)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.activateJars(JNLPClassLoader.java:1177)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.initializeResources(JNLPClassLoader.java:827)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.<init>(JNLPClassLoader.java:350)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.createInstance(JNLPClassLoader.java:423)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.getInstance(JNLPClassLoader.java:495)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.getInstance(JNLPClassLoader.java:468)
        at net.sourceforge.jnlp.Launcher.createApplication(Launcher.java:584)
        at net.sourceforge.jnlp.Launcher.launchApplication(Launcher.java:373)
        at net.sourceforge.jnlp.Launcher.access$300(Launcher.java:71)
        at net.sourceforge.jnlp.Launcher$TgThread.run(Launcher.java:660)
Caused by: java.lang.RuntimeException: JarIndex not found!
        at net.adoptopenjdk.icedteaweb.jdk89access.JarIndexAccess.<clinit>(JarIndexAccess.java:39)
        ... 13 more

        at net.sourceforge.jnlp.Launcher$TgThread.run(Launcher.java:681)
Caused by: java.lang.ExceptionInInitializerError
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.doActivateJars(JNLPClassLoader.java:1276)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.lambda$activateJars$3(JNLPClassLoader.java:1176)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.activateJars(JNLPClassLoader.java:1177)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.initializeResources(JNLPClassLoader.java:827)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.<init>(JNLPClassLoader.java:350)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.createInstance(JNLPClassLoader.java:423)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.getInstance(JNLPClassLoader.java:495)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.getInstance(JNLPClassLoader.java:468)
        at net.sourceforge.jnlp.Launcher.createApplication(Launcher.java:584)
        at net.sourceforge.jnlp.Launcher.launchApplication(Launcher.java:373)
        at net.sourceforge.jnlp.Launcher.access$300(Launcher.java:71)
        at net.sourceforge.jnlp.Launcher$TgThread.run(Launcher.java:660)
Caused by: java.lang.RuntimeException: JarIndex not found!
        at net.adoptopenjdk.icedteaweb.jdk89access.JarIndexAccess.<clinit>(JarIndexAccess.java:39)
        ... 13 more

edit: in case this helps anyone else, my issue was resolved by updating to the newly released (as of 6 hours ago) OpenWebStart v1.9.0 - https://github.com/karakun/OpenWebStart/releases

Please let me know if my issue was not related to adoptium/temurin-build and I will delete my post

gnu-andrew commented 10 months ago

As it is Debian that is using non-standard locations, this is their bug.

adoptium produce debian packages of temurin and advertise them as compatible with debian/ubuntu. that makes it adoptium's bug and not debian's. the configuration option is there so that distros, packagers, and implementers can best integrate java into their system as they best see fit. debian (and downstream distros like ubuntu) chose to use their own paths and as such temurin has to follow suite. You can see that prior to this debian had to actually patch the source every time to build with their desired library path locations https://salsa.debian.org/openjdk-team/openjdk/-/commit/07281144c2dd25ba4b8262120913ca70738a6fdf . Indeed the documentation at jdk implies that distros requested for there to be a "special shared directory" for jni libraries openjdk/jdk17u@b2bf2d2

I don't see any evidence on the bug that this was requested by "distros". It seems the patch was contributed by someone who couldn't replicate the same behaviour on their own local build and kindly fixed things. Maybe they are active in Debian, I don't know, but as package maintainer for RHEL, this is the first I've heard of the option and am not aware of a consensus on this option from other package maintainers. I was expecting a patch when I first saw this issue raised and was surprised there was a configure option.

Being "compatible with Debian/Ubuntu" can mean a lot of things. At its most simple, it means it runs on that system. I think it is unrealistic for third party builds to adopt every idiosyncrasy of Debian packaging. I can't speak for Temurin on whether they want to include this or not, but there is a maintenance debt to doing so and it would be better to resolve this for all builds upstream.

On the particular case of the multiarch tuple paths, those are difficult to obtain on a non-Debian system. I recently fixed the smartcard support upstream to account for these libraries (JDK-8009550) and they had to be hardcoded. I presume on Debian systems that the jni.library.path change or another patch works around this for them, but I've again not seen any attempt to fix it upstream.

I have no qualms with Debian wanting to use their own paths, but I do believe they should be contributing support for them upstream to OpenJDK & other projects, rather than just patching their own builds. It inevitably means people see differences between Debian builds and vanilla upstream builds. We've had our own share of local patches in RHEL and we make an effort to take them upstream where we can, because it both reduces the maintenance headache for us and also avoids confusion for end users.

They could have placed their libraries in /usr/java/packages/lib instead of /usr/lib/jni and they would have worked with any build of OpenJDK where the library path is left unmodified.

the /usr folder is strictly regulated and adding a java path directly in it would not be allowed as debian follows the FHS https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch04.html .Large software packages must not use a direct subdirectory under the /usr hierarchy. and any such java library could be a "large software package"

This is a strong case for getting the path included upstream.

The absence of these values is not specific to Temurin and you will encounter the same with builds from other vendors, such as Red Hat or Oracle.

These third party debian packages are not compatible with debian's chosen distribution packaging system and the third party packages from red had and oracle should be corrected as well.

That would happen automatically if support was added and maintained upstream. I don't see individual vendors adding them locally and having to maintain their own list of library paths, especially when there is an easy workaround using LD_LIBRARY_PATH to make such builds work with the non-standard Debian paths.

gnu-andrew commented 10 months ago

Hello,

I use Ubuntu 22.04, and use OpenWebStart for ScreenConnect in order to remote into servers. Over the past year or two, there have been numerous updates with no issues, but now this latest update it just freezes and won't open. I'm wondering if it's related to this issue - how can I collect more detailed logs to track it down?

My sincere apologies if this issue is not related to adoptium/temurin , however I do remember seeing this name mentioned during the update process so that's why I assume it's related

If this is indeed related, could someone share how I could roll this back so I can resume work?

This is what I'm seeing in my system log: image

and this is what i'm getting if i try to run javaws -jnlp ScreenConnect.client-xxx.jnlp:

[ITW-CORE][2023-12-04 10:37:38.047 CST][ERROR][net.adoptopenjdk.icedteaweb.jdk89access.JarIndexAccess] jdk.internal.util.jar.JarIndex not found
Exception in thread "ScreenConnect Client" java.lang.RuntimeException: java.lang.ExceptionInInitializerError[ITW-CORE][2023-12-04 10:37:38.047 CST][ERROR][net.sourceforge.jnlp.Launcher]
General Throwable encountered:
java.lang.ExceptionInInitializerError
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.doActivateJars(JNLPClassLoader.java:1276)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.lambda$activateJars$3(JNLPClassLoader.java:1176)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.activateJars(JNLPClassLoader.java:1177)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.initializeResources(JNLPClassLoader.java:827)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.<init>(JNLPClassLoader.java:350)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.createInstance(JNLPClassLoader.java:423)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.getInstance(JNLPClassLoader.java:495)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.getInstance(JNLPClassLoader.java:468)
        at net.sourceforge.jnlp.Launcher.createApplication(Launcher.java:584)
        at net.sourceforge.jnlp.Launcher.launchApplication(Launcher.java:373)
        at net.sourceforge.jnlp.Launcher.access$300(Launcher.java:71)
        at net.sourceforge.jnlp.Launcher$TgThread.run(Launcher.java:660)
Caused by: java.lang.RuntimeException: JarIndex not found!
        at net.adoptopenjdk.icedteaweb.jdk89access.JarIndexAccess.<clinit>(JarIndexAccess.java:39)
        ... 13 more

        at net.sourceforge.jnlp.Launcher$TgThread.run(Launcher.java:681)
Caused by: java.lang.ExceptionInInitializerError
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.doActivateJars(JNLPClassLoader.java:1276)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.lambda$activateJars$3(JNLPClassLoader.java:1176)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.activateJars(JNLPClassLoader.java:1177)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.initializeResources(JNLPClassLoader.java:827)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.<init>(JNLPClassLoader.java:350)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.createInstance(JNLPClassLoader.java:423)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.getInstance(JNLPClassLoader.java:495)
        at net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader.getInstance(JNLPClassLoader.java:468)
        at net.sourceforge.jnlp.Launcher.createApplication(Launcher.java:584)
        at net.sourceforge.jnlp.Launcher.launchApplication(Launcher.java:373)
        at net.sourceforge.jnlp.Launcher.access$300(Launcher.java:71)
        at net.sourceforge.jnlp.Launcher$TgThread.run(Launcher.java:660)
Caused by: java.lang.RuntimeException: JarIndex not found!
        at net.adoptopenjdk.icedteaweb.jdk89access.JarIndexAccess.<clinit>(JarIndexAccess.java:39)
        ... 13 more

edit: in case this helps anyone else, my issue was resolved by updating to the newly released (as of 6 hours ago) OpenWebStart v1.9.0 - https://github.com/karakun/OpenWebStart/releases

Please let me know if my issue was not related to adoptium/temurin-build and I will delete my post

I think you may have more luck raising this with the OpenWebStart community at first. Nothing stands out to me immediately as being Temurin-specific, or related to this issue, but it's been a long time since I used IcedTea-Web.

theofficialgman commented 10 months ago

These third party debian packages are not compatible with debian's chosen distribution packaging system and the third party packages from red had and oracle should be corrected as well.

That would happen automatically if support was added and maintained upstream. I don't see individual vendors adding them locally and having to maintain their own list of library paths, especially when there is an easy workaround using LD_LIBRARY_PATH to make such builds work with the non-standard Debian paths.

I do not think that the "workaround" of setting LD_LIBRARY_PATH would be suitable for distros since it would then mean that the normal system libraries as well as these java jni binaries can never have the same name (otherwise one would get priority over the other depending on the order of how the library paths are defined).

Copying @doko42 (Matthias Klose) who is the openjdk uploader for debian/ubuntu for their thoughts on having the functionality of https://salsa.debian.org/openjdk-team/openjdk/-/blob/openjdk-17/debian/rules#L395 implemented upstream so that 3rd party packagers don't need to manually specify these configuration args.