Bug 113630 - IncompatibleClassChangeError - AspectJ5 syntax - mixins
Summary: IncompatibleClassChangeError - AspectJ5 syntax - mixins
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows XP
: P3 major (vote)
Target Milestone: 1.5.0RC1   Edit
Assignee: Adrian Colyer CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-10-25 02:09 EDT by Mohan Radhakrishnan CLA
Modified: 2005-10-28 05:52 EDT (History)
0 users

See Also:


Attachments
java and aj files and a JUnit test case to reproduce this (2.51 KB, application/octet-stream)
2005-10-25 02:13 EDT, Mohan Radhakrishnan CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Mohan Radhakrishnan CLA 2005-10-25 02:09:18 EDT
The attached test case throws this error while executing using Eclipse 3.1 and 
AJDT 1.3.0
Comment 1 Mohan Radhakrishnan CLA 2005-10-25 02:13:56 EDT
Created attachment 28736 [details]
java and aj files and a JUnit test case to reproduce this

java and aj files and a JUnit test case to reproduce this.

I also think this bug might be a problem with my set up but it is recurring.
Comment 2 Andrew Clement CLA 2005-10-25 03:14:31 EDT
Not sure what error you get but I get IncompatibleClassChangeError when running
the JUnit test program included.

java.lang.IncompatibleClassChangeError
	at
com.blueprint.util.aspectj5.test.PropertySupportAspect5.ajc$interMethodDispatch1$com_blueprint_util_aspectj5_test_PropertySupportAspect5$com_blueprint_util_aspectj5_test_PropertySupportAspect5$PropertySupport$addPropertyChangeListener(PropertySupportAspect5.aj)
	at
com.blueprint.util.aspectj5.test.BeanTestCase.testPropertyChange(BeanTestCase.java:25)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:585)
	at junit.framework.TestCase.runTest(TestCase.java:154)
	at junit.framework.TestCase.runBare(TestCase.java:127)
	at junit.framework.TestResult$1.protect(TestResult.java:106)
	at junit.framework.TestResult.runProtected(TestResult.java:124)
	at junit.framework.TestResult.run(TestResult.java:109)
	at junit.framework.TestCase.run(TestCase.java:118)
	at junit.framework.TestSuite.runTest(TestSuite.java:208)
	at junit.framework.TestSuite.run(TestSuite.java:203)
	at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:478)
	at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)
	at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Comment 3 Mohan Radhakrishnan CLA 2005-10-25 03:47:05 EDT
That's right. It is in the bug summary above.
Comment 4 Andrew Clement CLA 2005-10-25 05:12:29 EDT
Ah yes, ignore me - I'm suffering bugzilla blindness from looking at too many
bugs.  The supplied testcase also highlights an interesting problem with
incremental compilation too.
Comment 5 Mohan Radhakrishnan CLA 2005-10-25 07:31:36 EDT
The incremental compilation bug is there in my mixin pattern implementation 
that doesn't use annotations but it works there.
Comment 6 Mohan Radhakrishnan CLA 2005-10-26 06:13:26 EDT
Do you have a workaround for this bug until it is fixed? Anything that would 
give me a annotation based mixin implementation.

Comment 7 Andrew Clement CLA 2005-10-26 06:19:18 EDT
I will look at this imminently and try to get you a workaround/fix - just need
to finish another bug first.
Comment 8 Andrew Clement CLA 2005-10-26 08:28:29 EDT
testcase is checked into CVS (not the incremental compilation problem, just the
IncompatibleClassChange problem).
Comment 9 Mohan Radhakrishnan CLA 2005-10-27 05:43:04 EDT
I changed the retention policy on both annotations to RUNTIME and the code is 
working now. My initial assumption that the problem might be my set up seems 
to be true.

Comment 10 Andrew Clement CLA 2005-10-27 06:22:18 EDT
I noticed this morning that this was the problem too.  I did append a note to
bugzilla but it failed to attach correctly, grrrrr.  Anyway, you should of
course get a nice message when this happens, and I've just put support in for that:

