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

Native-Image Support for Java Swing LookAndFeel #10410

Open
faber222 opened this issue Jan 4, 2025 · 1 comment
Open

Native-Image Support for Java Swing LookAndFeel #10410

faber222 opened this issue Jan 4, 2025 · 1 comment

Comments

@faber222
Copy link

faber222 commented Jan 4, 2025

Currently, when compiling a Java Swing application with GraalVM (native-image), I'm encountering issues when trying to use LookAndFeel, especially the Nimbus LookAndFeel. The error occurs when the FontConfiguration tries to access the font configuration but cannot find the java.home property, resulting in a failure to start the application.

I would like to suggest full support for LookAndFeel configuration in the context of native-image. GraalVM could be improved to handle Swing configuration details, such as font and theme (LookAndFeel) loading, when packaged as native binaries.

Specifically:

  • Ensure that font and appearance configurations (like Nimbus LookAndFeel) are loaded correctly in native environments.
  • Enable the use of UIManager.setLookAndFeel() without errors related to system configuration or fonts.
  • Provide a way to correctly set the java.home property during the execution of the native binary.

This improvement would benefit:

  • Developers building Java Swing applications who want to generate native executables with GraalVM.
  • Companies or developers who need portability and performance for Swing applications on native systems.
  • GraalVM users who need a robust solution to package their Java graphical applications into native binaries.

Currently, the only alternative is to continue using the traditional JAR to distribute the application or try to avoid using themes like Nimbus, but this does not solve the problem of usability and compatibility with native-image.

The error observed occurs when trying to set the NimbusLookAndFeel, which is the default look and feel in Java Swing. The failure is related to the missing java.home configuration, which native-image does not seem to correctly set for this type of graphical application.

Here is the error I'm encountering:

Exception in thread "main" java.lang.Error: java.home property not set
        at [email protected]/sun.awt.FontConfiguration.findFontConfigFile(FontConfiguration.java:180)
        at [email protected]/sun.awt.FontConfiguration.<init>(FontConfiguration.java:97)
        at [email protected]/sun.awt.windows.WFontConfiguration.<init>(WFontConfiguration.java:41)
        at [email protected]/sun.awt.Win32FontManager.createFontConfiguration(Win32FontManager.java:175)
        at [email protected]/sun.font.SunFontManager$2.run(SunFontManager.java:352)
        at [email protected]/sun.font.SunFontManager$2.run(SunFontManager.java:309)
        at [email protected]/java.security.AccessController.executePrivileged(AccessController.java:129)
        at [email protected]/java.security.AccessController.doPrivileged(AccessController.java:319)
        at [email protected]/sun.font.SunFontManager.<init>(SunFontManager.java:309)
        at [email protected]/sun.awt.Win32FontManager.<init>(Win32FontManager.java:83)
        at [email protected]/sun.font.PlatformFontInfo.createFontManager(PlatformFontInfo.java:37)
        at [email protected]/sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:51)
        at [email protected]/sun.font.FontUtilities.getFontConfigFUIR(FontUtilities.java:484)
        at [email protected]/javax.swing.plaf.nimbus.NimbusDefaults.<init>(NimbusDefaults.java:136)
        at [email protected]/javax.swing.plaf.nimbus.NimbusLookAndFeel.<init>(NimbusLookAndFeel.java:101)
        at [email protected]/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
        at [email protected]/java.lang.reflect.ReflectAccess.newInstance(ReflectAccess.java:128)
        at [email protected]/jdk.internal.reflect.ReflectionFactory.newInstance(ReflectionFactory.java:304)
        at [email protected]/java.lang.Class.newInstance(DynamicHub.java:725)
        at [email protected]/javax.swing.UIManager.setLookAndFeel(UIManager.java:637)
        at engtelecom.App.main(App.java:41)
        at [email protected]/java.lang.invoke.LambdaForm$DMH/sa346b79c.invokeStaticInit(LambdaForm$DMH)

And this is the version:

java version "21.0.5" 2024-10-15 LTS
Java(TM) SE Runtime Environment Oracle GraalVM 21.0.5+9.1 (build 21.0.5+9-LTS-jvmci-23.1-b48)
Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 21.0.5+9.1 (build 21.0.5+9-LTS-jvmci-23.1-b48, mixed mode, sharing)

Solution for Reflection Configuration

To make sure your application works well with GraalVM's native-image and includes the necessary configurations for reflection, you can follow these steps:

  1. Prepare the Java Program:

    • Ensure your program JAR is ready (e.g., app-all.jar).
  2. Generate Reflection Configuration:

    • Use GraalVM's native-image agent to capture reflection configuration by running your application with the native-image-agent:

      java -agentlib:native-image-agent=config-output-dir=graal-config -jar app-all.jar
    • This will create a graal-config directory with JSON files containing the necessary reflection configurations.

  3. Create the Native Executable:

    • Use the native-image command with the generated configuration to create the native executable:

      native-image -H:ConfigurationFileDirectories=graal-config -jar app-all.jar
    • The executable will be created in the same directory, named based on the JAR file (e.g., app-all.exe).

  4. Troubleshooting:

    • If you encounter errors related to fallback, use the --no-fallback option to help identify the issues:

      native-image --no-fallback -H:ConfigurationFileDirectories=graal-config -jar app-all.jar
    • If any reflection-related issues arise, you can manually update or edit the JSON files in the graal-config folder to include additional methods and classes that need reflection support.

I would be happy to help contribute to this feature if needed, by providing more technical details or conducting tests. I can help identify which components need to be adjusted to properly support Swing and LookAndFeel in GraalVM.

@oubidar-Abderrahim
Copy link
Member

Thank you for reaching out about this issue, We are aware of this limitation on the native image.
The straightforward approach to resolve this issue is to run your native executable with the flag -Djava.home=<path_to_graal_installation>

Also, Instead of having the entire GraalVM installation to run your image, a better solution is to substitute it with only the missing files, for this case:

  • create a folder named lib in the same directory as your executable file and copy into it both fontconfig.bfc and fontconfig.properties.src that are found under path_to_graal_installation/lib
  • run the application with app.exe -Djava.home=.

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