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

Potential memory leak in javafx.scene.control.ListView

XMLWordPrintable

    • x86_64
    • windows_10
    • Verified

      ADDITIONAL SYSTEM INFORMATION :
      Windows 10 64-bit

      A DESCRIPTION OF THE PROBLEM :
      Changing the ListView's data model using setItems prevents ListView from being garbage collected because SelectedItemsReadOnlyObservableList adds a non-weak listener to the data model (ObservableList)

      REGRESSION : Last worked in version 8u192

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      - create a ListView
      - change its data model by calling setItems( ObservableList<T> )
      - clear all references to the ListView but keep the data model
      - ListView cannot be garbage collected. This worked in earlier releases (JavaFX 8)


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      In earlier releases the ListView could be garbage collected even when the data model was kept
      ACTUAL -
      see UnitTest: test succeeded with JavaFX 8, but fails with JavaFX 11.0.2 and 12.0.1

      ---------- BEGIN SOURCE ----------
      package listview;

      import static org.junit.Assert.fail;

      import java.lang.ref.WeakReference;
      import java.util.concurrent.CountDownLatch;
      import java.util.concurrent.TimeUnit;

      import org.junit.Assert;
      import org.junit.Before;
      import org.junit.BeforeClass;
      import org.junit.Test;

      import javafx.application.Application;
      import javafx.application.Platform;
      import javafx.collections.FXCollections;
      import javafx.collections.ObservableList;
      import javafx.scene.control.ListView;
      import javafx.stage.Stage;

      public class ListViewTest {
      static CountDownLatch startupLatch;

      private WeakReference<ListView<?>> listViewRef;

      public static class TestApp extends Application {

      @Override
      public void start(Stage stage) throws Exception {
      startupLatch.countDown();
      }
      }

      private static ObservableList<String> items = FXCollections.observableArrayList();

      public ListViewTest() {

      }

      @BeforeClass
      public static void initJavaFX() {
      startupLatch = new CountDownLatch(1);
      new Thread(() -> Application.launch(TestApp.class, (String[]) null)).start();
      try {
      if (!startupLatch.await(15, TimeUnit.SECONDS)) {
      fail("Timeout waiting for FX runtime to start");
      }
      } catch (InterruptedException ex) {
      fail("Unexpected exception: " + ex);
      }
      }

      @Before
      public void initListView() throws Exception {
      CountDownLatch latch = new CountDownLatch(1);

      Platform.runLater(() -> {
      listViewRef = new WeakReference<>(new ListView<>(items));

      latch.countDown();

      });

      if (!latch.await(15, TimeUnit.SECONDS)) {
      fail("Timeout waiting for FX listview initialization");
      }

      }
      @Test
      public void testGarbageCollect() {
      for (int i = 0; i < 10; i++) {
      System.gc();
      System.runFinalization();

      if (listViewRef.get() == null) {
      break;
      }

      try {
      Thread.sleep(500);
      } catch (Exception ex) {

      }
      }
      Assert.assertTrue("Could not garbage collect listview", listViewRef.get() == null);
      }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      clear data model by calling setItems(null) to dispose ListView

      FREQUENCY : always


            arapte Ambarish Rapte
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: