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

TableView memory leak

    XMLWordPrintable

Details

    • Bug
    • Status: Resolved
    • P4
    • Resolution: Fixed
    • 7u15
    • 8
    • javafx
    • None

    Description

      TableCell's add a listener to the visibleLeafColumns property of TableView in the method TableCell.tableViewPropertyImpl(). This listener is not removed until the TableCells tableView property changes (which is probably almost never). We have long running fast moving tables and this leak is catastrophic for our application.

      We have hacked via reflection into the guts of TableView to clean up these references ourselves. It ain't pretty but it works. Should help you identify exactly where the issue is:

      static {
                  vlcField = TableView.class.getDeclaredField("visibleLeafColumns");
                  vlcField.setAccessible(true);

                  listenerHelperField = ObservableListWrapper.class.getDeclaredField("listenerHelper");
                  listenerHelperField.setAccessible(true);

                  weakRefField = WeakListChangeListener.class.getDeclaredField("ref");
                  weakRefField.setAccessible(true);

      }

         public static void reap(TableView<?> tableView) {
              try {
                  List<ListChangeListener> toRemove = null;
                  ObservableListWrapper<?> visibleLeafColumns = (ObservableListWrapper<?>) vlcField.get(tableView);
                  ListListenerHelper<?> listenerHelper = (ListListenerHelper<?>) listenerHelperField.get(visibleLeafColumns);
                  if (listenerHelper != null) {
                      Field changeListenersField = listenerHelper.getClass().getDeclaredField("changeListeners");
                      changeListenersField.setAccessible(true);
                      ListChangeListener<?>[] changeListeners = (ListChangeListener<?>[]) changeListenersField.get(listenerHelper);
                      for (ListChangeListener<?> changeListener : changeListeners) {
                          if (changeListener instanceof WeakListChangeListener) {
                              WeakReference weakReference = (WeakReference) weakRefField.get(changeListener);
                              if (weakReference != null && weakReference.get() == null) {
                                  if (toRemove == null) {
                                      toRemove = new ArrayList<ListChangeListener>();
                                  }
                                  toRemove.add(changeListener);
                              }
                          }
                      }
                  }
                  if (toRemove != null) {
                      System.out.println("Removing " + toRemove.size() + " refs");
                      for (ListChangeListener listChangeListener : toRemove) {
                          visibleLeafColumns.removeListener(listChangeListener);
                      }
                  }
              } catch (Exception ignore) {
              }
          }

      Attachments

        Activity

          People

            jgiles Jonathan Giles
            cdayjfx Craig Day (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:
              Imported: