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

MultipleSelectionModelBase generate ListChangeListener.Change having illegal from/to index.

XMLWordPrintable

    • x86
    • other

      FULL PRODUCT VERSION :
      1.8.0_102

      ADDITIONAL OS VERSION INFORMATION :
      Windows10 (64bit)

      A DESCRIPTION OF THE PROBLEM :
       In some cases, MultipleSelectionModelBase produces improper
      ListChangeListener.Change which have illegal from/to index.
      So, if getAddedSubList is invoked on such Change, it causes IndexOutOfBoundsException.

      It seems to me that implementation of MultiSelectionModelBase.selectedIndicesSeq
      field is the cause of this problem.

      This field is generated by createListFromBitSet, and provides the ObservableList
      view of BitMap field 'selectedIndices'. I think the cause of this problem is
      the internal state (lastGetIndex/lastGetValue) of this instance is not properly
      maintained when content of 'selectedIndices' is changed.

      For example, in my code for reproduction, the value of selectedIndices and
      lastGetIndex/lastGetValue changed as follows:

      A) Ater selection "a" and "b"

       selectedIndices = { 0, 1 }
       lastGetIndex/lastGetValue = 1/1 (cosistent)

      B) after quietClearSelection() in clearAndSelect()

       selectedIndices = { }
       lastGetIndex/lastGetValue = 1/1 (inconsistent)

      C) After select() in clearAndSelect()

       selectedIndices = { 2 }
       lastGetIndex/lastGetValue = 1/1 (inconsistent)
       
      At last, line 373 in MultiSelectionModelBase.java, indexOf(2)
      returns incorrect index -1 (expected result is 0).

      373: int changeIndex = selectedIndicesSeq.indexOf(row);
      374: change = new NonIterableChange.GenericAddRemoveChange<>(
      375: changeIndex, changeIndex+1, previousSelectedIndices, selectedIndicesSeq);


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run my reproduce program and push 'reproduce' button.


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      selection changed
       added 0 1
         [a]
      selection changed
       added 1 2
         [b]
      selection changed
       removed 0 1
         [a, b]
       added 0 1
         [c]

      ACTUAL -
      selection changed
       added 0 1
         [a]
      selection changed
       added 1 2
         [b]
      selection changed
       removed -1 0
         [a, b]
       added -1 0
      =>java.lang.IndexOutOfBoundsException in thread "JavaFX Application Thread"


      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException
      at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.subList(ReadOnlyUnbackedObservableList.java:136)
      at javafx.collections.ListChangeListener$Change.getAddedSubList(ListChangeListener.java:242)
      at test.App.lambda$0(App.java:34)
      at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:164)
      at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
      at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.callObservers(ReadOnlyUnbackedObservableList.java:75)
      at javafx.scene.control.MultipleSelectionModelBase$1.onChanged(MultipleSelectionModelBase.java:97)
      at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:329)
      at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
      at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.callObservers(ReadOnlyUnbackedObservableList.java:75)
      at javafx.scene.control.MultipleSelectionModelBase.clearAndSelect(MultipleSelectionModelBase.java:378)
      at javafx.scene.control.ListView$ListViewBitSetSelectionModel.clearAndSelect(ListView.java:1403)
      at test.App.lambda$1(App.java:44)
      ...


      REPRODUCIBILITY :
      This bug can be reproduced often.

      ---------- BEGIN SOURCE ----------
      package test;

      import javafx.application.Application;
      import javafx.collections.FXCollections;
      import javafx.collections.ListChangeListener.Change;
      import javafx.scene.Scene;
      import javafx.scene.control.Button;
      import javafx.scene.control.ListView;
      import javafx.scene.control.MultipleSelectionModel;
      import javafx.scene.control.SelectionMode;
      import javafx.scene.layout.VBox;
      import javafx.stage.Stage;

      public class App extends Application {
      static void log(String fmt, Object...args) {
      System.out.format(fmt, args);
      }

      @Override
      public void start(Stage primaryStage) {
      ListView<String> listView = new ListView<>(
      FXCollections.observableArrayList("a", "b", "c"));
      MultipleSelectionModel<String> sm = listView.getSelectionModel();
      sm.setSelectionMode(SelectionMode.MULTIPLE);
      sm.getSelectedItems().addListener((Change<? extends String> c) -> {
      log("selection changed\n");
      while (c.next()) {
      if (c.wasRemoved()) {
      log(" removed %d %d\n", c.getFrom(), c.getTo());
      log(" %s\n", c.getRemoved());
      }
      if (c.wasAdded()) {
      log(" added %d %d\n", c.getFrom(), c.getTo());
      log(" %s\n", c.getAddedSubList());
      }
      }
      });
      Button button = new Button("reproduce");
      button.setOnAction((ev) -> {
      sm.clearSelection();
      sm.select(0);
      sm.select(1);
      // following invocation causes IndexOutOfBoundsException
      sm.clearAndSelect(2);
      });
      VBox root = new VBox(button, listView);
      Scene scene = new Scene(root);
      primaryStage.setScene(scene);
      primaryStage.show();
      }

      public static void main(String[] args) {
      launch(args);
      }
      }

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

            scfitch Stephen Fitch
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: