JPackage app-image exe launches multiple exe's in JDK 17+ - java

The following small Java program and jpackage command create an app-image which when launched on Windows 10 launches multiple exe's. This does not happen before JDK 17. The same code and command using the JDK 16 jpackage results in only a single instance of Main.exe running in the Task Manager Details tab. Issue appears to still happen in JDK 18 and 19.
import javax.swing.*;
public class Main {
public static void main(String[] args) {
JDialog dialog = new JDialog();
dialog.setVisible(true);
}
}
jpackage --type app-image --input jpackage_test_jar --dest install/tmp --main-jar jpackage_test.jar --main-class Main
Result (Main.exe twice in Task Manager Details)
Tested the same code and jpackage command on JDKs 15, 16, 17, 18 and 19. Multiple exe's are launched on Windows 10 in JDKs 17, 18 and 19, but not in 15 or 16. JDK 15 was from AdoptOpenJDK, the rest were Eclipse Temurin from Eclipse Adoptium.

Related

Java program uses wrong locale when jpackaged

I am parsing strings representing German-style numbers (i.e., decimal comma and optional full stop for grouping thousands), e.g., "2.804,13"; this is just done using a DecimalFormat based on my desired Locale:
package loc_test;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Locale;
public class ParseNumbers {
static final DecimalFormat df = (DecimalFormat) NumberFormat.getNumberInstance(Locale.GERMANY);
public static void main(String[] args) throws Exception {
for (String s : new String[] { "2.815,53", "2815,53" }) {
System.out.println(String.format("%s \t-> %s", s, df.parse(s)));
}
}
}
This gives the desired output, e.g., when compiled and run from the command line:
2.815,53 -> 2815.53
2815,53 -> 2815.53
However, when I bundle it as a jpackage image (./gradlew jpackageImage using Gradle and the Badass Runtime Plugin) and run the resulting binary, the output seems to indicate that a wrong locale is used:
2.815,53 -> 2.815
2815,53 -> 281553
I have tried out a few things (in vain), and the problem does not seem to be in the code itself:
Added Locale.setDefault(Locale.GERMANY) in the main. Locale.getDefault() will show the German locale, but it has no effect.
Explicitly set -Duser.country=DE and -Duser.language=de via Java command line parameters. System.getProperty(...) shows the expected values, but again, no effect. (Also, from the command line, it also works with these being set to the system defaults.)
Added -Djava.locale.providers=COMPAT,CLDR,SPI to the jpackage Java command line parameters (from this thread). Again, I can verify from the main that the property is set correctly, but it makes no difference. (And seems to have been an issue with earlier Java versions anyway.)
I have seen the problem first using Java 16 with Gradle 7.2; and it has persisted after an update to Java 17 and Gradle 7.3. The problem has occurred both on an English Linux system and a German Windows machine.
Using --info with the jpackageImage command, Gradle shows me which JDK it is using:
Starting process 'command '.../.gradle/jdks/jdk-17+35/bin/jpackage''. Working directory: .../LocTest/app Command: .../.gradle/jdks/jdk-17+35/bin/jpackage --type app-image --input .../LocTest/app/build/install/app/lib --main-jar app.jar --main-class LocTest.App --dest .../LocTest/app/build/jpackage --name app --runtime-image .../LocTest/app/build/jre --java-options -Duser.country=DE --java-options -Duser.language=de --java-options -Djava.locale.providers=COMPAT,CLDR,SPI
When I use that .gradle/jdks/jdk-17+35/bin/java to run the class, i.e., run:
~/.gradle/jdks/jdk-17+35/bin/java -cp app/build/classes/java/main loc_test.App`
With this, the problem does not occur; the numbers are correct.
However, the problem does occur when I use the (supposedly same) JRE bundled with the jpackage image, i.e., I get the wrong numbers using:
./app/build/jpackage/app/lib/runtime/bin/java -cp app/build/classes/java/main/ loc_test.App
Why would the java, when packaged, ignore the locale?
Am I missing something here, or might this be a bug in jpackage or the plugin, or in the Java release itself?
The whole Gradle example project (very small) can be found at Github.
Check what modules are included in your runtime image.
For example when I run java --list-modules on JDK 17 I notice this module:
jdk.localedata
I don't know if it is required for this, but I bet that module isn't being included by jpackage unless it is specifically requested.
Run ./app/build/jpackage/app/lib/runtime/bin/java --list-modules and compare with ~/.gradle/jdks/jdk-17+35/bin/java --list-modules to confirm. Then consider making an image with jlink that includes jdk.localedata if it was missing to test this hypothesis.

Java program that is installed by a packaged installer (created with jpackage) runs in the background(doesn't open any window) - bug

I am new to java. Before I get straight to the point, let me introduce to you where I currently am. Sorry for the long story.
I made a packaged installer for my app with jpackage. I packaged a simple hello world program for the first time, just to test the jpackage command. Once it produced the packaged installer, I installed my hello world program with it.
Then I went to C:\Program Files\Hello World and then executed the HelloWorld.exe file.; but nothing happened. To debug the issue, I rebuilt the HelloWorld.jar file with an infinite loop at the end. Then I repackaged and reinstalled the program again. Then I ran the HelloWorld.exe again.
However, this time I saw a blue circle at my mouse's cursor for quite some time. So I opened task manager scrolled down, and then I found the HelloWorld program running in the list of background processes! Here is a screenshot:
screenshot of task manager
So, this is my question: Why is my java application, which I created with a packaged installer created by packaged, running in the background? Why isn't it opening any console windows?
EDIT: I forgot to include the command that I used to create my packaged installer. Here it is:
jpackage -t exe --name HelloWorld --input D:\Fida\Codeblocks\Java\Projects\HelloWorld\dist --dest D:\Fida\CodeBlocks\java --main-jar HelloWorld.jar --module-path "C:\Program Files\Java\jdk-16.0.1\jmods" --add-modules java.base --description "Hello World Program" --app-version 1.0.0 --vendor Fida --icon D:\icon_file.ico --copyright Fida --win-shortcut --win-menu
In order for a console to be shown when running the application, you must add the --win-console option when invoking jpackge:
Platform dependent option for creating the application launcher:
--win-console
Creates a console launcher for the application, should be
specified for application which requires console interactions

How can I make a native linux app executable in linux as part of JPackage installation

I am packaging a Java application (called Jaikoz) using JPackage (Java 14) for linux.
The java application has to sometimes call a c program called fpcalc64, on installation it gets stored in the app folder, but it only has rw permission
Question 1
Is there a way I can give it execute permission as part of install ?
Question 2
Even if I manually go into the app folder and use chmod 777 fpcalc64 to give full execute permission, it still doesn't run and my Java program complains it doesn't have permission, this continues to happen even if I restart the application, how can this be ?
e.g
Fails
Jul 4, 2020 11:17:46 AM: WARNING: Unable to retrieve an acoustic id for song 2 file /home/ubuntu/Downloads/RedSharp_-_Walk_in_the_row.mp3 because Cannot run program "/home/ubuntu/code/jthink/jaikoz/JaikozAppImage/jaikoz/lib/app/fpcalc64": error=13, Permission denied
But if I run from linux shell it works
ubuntu#ubuntu:~/code/jthink/jaikoz/JaikozAppImage/jaikoz/lib/app$ ls -l fpcalc*
-rwxrwxrwx 1 ubuntu ubuntu 2210876 Jul 4 11:15 fpcalc
-rwxrwxrwx 1 ubuntu ubuntu 2249272 Jul 4 11:15 fpcalc64
ubuntu#ubuntu:~/code/jthink/jaikoz/JaikozAppImage/jaikoz/lib/app$ ./fpcalc64 /home/ubuntu/Downloads/Red*
FILE=/home/ubuntu/Downloads/RedSharp_-_Walk_in_the_row.mp3
DURATION=273
FINGERPRINT=AQADtIsURmsSDc9i44-Iqsemr8a1MIOXKBHCi9CJ0M7R-MH5oNNy_Dp26ag55EmUJ5DjI-zREE-P9wz-odeKCyGbHXriIj8qbiYaPRue4_zx7MHHE1eiw1yE80d1IdmDnDy-LCeub_gVVLkGP8uHmTNhVjkicUeyh0MTHs_RE8-Jurg7XItwHVl-aFmHPGMq_Al-NCGFx0d6adD6I39RnQoaTXmK48JhTqOM58R19LED8yBf9LvQo1GW4viRk4Qm6cUvpHlRi8dn9MngFqRy-EdGlNPxHbp8oR8aLnvBLkb_4I8KS9Kh57jEKsOv4nD04UeZmZDyC64efLB1jK8Oj8hP-BSuF7aQ92h-4h1eKJJ1wYErregFzTWaH_m14Q--o9nsEe47Ij_EG33GI8e14xQf1Eifo5Z03IeeK2C0ODGaD6xl5Kh9OD68HdfwhuiPH33x9kg7HdpRuQgjnbiOe8Sn0EJt-AsR6sVxPQr65vg0aM8KjeTB5Hi4RviLJqYI7QoqsTApR4PPJwi_9LiHJmWCfmiyODWYX0OTLzfCB1c-4UQf6Dj0p3gH7xH8o8-Ja4rxoz--CHpy-EWPH_2h5dODUoaWmDmeo4ko5UKbzQquNJmGypnRfIEmkUEeRcZzVNwSBv3RsBo4dUZu6HKHrgkk-aiVPUR-vNJQ-WgYx-ija7hGZCc0_ngQ6gt8432Cpk6Fp0dzIjx03AjThOGO5lfwLMWF9MIX5Qp0NFn04w5vNFUufNGhpWJcPIrR4CS-5RHK_9BSDXcIPyZ-HOdBv3hQbjKafxA8adXw49OFPEWjFrWy42FD9Irh6sgrodEuPG0CmclSXNA6wmMGbb3QTTwa8cGDPoPHHddycXijBdKNvGD-4CyRb8F3wV-c4LXBKxHywNlB9kf3C7YeNHQCcsaJ_IOWPZEQHz-e6DhFnFFwIvyhE2ePfDnyY8pz6IJ1uMoO7WGIp8fXM9gqpsITdNnRkDu0RYdjPcHHoMl_qL4F9gjDMSUOKj8YTlF8NDtRoeqGpjv4MwiTN4WG-OFhTUuMVUly9FHRcD3wHTl0ZUO46miyfcFz1Dr8HLYZtMtxS0P4Q26OfBpcFd-xySx64gadHWF2QeYxHb8SCuWSHV6iS3gG44fHoM0wLzqa8NvxV3ihmUeuXLiUXeiF5iCPlzijWEIiqk-QH490PDnqo3mOv-Dk44qMTyEajauCqyfCvNAzNOPRL7hyQs3AH8e-ZBx6K_CPib3AaMrRKMePoel79Ieu4seXD0-uQI_RrDOGcsFz_CG-Q6OPs4fxHY90KNdKuOqPThX2x2jqoFV2BXK0R9Cpw8-KnIyPH48O7ngySujbJPAyFln4Qz-meCtKXSPy4zq6oqlyfDu-6MFNo3kQXtARcXvw4Dn6rQkY5ccVBv5wSTVyXKIOPVEOLUm_oC_2aGhqtAuaS0XZQ-ml4dC_4x_6TEO-qPBuHFRSHWEfmTjyb2ge9PEwnDhznEeYZw4OHdEzo8-L97gSXPLxojn7IKShbw_KHmEaBedBeifK4_sRppK64HkLXXnwHc0JbT8eqUT84OTxobKI9chv6PAe1CqDXEEppceRE1Oh6wquD_mM__B5ZGfx5YSu1OjRaH_QC9cOmWkBVzNYhkG1FxXFB155pE7wE39wTkmPSqeGI48P7UWqLqh19EfzlAS_408RXvDRHjpx4X6CHrkTGF15PEd2PUOrPPBxirg147tQlcepoz-a57gYEXqO3oOZN1AdPNMRWsePatsxRUd05oLuEz--En-HNq4Cxy0xrUflHmKVY3eh5Tl-_EPtUAg3H3m1GB3roWEkgQ9raOFHhA_hE99w6qjFw9pmdC06Ssh9MN3xB-mk4sLZTkV5mJPg6UevNjhlXLrQIFTUqZDyIf3xo77wpWiFO0HzCz_y458CPcOPhmCeDJcfPDjaw1aOE99YOCf0Hb-KJ6oAXTLxIz6u5YJvF33RH3ZytMgP6D_aa_iF_RE2hzCjKAFO9mj2GMc7Bs-O_6FwC02g9Qf35Xge4kPeG0ye43mCWjROvEa8Cc2Xoudx5Ceeo-Ee_PgjtfAT_Pjg_sgH-Q_C_MS9FGel4fjAMqimg8n649uDnEH1QfnhaUerHFeP_hGa88iF_sfV4WQ1nMfWC0dKp9BDNF9oPMFx_dDuIb3wk_CFtyZRXA7-4NNBTpa0IMweyEc-pnCVHJ8eWDum48sPxMWe51C9GY2eDvuFh1kCOdmxK4zQR-gPP8YZWjDXeNCXzLDmHNUjHFS-4hp-4moQi3yOU0IfNLJyXNJl9Dya7PmGf0d2aMdD9UhDJTpOYdyyoLrw40yOPCJ0lkH1G34t6MyPNEsiXSi1WegrWDn6rXh49N8RrSIS6zt85uiNP_hBEz4xysJnhCp1XDo-VVJg5slw4D0q4Uoe_KiuFL6CHipd5AmLRw-aL3GKacGRJzqSO3FwJi9-4c6Ekzm2G5eOW7GQK8pHNLF0dMWVQ2wm44FGIgxfvBSeJ8N9TAmp4LngXngraUGkLJAb9EOjkfg-4nF8bHqg8wKeHFf2oPqD5j_UDz_eLMV1fLlRwyPRZyyU7_jwREaYaWjH42WTEI2-ok6KXFGIH-KY-PiO64fOo3uQxtHhSaSIp0_gE0e6EhV1QldyGfl8-ErxCx-e6LiyNLiCKecBghQiADHAADJMAGeMMFoQAYA0kgCECSNEEKIQIIAII5QwBhACHABGAKWEEo4oQgVjggIBERGAOYGQIqgxJIBEAihHkQIMIWGAAggJBIAgAhEhkCJCQMEUMQQqIpQCQhgFhNUAAAIAck4IQQABLhEBgEHCGCMUUERgDARhQCipmEBACFgQAIIITZAAABACiABACGFIYEsAIoFQABoIFEgICAECAgI4AQggyghIgQNeCAMEIYAwgARCTgiSADCMUkGEIUAQwhgBQgABhJCKWEIFssAAaZQxQjFiiGKCCAGAUIAYo4RCkCEggCJSCEiBIcAwQokQBgECCJIECCUEM1ABBAgRkAICDCLCEEOEQwIRQRhCwFkAEGQGCY8UQ0AQAS4SAAhBFDEEWAEYIYwJoygAghmKAEAKEQIAEvIoQoAkCgJhiEKKECYgI8YhIglgyBgCACJAIASEMEgoooQRSCLCACGEGAMQIIQxJKBAwBgIkFBIAEMAIQQapZwzQgmBiCKIEeG5AUgYAwwDQhAEFHBAMAWIAA4QZCARyEKAIDHEEqIMAAQAYYAUFgBLjAACGYaAEIoAxggCgghiBEBgGGAAQ4AhAgAiBjkBAUHGEIeAABRQI4gAgBmhBCLGMQSAA8QJgBQABhlnFKAAAEqYAAYI5ABSTiilBBIGCMGoMGIAYRBghiEjgGACEUOREIICgQgASBklCHBAAIEUAgQBZgQSApCDlEKQAAIUcgYwA4AhgCpkgEAKGgQVUIYAxYASwDCiHALAEQcUAMICIQhRABJAiGYIACMIQUQgRYAzBCjABAHOACAUA0YQAABwRCIBwEFcCAIAAkAQgQgxDAgigDAKSEaQYEwQRBgSBjEhDDJIEOUEQUgBQqhBxAiACAMECEoYYYQRYYAQABkEEBBECEYEQoYQBBkSBBggiUFAAiIIIUKyIggABACAAAIDAA
Question 3
Do I have to store fpcalc64 in the bin folder rather than lib/app. If I do how do I do that, it is a precompiled binary ?
I found the solution (something I had hit before).
Since Java 9 when you call an external app with Java on linux is uses lib/jspawnhelper to decide how to run the application. Because I provided linux runtime but the runtime was built on Windows when it was checked into source control it had lost any execute permissions. Therefore when my application complained about permissions it was actually complaining about permissions on jspawnhelper.
I also found that if you do set the permissions they will be respected when you build the package. I didn't realize this because previosly I was building linux installer on Windows and had to add extra commands to Izpack installer to make them executable.
So in summary the solution was to set execute permissions on jspawnhelper and fpcalc and commit to source control, then Jpackage would work.

Embedding a Java application packaged as a jlink image in a macOS app

I am trying to embed a Java application into a native Mac app. The Java application is packaged with jlink (Java 9+) including a stripped down JRE.
I'm trying to use the Java Invocation Interface to create the JVM and launch the main class, but the program crashes at the the point where JNI_CreateJavaVM is called, because it can't find libjava.dylib.
In my Xcode project, I have a "Copy Files" phase that copies the entire jlink image (the folder containing bin, lib, etc. directories) into the application bundle, into the Contents/image directory.
$ ls -l Java\ Native\ Wrapper.app/Contents/image/
total 8
drwxr-xr-x 11 ahs staff 352 Jan 13 12:46 bin
drwxr-xr-x 6 ahs staff 192 Jan 13 12:46 conf
drwxr-xr-x 25 ahs staff 800 Jan 13 12:46 legal
drwxr-xr-x 52 ahs staff 1664 Jan 13 12:46 lib
-rw-r--r-- 1 ahs staff 717 Jan 13 12:46 release
The dylib file is there:
$ file Java\ Native\ Wrapper.app/Contents/image/lib/libjava.dylib
Java Native Wrapper.app/Contents/image/lib/libjava.dylib: Mach-O 64-bit dynamically linked shared library x86_64
My Objective-C code links against the JNI library in lib/jli/libjli.dylib. Xcode automatically copies it into the Frameworks directory of the app bundle.
When I run the program, I get the following error on the console:
Error: could not find libjava.dylib
Failed to GetJREPath()
I added the image/lib directory to the runtime search path. Inspecting the binary with otool confirms it:
$ otool -l Java\ Native\ Wrapper
...
Load command 18
cmd LC_RPATH
cmdsize 48
path #executable_path/../Frameworks (offset 12)
Load command 19
cmd LC_RPATH
cmdsize 48
path #executable_path/../image/lib (offset 12)
...
I am really stumped here. I've tried copying the dylibs to the Frameworks directory, that didn't work.
What am I doing wrong?
It should work just fine. If I create user specific variable - JAVA_HOME (User-Defined Settings) and set it such way it points to jlink based version of Java.
JAVA_HOME: $(HOME)/tmp/jdk-13-stripped
and then, I make sure to add: $(JAVA_HOME)/jdk-13-stripped/lib as a resource (it will end up inside Resources dir of the final application) and then, I set following settings:
Run Search Paths: #executable_path/../Resources/lib/server
Header Search Paths: $(JAVA_HOME)/include and $(JAVA_HOME)/include/darwin
Library Search Paths: $(JAVA_HOME)/lib/server
Other Linker Flags: -L$(JAVA_HOME)/lib/server -ljvm
and then, I run the code
> ./CallJVM
Hello from Java
If I check which image was loaded, it is taken from the proper location
> lldb CallJVM
(lldb) image list
...
...
[ 7] .... .../Debug/CallJVM.app/Contents/Resources/lib/server/libjvm.dylib
Update
In case someone needs video tutorial related to this topic, here you go: Embedding JVM inside macOS application bundle (using XCode)

Running JavaFX jar on Ubuntu

I'm unable to run jar files of JavaFX applications on my Ubuntu virtual machine and I don't know why. It just says that it can't find the main file of the jar. Other jars of for example Swing applications seem to work fine. This is what I get when I run java -version on Ubuntu:
It seems like it has Java 8 where JavaFX should be included by default, so why can't I run the jars?
Edit: The jar consists of one class that looks like this:
import javafx.application.Application;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {launch(args);}
public void start(Stage ps) {
ps.show();
}
}
And it was created with the command jar cfe javafxjar.jar Main Main.class
The jar executes without problems on Windows 10, but fails with this message on Ubuntu:
Today I've also bumped into this problem.
In my case the reason was OpenJDK.
It does not contain OpenJFX by default.
The solution was: sudo apt-get install openjfx
And now all works like a charm.
Could it be due to the JAVA_TOOL_OPTIONS:
$ unset JAVA_TOOL_OPTIONS
$ java -jar javafxjar.jar

Categories