Native libraries: Java FX load conflict in multiple classloaders
See original GitHub issueHello @mordechaim, I am running a business application through an update4j launcher application. (My main method, not delegate mode.)
Then I create a Windows installer using jpackage, and distribute a custom JRE created by jlink
and the following modules:
java.base,java.desktop,java.xml,jdk.unsupported,jdk.unsupported.desktop,java.sql,java.scripting,jdk.xml.dom,jdk.jsobject,java.naming
The Java FX modules are loaded on the business app’s modulepath using update4j.
When I run the installed application, it updates and works fine, until it needs to display a Java FX window. Then it crashes with a chain of exceptions that the DLLs are already loaded in a different classloader. (The same error is displayed for every dll.)
Loading library api-ms-win-core-console-l1-1-0 from resource failed: java.lang.UnsatisfiedLinkError: Native Library C:\Users\win\.openjfx\cache\11.0.2\api-ms-win-core-console-l1-1-0.dll already loaded in another classloader
java.lang.UnsatisfiedLinkError: Native Library ${user.home}\.openjfx\cache\11.0.2\api-ms-win-core-console-l1-1-0.dll already loaded in another classloader
at java.base/java.lang.ClassLoader$NativeLibrary.loadLibrary(Unknown Source)
at java.base/java.lang.ClassLoader.loadLibrary0(Unknown Source)
at java.base/java.lang.ClassLoader.loadLibrary(Unknown Source)
at java.base/java.lang.Runtime.load0(Unknown Source)
at java.base/java.lang.System.load(Unknown Source)
at javafx.graphics/com.sun.glass.utils.NativeLibLoader.installLibraryFromResource(NativeLibLoader.java:214)
at javafx.graphics/com.sun.glass.utils.NativeLibLoader.loadLibraryFromResource(NativeLibLoader.java:194)
at javafx.graphics/com.sun.glass.utils.NativeLibLoader.loadLibraryInternal(NativeLibLoader.java:135)
at javafx.graphics/com.sun.glass.utils.NativeLibLoader.loadLibrary(NativeLibLoader.java:53)
at javafx.graphics/com.sun.javafx.tk.Toolkit.loadMSWindowsLibraries(Toolkit.java:172)
at javafx.graphics/com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:212)
at javafx.graphics/com.sun.javafx.perf.PerformanceTracker.logEvent(PerformanceTracker.java:100)
at javafx.graphics/javafx.scene.Node.<clinit>(Node.java:408)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Unknown Source)
at java.base/java.lang.reflect.ReflectAccess.newInstance(Unknown Source)
at java.base/jdk.internal.reflect.ReflectionFactory.newInstance(Unknown Source)
at java.base/java.lang.Class.newInstance(Unknown Source)
at classpath//javafx.fxml.FXMLLoader$InstanceDeclarationElement.constructValue(FXMLLoader.java:1019)
at classpath//javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:754)
at classpath//javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2722)
at classpath//javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2552)
at classpath//javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
at classpath//javafx.fxml.FXMLLoader.load(FXMLLoader.java:2435)
at classpath//com.my.JavaFXScreen.<init>(JavaFXScreen.java:53)
My presumption is that this conflicts with how update4j loads the libraries. (Could there be a potential solution found here?) https://stackoverflow.com/questions/36936948/java-lang-unsatisfiedlinkerror-native-library-xxx-so-already-loaded-in-another
Issue Analytics
- State:
- Created 4 years ago
- Comments:14 (8 by maintainers)
Top GitHub Comments
Ok, the issue most likely is
FXMLLoader
looking at the wrong classloader. Checkout the documentation forLaunchContext.getClassLoader()
and see how I did it in the demo business app. If you useDynamicClassLoader
you don’t need this, it will just work.Anything else seems to me like a pure configuration issue, and the Maven artifacts nicely handles the configuration for you. Perhaps you should mark the native files for classpath and loaded dynamically? I haven’t tried it myself, so can’t tell. Again, using
DynamicClassLoader
as the system class loader should workaround this issue.Please note that if you don’t include the JavaFX modules when linking with jlink, the platform-specific binaries of JavaFX are not included in the jlink image. Therefore, when you try to load the JavaFX modules, you get exceptions. I was trying to do the same in my project in order to keep JavaFX jars together with my application jars (and separate from the base image), but I never found a way to just include the JavaFX binaries in the image and leave the JavaFX jars outside the merged modules file. Therefore, I think this has nothing to do with update4j.
PS. If you ever figure this out, I would be very interested to know the way you did it.