Replies: 6 comments 6 replies
-
Today I tried GraalVM on Windows, which requires Visual Studio to be installed.But the effect is good after packaging. |
Beta Was this translation helpful? Give feedback.
-
@fvarrui GraalVM does not create installation packages for the various operating systems. You should be able to use the same packaging programs that you use now with JavaPackager where you would just take the native image that GraalVM creates and use it as the executable that gets installed from the package installer. I've been creating native images with GraalVM for some time now, and it can be tricky to get Java programs to compile properly with it. Especially when dealing with reflection, as the GraalVM native-image compiler does not know how to extrapolate reflection calls in the project. To handle reflection, the user would need to be instructed on how to generate the <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>${maven-assembly-plugin}</version>
<configuration>
<archive>
<manifest>
<mainClass>${mainClass}</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin> then once they have build the jar using
They then interact with the program getting it to engage all code that uses reflection then quit the app and that will place the json files in the project's <profiles>
<!--native profile-->
<profile>
<id>native</id>
<build>
<plugins>
<!-- Maven Jar Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin}</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>${mainClass}</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<!-- GraalVM Native Maven Plugin -->
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>${native-maven-plugin}</version>
<extensions>true</extensions>
<configuration>
<imageName>${imageName}</imageName>
<mainClass>${mainClass}</mainClass>
<verbose>true</verbose>
<imageName>${imageName}</imageName>
<buildArgs>
<arg>--no-fallback</arg>
<arg>--verbose</arg>
<arg>-H:ReflectionConfigurationFiles=/ProjectFolder/graalvm/reflect-config.json</arg>
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles> And create the native-image like this: mvn clean -Pnative native: compile Not sure how you would incorporate any or all of that into JavaPackager, but perhaps some of this info might help ... or not. ☺ Mike |
Beta Was this translation helpful? Give feedback.
-
@fvarrui Also, getting GraalVM to compile native-images of JavaFX projects is an art in it of itself. I've done it a couple of times, where I usually leverage GitHub Actions because that seemed to be easier, but then I did successfully build one JavaFX project locally without using GitHub Actions. If you're interested in that, I'll share the POM file with you... Actually here is that pom file ... my mistake, I guess I did use GitHub Actions to build that one too ... Here is the workflow file ... ill see if I can find the one FX project that I did manage to compile without GH Actions. |
Beta Was this translation helpful? Give feedback.
-
Hi @EasyG0ing1! Thanks so much!!! I should learn a bit more about GraalVM, and this info is a good starting point. I'm still not sure how to integrate it into JP, but it will surely be replacing/adding new ArtifactGenerators to generate Windows/Mac/Linux applications with GraalVM, and combining them with the installer generators (Setup, MSI, DEB, RPM, DMG, ...). Maybe we could keep the current behavior and have it use this GraalVM functionality when used as JDK. |
Beta Was this translation helpful? Give feedback.
-
@fvarrui - So I been thinking about this, and your statement "I'm still not sure how to integrate it into JP" is indeed the biggest hurdle if you do want to add it. Graal is an amazing tool... making native binaries out of Java code is a real treat ... code runs faster and no need for a JVM. And with that luxury comes complexity. It is by no means a one-size-fits-all compiler. This pom file setup is what I have learned works well for Java programs that don't use JavaFX and also when they don't use AWT. GraalVM doesn't really support AWT but there are things you can do to get it to work but that depends on calls your making or which AWT libraries you're using. <build>
<plugins>
<!-- Maven Compiler Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin}</version>
<configuration>
<source>21</source>
<target>21</target>
</configuration>
</plugin>
<!-- Maven Assembly Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>${maven-assembly-plugin}</version>
<configuration>
<archive>
<manifest>
<mainClass>${mainClass}</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<!--native profile-->
<profile>
<id>native</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin}</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>${mainClass}</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<!-- GraalVM Native Maven Plugin -->
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>${native-maven-plugin}</version>
<extensions>true</extensions>
<configuration>
<imageName>${imageName}</imageName>
<mainClass>${mainClass}</mainClass>
<verbose>true</verbose>
<imageName>${imageName}</imageName>
<buildArgs>
<arg>--no-fallback</arg>
<arg>--verbose</arg>
<arg>-H:+ReportExceptionStackTraces</arg>
<arg>-H:ReflectionConfigurationFiles=${project.basedir}/graalvm/reflect-config.json</arg>
<arg>-H:JNIConfigurationFiles=${project.basedir}/graalvm/jni-config.json</arg>
<arg>-H:ResourceConfigurationFiles=${project.basedir}/graalvm/resource-config.json</arg>
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles> When I compile for native-image, I do this: mvn clean -Pnative native:compile Where you see the plugins issue graal command line arguments where it is referencing a folder off the project root called graalvm. That folder is auto generated when you run your program from Java using a specific switch and you run the JAR file .... like this mvn clean package
java -agentlib:native-image-agent=config-output-dir=%PROJECT_PATH%/graalvm -jar target/ProjectName-1.0.1-jar-with-dependencies.jar I found that using the Maven Assembly plugin to make a FAT jar was the only way to go about this without needing to include all of the paths to all of the libraries in that java -jar command. But that command will monitor the program as it's running and it will spot any "out of band" calls such as SOME AWT and any reflection that is used in the program. So the idea is to run the jar using that method and then put the program through its paces so that it does everything that it can do so that the native-image assistant can see everything that needs to be included in that folder. And it just puts json files in there with specific references to the reflection calls that were used in the program. Then those command line arguments that I have in the native-mavin-plugin will use those files and include the reflection references in the final compiled code. Without doing that, the code will compile fine it just will only run until it encounters its first use of reflection then it will throw an error. I mention all of this, because I think that perhaps the most beneficial use for integrating graalvm into your project would initially be from a basic level where some of this complexity could be removed from the user. For example, perhaps you could do something where we would only need to type Also, using that basic pom file framework that I've found works well for CLI applications, perhaps that could be somehow packaged into your project. And those things alone could offer people an ability to make native-images for only certain kinds of Java programs. Which is pretty much anything that isn't JavaFX or AWT. Though gluon has a plugin for JavaFX, its primary design goal is for Android programs though I have gotten it work one or twice with a very basic JavaFX program. GitHub workflows seem to be the best way to native-image compile a JavaFX program. And of course, you have to use the graalvm JDK for all of it and anything before version 21 is a painful process because it only works with an older version of Maven making it more difficult to use. But version 21 can use the latest versions of Maven no problem. And I can't remember but that incompatibility with newer versions of Maven for the pre 21 Graalvm's might be limited to JavaFX ... but it shouldn't matter, 21 is the latest release with 22 already almost here (they offer it as a selection on their web site but then when you select it, the message comes up that says it's gonna be here soon). |
Beta Was this translation helpful? Give feedback.
-
Now
GraalVM
can generate a native app, I think it is wonderful. Why not support it?Beta Was this translation helpful? Give feedback.
All reactions