b.addPropertyChangeListener( "name", this );
  ^^^^^^^^^^^^^^^^^^^^
BeanTestCase.java:18:0::0 The method addPropertyChangeListener(String,
BeanTestCase) is undefined for the type Bean

declare parents: @javaBean * implements PropertySupport;
                  ^^^^^
PropertySupportAspect5.aj:9:0::0 Failing match because annotation 'javaBean' on
type 'Bean' has SOURCE retention.  Matching allowed when RetentionPolicy is
CLASS or RUNTIME


I'll check it in imminently.
Comment 11 Andrew Clement CLA 2005-10-27 06:24:04 EDT
For the sake of completeness I want to include my trip round the houses to
discover the annotation was SOURCE (should have realised straightaway, doh!)

===

Exception in thread "main" java.lang.IncompatibleClassChangeError
        at
PropertySupportAspect5.ajc$interMethodDispatch1$PropertySupportAspect5$PropertySupportAspect5$PropertySupport$addPropertyChangeListener(PropertySupportAspect5.aj)
        at BeanTestCase.testPropertyChange(BeanTestCase.java:18)
        at BeanTestCase.main(BeanTestCase.java:13)

line18 in BeanTestCase is:

b.addPropertyChangeListener( "name", this );

which in the bytecode looks like this:

PropertySupportAspect5.ajc$interMethodDispatch1$PropertySupportAspect5$PropertySupportAspect5$PropertySupport$addPropertyChangeListener(b,
"name", this);


In PropertySupportAspect5 we find:

    public static void
ajc$interMethodDispatch1$PropertySupportAspect5$PropertySupportAspect5$PropertySupport$addPropertyChangeListener(PropertySupportAspect5$PropertySupport,
java.beans.PropertyChangeListener);
    public static void
ajc$interMethodDispatch1$PropertySupportAspect5$PropertySupportAspect5$PropertySupport$addPropertyChangeListener(PropertySupportAspect5$PropertySupport,
java.lang.String, java.beans.PropertyChangeListener);

first one takes a propertysupport object and a propertychangelistener.
second one takes a propertysupport object, a string and a propertychangelistener

in this case we are calling the '2nd' one from BeanTestCase

javap -verbose PropertySupport5 gives:

public static void
ajc$interMethod$PropertySupportAspect5$PropertySupportAspect5$PropertySupport$addPropertyChangeListener(PropertySupportAspect5$PropertySupport,
java.beans.PropertyChangeListener);
  Code:
   Stack=0, Locals=2, Args_size=2
   0:	return

public static void
ajc$interMethodDispatch1$PropertySupportAspect5$PropertySupportAspect5$PropertySupport$addPropertyChangeListener(PropertySupportAspect5$PropertySupport,
java.beans.PropertyChangeListener);
  Code:
   Stack=2, Locals=2, Args_size=2
   0:	aload_0
   1:	aload_1
   2:	invokeinterface	#53,  2; //InterfaceMethod
PropertySupportAspect5$PropertySupport.addPropertyChangeListener:(Ljava/beans/PropertyChangeListener;)V
   7:	return

public static void
ajc$interMethod$PropertySupportAspect5$PropertySupportAspect5$PropertySupport$addPropertyChangeListener(PropertySupportAspect5$PropertySupport,
java.lang.String, java.beans.PropertyChangeListener);
  Code:
   Stack=0, Locals=3, Args_size=3
   0:	return

public static void
ajc$interMethodDispatch1$PropertySupportAspect5$PropertySupportAspect5$PropertySupport$addPropertyChangeListener(PropertySupportAspect5$PropertySupport,
java.lang.String, java.beans.PropertyChangeListener);
  Code:
   Stack=3, Locals=3, Args_size=3
   0:	aload_0
   1:	aload_1
   2:	aload_2
   3:	invokeinterface	#59,  3; //InterfaceMethod
