Skip to content
Advertisement

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:

  1. Added Locale.setDefault(Locale.GERMANY) in the main. Locale.getDefault() will show the German locale, but it has no effect.
  2. 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.)
  3. 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.

Advertisement

Answer

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.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement