3

I have the following problem. I need to use some 3rd-party Swing-Components that I cannot change and have no influence on. However, in our situation one UI-component causes the following problem, after which it is no longer usable:

    Uncaught exception in thread Thread[AWT-EventQueue-0,6,main]: 
     java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
        at java.util.ArrayList.rangeCheck(ArrayList.java:653) ~[na:1.8.0_20]
        at java.util.ArrayList.get(ArrayList.java:429) ~[na:1.8.0_20]
        at java.awt.Container.createHierarchyEvents(Container.java:1439) ~[na:1.8.0_20]
        at java.awt.Container.createHierarchyEvents(Container.java:1439) ~[na:1.8.0_20]
        at java.awt.Container.createHierarchyEvents(Container.java:1439) ~[na:1.8.0_20]
        at java.awt.Container.createHierarchyEvents(Container.java:1439) ~[na:1.8.0_20]
        at java.awt.Component.hide(Component.java:1701) ~[na:1.8.0_20]
        at java.awt.Window.hide(Window.java:1117) ~[na:1.8.0_20]
        at javax.swing.Popup.hide(Popup.java:125) ~[na:1.8.0_20]
        at javax.swing.PopupFactory$HeavyWeightPopup.hide(PopupFactory.java:474) ~[na:1.8.0_20]
        at javax.swing.JPopupMenu.setVisible(JPopupMenu.java:796) ~[na:1.8.0_20]
        at some.3rd.party.library.Component

Edit: Funny enough, the component does only cause this exception if we add a HierarchyEventListener to the Toolkit (via Toolkit.getDefaultToolkit().addAWTEventListener(ours, AWTEvent.HIERARCHY_EVENT_MASK);) ... And it seems that this is a rare use case. Otherwise the code in java.awt.Container that throws this exception does not get called at all!

Some Internet research indicates that the underlying cause is that the component is modified outside the EventQueue-Thread (from some code within the component!), but I think I can exclude the possibility.

Since I cannot access the code of the UI-component (and anyway have no idea where the problem gets caused), my proposed solution was to use java bootclasspath-option or javaagent technology to modify the java.awt.Container class and essentially surround the createHierarchyEvents with a try-catch-block. Honestly I don't care about the exception, as long as the component can still be used.

Edit2: Problem occurs on Win and Mac and the L&F doesn't seem to make a difference either. However, the problem is non-deterministic, meaning that it sometimes occurs at the second or third attempt.

Any ideas on that? Suggestions, how to proceed? Is this a good idea? Alternatives? Thanks for any input!

roesslerj
  • 2,611
  • 5
  • 30
  • 44
  • 3
    `Some Internet research indicates that the underlying cause is that the component is modified outside the EventQueue-Thread` - then make sure the code is executed on the EDT, by wrapping the code that uses that component in a `SwingUtilities.invokeLater(..)`. – camickr Oct 20 '15 at 14:49
  • @camickr Thanks for the hint, but the problematic code resides inside the component – with other words: It is not our code that modifies the component outside the EDT-Thread. – roesslerj Oct 20 '15 at 15:00
  • 1
    Well, I'm just suggesting that people don't usually release components that "always" cause an Exception, so I was guessing that the problem was the context of how you are using/invoking the component. Maybe you invoke the component somehow from a non EDT Thread? – camickr Oct 20 '15 at 15:12
  • Funny enough, this component does only cause this exception if we add a `HierarchyEventListener` to the Toolkit (via `Toolkit.getDefaultToolkit().addAWTEventListener(ours, AWTEvent.HIERARCHY_EVENT_MASK);`) ... And it seems that this is a rare use case. Otherwise the code in `java.awt.Container` that throws this exception does not get called at all! -- Hence our idea of wrapping it in a try-catch-block. – roesslerj Oct 20 '15 at 15:14
  • 1
    So the uniqueness is the HierarchyEventListener, so I'm suggesting that whatever code you invoke in that listener should be wrapped in a SwingUtiltities.invokeLater(). Some components place events at the end of the EDT so your code may now be executing in the middle of these events so the component is not in a final state when your code executes. That's my last suggestion, good luck. – camickr Oct 20 '15 at 15:21
  • @camickr Thanks for your thoughts. I wrapped all the code in the listener in `SwingUtiltities.invokeLater()` and still get the exception. Also I paused all threads except the EDT and _still_ get the exception, making me conclude that this is actually not the problem... – roesslerj Oct 20 '15 at 15:39
  • 1
    What happens with other L&Fs, for [example](http://stackoverflow.com/a/11949899/230513)? – trashgod Oct 20 '15 at 19:17
  • @trashgod Thanks for the input, but the L&F doesn't seem to make a difference. I tried 3 different L&Fs and it occurs both on Mac and Win (with according L&Fs). – roesslerj Oct 20 '15 at 20:42

1 Answers1

1

I know this is old, but I found this question when researching a similar exception.

I was doing everything on the EDT as is required and all the components in question were mine. No third party code to point fingers at.

It turned out that we had a situation where a HiearchyListener was responding to a component being hidden. Part of that action was to remove itself from further listening via removeHierarchyListener().

That broke the code in Container.createHierarchyEvents (the source of this exception). Our solution was to delay the listener cleanup via an InvokeLater.

On the surface that sounds like an obvious pitfall, but I couldn't find it documented anywhere to say "don't add/remove listeners when handling an event".

Chris Holt
  • 655
  • 1
  • 6
  • 19