PropertySupportAspect5$PropertySupport.addPropertyChangeListener:(Ljava/lang/String;Ljava/beans/PropertyChangeListener;)V
   8:	return

In the case where we call the 3arg variant of
ajc$<...>$addPropertyChangeListener() you can see that it calls
PropertySupport5$PropertySupport.addPropertyChangeListener(PropertyChangeListener)

In PropertySupportAspect5$PropertySupport we see:

    public abstract void
addPropertyChangeListener(java.beans.PropertyChangeListener);
    public abstract void addPropertyChangeListener(java.lang.String,
java.beans.PropertyChangeListener);

And in 'Bean' which is declare parents'd to implement that interface we see:

public class Bean extends java.lang.Object implements java.io.Serializable{
    private java.lang.String name;
    public Bean();
    public java.lang.String getName();
    public void setName(java.lang.String);
}

errrrrr!  It's missing.  Bean should be marked as implementing PropertySupport
and it should have the default implementations from the aspect stuffed into it.

So, you get IncompatibleClassChangeError.

First, lets turn on showWeaveInfo to see what it says:


Type 'PropertySupportAspect5$PropertySupport' (PropertySupportAspect5.aj) has
intertyped method from 'PropertySupportAspect5' (PropertySupportAspect5.aj:'void
PropertySupportAspect5$PropertySupport.addPropertyChangeListener(java.beans.PropertyChangeListener)')
Type 'PropertySupportAspect5$PropertySupport' (PropertySupportAspect5.aj) has
intertyped method from 'PropertySupportAspect5' (PropertySupportAspect5.aj:'void
PropertySupportAspect5$PropertySupport.addPropertyChangeListener(java.lang.String,
java.beans.PropertyChangeListener)')
Type 'PropertySupportAspect5$PropertySupport' (PropertySupportAspect5.aj) has
intertyped method from 'PropertySupportAspect5' (PropertySupportAspect5.aj:'void
PropertySupportAspect5$PropertySupport.removePropertyChangeListener(java.lang.String,
java.beans.PropertyChangeListener)')
Type 'PropertySupportAspect5$PropertySupport' (PropertySupportAspect5.aj) has
intertyped method from 'PropertySupportAspect5' (PropertySupportAspect5.aj:'void
PropertySupportAspect5$PropertySupport.removePropertyChangeListener(java.beans.PropertyChangeListener)')
Type 'PropertySupportAspect5$PropertySupport' (PropertySupportAspect5.aj) has
intertyped method from 'PropertySupportAspect5' (PropertySupportAspect5.aj:'void
PropertySupportAspect5$PropertySupport.hasListeners(java.lang.String)')
Type 'PropertySupportAspect5$PropertySupport' (PropertySupportAspect5.aj) has
intertyped method from 'PropertySupportAspect5' (PropertySupportAspect5.aj:'void
PropertySupportAspect5$PropertySupport.firePropertyChange(Bean,
java.lang.String, java.lang.String, java.lang.String)')

Interestingly there is *nothing* about the declare parents working.  Let's
change the decp statement to explicitly target Bean.

Extending interface set for type 'Bean' (Bean.java) to include
'PropertySupportAspect5$PropertySupport' (PropertySupportAspect5.aj)
Type 'Bean' (Bean.java) has intertyped method from 'PropertySupportAspect5'
(PropertySupportAspect5.aj:'void
PropertySupportAspect5$PropertySupport.addPropertyChangeListener(java.beans.PropertyChangeListener)')
Type 'Bean' (Bean.java) has intertyped method from 'PropertySupportAspect5'
(PropertySupportAspect5.aj:'void
PropertySupportAspect5$PropertySupport.addPropertyChangeListener(java.lang.String,
java.beans.PropertyChangeListener)')
Type 'Bean' (Bean.java) has intertyped method from 'PropertySupportAspect5'
(PropertySupportAspect5.aj:'void
PropertySupportAspect5$PropertySupport.removePropertyChangeListener(java.lang.String,
java.beans.PropertyChangeListener)')
Type 'Bean' (Bean.java) has intertyped method from 'PropertySupportAspect5'
(PropertySupportAspect5.aj:'void
PropertySupportAspect5$PropertySupport.removePropertyChangeListener(java.beans.PropertyChangeListener)')
Type 'Bean' (Bean.java) has intertyped method from 'PropertySupportAspect5'
(PropertySupportAspect5.aj:'void
PropertySupportAspect5$PropertySupport.hasListeners(java.lang.String)')
Type 'Bean' (Bean.java) has intertyped method from 'PropertySupportAspect5'
(PropertySupportAspect5.aj:'void
PropertySupportAspect5$PropertySupport.firePropertyChange(Bean,
java.lang.String, java.lang.String, java.lang.String)')

Type 'PropertySupportAspect5$PropertySupport' (PropertySupportAspect5.aj) has
intertyped method from 'PropertySupportAspect5' (PropertySupportAspect5.aj:'void
PropertySupportAspect5$PropertySupport.addPropertyChangeListener(java.beans.PropertyChangeListener)')
Type 'PropertySupportAspect5$PropertySupport' (PropertySupportAspect5.aj) has
intertyped method from 'PropertySupportAspect5' (PropertySupportAspect5.aj:'void
PropertySupportAspect5$PropertySupport.addPropertyChangeListener(java.lang.String,
java.beans.PropertyChangeListener)')
Type 'PropertySupportAspect5$PropertySupport' (PropertySupportAspect5.aj) has
intertyped method from 'PropertySupportAspect5' (PropertySupportAspect5.aj:'void
PropertySupportAspect5$PropertySupport.removePropertyChangeListener(java.lang.String,
java.beans.PropertyChangeListener)')
Type 'PropertySupportAspect5$PropertySupport' (PropertySupportAspect5.aj) has
intertyped method from 'PropertySupportAspect5' (PropertySupportAspect5.aj:'void
PropertySupportAspect5$PropertySupport.removePropertyChangeListener(java.beans.PropertyChangeListener)')
Type 'PropertySupportAspect5$PropertySupport' (PropertySupportAspect5.aj) has
intertyped method from 'PropertySupportAspect5' (PropertySupportAspect5.aj:'void
PropertySupportAspect5$PropertySupport.hasListeners(java.lang.String)')
Type 'PropertySupportAspect5$PropertySupport' (PropertySupportAspect5.aj) has
intertyped method from 'PropertySupportAspect5' (PropertySupportAspect5.aj:'void
PropertySupportAspect5$PropertySupport.firePropertyChange(Bean,
java.lang.String, java.lang.String, java.lang.String)')

You can see Bean gets a lot more action now and the testcase runs fine.  So the
question is why '@javaBean *' didn't appear to match the Bean type in some ways
but did in others...

Breakpoint in DeclareParents.maybeGetNewParent() - what does it think?

It is called during AjLookupEnvironment.completeTypeBindings() (i.e. during
compilation)
- it succeeds and returns PropertySupportAspect5$PropertySupport

In BcelWeaver we also do the declare parents (for the case of binary weaving). 
Here the match fails and the decp doesn't apply.  Why is that?  Well it turns
out that the annotation has SOURCE retention so of course it is lost and never
put into the bytecode.  

So the fix is for us to put out an message if you attempt to match on a SOURCE
annotation.
Comment 12 Andrew Clement CLA 2005-10-27 06:49:52 EDT
Fix checked in to give the nice new messages.  Will close when build available.
Comment 13 Andrew Clement CLA 2005-10-28 05:52:55 EDT
Fix available - i believe incremental case is a symptom of the same problem. 
Please reopen if you still see a problem with the incremental compilation.