AW: WG: Minimal reproduction example for JDK-8217953 NPE in TableCellSkin

Kevin Rushforth kevin.rushforth at oracle.com
Fri Feb 14 13:17:49 UTC 2020


Hi Ben,

Thank you. That does indeed reproduce the problem for me on the 100th 
iteration. I've attached your test program to the bug report.

-- Kevin


On 2/13/2020 11:22 PM, Peter, Benjamin wrote:
> Hello Kevin,
>
> sure, will do :-).
>
>
> ==== BEGIN ====
>
> import java.util.List;
> import java.util.concurrent.atomic.AtomicInteger;
>
> import javafx.application.Application;
> import javafx.application.Platform;
> 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.stage.Stage;
>
> public class TableViewCellDisposeProblem extends Application {
>      
>      public static class Person {
>          private StringProperty firstName;
>
>          public void setFirstName(String value) {
>              firstNameProperty().set(value);
>          }
>
>          public String getFirstName() {
>              return firstNameProperty().get();
>          }
>
>          public StringProperty firstNameProperty() {
>              if (firstName == null)
>                  firstName = new SimpleStringProperty(this, "firstName");
>              return firstName;
>          }
>
>          private StringProperty lastName;
>
>          public void setLastName(String value) {
>              lastNameProperty().set(value);
>          }
>
>          public String getLastName() {
>              return lastNameProperty().get();
>          }
>
>          public StringProperty lastNameProperty() {
>              if (lastName == null)
>                  lastName = new SimpleStringProperty(this, "lastName");
>              return lastName;
>          }
>
>          public Person(String firstName, String lastName) {
>              setFirstName(firstName);
>              setLastName(lastName);
>          }
>      }
>
>      private ObservableList<Person> teamMembers = FXCollections.observableArrayList( //
>              List.of( //
>                      new Person("William", "Reed"), //
>                      new Person("James", "Michaelson"), //
>                      new Person("Julius", "Dean") //
>              ));
>
>      TableView<Person> table = new TableView<>();
>      
>      private AtomicInteger updateCount = new AtomicInteger();
>
>      public void updateLoop() {
>          Thread thread = new Thread(() -> {
>              while (true) {
>                  System.out.println("updating i = "+ updateCount.incrementAndGet());
>                  Platform.runLater(() -> {
>                      // Trigger column visibility - Without this, no exception observed!
>                      TableColumn<Person, ?> secondColumn = table.getColumns().get(1);
>                      secondColumn.setVisible(!secondColumn.isVisible());
>                  });
>                  try {
>                      Thread.sleep(100);
>                  } catch (InterruptedException e) {
>                      System.out.println("interrupted");
>                      break;
>                  }
>              }
>          });
>          thread.setDaemon(true);
>          thread.start();
>      }
>
>      @Override
>      public void start(Stage primaryStage) throws Exception {
>          primaryStage.setScene(new Scene(table, 800, 600));
>          table.setItems(teamMembers);
>
>          TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
>          firstNameCol.setCellValueFactory(new PropertyValueFactory<>("firstName"));
>          TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
>          lastNameCol.setCellValueFactory(new PropertyValueFactory<>("lastName"));
>
>          table.getColumns().setAll(firstNameCol, lastNameCol);
>          primaryStage.show();
>          updateLoop();
>      }
>
>      public static void main(String[] args) {
>          Application.launch(args);
>      }
> }
>
> /*
>   * After 100 updates following Exception occurs (of 5 test runs, sleep time varied):
>   *
>   * [WARNING]
> 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:1039)
>      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.layoutChildren (VirtualFlow.java:1250)
>      at javafx.scene.Parent.layout (Parent.java:1206)
>      at javafx.scene.Parent.layout (Parent.java:1213)
>      at javafx.scene.Scene.doLayoutPass (Scene.java:576)
>      at javafx.scene.Scene$ScenePulseListener.pulse (Scene.java:2482)
>      at com.sun.javafx.tk.Toolkit.lambda$runPulse$2 (Toolkit.java:412)
>      at 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)
>      at com.sun.glass.ui.gtk.GtkApplication._runLoop (Native Method)
>      at com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11 (GtkApplication.java:277)
>      at java.lang.Thread.run (Thread.java:834)
> updating
> [WARNING]
> 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:9658)
>      at javafx.scene.Node$1.doProcessCSS (Node.java:471)
>      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:1368)
>      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:9540)
>      at javafx.scene.Node.processCSS (Node.java:9533)
>      at javafx.scene.Node.processCSS (Node.java:9533)
>      at javafx.scene.Node.processCSS (Node.java:9533)
>      at javafx.scene.Node.processCSS (Node.java:9533)
>      at javafx.scene.Node.processCSS (Node.java:9533)
>      at javafx.scene.Scene.doCSSPass (Scene.java:569)
>      at javafx.scene.Scene$ScenePulseListener.pulse (Scene.java:2477)
>      at com.sun.javafx.tk.Toolkit.lambda$runPulse$2 (Toolkit.java:412)
>      at 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)
>      at com.sun.glass.ui.gtk.GtkApplication._runLoop (Native Method)
>      at com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11 (GtkApplication.java:277)
>      at java.lang.Thread.run (Thread.java:834)
> updating
>
> */
>
> ===== END ====
>
> best wishes,
>
> Ben
>
>> -----Ursprüngliche Nachricht-----
>> Von: Kevin Rushforth <kevin.rushforth at oracle.com>
>> Gesendet: Donnerstag, 13. Februar 2020 15:46
>> An: Peter, Benjamin <B.Peter at gsi.de>; openjfx-dev at openjdk.java.net
>> Betreff: Re: WG: Minimal reproduction example for JDK-8217953 NPE in
>> TableCellSkin
>>
>> Unfortunately, attachments don't make it through the openjdk mailing list filters.
>> Can you just paste it inline?
>>
>> Thanks.
>>
>> -- Kevin
>>
>>
>> On 2/13/2020 6:02 AM, Peter, Benjamin wrote:
>>> Hello devs,
>>>
>>> same example but with the file as attachment and without header.
>>>
>>>
>>> regards,
>>>
>>> Ben
>>>
>>> -----Ursprüngliche Nachricht-----
>>> Von: openjfx-dev <openjfx-dev-bounces at openjdk.java.net> Im Auftrag von
>>> Peter, Benjamin
>>> Gesendet: Donnerstag, 13. Februar 2020 11:54
>>> An: openjfx-dev at openjdk.java.net
>>> Betreff: Minimal reproduction example for JDK-8217953 NPE in
>>> TableCellSkin
>>>
>>> Dear FX devs,
>>>
>>> please accept my minimal reproduction example for JDK-8217953
>> "NullPointerException when TableCellSkin gets disposed twice"
>>> In the report it says there was no luck reproducing it - I hope this could now be
>> beneficial for a solution to this problem.
>>> I could repeatedly trigger the problem after 100 of my update cycles - which
>> interestingly corresponds to the following constant which can be found along the
>> stacktrace.
>>> javafx.scene.control.skin.TableRowSkinBase.DEFAULT_FULL_REFRESH_COUNTER
>> = 100 Surely - could be coincidence - but also a hot lead.
>>>
>>> I can also confirm it is still reproducable in jfx 11 and 13.
>>>
>>> It is available as public domain gist on github:
>>>
>>> https://gist.github.com/dedeibel/d02fb51c59942bebcb6e418f23d310fb
>>>
>>>
>>>
>>> Thank you for your work and cooperation,
>>>
>>> with kind regards,
>>>
>>>
>>> Benjamin Peter



More information about the openjfx-dev mailing list