Skip to content
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

Exception in Native Image Application Start with Ikonli #170

Open
infinite-dev22 opened this issue Jan 26, 2025 · 5 comments
Open

Exception in Native Image Application Start with Ikonli #170

infinite-dev22 opened this issue Jan 26, 2025 · 5 comments
Assignees
Milestone

Comments

@infinite-dev22
Copy link

Description

When attempting to run a JavaFX application using Ikonli in a native image compiled with Liberica NIK, the application fails to start and throws the following exception:

Exception in Application start method
Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
	at [email protected]/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:893)
	at [email protected]/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:196)
	at [email protected]/java.lang.Thread.runWith(Thread.java:1588)
	at [email protected]/java.lang.Thread.run(Thread.java:1575)
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:837)
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:813)
Caused by: java.lang.ExceptionInInitializerError
	at org.kordamp.ikonli.javafx.FontIcon.lambda$new$2(FontIcon.java:76)
	at [email protected]/com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:386)
	at [email protected]/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:91)
	at [email protected]/javafx.beans.property.ObjectPropertyBase.fireValueChangedEvent(ObjectPropertyBase.java:106)
	at [email protected]/javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:113)
	at [email protected]/javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147)
	at [email protected]/javafx.css.StyleableObjectProperty.set(StyleableObjectProperty.java:123)
	at org.kordamp.ikonli.javafx.FontIcon.setIconCode(FontIcon.java:231)
	at org.kordamp.ikonli.javafx.FontIcon.<init>(FontIcon.java:97)
	at inc.nomard.spoty.features.authentication.layout.KYCLayout.buildCloseButton(KYCLayout.java:203)
	at inc.nomard.spoty.features.authentication.layout.KYCLayout.init(KYCLayout.java:197)
	at inc.nomard.spoty.features.authentication.layout.KYCLayout.<init>(KYCLayout.java:49)
	at inc.nomard.spoty.features.authentication.view.AuthScreen.buildContentPane(AuthScreen.java:132)
	at inc.nomard.spoty.features.authentication.view.AuthScreen.init(AuthScreen.java:160)
	at inc.nomard.spoty.features.authentication.view.AuthScreen.<init>(AuthScreen.java:41)
	at inc.nomard.spoty.Main.createPrimaryScene(Main.java:57)
	at inc.nomard.spoty.Main.initializePrimaryStage(Main.java:38)
	at inc.nomard.spoty.Main.start(Main.java:126)
	at [email protected]/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:839)
	at [email protected]/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:483)
	at [email protected]/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:456)
	at [email protected]/java.security.AccessController.executePrivileged(AccessController.java:132)
	at [email protected]/java.security.AccessController.doPrivileged(AccessController.java:400)
	at [email protected]/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:455)
	at [email protected]/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
	at [email protected]/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
	at [email protected]/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$10(GtkApplication.java:264)
	... 4 more
Caused by: java.lang.NullPointerException
	at org.kordamp.ikonli.javafx.IkonResolver.<clinit>(IkonResolver.java:45)
	... 31 more

The root cause appears to be a NullPointerException in the static initializer of IkonResolver. This issue seems to prevent the proper initialization of FontIcon and subsequently crashes the application.

Steps to Reproduce

  1. Create a JavaFX application that utilizes Ikonli FontIcon.
  2. Compile the application into a native image using GraalVM.
  3. Run the compiled native image.

Expected Behavior

The application should start successfully and display the JavaFX UI with the Ikonli icons.

Actual Behavior

The application crashes on startup, with the above exception being thrown.

Environment

  • Ikonli Version: 12.3.1
  • JavaFX Version: 23
  • JDK Version: JDK 23.0.1
  • Native Image Tool Version: Liberica NIK 24.1.1 Full
  • Operating System: Ubuntu 24.04

MRE

private FontIcon buildIcon() {
        var icon = new FontIcon(FontAwesomeSolid.CIRCLE);
        icon.getStyleClass().add("close-icon");
        icon.setIconSize(15);
        return icon;
    }

Logs and Stack Trace

Full stack trace is provided above.

@aalmiray
Copy link
Collaborator

Line 45 points to

String fontResource = handler.getFontResource().toExternalForm();

Which may be causes by missing resources in the native image. One way to solve this is for your app/consumer to explicitly lists resources that should be added to the native image.

Going forward, Ikonli could provide metadata files to include these resources.

@aalmiray aalmiray self-assigned this Jan 26, 2025
@infinite-dev22
Copy link
Author

Thank you for the prompt response! Explicitly listing resources that should be adde to the native image does the trick. My reflect-config.json file has the following content:

[
    {
        "name": "org.kordamp.ikonli.fontawesome",
        "allDeclaredConstructors": true,
        "allPublicConstructors": true,
        "allDeclaredMethods": true,
        "allPublicMethods": true
    },
    {
        "name": "org.kordamp.ikonli.bootstrapicons",
        "allDeclaredConstructors": true,
        "allPublicConstructors": true,
        "allDeclaredMethods": true,
        "allPublicMethods": true
    },
    {
        "name": "org.kordamp.ikonli.material",
        "allDeclaredConstructors": true,
        "allPublicConstructors": true,
        "allDeclaredMethods": true,
        "allPublicMethods": true
    },
    {
        "name": "org.kordamp.ikonli.materialdesign",
        "allDeclaredConstructors": true,
        "allPublicConstructors": true,
        "allDeclaredMethods": true,
        "allPublicMethods": true
    },
    {
        "name": "org.kordamp.ikonli.Ikon",
        "allDeclaredConstructors": true,
        "allPublicConstructors": true,
        "allDeclaredMethods": true,
        "allPublicMethods": true,
        "allDeclaredFields": true,
        "allPublicFields": true
    },
    {
        "name": "org.kordamp.ikonli.IkonHandler",
        "allDeclaredConstructors": true,
        "allPublicConstructors": true,
        "allDeclaredMethods": true,
        "allPublicMethods": true,
        "allDeclaredFields": true,
        "allPublicFields": true
    },
    {
        "name": "org.kordamp.ikonli.fontawesome5.FontAwesomeSolidIkonHandler",
        "allDeclaredConstructors": true,
        "allPublicConstructors": true,
        "allDeclaredMethods": true,
        "allPublicMethods": true,
        "allDeclaredFields": true,
        "allPublicFields": true
    }
]

@aalmiray
Copy link
Collaborator

One thing is to specify reflection settings, another is to define which resources should be included. Did you provide both?

@aalmiray
Copy link
Collaborator

Just to be sure, I'm talking about a file like this one https://github.com/jreleaser/jreleaser/blob/main/plugins/jreleaser/src/main/resources/META-INF/native-image/org.jreleaser/jreleaser/resource-config.json where the font file should be included.

@aalmiray aalmiray added this to the 12.4.0 milestone Jan 27, 2025
@infinite-dev22
Copy link
Author

One thing is to specify reflection settings, another is to define which resources should be included. Did you provide both?

I only specified reflection settings

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants