JDK-8274768 : The whitespace separator used by java.text.NumberFormat#format(long) has changed
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.text
  • Affected Version: 13,17,18
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2021-10-04
  • Updated: 2021-10-07
  • Resolved: 2021-10-05
Related Reports
Duplicate :  
Description
ADDITIONAL SYSTEM INFORMATION :
Reproduced with on Linux Ubuntu 20.04.3 LTS. Probably OS-agnostic?

./java -version
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=gasp
openjdk version "17" 2021-09-14
OpenJDK Runtime Environment (build 17+35-2724)
OpenJDK 64-Bit Server VM (build 17+35-2724, mixed mode, sharing)

To be more precise, I have tracked down this behavior to have changed in Java 13. 

A DESCRIPTION OF THE PROBLEM :
The whitespace separator used by java.text.NumberFormat#format(long) has changed in Java 17, for the French locale (and maybe for others locales which use whitespace separators).
In Java 11, this character was: NO-BREAK SPACE (U+00A0)
In Java 17, this character is: 'NARROW NO-BREAK SPACE' (U+202F)

We have numerous unit tests which rely on this behavior, and which expect the first character.
Granted, this separator character was never officially specified by the method documentation. However:
1) there does not appear to be a rationale for modifying the previous behavior, and we assume the change to be accidental?
2) from what I can see, the second character requires for the whole String to be internally encoded as UTF-16 (two bytes per character), rather than ISO-8859-1/Latin-1, as possible with the former character. So the new behavior doubles the memory used, for all Strings formatted according to the French locale.

REGRESSION : Last worked in version 11.0.12

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the test case below

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expect the test case below to succeed, independently from the Java version used
ACTUAL -
The test succeeds with Java 11, 12,
It fails with Java 13, 14, 17, with this puzzling message: org.junit.ComparisonFailure: 
Expected :1 000
Actual   :1 000


---------- BEGIN SOURCE ----------
import java.text.*;
import java.util.*;

import org.junit.*;

/**
 * Succeeds with Java 11, 12,
 * Fails with Java 13, 14, 17
 */
public final class FrNumberFormatTest
{
	/**
	 * This was the number separator in Java 8, 11 and 12.
	 */
	private static final String NBSP = "\u00A0";

	/**
	 * This appears to be the number separator in Java 13 to 17.
	 * https://en.wikipedia.org/wiki/Template:Narrow_no-break_space
	 */
	private static final String NNBSP = "\u202F";

	@Test
	public void checkNumberFormat()
	{
		final String formatted = this.formatFr(1000);
		Assert.assertEquals("1 000", formatted);
	}

	@Test
	public void checkSeparator()
	{
		final String formatted = this.formatFr(1000);
		Assert.assertEquals(NBSP, formatted.substring(1, 2));
	}

	private String formatFr(int number) {
		final NumberFormat format = NumberFormat.getInstance(Locale.FRANCE);
		return format.format(number);
	}
}

---------- END SOURCE ----------

FREQUENCY : always



Comments
Probably it is apparent at this moment, yes this is a duplicate of JDK-8225245.
07-10-2021

Additional Information from submitter: =========================== Could the issue be related to this ticket? https://bugs.openjdk.java.net/browse/JDK-8225245
07-10-2021

The observations on Windows 10: JDK 8: checkNumberFormat failed, checkSeparator: passed JDK 11: checkNumberFormat failed, checkSeparator: passed JDK 12: checkNumberFormat failed, checkSeparator: passed JDK 13ea+20: checkNumberFormat failed, checkSeparator: passed JDK 13ea+21: checkNumberFormat failed, checkSeparator: failed JDK 17: checkNumberFormat failed, checkSeparator: failed JDK 18ea+1: checkNumberFormat failed, checkSeparator: failed
05-10-2021

The change is due to the change in CLDR which is the upstream source of JDK.
05-10-2021