JDK-5049957 : JTableHeader+custom TableCellRenderer+XP L&F crashes if user hotswaps XP theme
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 5.0,6
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2004-05-19
  • Updated: 2010-05-17
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
Name: gm110360			Date: 05/19/2004


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

java version "1.5.0-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta-b32c)
Java HotSpot(TM) Client VM (build 1.5.0-beta-b32c, mixed mode)

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

A DESCRIPTION OF THE PROBLEM :
Using a custom TableCellRenderer for JTableHeader (like the TableSorter explained in Swing Tutorial does)  with XP look & feel leads to an unrecoverable crash of Swing painting loop when user hotswaps the Windows XP desktop colors theme (i.e. from "blue" to "light gray") "under the feet" of the Java application.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create a JFrame.
Create a JTable.
Create a custom TableCellRenderer.
Get  JTable's JTableHeader and replace its default renderer with the custom one.
Add the JTable to a JScrollPane and the JScrollPane to the content panel of the JFrame.
Display the JFrame in an application with XP look and feel enabled.
While the JFrame is displayed,  open the Windows desktop properties and change the current color theme (i.e. from "blue" to "light gray")


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
JFrame look & feel change reflecting the modified  desktop color theme.  Application continues to run normally.
ACTUAL -
Application stops repainting itself,  because of an uncaught NPE thrown during the painting loop.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Using JSDK1.4.2:

java.lang.NullPointerException
        at com.sun.java.swing.plaf.windows.WindowsTableHeaderUI$XPDefaultRendere
r.paint(WindowsTableHeaderUI.java:81)
        at javax.swing.CellRendererPane.paintComponent(CellRendererPane.java:134
)
        at javax.swing.plaf.basic.BasicTableHeaderUI.paintCell(BasicTableHeaderU
I.java:401)
        at javax.swing.plaf.basic.BasicTableHeaderUI.paint(BasicTableHeaderUI.ja
va:341)
        at javax.swing.plaf.ComponentUI.update(ComponentUI.java:142)
        at javax.swing.JComponent.paintComponent(JComponent.java:541)
        at javax.swing.JComponent.paint(JComponent.java:808)
        at javax.swing.JComponent.paintChildren(JComponent.java:647)
        at javax.swing.JComponent.paint(JComponent.java:817)
        at javax.swing.JViewport.paint(JViewport.java:722)
        at javax.swing.JComponent.paintChildren(JComponent.java:647)
        at javax.swing.JComponent.paint(JComponent.java:817)
        at javax.swing.JComponent.paintChildren(JComponent.java:647)
        at javax.swing.JComponent.paint(JComponent.java:817)
        at javax.swing.JComponent.paintChildren(JComponent.java:647)
        at javax.swing.JComponent.paint(JComponent.java:817)
        at javax.swing.JLayeredPane.paint(JLayeredPane.java:557)
        at javax.swing.JComponent.paintChildren(JComponent.java:647)
        at javax.swing.JComponent.paintWithOffscreenBuffer(JComponent.java:4802)

        at javax.swing.JComponent.paintDoubleBuffered(JComponent.java:4748)
        at javax.swing.JComponent.paint(JComponent.java:798)
        at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:21)

        at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:
60)
        at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97
)
        at java.awt.Container.paint(Container.java:1312)
        at sun.awt.RepaintArea.paint(RepaintArea.java:177)
        at sun.awt.windows.WComponentPeer.handleEvent(WComponentPeer.java:260)
        at java.awt.Component.dispatchEventImpl(Component.java:3678)
        at java.awt.Container.dispatchEventImpl(Container.java:1627)
        at java.awt.Window.dispatchEventImpl(Window.java:1606)
        at java.awt.Component.dispatchEvent(Component.java:3477)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:456)
        at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchTh
read.java:201)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThre
ad.java:151)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:145)

        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:137)

        at java.awt.EventDispatchThread.run(EventDispatchThread.java:100)


Using JSDK 1.5.0-beta:

java.lang.NullPointerException
        at com.sun.java.swing.plaf.windows.WindowsTableHeaderUI$XPDefaultRendere
