JDK-6495408 : REGRESSION: JTabbedPane throws ArrayIndexOutOfBoundsException
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 5.0,5.0u9
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2006-11-20
  • Updated: 2011-02-16
  • Resolved: 2009-05-18
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7
6u14 b03Fixed 7Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_09"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_09-b01)
Java HotSpot(TM) Client VM (build 1.5.0_09-b01, mixed mode)

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

A DESCRIPTION OF THE PROBLEM :
ArrayIndexOutOfBoundsException  at  javax.swing.plaf.basic.BasicTabbedPaneUI.tabForCoordinate(BasicTabbedPaneUI.java:1286) with a JTabbedPane with tab position LEFT. Seems to be a regression of bug 4962642 which is marked as fixed, reproducible always when the mouse pointer is over the position where the new tab will appear.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
See bug 4962642, exception is reproducible always when the mouse pointer is over the position where the new tab will appear.

Turns out reproducing this was not as trivial as I thought, seems to involve a critical timing issue somewhere. Anyway, long story short, the code below reliably reproduces the Exception I see in my code. Key seems to be time spent generating or rendering the icon on the tab (tabs in my app have thumbnails in them).

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 1
        at javax.swing.plaf.basic.BasicTabbedPaneUI.tabForCoordinate(BasicTabbedPaneUI.java:1286)
        at javax.swing.plaf.basic.BasicTabbedPaneUI.setRolloverTab(BasicTabbedPaneUI.java:499)
        at javax.swing.plaf.basic.BasicTabbedPaneUI.access$1200(BasicTabbedPaneUI.java:37)
        at javax.swing.plaf.basic.BasicTabbedPaneUI$Handler.mouseEntered(BasicTabbedPaneUI.java:3219)
        at java.awt.Component.processMouseEvent(Component.java:5497)
        at javax.swing.JComponent.processMouseEvent(JComponent.java:3126)
        at java.awt.Component.processEvent(Component.java:5253)
        at java.awt.Container.processEvent(Container.java:1966)
        at java.awt.Component.dispatchEventImpl(Component.java:3955)
        at java.awt.Container.dispatchEventImpl(Container.java:2024)
        at java.awt.Component.dispatchEvent(Component.java:3803)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4212)
        at java.awt.LightweightDispatcher.trackMouseEnterExit(Container.java:4017)
        at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3874)
        at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3822)
        at java.awt.Container.dispatchEventImpl(Container.java:2010)
        at java.awt.Window.dispatchEventImpl(Window.java:1778)
        at java.awt.Component.dispatchEvent(Component.java:3803)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
        at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:242)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)


---------- BEGIN SOURCE ----------
import java.awt.*;
import javax.swing.*;
import static java.awt.RenderingHints.*;
import java.awt.event.KeyEvent;
import java.awt.geom.GeneralPath;
public class BugReport {
    public static void main(String[] args) throws Exception {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
       
        final JTabbedPane tabs = new JTabbedPane();
        tabs.setTabPlacement(JTabbedPane.LEFT);
       
        // Another (bonus) bug - if one of the tabs has html text in it
        // adding a tab with a null component will then generate an NPE
        // in Vector.elementAt(), uncomment the line below to see this
        tabs.addTab("<HTML><FONT size = 10>TAB</FONT></HTML>",new JPanel());
        tabs.addTab(null, new TabIcon(), new JPanel());
       
        JFrame frame = new JFrame("Bug Report");
        frame.setContentPane(tabs);
        frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
        frame.setBounds(100,100,200,600);
        frame.setVisible(true);
       
        Thread.sleep(1000);
       
        final Robot robot = new Robot();
        final Rectangle d = new Rectangle();
        final Point p = new Point();
       
        Runnable runner = new Runnable(){
            public void run(){
                try {
                    for (int i=0; i<7; i++){
                        Thread.sleep(1000);
                        SwingUtilities.invokeLater(new Runnable(){
                            public void run(){
                                int tab = tabs.getTabCount()-1;
                                d.setBounds(tabs.getBoundsAt(tab));
                                p.setLocation(d.x+d.width/2,d.y+d.height/2);
                                SwingUtilities.convertPointToScreen(p,tabs);
                                robot.mouseMove(p.x,p.y+d.height);
                                tabs.addTab(null, new TabIcon(), null);
                            }
                        });
                    }
                } catch (Exception ex) {}
            }
        };
        runner.run();
    }
   
    static final class TabIcon implements Icon {
        final int W = 60;
        public TabIcon() {
        }
        public int getIconHeight() {
            return W;
        }
        public int getIconWidth() {
            return W;
        }
        public void paintIcon(Component c, Graphics g, int x, int y) {
            Graphics2D g2 = (Graphics2D)g.create();
            Color iconColor = Color.BLUE;
            g2.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);
            g2.setRenderingHint(KEY_RENDERING, VALUE_RENDER_QUALITY);
            g2.setColor(Color.BLUE);
            g2.fillOval(x, y, W, W);
            g2.setColor(Color.RED);
            GeneralPath path = new GeneralPath();
            path.moveTo(x+W/2,y+W/2);
            for (int i=0; i<10000; i++){
                path.lineTo(x+W/4+(float)Math.random()*W/2, y+W/4+(float)Math.random()*W/2);
            }
            g2.draw(path);
            g2.dispose();
        }
    }
}
---------- END SOURCE ----------


REPRODUCIBILITY :
This bug can be reproduced always.

Comments
WORK AROUND add new JPanel() instead of null tabs.addTab(null, new TabIcon(), new JPanel());
21-11-2006

EVALUATION For the root of the problem please see evaluation for 4962642 The fix for 4962642 is incomplete, it doesn't take into account the case when null component is added to a JTabbedPane see JTabbedPane.insertTab() if (component != null) { addImpl(component, null, -1); component.setVisible(false); } if component is null we don't call addImpl and BasicTabbedPane.Handler.componentAdded() is not called as well -> isRunsDirty is not set to true which causes the problem
21-11-2006