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

ClassValue::remove cannot ensure computation observes up-to-date state

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 25
    • 25
    • core-libs
    • None
    • master
    • Fix failed

      ClassValue::remove does not halt ongoing computations. As a result, a later-installed value may not observe the state changes that happens-before the removal call if the computation began before the remove call, which is almost impossible to guarantee without external synchronization, defeating the point of ClassValue.

      See example:

      AtomicInteger input = new AtomicInteger(0);
      ClassValue<Integer> cv = new ClassValue<>() {
          @Override
          protected Integer computeValue(Class<?> type) {
              // must get early to represent using outdated input
              int v = input.get();
              try {
                  Thread.sleep(COMPUTE_TIME_MILLIS);
              } catch (InterruptedException ex) {
                  throw new RuntimeException(ex);
              }
              return v;
          }
      };
      var innocuous = Thread.startVirtualThread(() -> cv.get(int.class));
      var refreshInput = Thread.startVirtualThread(() -> {
          input.incrementAndGet();
          cv.remove(int.class); // Let's recompute with updated inputs!
      });
      try {
          innocuous.join();
          refreshInput.join();
      } catch (InterruptedException ex) {
          throw new RuntimeException(ex);
      }
      assertEquals(1, input.get(), "input not updated");
      assertEquals(1, cv.get(int.class), "CV not using up-to-date input");

            liach Chen Liang
            liach Chen Liang
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: