Bug 1700927 - compiled javafx applications are not portable because of high glibc dependencies
Summary: compiled javafx applications are not portable because of high glibc dependencies
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: Fedora
Classification: Fedora
Component: java-1.8.0-openjdk
Version: 29
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
Assignee: Severin Gehwolf
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2019-04-17 16:43 UTC by Jon Harper
Modified: 2019-04-24 16:27 UTC (History)
10 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2019-04-19 09:53:28 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description Jon Harper 2019-04-17 16:43:53 UTC
Description of problem:
When compiling a javafx bundle for distribution, the fedora openjdk is copied in the bundle. Compared to some other distributions of the openjdk (e.g. oracle), the linked C symbols in some .so require high version of the glibc, which makes the app crash on other distributions. For example, building on fedora 29 crashes on ubuntu 18 because the required glibc version is 2.28 and ubuntu has 2.27.

#oracle jdk
nm jdk1.8.0_202/jre/lib/amd64/libnio.so  | grep -o @@GLIBC.*[0-9]*  | sort | uniq  -c
     90 @@GLIBC_2.2.5
      2 @@GLIBC_2.3
      3 @@GLIBC_2.3.2
      4 @@GLIBC_2.4

# fedora 28 openjdk
$ nm /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.201.b09-2.fc29.x86_64/jre/lib/amd64/libnio.so  | grep -o @@GLIBC.*[0-9]*  | sort | uniq  -c
     90 @@GLIBC_2.2.5
      1 @@GLIBC_2.28
      1 @@GLIBC_2.3
      3 @@GLIBC_2.3.2
      5 @@GLIBC_2.4
      1 @@GLIBC_2.7

$ ./hello-world
java.lang.UnsatisfiedLinkError: /tmp/gse-fedo/runtime/lib/amd64/libnio.so: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by /tmp/gse-fedo/runtime/lib/amd64/libnio.so)
	at java.lang.ClassLoader$NativeLibrary.load(Native Method)
	at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1845)
	at java.lang.Runtime.loadLibrary0(Runtime.java:870)
	at java.lang.System.loadLibrary(System.java:1122)
	at sun.nio.fs.UnixNativeDispatcher$1.run(UnixNativeDispatcher.java:573)
	at sun.nio.fs.UnixNativeDispatcher$1.run(UnixNativeDispatcher.java:571)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.nio.fs.UnixNativeDispatcher.<clinit>(UnixNativeDispatcher.java:571)
	at sun.nio.fs.UnixFileSystem.<init>(UnixFileSystem.java:67)
	at sun.nio.fs.LinuxFileSystem.<init>(LinuxFileSystem.java:39)
	at sun.nio.fs.LinuxFileSystemProvider.newFileSystem(LinuxFileSystemProvider.java:46)
	at sun.nio.fs.LinuxFileSystemProvider.newFileSystem(LinuxFileSystemProvider.java:39)
	at sun.nio.fs.UnixFileSystemProvider.<init>(UnixFileSystemProvider.java:56)
	at sun.nio.fs.LinuxFileSystemProvider.<init>(LinuxFileSystemProvider.java:41)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at java.lang.Class.newInstance(Class.java:442)
	at sun.nio.fs.DefaultFileSystemProvider.createProvider(DefaultFileSystemProvider.java:48)
	at sun.nio.fs.DefaultFileSystemProvider.create(DefaultFileSystemProvider.java:63)
	at java.nio.file.FileSystems$DefaultFileSystemHolder.getDefaultProvider(FileSystems.java:108)
	at java.nio.file.FileSystems$DefaultFileSystemHolder.access$000(FileSystems.java:89)
	at java.nio.file.FileSystems$DefaultFileSystemHolder$1.run(FileSystems.java:98)
	at java.nio.file.FileSystems$DefaultFileSystemHolder$1.run(FileSystems.java:96)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.nio.file.FileSystems$DefaultFileSystemHolder.defaultFileSystem(FileSystems.java:96)
	at java.nio.file.FileSystems$DefaultFileSystemHolder.<clinit>(FileSystems.java:90)
	at java.nio.file.FileSystems.getDefault(FileSystems.java:176)
[...]




Version-Release number of selected component (if applicable):


How reproducible:
always

Steps to Reproduce:
1. build a javafx bundle on fedora 29
2. run it on ubuntu 18.04
3.

Actual results:
doesn't work

Expected results:
should work

Additional info:

Comment 1 Mat Booth 2019-04-18 10:47:50 UTC
libnio.so is supplied by the openjdk package and not the openjdk package, reassigning

Comment 2 Severin Gehwolf 2019-04-19 08:25:19 UTC
Jon,

I'm not sure what "build a javafx bundle" means exactly and how it works. But from the stacktrace it appears it bundles JDK libs and/or the JDK runtime. If that's the case, then this behaviour is expected. Fedora OpenJDK rpm builds are distribution integrated and are as such not portable to non-Fedora distributions. From the sounds of it, you want to do bundling of the JDK. For this to have a chance of working, you'd need to start from a portable JDK build to begin with. Distribution builds of Fedora are not that. Example of libsunec.so on Fedora (they directly link to system libraries):

$ rpm -ql java-1.8.0-openjdk-headless | grep libsunec
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.201.b09-6.fc29.x86_64/jre/lib/amd64/libsunec.so
$ ldd /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.201.b09-6.fc29.x86_64/jre/lib/amd64/libsunec.so
	linux-vdso.so.1 (0x00007fffda3ff000)
	libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007fa60064e000)
	libssl3.so => /lib64/libssl3.so (0x00007fa6005f3000)
	libsmime3.so => /lib64/libsmime3.so (0x00007fa6005c8000)
	libnss3.so => /lib64/libnss3.so (0x00007fa600497000)
	libnssutil3.so => /lib64/libnssutil3.so (0x00007fa600464000)
	libplds4.so => /lib64/libplds4.so (0x00007fa60045f000)
	libplc4.so => /lib64/libplc4.so (0x00007fa600456000)
	libnspr4.so => /lib64/libnspr4.so (0x00007fa600414000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fa6003f2000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007fa6003ec000)
	libm.so.6 => /lib64/libm.so.6 (0x00007fa600268000)
	libc.so.6 => /lib64/libc.so.6 (0x00007fa6000a2000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fa600085000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fa600827000)
	librt.so.1 => /lib64/librt.so.1 (0x00007fa60007b000)
$ rpm -qf /lib64/libnss3.so
nss-3.43.0-1.fc29.x86_64

Contrast this to a portable build [1]:

$ ./bin/java -version
openjdk version "1.8.0_212"
OpenJDK Runtime Environment (build 1.8.0_212-b03)
OpenJDK 64-Bit Server VM (build 25.212-b03, mixed mode)
$ find | grep sunec.so
./jre/lib/amd64/libsunec.so
$ ldd ./jre/lib/amd64/libsunec.so
	linux-vdso.so.1 (0x00007ffc2d03b000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f70d2dc8000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f70d320a000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f70d2dad000)

Of course there remain certain dependencies still, like in your example, glibc. The approach taken to make them as portable as possible is to build on older systems, like CentOS 6, so that minimal glibc requirement will likely be satisfied. With that said, there are still systems on which those "portable" builds won't run. For example on CentOS 5, even the Oracle JDK build would likely not run.


You've got a couple of options:

1.) Use the Fedora stack, but package it as a container image.
    Run the container image on the host system you need.
2.) Get a portable OpenJDK build, use that JDK as base for your
    javafx bundle. I'm not sure whether any of them have OpenJFX
    integrated, though. So you might have to jump through some
    hoops. E.g. [1] or their vendor'ed AdoptOpenJDK builds

Currently there are no plans to ship a portable OpenJDK as part of the Fedora distribution via RPMs. So from a distribution point of view, there is little we can do.

[1] https://adoptopenjdk.net/upstream.html

Comment 3 Severin Gehwolf 2019-04-19 09:53:28 UTC
Closing this as per comment 2. OpenJDK rpm builds in fedora build with the distro glibc version (there is only one per Fedora version), hence the error is expected. Feel free to reopen if I got something wrong.

Comment 4 Jon Harper 2019-04-23 18:28:02 UTC
Hi,

Thank you for taking the time to answer. I understand your point. I'm curious though, are languages like C or go when linking statically considered the same ? IE can the fedora shipped gcc or golang be officially used to build a static binary that will run on another distro ? If so, why support it on C/go and not java ? Is it because upstream go is designed for it, whereas upstream java is not considered designed for it ?

Cheers,
Jon

PS:
> I'm not sure what "build a javafx bundle" means exactly and how it works.  But from the stacktrace it appears it bundles JDK libs and/or the JDK runtime.
Also, for the record, here's an example build of a bundle from the command line, which should point you to the relevant documentation. Your guess was pretty accurate:

# using jdk8
$ cat src/HelloWorld.java 
public class HelloWorld {
  public static void main(String[] args) {
    System.out.println("Hello World!");
  }
}
$ javac -d classes/ src/HelloWorld.java
$ javapackager -createjar -appclass HelloWorld    -srcdir classes/ -outdir out -outfile outjar -v
$ javapackager -deploy -native image -srcfiles out/outjar.jar -appclass HelloWorld -outdir out -outfile test
No base JDK. Package will use system JRE.
No base JDK. Package will use system JRE.
Creating app bundle: out/bundles/HelloWorld
$ file out/bundles/HelloWorld/HelloWorld 
out/bundles/HelloWorld/HelloWorld: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=611374360cf037f66687a6b91d3b629e9f660361, not stripped
$ /tmp/foo/out/bundles/HelloWorld/HelloWorld 
Hello World!

Comment 5 Mat Booth 2019-04-24 16:27:41 UTC
Jon, what this appears to be doing is simply bundling some dynamic so's and not generating a statically linked executable, so I don't think it's analogous to C/Go at all.


Note You need to log in before you can comment on or make changes to this bug.