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

updateUI causes StackOverflowError in JTableHeaders that are their own renderers

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 6
    • client-libs

      FULL PRODUCT VERSION :
      java version "1.6.0"
      Java(TM) SE Runtime Environment (build 1.6.0-b105)
      Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)

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

      A DESCRIPTION OF THE PROBLEM :
      A JTableHeader that implements TableCellRenderer and is set as its own DefaultRenderer will cause a StackOverFlowError in updateUI().
      This is caused by
              TableCellRenderer renderer = getDefaultRenderer();
              if (!(renderer instanceof UIResource) && renderer instanceof Component) {
                  SwingUtilities.updateComponentTreeUI((Component)renderer);
              }
      in JTableHeader.java. updateComponentTreeUI calls updateUI and this leads to infinite recursion in the described situation.
      The above code should be changed to
      TableCellRenderer renderer = getDefaultRenderer();
              if (renderer != this && !(renderer instanceof UIResource) && renderer instanceof Component) {
                  SwingUtilities.updateComponentTreeUI((Component)renderer);
              }

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Write a JTableHeader that implements TableCellRenderer. Create an instance head. Call head.setDefaultRenderer(head). Call updateUI().

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      no error
      ACTUAL -
      StackOverflowError

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      java.lang.StackOverflowError
              at java.awt.Container.findComponentAtImpl(Container.java:2498)
              at java.awt.Container.findComponentAtImpl(Container.java:2528)
              at java.awt.Container.findComponentAtImpl(Container.java:2528)
              at java.awt.Container.findComponentAtImpl(Container.java:2528)
              at java.awt.Container.findComponentAtImpl(Container.java:2528)
              at java.awt.Container.findComponentAt(Container.java:2492)
              at sun.awt.windows.WGlobalCursorManager.findComponentAt(Native Method)
              at sun.awt.GlobalCursorManager._updateCursor(GlobalCursorManager.java:180)
              at sun.awt.GlobalCursorManager.updateCursorImmediately(GlobalCursorManager.java:82)
              at sun.awt.windows.WComponentPeer.updateCursorImmediately(WComponentPeer.java:538)
              at java.awt.Component.updateCursorImmediately(Component.java:2762)
              at java.awt.Container.remove(Container.java:1170)
              at java.awt.Container.remove(Container.java:1203)
              at javax.swing.plaf.basic.BasicTableHeaderUI.uninstallUI(BasicTableHeaderUI.java:333)
              at javax.swing.JComponent.setUI(JComponent.java:646)
              at javax.swing.table.JTableHeader.setUI(JTableHeader.java:437)
              at javax.swing.table.JTableHeader.updateUI(JTableHeader.java:451)
              at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1206)
              at javax.swing.SwingUtilities.updateComponentTreeUI(SwingUtilities.java:1197)
              at javax.swing.table.JTableHeader.updateUI(JTableHeader.java:455)
              at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1206)
              at javax.swing.SwingUtilities.updateComponentTreeUI(SwingUtilities.java:1197)
              at javax.swing.table.JTableHeader.updateUI(JTableHeader.java:455)
              at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1206)
              at javax.swing.SwingUtilities.updateComponentTreeUI(SwingUtilities.java:1197)
      etc.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.awt.*;
      import javax.swing.*;
      import javax.swing.table.*;
      public class StackOverflowHeader extends JTableHeader implements TableCellRenderer {
          public StackOverflowHeader() {
              setDefaultRenderer(this);
          }

          public Component getTableCellRendererComponent(JTable table, Object value,
              boolean isSelected, boolean hasFocus, int row, int col) {
              return new JLabel(String.valueOf(value));
          }

          private static class SimpleTableDemo extends JPanel {
              public SimpleTableDemo() {
                  super(new GridLayout(1,0));

                  String[] columnNames = {"First Name",
                      "Last Name",
                      "Sport",
                      "# of Years",
                  "Vegetarian"};

                  Object[][] data = {
                      {"Mary", "Campione",
                      "Snowboarding", new Integer(5), new Boolean(false)},
                      {"Alison", "Huml",
                      "Rowing", new Integer(3), new Boolean(true)},
                      {"Kathy", "Walrath",
                      "Knitting", new Integer(2), new Boolean(false)},
                      {"Sharon", "Zakhour",
                      "Speed reading", new Integer(20), new Boolean(true)},
                      {"Philip", "Milne",
                      "Pool", new Integer(10), new Boolean(false)}
                  };

                  final JTable table = new JTable(data, columnNames);
                  table.setPreferredScrollableViewportSize(new Dimension(500, 70));
                  //table.setFillsViewportHeight(true);
                  table.setTableHeader(new StackOverflowHeader());

                  //Create the scroll pane and add the table to it.
                  JScrollPane scrollPane = new JScrollPane(table);

                  //Add the scroll pane to this panel.
                  add(scrollPane);
              }

          }

          /**
           * Create the GUI and show it. For thread safety,
           * this method should be invoked from the
           * event-dispatching thread.
           */
          private static void createAndShowGUI() {
              //Create and set up the window.
              JFrame frame = new JFrame("SimpleTableDemo");
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

              //Create and set up the content pane.
              SimpleTableDemo newContentPane = new SimpleTableDemo();
              newContentPane.setOpaque(true); //content panes must be opaque
              frame.setContentPane(newContentPane);

              //Display the window.
              frame.pack();
              frame.setVisible(true);
              SwingUtilities.updateComponentTreeUI(frame); //calls StackOverflowHeader.updateUI()
          }

          public static void main(String[] args) {
              //Schedule a job for the event-dispatching thread:
              //creating and showing this application's GUI.
              javax.swing.SwingUtilities.invokeLater(new Runnable() {
                      public void run() {
                          createAndShowGUI();
                      }
              });
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      override updateUI() as follows
          public void updateUI(){
              setUI((TableHeaderUI)UIManager.getUI(this));
          }

            Unassigned Unassigned
            igor Igor Nekrestyanov (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: