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

Default implementation of ConcurrentMap::compute can throw NPE

XMLWordPrintable

    • b104
    • generic
    • generic
    • Verified

      FULL PRODUCT VERSION :
      jara@hazelpad:~/devel/oss/maven-plugins$ java -version
      java version "1.8.0_66"
      Java(TM) SE Runtime Environment (build 1.8.0_66-b17)
      Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      irrelevant

      EXTRA RELEVANT SYSTEM CONFIGURATION :
      Paul Sandoz has confirmed it's a bug. See http://mail.openjdk.java.net/pipermail/core-libs-dev/2015-December/037432.html

      A DESCRIPTION OF THE PROBLEM :
      Default implementation of `compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)` in JDK8 `ConcurrentMap` assumes map implementations do not support null values.

      This is the begin of the default implementation:

      default V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
              Objects.requireNonNull(remappingFunction);
              V oldValue = get(key);
              for(;;) {
                  V newValue = remappingFunction.apply(key, oldValue);
                  if (newValue == null) {
                      // delete mapping
                      if (oldValue != null || containsKey(key)) {
                          // something to remove
                          if (remove(key, oldValue)) {
      [...]


      Let's say we have an empty map and 2 threads:
      T1 is calling the `compute('foo', someFunction)`
      T2 is concurrently calling calling `put('foo', 'bar');`

      so the T1 will get `oldValue = null`, but `containsKey()` will return `true` - because T2 already created the mapping `foo -> bar`. Hence T1 will call `remove('foo', null)` !

      Contract of `remove()` says: `throws NullPointerException if the specified key or value is null, and this map does not permit null keys or values optional.` -> the T1 will throw NPE.


      REPRODUCIBILITY :
      This bug can be reproduced always.

        1. TestMapDefaultCompute.java
          0.6 kB
          Pallavi Sonal
        2. TestMapDefaultCompute.java
          0.5 kB
          Pallavi Sonal
        3. TestMapDefaultCompute.java
          0.5 kB
          Pallavi Sonal

            martin Martin Buchholz
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            8 Start watching this issue

              Created:
              Updated:
              Resolved: