Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8354522

Clones of DecimalFormat cause interferences when used concurrently

XMLWordPrintable

    • master
    • generic
    • generic

      ADDITIONAL SYSTEM INFORMATION :
      java -version
      java version "24" 2025-03-18
      Java(TM) SE Runtime Environment (build 24+36-3646)
      Java HotSpot(TM) 64-Bit Server VM (build 24+36-3646, mixed mode, sharing)

      A DESCRIPTION OF THE PROBLEM :
      The DigitList class used in DecimalFormat does not reset the data array in its clone method. This can cause interference when clones are used concurrently.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Save attached test case as DecimalFormatTest.java
      Run with "java DecimalFormatTest.java"



      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Sample output should report mismatchCount = 0

      ACTUAL -
      non-zero mismatchCount

      ---------- BEGIN SOURCE ----------
      import java.math.BigDecimal;
      import java.text.DecimalFormat;
      import java.util.concurrent.Executors;
      import java.util.concurrent.atomic.AtomicInteger;

      public class DecimalFormatTest {
          static AtomicInteger mismatchCount = new AtomicInteger(0);

          public static void main(String[] args) {
              DecimalFormat df = new DecimalFormat("#");
              String str = df.format(Math.PI); // initial use of formatter
              System.out.println(str);

              try (var ex = Executors.newThreadPerTaskExecutor(Thread.ofPlatform().factory())) {
                  for (int i = 0; i < 50; i++) {
                      // each thread gets its own clone of df
                      DecimalFormat threadDf = (DecimalFormat) df.clone();
                      ex.execute(makeTask(threadDf));
                  }
              }

              System.out.println("mismatchCount = " + mismatchCount);
          }

          private static Runnable makeTask(DecimalFormat threadDf) {
              return () -> {
                  for (int i = 0; i < 1000000; i++) {
                      String dfString = threadDf.format(BigDecimal.valueOf(i));
                      String str = String.valueOf(i);
                      if (!str.equals(dfString)) {
                          System.err.println("mismatch: str = " + str + " dfString = " + dfString);
                          mismatchCount.incrementAndGet();
                      }
                  }
              };
          }
      }
      ---------- END SOURCE ----------

            jlu Justin Lu
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: