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

DefaultRowSorter may throw NullPointerException when adding model elements

XMLWordPrintable

    • b76
    • x86
    • windows_xp

      FULL PRODUCT VERSION :
      java version "1.6.0-beta"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.6.0-beta-b59g)
      Java HotSpot(TM) Client VM (build 1.6.0-beta-b59g, mixed mode, sharing)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows XP [Version 5.1.2600]

      A DESCRIPTION OF THE PROBLEM :
      If a TableRowSorter is used on a JTable, and a row filter is set on the row sorter, subsequent element additions to the table model may cause undocumented NullPointerExceptions to be thrown.

      The JTable, notified by the table model of the element addition, calls DefaultRowSorter.rowsInserted. This method typically causes Arrays.binarySearch to be invoked (via method insertInOrder). The binary search causes multiple invocations of Row.compareTo. The latter method uses method DefaultRowSorter.compare.

      The latter method assumes that field cachedSortKeys is not null, which in this scenario is not the case. Hence the NPE.

      Another NPE is thrown as well, by method DefaultRowSorter.convertRowIndexToModel. It turns out that field viewToModel is indeed an array, but the array members are null. Hence the second NPE, when method convertRowIndexToModel tries to dereference one such array member.

      The 2 NPEs do not occur if sort keys are set before adding model elements, either by a user gesture or programmatically. If the row sorter is used without row filter, the NPEs do not occur either.

      Stack trace:

      Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
              at javax.swing.DefaultRowSorter.compare(DefaultRowSorter.java:845)
              at javax.swing.DefaultRowSorter.access$100(DefaultRowSorter.java:91)
              at javax.swing.DefaultRowSorter$Row.compareTo(DefaultRowSorter.java:1277)
              at javax.swing.DefaultRowSorter$Row.compareTo(DefaultRowSorter.java:1267)
              at java.util.Arrays.binarySearch(Arrays.java:1654)
              at javax.swing.DefaultRowSorter.insertInOrder(DefaultRowSorter.java:901)
              at javax.swing.DefaultRowSorter.rowsInserted0(DefaultRowSorter.java:959)
              at javax.swing.DefaultRowSorter.rowsInserted(DefaultRowSorter.java:786)
              at javax.swing.JTable.notifySorter(JTable.java:4013)
              at javax.swing.JTable.sortedTableChanged(JTable.java:3827)
              at javax.swing.JTable.tableChanged(JTable.java:4155)
              at javax.swing.table.AbstractTableModel.fireTableChanged(AbstractTableModel.java:280)
              at javax.swing.table.AbstractTableModel.fireTableRowsInserted(AbstractTableModel.java:215)
              at javax.swing.table.DefaultTableModel.insertRow(DefaultTableModel.java:358)
              at javax.swing.table.DefaultTableModel.addRow(DefaultTableModel.java:332)
              at javax.swing.table.DefaultTableModel.addRow(DefaultTableModel.java:343)
              at sortingandfiltering.AppFrame.jButton1ActionPerformed(AppFrame.java:62)
              at sortingandfiltering.AppFrame.access$000(AppFrame.java:10)
              at sortingandfiltering.AppFrame$2.actionPerformed(AppFrame.java:35)
              at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1957)
              at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2278)
              at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:377)
              at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:232)
              at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:234)
              at java.awt.Component.processMouseEvent(Component.java:5955)
              at javax.swing.JComponent.processMouseEvent(JComponent.java:3285)
              at java.awt.Component.processEvent(Component.java:5720)
              at java.awt.Container.processEvent(Container.java:1960)
              at java.awt.Component.dispatchEventImpl(Component.java:4365)
              at java.awt.Container.dispatchEventImpl(Container.java:2018)
              at java.awt.Component.dispatchEvent(Component.java:4195)
              at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4222)
              at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3886)
              at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3816)
              at java.awt.Container.dispatchEventImpl(Container.java:2004)
              at java.awt.Window.dispatchEventImpl(Window.java:2210)
              at java.awt.Component.dispatchEvent(Component.java:4195)
              at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
              at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
              at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
              at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
              at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
              at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
              at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)
      Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
              at javax.swing.DefaultRowSorter.convertRowIndexToModel(DefaultRowSorter.java:443)
              at javax.swing.JTable.convertRowIndexToModel(JTable.java:2567)
              at javax.swing.JTable.getValueAt(JTable.java:2642)
              at javax.swing.JTable.prepareRenderer(JTable.java:5520)
              at javax.swing.plaf.basic.BasicTableUI.paintCell(BasicTableUI.java:2043)
              at javax.swing.plaf.basic.BasicTableUI.paintCells(BasicTableUI.java:1945)
              at javax.swing.plaf.basic.BasicTableUI.paint(BasicTableUI.java:1741)
              at javax.swing.plaf.ComponentUI.update(ComponentUI.java:143)
              at javax.swing.JComponent.paintComponent(JComponent.java:710)
              at javax.swing.JComponent.paint(JComponent.java:975)
              at javax.swing.JComponent.paintToOffscreen(JComponent.java:5077)
              at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:279)
              at javax.swing.RepaintManager.paint(RepaintManager.java:1079)
              at javax.swing.JComponent._paintImmediately(JComponent.java:5025)
              at javax.swing.JComponent.paintImmediately(JComponent.java:4843)
              at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:688)
              at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:644)
              at javax.swing.RepaintManager.seqPaintDirtyRegions(RepaintManager.java:624)
              at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:128)
              at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
              at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
              at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
              at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
              at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
              at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
              at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
              at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)




      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package sortingandfiltering;

      import java.awt.BorderLayout;
      import javax.swing.JFrame;
      import javax.swing.RowFilter;
      import javax.swing.table.DefaultTableModel;
      import javax.swing.table.TableModel;
      import javax.swing.table.TableRowSorter;

      public class AppFrame extends JFrame {
          
          public AppFrame() {
              jScrollPane1 = new javax.swing.JScrollPane();
              jTable1 = new javax.swing.JTable();
              jButton1 = new javax.swing.JButton();
              
              setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
              jTable1.setModel(new javax.swing.table.DefaultTableModel(
                      new Object [][] { },
                      new String [] { "Name" }
              ) {
                  Class[] types = new Class [] {
                      java.lang.String.class
                  };
                  
                  public Class getColumnClass(int columnIndex) {
                      return types [columnIndex];
                  }
              });
              jScrollPane1.setViewportView(jTable1);
              
              jButton1.setText("Load data");
              jButton1.addActionListener(new java.awt.event.ActionListener() {
                  public void actionPerformed(java.awt.event.ActionEvent evt) {
                      jButton1ActionPerformed(evt);
                  }
              });
              
              TableRowSorter<TableModel> rowSorter = new TableRowSorter<TableModel>(jTable1.getModel());
              jTable1.setRowSorter(rowSorter);
              
              RowFilter<TableModel, Integer> rowFilter = new RowFilter<TableModel, Integer>() {
                  
                  public boolean include(RowFilter.Entry<? extends TableModel, ? extends Integer> entry) {
                      // Dummy filter
                      return true;
                  }
              };
              
              rowSorter.setRowFilter(rowFilter);
              
              add(jScrollPane1, BorderLayout.CENTER);
              add(jButton1, BorderLayout.SOUTH);
              pack();
          }
          
          private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
              DefaultTableModel tableModel = (DefaultTableModel) jTable1.getModel();
              tableModel.setRowCount(0);
              
              tableModel.addRow(new Object[] { "John Smith" });
              tableModel.addRow(new Object[] { "Linda Smith" }); // This one fails!!
              tableModel.addRow(new Object[] { "Paul Smith" });
              tableModel.addRow(new Object[] { "Duncan Smith" });
          }
          
          public static void main(String args[]) {
              java.awt.EventQueue.invokeLater(new Runnable() {
                  public void run() {
                      new AppFrame().setVisible(true);
                  }
              });
          }
          
          private javax.swing.JButton jButton1;
          private javax.swing.JScrollPane jScrollPane1;
          private javax.swing.JTable jTable1;
      }

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

            svioletsunw Scott Violet (Inactive)
            rmandalasunw Ranjith Mandala (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: