Bug 19566 - Invalid ClassCastException thrown at runtime
Summary: Invalid ClassCastException thrown at runtime
Status: RESOLVED WORKSFORME
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 2.0   Edit
Hardware: PC Windows 2000
: P3 critical (vote)
Target Milestone: 2.0 F3   Edit
Assignee: Philipe Mulet CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2002-06-06 22:55 EDT by Randy Hudson CLA
Modified: 2002-06-12 04:46 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Randy Hudson CLA 2002-06-06 22:55:21 EDT
Draw2d has a listener interface called AncestorListener with 3 methods.  It has 
an adapter implementation called AncestorListener.Stub.

In another class I am creating an anonymous AncestorListener.Stub(){}.  This 
listener gets added to a List using addAncestorListener(AncestorListener 
listener):

	ancestorListener = new AncestorListener.Stub() {
		public void ancestorAdded(IFigure ancestor) {
		}

		public void ancestorRemoved(IFigure ancestor) {
		}

		public void ancestorMoved(IFigure ancestor) {
			placeCellEditor();
		}
	};

The field ancestorListener is typed as AncestorListener.

Later, when enumerating through the listeners, I get a ClassCastException.  
This is impossible.

Here is the interface:
public interface AncestorListener {

/**
 * Called when an ancestor has been added into the listening
 * figure's hierarchy.
 */
public void ancestorAdded(IFigure ancestor);

/**
 * Called when an ancestor has moved to a new location.
 */
public void ancestorMoved(IFigure ancestor);

/**
 * Called when an ancestor has been removed from the listening
 * figure's hierarchy.
 */
public void ancestorRemoved(IFigure ancestor);

class Stub implements AncestorListener {
	public void ancestorMoved(IFigure ancestor){}
	public void ancestorAdded(IFigure ancestor){}
	public void ancestorRemoved(IFigure ancestor){}
}

}


If I change the anonymous implementer to be "new AncestorListener(){}", 
implementing all of the methods, the class cast problem goes away.  If I add 
back in ".Stub" to make it "new AncestorListener.Stub(){}", it comes back.  
Even after shutdown, restart, and full build.
Comment 1 Philipe Mulet CLA 2002-06-07 12:47:28 EDT
Maybe I'm missing some steps, but the following works fine:

X.java
[import java.util.ArrayList;
import java.util.Iterator;

public class X {
	
	AncestorListener listener = new AncestorListener.Stub() {
		public void ancestorAdded(Object ancestor) {
		}
		public void ancestorMoved(Object ancestor) {
		}
		public void ancestorRemoved(Object ancestor) {
		}
	};

	public static void main(String[] arguments) {
		
		new X().foo();
	}	
	
	void foo(){
		ArrayList list = new ArrayList();
		list.add(this.listener);
		
		Iterator iter = list.iterator();
		while (iter.hasNext()) {
			AncestorListener element = (AncestorListener) iter.next
();
			System.out.println(element);
		}
	}
}]


AncestorListener.java
[public interface AncestorListener {

	/**
	 * Called when an ancestor has been added into the listening
	 * figure's hierarchy.
	 */
	public void ancestorAdded(Object ancestor);

	/**
	 * Called when an ancestor has moved to a new location.
	 */
	public void ancestorMoved(Object ancestor);

	/**
	 * Called when an ancestor has been removed from the listening
	 * figure's hierarchy.
	 */
	public void ancestorRemoved(Object ancestor);

	class Stub implements AncestorListener {
		public void ancestorMoved(Object ancestor) {
		}
		public void ancestorAdded(Object ancestor) {
		}
		public void ancestorRemoved(Object ancestor) {
		}
	}

}
]
Comment 2 Randy Hudson CLA 2002-06-07 13:52:55 EDT
I can reproduce this over and over in my workspace.  Can you think of something 
I would be doing wrong?
Comment 3 Randy Hudson CLA 2002-06-07 14:30:59 EDT
You can now reproduce this by checking out:
org.eclipse.gef
org.eclipse.draw2d
org.eclipse.gef.examples.logic

from the dev.eclipse.org/eclipse/tools CVS server.
Load this into an F2 workspace, which also has F2 org.eclipse.ui + dependencies 
loaded as PDE projects.
Launch the runtime workbench.
1) Run the Logic Wizard on a simple project, and create a 4-bit adder in the 
simple project.
2) Drop a label inside a Circuit with some other parts in it.  Resize the 
circuit until it has scrollbars.
3) double click on the label.
4) Scroll the circuit.

This will work until you make the following change.  Shutdown the runtime 
workbench and then change line #169 of DirectEditManager to read:
	ancestorListener = new AncestorListener.Stub() {

If you do this, you will get ClassCastException during step 4 above.
Comment 4 Randy Hudson CLA 2002-06-07 14:32:17 EDT
Runtime JRE is SUN JRE 1.3.1 R08
Comment 5 Philipe Mulet CLA 2002-06-07 19:31:02 EDT
I'll give it a try then, however did you change the default compiler settings ? 
Comment 6 Philipe Mulet CLA 2002-06-07 19:37:03 EDT
Did you fail with the exact test case I pasted in before ?
Comment 7 Philipe Mulet CLA 2002-06-09 09:05:25 EDT
Haven't been able to reproduce so far. One question though: could you have got 
confused by the presence of javax.swing.event.AncestorListener ?
Comment 8 Randy Hudson CLA 2002-06-09 19:06:41 EDT
I don't see any imports to that type in my code, do you?

It should be sufficient to verify the AncestorListener.Stub is not implementing 
the wrong interface, because making the anonymous inner class the Stub versus 
the interface is what causes the problem.

You cannot reproduce this on F2?  Compiler settings are first two Error, next  
4 Warnings, the rest ignore.  I think this is default.
Comment 9 Philipe Mulet CLA 2002-06-10 04:17:38 EDT
I cannot reproduce so far (missing com.ibm.etools. projects). But did you 
reproduce the problem with the 2 files I pasted in this PR ?
Comment 10 Randy Hudson CLA 2002-06-10 09:47:41 EDT
As far as I can tell, the project are released to HEAD in eclipse/tools.
What specifically can you not find?

I'll try your smaller test case, just for fun.
Comment 11 Randy Hudson CLA 2002-06-10 09:52:25 EDT
Smaller test does not reproduce the problem.
I could put my workspace on wall "I" if it would help.
Comment 12 Philipe Mulet CLA 2002-06-10 12:05:43 EDT
Missing projects are com.ibm.etools.draw2d and com.ibm.etools.gef.
A constructed workspace would indeed be interesting.
Comment 13 Philipe Mulet CLA 2002-06-10 12:45:00 EDT
I manually recreated the missing projects from an old version of them I had 
around. These are likely obsolete, but exposed the fact that at that time, 
AncestorListener.Stub was a subclass of Object, not an implementation of 
AncestorListener (com.ibm.etools.draw2d).

Please double check that Stub hierarchy is effectively what it should be. The 
one which matters is the one found first on the classpath order from 
DirectEditManager (in #hookCellEditor).
Comment 14 Randy Hudson CLA 2002-06-10 13:28:27 EDT
The problem is specific to my workspace.  I *did* make the correction in this 
workspace that Stub was not implementing the interface.  Obviously I did this 
right away because otherwise I would have a compile error.

I tried to recreate the problem in a fresh workspace and could not.  However, I 
did reproduce the problem twice because I "cloned" (copied) my workspace prior 
to changing the code.  I cloned my workspace in order to release the code to 
dev.eclipse.org.  When I found the problem in my internal workspace, I was able 
to reproduce it again in my "Open Source" workspace.  The ancestor listener was 
originally a FigureListener, so the entire change involved: change a field, 
anonymous inner-class, and then fixing Stub.
Comment 15 Philipe Mulet CLA 2002-06-11 11:10:51 EDT
Might then be an incremental compilation bug, where an obsolete type would not 
have been rebuilt... sounds weird.

Are you running in autobuild mode ? Did you cancel a build before ?
Comment 16 Randy Hudson CLA 2002-06-11 11:24:13 EDT
I always run in autobuild, but even exiting the workbench and invoking full-
build doesn't fix the problem.

Have you reproduced it?
Comment 17 Philipe Mulet CLA 2002-06-11 11:30:19 EDT
No we cannot reproduce so far.
Comment 18 Philipe Mulet CLA 2002-06-11 11:56:52 EDT
Was able to drop label without any problem using your workspace (had to rebuild 
completely after adjusting JRE to my local install).

- launched Eclipse using launch config (disabled all external plugins)
- created simple project P
- add other resource: Examples/GEF/Logic Diagram
- selected 4-bits adder
- select label in toolbar, dropped it into Circuit #9 (just below Circuit #8)
- could scroll Circuit #9 without getting any exception
Comment 19 Randy Hudson CLA 2002-06-11 13:00:56 EDT
and the anonymous inner class is an AncestorListener.Stub()?  I zipped it up to 
you without the .Stub() being used.
Comment 20 Philipe Mulet CLA 2002-06-11 13:13:28 EDT
Yes, I tried with both cases, using member type Stub or not, didn't make a 
difference, as one would expect.
Comment 21 Philipe Mulet CLA 2002-06-12 04:46:19 EDT
There is no evidence of a classfile being wrong, even checking the binaries 
generated in Randy's original workspace did show the proper hierarchy.

Closing as not reproduceable.