r.paint(WindowsTableHeaderUI.java:138)
        at javax.swing.CellRendererPane.paintComponent(CellRendererPane.java:134
)
        at javax.swing.plaf.basic.BasicTableHeaderUI.paintCell(BasicTableHeaderU
I.java:394)
        at javax.swing.plaf.basic.BasicTableHeaderUI.paint(BasicTableHeaderUI.ja
va:341)
        at javax.swing.plaf.ComponentUI.update(ComponentUI.java:142)
        at javax.swing.JComponent.paintComponent(JComponent.java:714)
        at javax.swing.JComponent.paint(JComponent.java:977)
        at javax.swing.JComponent.paintChildren(JComponent.java:814)
        at javax.swing.JComponent.paint(JComponent.java:986)
        at javax.swing.JViewport.paint(JViewport.java:722)
        at javax.swing.JComponent.paintChildren(JComponent.java:814)
        at javax.swing.JComponent.paint(JComponent.java:986)
        at javax.swing.JComponent.paintChildren(JComponent.java:814)
        at javax.swing.JComponent.paint(JComponent.java:986)
        at javax.swing.JComponent.paintChildren(JComponent.java:814)
        at javax.swing.JComponent.paint(JComponent.java:986)
        at javax.swing.JLayeredPane.paint(JLayeredPane.java:559)
        at javax.swing.JComponent.paintChildren(JComponent.java:814)
        at javax.swing.JComponent.paintWithOffscreenBuffer(JComponent.java:4882)

        at javax.swing.JComponent.paintDoubleBuffered(JComponent.java:4828)
        at javax.swing.JComponent.paint(JComponent.java:967)
        at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:21)

        at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:
60)
        at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97
)
        at java.awt.Container.paint(Container.java:1704)
        at javax.swing.JFrame.update(JFrame.java:392)
        at sun.awt.RepaintArea.updateComponent(RepaintArea.java:239)
        at sun.awt.RepaintArea.paint(RepaintArea.java:216)
        at sun.awt.windows.WComponentPeer.handleEvent(WComponentPeer.java:247)
        at java.awt.Component.dispatchEventImpl(Component.java:4007)
        at java.awt.Container.dispatchEventImpl(Container.java:2019)
        at java.awt.Window.dispatchEventImpl(Window.java:1757)
        at java.awt.Component.dispatchEvent(Component.java:3779)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
        at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchTh
read.java:234)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThre
ad.java:163)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)

        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)




REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

public class XPTableHeaderTest extends JFrame {

   public XPTableHeaderTest() {
      super("XPTableHeaderTest");
      JTable table = new JTable(new Object[][] {
                                new Object[] {"a1", "b1", "c1"}
                                ,
                                new Object[] {"a2", "b2", "c2"}
      }
         ,
         new Object[] {"A", "B", "C"});
      JTableHeader header = table.getTableHeader();
      header.setDefaultRenderer(new CustomRenderer(
         header.getDefaultRenderer()));
      getContentPane().setLayout(new BorderLayout());
      getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
      setBounds(0, 0, 640, 400);
      validate();
   }

   public static void main(String[] args) {
      try {
         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
      } catch (Exception ex) {
         ex.printStackTrace();
      }

      new XPTableHeaderTest().show();
   }


   private static class CustomRenderer implements TableCellRenderer {
      private TableCellRenderer delegate;

      public CustomRenderer(TableCellRenderer delegate) {
         this.delegate = delegate;
      }

      public Component getTableCellRendererComponent(JTable table,
         Object value,
         boolean isSelected,
         boolean hasFocus,
         int row,
         int column) {
         return delegate.getTableCellRendererComponent(table,
            value, isSelected, hasFocus, row, column);

      }
   }
}
---------- END SOURCE ----------
(Incident Review ID: 270368) 
======================================================================
###@###.### 10/13/04 18:37 GMT

