I am very occasionally seeing the following stacktrace which matches the one in RT-36889 in our application running with a jar built from the latest 8u-dev codebase.
Exception in thread "JavaFX Application Thread" java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.ArrayList.elementData(ArrayList.java:403)
at java.util.ArrayList.get(ArrayList.java:416)
at com.sun.javafx.scene.control.skin.VirtualFlow$ArrayLinkedList.get(VirtualFlow.java:2741)
at com.sun.javafx.scene.control.skin.VirtualFlow.layoutChildren(VirtualFlow.java:949)
at javafx.scene.Parent.layout(Parent.java:1074)
at javafx.scene.Parent.layout(Parent.java:1080)
at javafx.scene.Parent.layout(Parent.java:1080)
at javafx.scene.Scene.doLayoutPass(Scene.java:530)
at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2358)
at com.sun.javafx.tk.Toolkit.lambda$runPulse$26(Toolkit.java:314)
at com.sun.javafx.tk.Toolkit$$Lambda$152/85650081.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:313)
...
So I have managed to cook up the following test class that can reproduce the stacktrace. (I had a hunch that it had something to do with list data changing while it is already laying out from a size change so this is why I have that crazy thread replacing all the list data every 500 ms...)
1. Run the test class below.
2. Drag the bottom of the window up until there is no more room for the list at all (ie. the stage height is 0). Then the stacktrace will be output to the console.
*********************************************** Test Class **************************************************
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class ListViewTest extends Application {
@Override
public void start(final Stage primaryStage) throws Exception {
final Double[] data = {0d, 333d, 666d, 333d, 666d, 333d, 666d, 333d, 666d,
333d, 666d, 333d, 666d, 333d, 666d};
final ListView<Double> list = new ListView<>();
list.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
list.getItems().setAll(data);
primaryStage.centerOnScreen();
primaryStage.setHeight(350);
primaryStage.setWidth(500);
primaryStage.setScene(new Scene(new StackPane(list)));
primaryStage.show();
new Thread() {
@Override public void run() {
try {
while( true ) {
Thread.sleep(500);
Platform.runLater(new Runnable() {
@Override public void run() {
list.getItems().setAll(data);
}
});
}
} catch (InterruptedException e) {
}
}
}.start();
}
public static void main(String[] args) throws Exception {
launch(args);
}
}
Exception in thread "JavaFX Application Thread" java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.ArrayList.elementData(ArrayList.java:403)
at java.util.ArrayList.get(ArrayList.java:416)
at com.sun.javafx.scene.control.skin.VirtualFlow$ArrayLinkedList.get(VirtualFlow.java:2741)
at com.sun.javafx.scene.control.skin.VirtualFlow.layoutChildren(VirtualFlow.java:949)
at javafx.scene.Parent.layout(Parent.java:1074)
at javafx.scene.Parent.layout(Parent.java:1080)
at javafx.scene.Parent.layout(Parent.java:1080)
at javafx.scene.Scene.doLayoutPass(Scene.java:530)
at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2358)
at com.sun.javafx.tk.Toolkit.lambda$runPulse$26(Toolkit.java:314)
at com.sun.javafx.tk.Toolkit$$Lambda$152/85650081.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:313)
...
So I have managed to cook up the following test class that can reproduce the stacktrace. (I had a hunch that it had something to do with list data changing while it is already laying out from a size change so this is why I have that crazy thread replacing all the list data every 500 ms...)
1. Run the test class below.
2. Drag the bottom of the window up until there is no more room for the list at all (ie. the stage height is 0). Then the stacktrace will be output to the console.
*********************************************** Test Class **************************************************
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class ListViewTest extends Application {
@Override
public void start(final Stage primaryStage) throws Exception {
final Double[] data = {0d, 333d, 666d, 333d, 666d, 333d, 666d, 333d, 666d,
333d, 666d, 333d, 666d, 333d, 666d};
final ListView<Double> list = new ListView<>();
list.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
list.getItems().setAll(data);
primaryStage.centerOnScreen();
primaryStage.setHeight(350);
primaryStage.setWidth(500);
primaryStage.setScene(new Scene(new StackPane(list)));
primaryStage.show();
new Thread() {
@Override public void run() {
try {
while( true ) {
Thread.sleep(500);
Platform.runLater(new Runnable() {
@Override public void run() {
list.getItems().setAll(data);
}
});
}
} catch (InterruptedException e) {
}
}
}.start();
}
public static void main(String[] args) throws Exception {
launch(args);
}
}