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

Javadocs for java 8 version of HashMap.computeIfAbsent() is incorrect.

XMLWordPrintable

      ADDITIONAL SYSTEM INFORMATION :
      RHEL 7.5. Java 8.

      A DESCRIPTION OF THE PROBLEM :
      The java 9 Javadoc for HashMap.computeIfAbsent() states that "The mapping function should not modify this map during computation". This is an important caveat. Unfortunately the java 8 javadocs do not include this important warning despite the fact that the method is impacted by the same issue. Worse still, the java 8 implementation of the method does not throw a ConcurrentModificationException if a mapping function modifies the map - instead it can silently result in bad entries in the Map.

      REGRESSION : Last worked in version 8u192

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the attached source on java 8. It prints out many lines of text because the contents of the Map are not as expected. On Java 11 it crashes with a ConcurrentModificationException message (which is not strictly correct since it is a single-threaded process).

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The test should either work or it should fail with an error or there should be a comment in the java 8 javadocs to indicate the potential problem.
      ACTUAL -
      The test fails when loadFactor is set above 1.0.

      ---------- BEGIN SOURCE ----------
      import java.util.HashMap;

      public class CIF {
              public static HashMap<Integer, Integer> hMap = new HashMap<Integer, Integer>(2048, 100.0f);
              public static void main(String[] args) throws Exception {

                      for (int i=0; i<100000; i++) {
                              hMap.computeIfAbsent(i, k -> f(k));
                              // System.out.println("(2) " + i + " " + hMap.get(i));
                      }
                      for (int i=0; i<200000; i++) {
                              if (hMap.get(i) != i) {
                                      System.out.println(i + " -> " + hMap.get(i));
                              }
                      }
              }

              static int f(int idx) {
                      idx += 100000;
                      hMap.computeIfAbsent(idx, k -> f1(k));
                      return idx-100000;
              }

              static int f1(int idx) {
                      hMap.computeIfAbsent(idx-100000, k -> f2(k));
                      // System.out.println("(1) " + (idx-100000) + " " + hMap.get(idx-100000));
                      return idx;
              }

              static int f2(int idx) {
                      return idx+1;
              }
      }

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

      CUSTOMER SUBMITTED WORKAROUND :
      Ensure that we do not modify the map inside the mapping function - which is not a limitation mentioned in the javadocs.

      FREQUENCY : always


            psonal Pallavi Sonal (Inactive)
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: