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

ConcurrentModificationException in EventType constructor

XMLWordPrintable

    • b09
    • 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:
              4 Start watching this issue

                Created:
                Updated:
                Resolved: