JDK-7148143 : PropertyChangeSupport.addPropertyChangeListener can throw ClassCastException
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.beans
  • Affected Version: 7
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_7
  • CPU: x86
  • Submitted: 2012-02-23
  • Updated: 2012-03-27
  • Resolved: 2012-03-14
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 7 JDK 8
7u6Fixed 8 b30Fixed
Description
FULL PRODUCT VERSION :
java version "1.7.0_03"
Java(TM) SE Runtime Environment (build 1.7.0_03-b05)
Java HotSpot(TM) Client VM (build 22.1-b02, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7600]

A DESCRIPTION OF THE PROBLEM :
Under Java7 there's a regression in PropertyChangeSupport.addPropertyChangeListener(String, PropertyChangeListener) whereby a ClassCastException is thrown when the specified listener extends EventListenerProxy<T> and T does not extend PropertyChangeListener.

It appears to be due to PropertyChangeSupport.PropertyChangeListenerMap wrongly assuming that all wrapped EventListenerProxy<?> listeners are EventListenerProxy<PropertyChangeListener>.  The unwrapping in PropertyChangeListenerMap.extract should be restricted to PropertyChangeListenerProxys.

REGRESSION.  Last worked in version 6u29

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached test case.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Test case completing successfully.
ACTUAL -
The attached exception is thrown.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.ClassCastException: Main$MyListener cannot be cast to java.beans.PropertyChangeListener
	at java.beans.PropertyChangeSupport.addPropertyChangeListener(PropertyChangeSupport.java:201)
	at Main.main(Main.java:36)


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.EventListener;
import java.util.EventListenerProxy;

public class Main
{
	public static class MyListener implements EventListener
	{
	}
	
	public static class MyProxyListener extends EventListenerProxy<MyListener> implements PropertyChangeListener
	{
		public MyProxyListener(MyListener proxy)
		{
			super(proxy);
		}
		
		@Override
		public void propertyChange(PropertyChangeEvent event)
		{
		}
	}
	
	public static void main(String[] args)
	{
		MyListener listener = new MyListener();
		PropertyChangeListener proxyListener = new MyProxyListener(listener);
		PropertyChangeSupport support = new PropertyChangeSupport(new Main());
		
		// OK
		support.addPropertyChangeListener(proxyListener);
		
		// throws ClassCastException in Java7
		support.addPropertyChangeListener("foo", proxyListener);
	}
}

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

CUSTOMER SUBMITTED WORKAROUND :
Introduce EventListenerProxy2 as a copy of EventListenerProxy and extend that instead for added property change listeners, if possible.

Comments
EVALUATION We should implement the extract method for specific classes only.
29-02-2012