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

ConcurrentModificationException in EventType constructor

XMLWordPrintable

    • Fix Understood
    • generic
    • generic

      A DESCRIPTION OF THE PROBLEM :
      Our application uses JavaFX and loads its classes in parallel to improve startup performance. Because of that, the JavaFX classes are loaded in parallel too. Some of these classes create EventType instances in their static initializers. Unfortunately, the WeakHashMap used in EventType::register is not thread-safe, and using it concurrently sometimes triggers the ConcurrentModificationException.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the test case code. You might need to do it several times to trigger the exception.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      No exception is thrown: static initializers of JavaFX classes are thread-safe
      ACTUAL -
      The ConcurrentModificationException exception is thrown.

      ---------- BEGIN SOURCE ----------
      package org.example;

      import javafx.application.Platform;

      import java.util.List;
      import java.util.concurrent.Callable;
      import java.util.concurrent.ExecutionException;
      import java.util.concurrent.Executors;
      import java.util.concurrent.Future;
      import java.util.stream.Stream;

      public class Main {

          public static void main(String[] args) {
              Platform.startup(() -> {
                  try (var executor = Executors.newCachedThreadPool()) {
                      try {
                          List<Future<Class<?>>> futures = executor.invokeAll(Stream.of(
                                  "com.sun.javafx.event.RedirectedEvent",
                                  "javafx.concurrent.WorkerStateEvent",
                                  "javafx.css.TransitionEvent",
                                  "javafx.event.ActionEvent",
                                  "javafx.event.EventType",
                                  "javafx.scene.control.CheckBoxTreeItem",
                                  "javafx.scene.control.ChoiceBox",
                                  "javafx.scene.control.ComboBoxBase",
                                  "javafx.scene.control.DialogEvent",
                                  "javafx.scene.control.ListView",
                                  "javafx.scene.control.Menu",
                                  "javafx.scene.control.MenuButton",
                                  "javafx.scene.control.MenuItem",
                                  "javafx.scene.control.ScrollToEvent",
                                  "javafx.scene.control.SortEvent",
                                  "javafx.scene.control.Tab",
                                  "javafx.scene.control.TableColumn",
                                  "javafx.scene.control.TreeItem",
                                  "javafx.scene.control.TreeTableColumn",
                                  "javafx.scene.control.TreeTableView",
                                  "javafx.scene.control.TreeView",
                                  "javafx.scene.input.ContextMenuEvent",
                                  "javafx.scene.input.DragEvent",
                                  "javafx.scene.input.GestureEvent",
                                  "javafx.scene.input.InputMethodEvent",
                                  "javafx.scene.input.KeyEvent",
                                  "javafx.scene.input.MouseDragEvent",
                                  "javafx.scene.input.MouseEvent",
                                  "javafx.scene.input.RotateEvent",
                                  "javafx.scene.input.ScrollEvent",
                                  "javafx.scene.input.SwipeEvent",
                                  "javafx.scene.input.TouchEvent",
                                  "javafx.scene.input.ZoomEvent",
                                  "javafx.scene.media.MediaErrorEvent",
                                  "javafx.scene.transform.TransformChangedEvent",
                                  "javafx.scene.web.WebErrorEvent",
                                  "javafx.scene.web.WebEvent",
                                  "javafx.stage.WindowEvent"
                          ).map(className -> (Callable<Class<?>>) () -> Class.forName(className)).toList());
                          for (Future<Class<?>> future : futures) {
                              future.get();
                          }
                      } catch (InterruptedException | ExecutionException e) {
                          throw new RuntimeException(e);
                      }
                  }
                  System.exit(0);
              });
          }
      }
      ---------- END SOURCE ----------

            angorya Andy Goryachev
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: