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

HashMap.computeIfAbsent() adds entry that HashMap.get() does not find.

    Details

    • Subcomponent:
    • Resolved In Build:
      b59
    • CPU:
      x86_64
    • OS:
      windows_7
    • Verification:
      Verified

      Backports

        Description

        FULL PRODUCT VERSION :
        java version "1.8.0_31"
        Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
        Java HotSpot(TM) Client VM (build 25.31-b07, mixed mode, sharing)


        A DESCRIPTION OF THE PROBLEM :
        If the function supplied to computeIfAbsent adds items to the same HashTable on which the function is called from and the internal table is enlarged because of this, the new entry will be added to the wrong place in the Map's internal table making it inaccessible.

        Javadoc for Map.computeIfAbsent() is:

             * <pre> {@code
             * if (map.get(key) == null) {
             * V newValue = mappingFunction.apply(key);
             * if (newValue != null)
             * map.put(key, newValue);
             * }
             * }

        The implementation does not act this way when the internal table is enlarged.

        This was debugged using the source code for HashMap.


        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Compile are run the given test case.



        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        The entry added to the Map will be accessible. So the assert should not fail.

        assert map.containsKey(KEY);
        ACTUAL -
        Entry added is inaccessible. Assertion fails.

        REPRODUCIBILITY :
        This bug can be reproduced always.

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


        public class HashMapTest {
        public static void main(String[] args) {
        final int LIMIT = 64;
        Map<String, String> map = new HashMap<>();
        final String KEY = "key";

        map.computeIfAbsent(KEY, k -> {
        for(int i=0; i<LIMIT; ++i)
        map.put(i+"", "junk");
        return "value";

        });

        System.out.println("map.contains = "+map.containsKey(KEY));
        assert map.containsKey(KEY);
        }
        }

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

        CUSTOMER SUBMITTED WORKAROUND :
        Don't use computeIfAbsent() on HashMap. You can use the following static method workaround.

        public static <K, V> V computeIfAbsent(Map<K,V> map, K key, Function<? super K, ? extends V> mappingFunction) {
        if (map.containsKey(key))
        return map.get(key);
        else {
        V v = mappingFunction.apply(key);
        map.put(key, v);
        return v;
        }
        }

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  bchristi Brent Christian
                  Reporter:
                  webbuggrp Webbug Group
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  7 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved: