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

Peter, Benjamin B.Peter at gsi.de
Fri Feb 14 07:22:11 UTC 2020


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