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 <[email protected]>
> Gesendet: Donnerstag, 13. Februar 2020 15:46
> An: Peter, Benjamin <[email protected]>; [email protected]
> 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 <[email protected]> Im Auftrag von
> > Peter, Benjamin
> > Gesendet: Donnerstag, 13. Februar 2020 11:54
> > An: [email protected]
> > 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