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

NullPointerException in TableCellSkin when automatically resizing cells

XMLWordPrintable

    • x86
    • os_x

      A DESCRIPTION OF THE PROBLEM :
      I have reproduced this bug in versions 15, 14, and 12.
      The TableCellSkin appears to be not entirely reliable. I have been able to reproduce the following NullPointerException by hiding and showing a column in a table view whenever a cell is selected, and then scrolling continuously (see attached source code). The bug appears to occur after scrolling down for 98 rows.

      Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
      at javafx.scene.control.skin.TableCellSkin.tableColumnProperty(TableCellSkin.java:97)
      at javafx.scene.control.skin.TableCellSkinBase.getTableColumn(TableCellSkinBase.java:123)
      at javafx.scene.control.skin.TableCellSkinBase.dispose(TableCellSkinBase.java:136)
      at javafx.scene.control.skin.TableCellSkin.dispose(TableCellSkin.java:88)
      at javafx.scene.control.Control$2.invalidated(Control.java:267)
      at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
      at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147)
      at javafx.css.StyleableObjectProperty.set(StyleableObjectProperty.java:82)
      at javafx.scene.control.Control$2.set(Control.java:250)
      at javafx.scene.control.Control$2.set(Control.java:233)
      at javafx.scene.control.Control.setSkin(Control.java:230)
      at javafx.scene.control.skin.TableRowSkinBase.recreateCells(TableRowSkinBase.java:715)
      at javafx.scene.control.skin.TableRowSkinBase.updateCells(TableRowSkinBase.java:505)
      at javafx.scene.control.skin.TableRowSkinBase.checkState(TableRowSkinBase.java:649)
      at javafx.scene.control.skin.TableRowSkinBase.computePrefHeight(TableRowSkinBase.java:588)
      at javafx.scene.control.Control.computePrefHeight(Control.java:570)
      at javafx.scene.Parent.prefHeight(Parent.java:1040)
      at javafx.scene.layout.Region.prefHeight(Region.java:1559)
      at javafx.scene.control.skin.VirtualFlow.resizeCell(VirtualFlow.java:1923)
      at javafx.scene.control.skin.VirtualFlow.addLeadingCells(VirtualFlow.java:2030)
      at javafx.scene.control.skin.VirtualFlow.scrollPixels(VirtualFlow.java:1601)
      at javafx.scene.control.skin.VirtualFlow.tryScrollOneCell(VirtualFlow.java:1489)
      at javafx.scene.control.skin.VirtualFlow.scrollTo(VirtualFlow.java:1462)
      at javafx.scene.control.skin.TableViewSkinBase.onSelectBelowCell(TableViewSkinBase.java:629)
      at javafx.scene.control.skin.TableViewSkin.lambda$new$9(TableViewSkin.java:128)
      at com.sun.javafx.scene.control.behavior.TableViewBehaviorBase.selectNextRow(TableViewBehaviorBase.java:839)
      at com.sun.javafx.scene.control.behavior.TableViewBehaviorBase.lambda$new$12(TableViewBehaviorBase.java:156)
      at com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
      at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
      at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
      at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
      at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
      at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
      at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
      at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
      at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
      at javafx.event.Event.fireEvent(Event.java:198)
      at javafx.scene.Scene$KeyHandler.process(Scene.java:4098)
      at javafx.scene.Scene.processKeyEvent(Scene.java:2157)
      at javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2625)
      at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:217)
      at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:149)
      at java.base/java.security.AccessController.doPrivileged(Native Method)
      at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent$1(GlassViewEventHandler.java:248)
      at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:412)
      at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent(GlassViewEventHandler.java:247)
      at com.sun.glass.ui.View.handleKeyEvent(View.java:547)
      at com.sun.glass.ui.View.notifyKey(View.java:971)
      Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
      at javafx.scene.control.skin.TableCellSkin.tableColumnProperty(TableCellSkin.java:97)
      at javafx.scene.control.skin.TableCellSkinBase.getTableColumn(TableCellSkinBase.java:123)
      at javafx.scene.control.skin.TableCellSkinBase.dispose(TableCellSkinBase.java:136)
      at javafx.scene.control.skin.TableCellSkin.dispose(TableCellSkin.java:88)
      at javafx.scene.control.Control$2.invalidated(Control.java:267)
      at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
      at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147)
      at javafx.css.StyleableObjectProperty.set(StyleableObjectProperty.java:82)
      at javafx.scene.control.Control$2.set(Control.java:250)
      at javafx.scene.control.Control$2.set(Control.java:233)
      at javafx.scene.control.Control.setSkin(Control.java:230)
      at javafx.scene.control.skin.TableRowSkinBase.recreateCells(TableRowSkinBase.java:715)
      at javafx.scene.control.skin.TableRowSkinBase.updateCells(TableRowSkinBase.java:505)
      at javafx.scene.control.skin.TableRowSkinBase.checkState(TableRowSkinBase.java:649)
      at javafx.scene.control.skin.TableRowSkinBase.computePrefHeight(TableRowSkinBase.java:588)
      at javafx.scene.control.Control.computePrefHeight(Control.java:570)
      at javafx.scene.Parent.prefHeight(Parent.java:1040)
      at javafx.scene.layout.Region.prefHeight(Region.java:1559)
      at javafx.scene.control.skin.VirtualFlow.resizeCell(VirtualFlow.java:1923)
      at javafx.scene.control.skin.VirtualFlow.addTrailingCells(VirtualFlow.java:2125)
      at javafx.scene.control.skin.VirtualFlow.layoutChildren(VirtualFlow.java:1253)
      at javafx.scene.Parent.layout(Parent.java:1207)
      at javafx.scene.Parent.layout(Parent.java:1214)
      at javafx.scene.Parent.layout(Parent.java:1214)
      at javafx.scene.Scene.doLayoutPass(Scene.java:576)
      at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2510)
      at com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:412)
      at java.base/java.security.AccessController.doPrivileged(Native Method)
      at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:411)
      at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:438)
      at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:563)
      at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:543)
      at com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:536)
      at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:342)
      at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
      Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
      at javafx.scene.control.skin.CellSkinBase$StyleableProperties$1.isSettable(CellSkinBase.java:166)
      at javafx.scene.control.skin.CellSkinBase$StyleableProperties$1.isSettable(CellSkinBase.java:161)
      at javafx.scene.CssStyleHelper.transitionToState(CssStyleHelper.java:666)
      at javafx.scene.Node.doProcessCSS(Node.java:9660)
      at javafx.scene.Node$1.doProcessCSS(Node.java:472)
      at com.sun.javafx.scene.NodeHelper.processCSSImpl(NodeHelper.java:192)
      at com.sun.javafx.scene.ParentHelper.superProcessCSSImpl(ParentHelper.java:93)
      at com.sun.javafx.scene.ParentHelper.superProcessCSS(ParentHelper.java:63)
      at javafx.scene.Parent.doProcessCSS(Parent.java:1369)
      at javafx.scene.Parent$1.doProcessCSS(Parent.java:125)
      at com.sun.javafx.scene.ParentHelper.processCSSImpl(ParentHelper.java:98)
      at com.sun.javafx.scene.control.ControlHelper.superProcessCSSImpl(ControlHelper.java:63)
      at com.sun.javafx.scene.control.ControlHelper.superProcessCSS(ControlHelper.java:55)
      at javafx.scene.control.Control.doProcessCSS(Control.java:886)
      at javafx.scene.control.Control$1.doProcessCSS(Control.java:89)
      at com.sun.javafx.scene.control.ControlHelper.processCSSImpl(ControlHelper.java:67)
      at com.sun.javafx.scene.NodeHelper.processCSS(NodeHelper.java:145)
      at javafx.scene.Node.processCSS(Node.java:9542)
      at javafx.scene.Node.processCSS(Node.java:9535)
      at javafx.scene.Node.processCSS(Node.java:9535)
      at javafx.scene.Node.processCSS(Node.java:9535)
      at javafx.scene.Node.processCSS(Node.java:9535)
      at javafx.scene.Node.processCSS(Node.java:9535)
      at javafx.scene.Node.processCSS(Node.java:9535)
      at javafx.scene.Scene.doCSSPass(Scene.java:569)
      at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2505)
      at com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:412)
      at java.base/java.security.AccessController.doPrivileged(Native Method)
      at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:411)
      at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:438)
      at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:563)
      at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:543)
      at com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:536)
      at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:342)
      at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)

      In this stack trace, a call to VirtualFlow.addLeadingCells is made by VirtualFlow.scrollPixels. However, I have seen a similar crash where VirtualFlow.addLeadingCells is called by VirtualFlow.layoutChildren, so it is likely that the same bug can be exhibited via different actions.

      The immediate cause of the crash is the access of a null skinnable in TableCellSkin.tableColumnProperty. On surface-level examination, a simple null check in TableCellSkin.tableColumnProperty - and in its caller TableCellSkinBase.getTableColumn - appears to alleviate the problem.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      - Launch test program
      - Select cell 0 in table view
      - Hold the down arrow key to scroll continuously

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Table view should scroll until the last cell is selected
      ACTUAL -
      NullPointerException is thrown after scrolling for some time; seemingly after scrolling for 98 cells

      ---------- BEGIN SOURCE ----------
      import java.util.ArrayList;
      import java.util.List;

      import javafx.application.Application;
      import javafx.beans.property.SimpleStringProperty;
      import javafx.beans.property.StringProperty;
      import javafx.collections.FXCollections;
      import javafx.collections.ObservableList;
      import javafx.scene.Scene;
      import javafx.scene.control.TableColumn;
      import javafx.scene.control.TableView;
      import javafx.scene.control.cell.PropertyValueFactory;
      import javafx.scene.layout.BorderPane;
      import javafx.stage.Stage;

      public class MyApplication extends Application
      {
          @Override
          public void start(Stage stage)
          {
              List<Obj> list = createList();
              ObservableList<Obj> rows = FXCollections.observableArrayList(list);
              TableView<Obj> tableView = new TableView<>();
              tableView.setItems(rows);

              TableColumn<Obj, String> myColumn = new TableColumn<>("Column");
              myColumn.setCellValueFactory(new PropertyValueFactory<>(list.get(0).stringProperty().getName()));
              tableView.getColumns().add(myColumn);

              tableView.selectionModelProperty().get().selectedItemProperty().addListener((obs, o, n) ->
              {
                  myColumn.setVisible(false);
                  myColumn.setVisible(true);
              });

              BorderPane root = new BorderPane(tableView);
              Scene scene = new Scene(root, 500, 200);
              stage.setScene(scene);
              stage.show();
          }

          private List<Obj> createList()
          {
              var list = new ArrayList<Obj>();
              for (int i = 0; i < 1000; i++)
              {
                  list.add(new Obj(String.valueOf(i)));
              }
              return list;
          }

          public static class Obj
          {
              private StringProperty string;
              public void setString(String value) { stringProperty().set(value); }
              public StringProperty stringProperty() {
                  if (string == null) string = new SimpleStringProperty(this, "string");
                  return string;
              }

              public Obj(String string) {
                  setString(string);
              }
          }
      }

      ---------- END SOURCE ----------

      FREQUENCY : always


            aghaisas Ajit Ghaisas
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: