JDK-6433222 : EventHandler will throw ArrayIndexOutOfBoundsException in can't find method
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.beans
  • Affected Version: 5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: linux
  • CPU: x86
  • Submitted: 2006-06-02
  • Updated: 2011-02-16
  • Resolved: 2006-06-02
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Linux rpc268 2.6.15-gentoo-r1 #1 SMP Tue Mar 7 16:41:59 GMT 2006 i686 Intel(R) Pentium(R) D CPU 3.20GHz GenuineIntel GNU/Linux


A DESCRIPTION OF THE PROBLEM :
This is also described in bug 4511992, but that is falsely closed and referred to a not-so-very-relevant bug about the documentation.

There is a bug in the CODE of EventHandler.java

If calling EventHandler.create(SomeListener.class, this, "wrong") and invoking

    public static <T> T create(Class<T> listenerInterface,
                               Object target, String action)

then both eventPropertyName and listenerMethodName will be set to null, and when the EventHandler is invoked:

            if (eventPropertyName == null) {     // Nullary method.
                newArgs = new Object[]{};
                argTypes = new Class[]{};
                if (targetMethod == null) {
                    targetMethod = ReflectionUtils.getMethod(target.getClass(),
                                                             action, argTypes);
                }
                if (targetMethod == null) {
                    targetMethod = ReflectionUtils.getMethod(target.getClass(),
                             "set" + NameGenerator.capitalize(action), argTypes);
                }

which should throw a runtime error if "getWrong" or "setWrong" does not exist:

                if (targetMethod == null) {
                    throw new RuntimeException("No method called: " +
                                               action + " on class " +
                                               target.getClass() + " with argument "
                                               + argTypes[0]);
 }

.. but obviously this won't work when argTypes is an empty array. And so an ArrayIndexOfBoundsException is thrown instead.

  Suggested fix:

Avoid using argTypes[0] in the exception throwing.



STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile swing-code given with 1.5, run with 1.5

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Expected RunTimeException to help explain somewhat that "nonExisting" was not a very good argument for EventHandler.create(), ie a traceback with something like:

Exception in thread "AWT-EventQueue-0" java.lang.RuntimeException: No method called nonExisting on class EventCrasher.

ACTUAL -
The internal "raise exception" code of EventHandler.invokeInternal has a bug where it reads from an empty array:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0
        at java.beans.EventHandler.invokeInternal(EventHandler.java:379)
        at java.beans.EventHandler.access$000(EventHandler.java:205)
        at java.beans.EventHandler$1.run(EventHandler.java:338)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.beans.EventHandler.invoke(EventHandler.java:336)
        at $Proxy0.focusGained(Unknown Source)
        at java.awt.AWTEventMulticaster.focusGained(AWTEventMulticaster.java:162)
        at java.awt.Component.processFocusEvent(Component.java:5377)
        at java.awt.Component.processEvent(Component.java:5244)
        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.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1810)
        at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:831)
        at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:480)
        at java.awt.Component.dispatchEventImpl(Component.java:3841)
        at java.awt.Container.dispatchEventImpl(Container.java:2024)
        at java.awt.Component.dispatchEvent(Component.java:3803)
        at sun.awt.X11.XWindow$1.run(XWindow.java:331)
        at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:461)
        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)



REPRODUCIBILITY :
This bug can be reproduced occasionally.

---------- BEGIN SOURCE ----------
import java.awt.event.FocusListener;
import java.beans.EventHandler;

import javax.swing.JFrame;
import javax.swing.JTextField;

public class EventCrasher extends JFrame {

	public EventCrasher() {
		super();
		JTextField field = new JTextField("Hello", 25);
		this.add(field);
		field.addFocusListener((FocusListener) EventHandler.create(
			FocusListener.class, this, "nonExisting"));
	}

	public static void main(String[] args) {
		EventCrasher a = new EventCrasher();
		a.setVisible(true);
		a.toFront();

	}

}

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

CUSTOMER SUBMITTED WORKAROUND :
(For the user):   Use a method name that exists
(For Sun):  Don't include argTypes[0] when throwing exceptions. Include unittests that try to raise the expected exceptions.