0

I have created a shaded jar which runs on java 11. Everything works fine when i have no other java version than 11 installed

But when i also install and set java home to java 8

JAVA_HOME: C:\jdk\ (Jar Working)

JAVA_HOME: C:\jdk\jre\ (Jar Not Working shows blank screen) [1]: https://i.stack.imgur.com/s28ef.jpg

Note: c:\jdk is java 8 path

Below is my pom for creating shaded jar

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>test</name>
<description>test</description>


<properties>
    <!-- Generic properties -->
    <java.version>11.0.7</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.0</version>
            <configuration>
                <source>11</source>
                <target>11</target>
            </configuration>
        </plugin>

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.2.1</version>
            <executions>
                <execution>
                    <goals>
                        <goal>java</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>

                <mainClass>GUIStarter</mainClass>
                <systemProperties>
                <systemProperty>
                    <key>prism.allowhidpi</key>
                    <value>false</value>
                </systemProperty>
            </systemProperties>
            </configuration>
        </plugin>
        <plugin>
            <groupId>com.zenjava</groupId>
            <artifactId>javafx-maven-plugin</artifactId>
            <version>8.1.3-SNAPSHOT</version>
            <configuration>
                <mainClass>GUIStarter</mainClass>
                <bundler>EXE</bundler>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-maven-plugin</artifactId>
            <version>0.0.3</version>
            <configuration>
                <options>
                    <option>--add-opens</option>
                    <option>javafx.graphics/javafx.css=ALL-UNNAMED</option>
                    <option>--add-opens</option>
                    <option>javafx.base/com.sun.javafx.runtime=ALL-UNNAMED</option>
                    <option>--add-opens</option>
                    <option>javafx.controls/com.sun.javafx.scene.control.behavior=ALL-UNNAMED</option>
                    <option>--add-opens</option>
                    <option>javafx.controls/com.sun.javafx.scene.control=ALL-UNNAMED</option>
                    <option>--add-opens</option>
                    <option>javafx.base/com.sun.javafx.binding=ALL-UNNAMED</option>
                    <option>--add-opens</option>
                    <option>javafx.base/com.sun.javafx.event=ALL-UNNAMED</option>
                    <option>--add-opens</option>
                    <option>javafx.graphics/com.sun.javafx.stage=ALL-UNNAMED</option>
                    <option>--add-exports</option>
                    <option>javafx.controls/com.sun.javafx.scene.control.behavior=com.jfoenix</option>
                    <option>--add-exports</option>
                    <option>javafx.controls/com.sun.javafx.scene.control=com.jfoenix</option>
                    <option>--add-exports</option>
                    <option>javafx.base/com.sun.javafx.binding=com.jfoenix</option>
                    <option>--add-exports</option>
                    <option>javafx.graphics/com.sun.javafx.stage=com.jfoenix</option>
                    <option>--add-exports</option>
                    <option>javafx.base/com.sun.javafx.event=com.jfoenix</option>
                </options>
                <mainClass>GUIStarter</mainClass>
            </configuration>
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.0.0</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <options>
                            <option>--add-opens</option>
                            <option>javafx.controls/com.sun.javafx.scene.control.behavior=com.jfoenix
                            </option>
                            <option>--add-opens</option>
                            <option>javafx.controls/com.sun.javafx.scene.control=com.jfoenix
                            </option>
                        </options>
                        <transformers>
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <manifestEntries>
                                <Multi-Release>true</Multi-Release>
                                <Main-Class>GUIStarter</Main-Class>
                                </manifestEntries>

                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

I Tried executing Jar from Command Prompt getting below exception on startup

java.lang.NullPointerException
    at com.sun.javafx.font.directwrite.DWGlyph.createBitmap(DWGlyph.java:287)
    at com.sun.javafx.font.directwrite.DWGlyph.getCachedBitmap(DWGlyph.java:273)
    at com.sun.javafx.font.directwrite.DWGlyph.getD2DMask(DWGlyph.java:167)
    at com.sun.javafx.font.directwrite.DWGlyph.getPixelData(DWGlyph.java:352)
    at com.sun.prism.impl.GlyphCache.getCachedGlyph(GlyphCache.java:258)
    at com.sun.prism.impl.GlyphCache.render(GlyphCache.java:148)
    at com.sun.prism.impl.ps.BaseShaderGraphics.drawString(BaseShaderGraphics.java:2101)
    at com.sun.javafx.sg.prism.NGText.renderText(NGText.java:312)
    at com.sun.javafx.sg.prism.NGText.renderContent2D(NGText.java:270)
    at com.sun.javafx.sg.prism.NGShape.renderContent(NGShape.java:261)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:578)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:578)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
    at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:578)
    at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
    at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at com.sun.javafx.tk.quantum.ViewPainter.doPaint(ViewPainter.java:479)
    at com.sun.javafx.tk.quantum.ViewPainter.paintImpl(ViewPainter.java:328)
    at com.sun.javafx.tk.quantum.PresentingPainter.run(PresentingPainter.java:91)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
    at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125)
    at java.base/java.lang.Thread.run(Thread.java:834)
Viraj Shedge
  • 1
  • 2
  • 4
  • What is in the [shaded jar file](https://docs.oracle.com/javase/tutorial/deployment/jar/view.html)? Are the Java FX11+ classes and native libraries in there that are incompatible with the JavaFX classes and native libraries in Java 8? Also, a target of 11 for the compiler will likely create Java bytecode which is incompatible with Java 8. – jewelsea May 05 '21 at 19:06
  • Also note, Java 11 does not include JavaFX, so you would need to include that in your [fat jar](https://stackoverflow.com/questions/55300695/jdk11-javafx-how-do-i-make-a-fat-jar-without-build-depdency-management), but JavaFX 8 does include JavaFX and it is a different incompatible version, so you cannot include JavaFX classes in your fat jar for execution on JavaFX 8, so I don't see how you would be able to achieve what you want and create a single Jar capable of running on both Java 11 and Java 8. – jewelsea May 05 '21 at 19:10
  • 1
    @jewelsea i dont want my jar to be able to run on both java 8 and java 11, i want my jar to run only on java 11 and for that i am providing bundled 11 jre to client and that is working fine, but when a client has pre installed java_home set to 1.8 jre it is giving me the null pointer exception which i have posted – Viraj Shedge May 05 '21 at 20:34
  • I see, that information is helpful and wasn't clear to me from your question. – jewelsea May 05 '21 at 20:59
  • Hi All, Thanks for your answers i was able to fix this issue. I had a jar org.openjfx » javafx-graphics » 11.0.2 which was giving the null pointer exception i updated the jar to version 13 and the issue was solved. So any version from 13 does not give null pointer exception. – Viraj Shedge May 09 '21 at 16:56
  • That resolution does not make a lot of sense or at least seems quite fragile if indeed it was a mixup between Java 8 runtimes and JavaFX 11+ runtimes, as those things are inherently incompatible. – jewelsea May 10 '21 at 00:37
  • @jewelsea I agree the fix does not make sense, but I just encountered the same problem with the same solution; upgrading open JavaFX version 11 -> 17 resolved the problem. Maybe an implementation issue in openjfx 11 that was solved in later versions. – MrDetail Nov 23 '22 at 22:01

2 Answers2

1

The basic answer is quite simple. JavaFX 11+ does not run on Java 8. This has nothing to do with your shading or what ever.

mipa
  • 10,369
  • 2
  • 16
  • 35
  • I know JavaFx11+ does not run on Java 8. Source and target is mentioned as 11 in maven compiler plugin. Jar is even getting executed with current version of java have checked in task manager. It is also working when environment variable java_home is pointing to jdk.Only time it is giving issue is when environment variable java_home is pointing to jre. – Viraj Shedge May 05 '21 at 13:03
1

i want my jar to run only on java 11 and for that i am providing bundled 11 jre to client and that is working fine, but when a client has pre installed java_home set to 1.8 jre it is giving me the null pointer exception which i have posted

You will need a deployment method which is independent to the JAVA_HOME setting, so that setting does not interfere with the execution of your application. The rest of this answer provides some options which might be used to achieve that.


I suggest not using the zenjava JavaFX Maven plugin, which I believe is old and unmaintained, instead use the openjfx JavaFX Maven plugin.

Shading is also likely not necessary.

Rather than shipping Java 11, you may wish to instead package the application and its required Java runtime components using the JavaFX Maven Plugin integration with jlink.

For information on jlink and how to use it in standalone mode, see this jlink man page and the Baeldung jlink tutorial.

The openjfx docs which I linked previously have info on creating a "Custom JDK+JavaFX image" which describes the process for using the jlink command line tool to create a runtime image for a JavaFX application.

However, since you are already using Maven, it is probably easier to use the JavaFX Maven Plugin's in-built integration with jlink rather than the standalone command line jlink tool. The JavaFX maven plugin integration with jlink also has an option to create a launcher script. I believe, if you use that, it will be independent of the JAVA_HOME setting in the environment (see the documentation I linked on the openjfx JavaFX maven plugin for more information on how to achieve this).

You could also make use the javapackager tool from Java 14+ to generate installers for your application if desired.


For anybody who comes across this question and is interested in mechanisms for JavaFX deployment, I believe that, currently, the first stop for information should be the openjfx documentation.

jewelsea
  • 150,031
  • 14
  • 366
  • 406