Comments
EVALUATION apparently this bug is still reproducible on 1.6 --- bugid: 6509786 The bug 5049957 appears to still be present. I have confirmed that the following code from an external reporter still exhibits this bug, or at least what appears to be this bug. OK, here is the code. Simply run this application on a Windows XP machine and then change the XP theme. A NPE will be thrown. [code] import java.awt.BorderLayout; import java.awt.Component; import java.awt.EventQueue; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.table.JTableHeader; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumnModel; import com.sun.java.swing.plaf.windows.WindowsLookAndFeel; public class NPETest extends JFrame { private JTable table; private JScrollPane pane; private class HeaderRenderer implements TableCellRenderer { private TableCellRenderer tableCellRenderer; public HeaderRenderer(TableCellRenderer tableCellRenderer) { this.tableCellRenderer = tableCellRenderer; } public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,int row, int column) { Component c = tableCellRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); return c; } } class MyHeader extends JTableHeader { public MyHeader(TableColumnModel model) { super(model); setDefaultRenderer(new HeaderRenderer(getDefaultRenderer())); } } public NPETest() { try { UIManager.setLookAndFeel(new WindowsLookAndFeel()); } catch (UnsupportedLookAndFeelException ulafe) { } Object[][] data = new Object[][] {{1, 2, 3, 4, 5, 6}, {2, 4, 8, 9, 5, 7}, {3, 1, 6, 5, 3, 2}, {4, 6, 6, 7, 6, 8}}; String[] colNames = new String[] {"A", "B", "C", "D", "E", "F"}; setLayout(new BorderLayout()); pane = new JScrollPane(); table = new JTable(data, colNames); table.setTableHeader(new MyHeader(table.getColumnModel())); pane.setViewportView(table); add(pane, BorderLayout.CENTER); pack(); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } /** * @param args */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { new NPETest().setVisible(true); } }); } } [/code] It produces the following stack trace in the latest version of Java 6 available from java.sun.com when switching the theme in Windows XP Pro, SP 2. java.lang.NullPointerException at com.sun.java.swing.plaf.windows.WindowsTableHeaderUI$XPDefaultRenderer.paint(WindowsTableHeaderUI.java:95) at javax.swing.CellRendererPane.paintComponent(CellRendererPane.java:134) at javax.swing.plaf.basic.BasicTableHeaderUI.paintCell(BasicTableHeaderUI.java:665) at javax.swing.plaf.basic.BasicTableHeaderUI.paint(BasicTableHeaderUI.java:607) at javax.swing.plaf.ComponentUI.update(ComponentUI.java:143) at javax.swing.JComponent.paintComponent(JComponent.java:758) at javax.swing.JComponent.paint(JComponent.java:1022) at javax.swing.JComponent.paintChildren(JComponent.java:859) at javax.swing.JComponent.paint(JComponent.java:1031) at javax.swing.JViewport.paint(JViewport.java:747) at javax.swing.JComponent.paintChildren(JComponent.java:859) at javax.swing.JComponent.paint(JComponent.java:1031) at javax.swing.JComponent.paintChildren(JComponent.java:859) at javax.swing.JComponent.paint(JComponent.java:1031) at javax.swing.JComponent.paintChildren(JComponent.java:859) at javax.swing.JComponent.paint(JComponent.java:1031) at javax.swing.JComponent.paintChildren(JComponent.java:859) at javax.swing.JComponent.paint(JComponent.java:1031) at javax.swing.JComponent.paintChildren(JComponent.java:859) at javax.swing.JComponent.paint(JComponent.java:1031) at javax.swing.JComponent.paintChildren(JComponent.java:859) at javax.swing.JSplitPane.paintChildren(JSplitPane.java:1026) at javax.swing.JComponent.paint(JComponent.java:1031) at javax.swing.JComponent.paintChildren(JComponent.java:859) at javax.swing.JComponent.paint(JComponent.java:1031) at javax.swing.JComponent.paintChildren(JComponent.java:859) at javax.swing.JComponent.paint(JComponent.java:1031) at javax.swing.JComponent.paintChildren(JComponent.java:859) at javax.swing.JSplitPane.paintChildren(JSplitPane.java:1026) at javax.swing.JComponent.paint(JComponent.java:1031) at javax.swing.JComponent.paintChildren(JComponent.java:859) at javax.swing.JComponent.paint(JComponent.java:1031) at javax.swing.JComponent.paintChildren(JComponent.java:859) at javax.swing.JComponent.paint(JComponent.java:1031) at javax.swing.JComponent.paintChildren(JComponent.java:859) at javax.swing.JComponent.paint(JComponent.java:1031) at javax.swing.JLayeredPane.paint(JLayeredPane.java:564) at javax.swing.JComponent.paintChildren(JComponent.java:859) at javax.swing.JComponent.paintToOffscreen(JComponent.java:5111) at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:285) at javax.swing.RepaintManager.paint(RepaintManager.java:1128) at javax.swing.JComponent.paint(JComponent.java:1008) at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:21) at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60) at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97) at java.awt.Container.paint(Container.java:1797) at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:734) at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:679) at javax.swing.RepaintManager.seqPaintDirtyRegions(RepaintManager.java:659) 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) *** (#1 of 1): 2007-01-04 15:30:08 EST ###@###.### --- reopening this bug.
19-03-2007

EVALUATION [SQE] Risk: NORMAL Compile and run the test program from the description. Switch XP themes while the program is running. The program should not crash or throw an exception. Affects Swing applications running on Windows XP with the Windows XP Look and Feel. This affects only JTables using custom JTableHeader renderers. [/SQE]
17-11-2005

EVALUATION My own research indicates that the skin field in the XPDefaultRenderer inner class is becoming null when the theme changes. I'm not sure if this is the same reference that ###@###.### was talking about in his evaluation note. A test which can re-initalize the skin field based on the current theme fixes the NPE.
14-11-2005

CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mustang
25-09-2004

EVALUATION The default header renderer on XP is an inner class of WindowsTableHeaderUI. It is not a static class, so it still has a reference to the outer class instance after that instance has been uninstalled. ###@###.### 2004-05-24
24-05-2004