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 themain
.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 themain
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.
CodePudding user response:
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.