Bug 104603 - ClassGenException in weaver/bcel/ShadowRange:extractInstructionsInto()
Summary: ClassGenException in weaver/bcel/ShadowRange:extractInstructionsInto()
Status: RESOLVED WORKSFORME
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: 1.2   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Andrew Clement CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-07-20 20:14 EDT by Darren Price CLA
Modified: 2006-05-25 05:23 EDT (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Darren Price CLA 2005-07-20 20:14:31 EDT
This problem may only occur when Aspect/J tries to do a weaveAroundInline() on 
an instruction list that includes a Select.  Our usage of Aspect/J only rarely 
causes it to use weaveAroundInline(), so I don't have any other cases for 
comparison.

In ShadowRange:extractInstructionsInto(), my instruction list includes a 
Select.  Each of the targets of the Select has a list of targetters that 
includes what appears to be a Select from some other instantiation of the 
instruction list, in addition to the local Select.  The updateTarget() call on 
the bogus Select targetter causes the ClassGenException (stack trace attached 
below).

My clumsy band-aid (also attached below) is to clean the bad state from the 
Select targets at the top of extractInstructionsInto().  However, I presume 
that the real fix needs to be done at the point the bad state was introduced 
into the instruction list.

I noticed that a possibly similar problem was reported awhile back, but 
apparently not in a reliably reproducible way.  From browsing through the top 
of the CVS tree, it appears that the weaver/bcel directory hasn't changed 
drastically since 1.2, so I assume that this problem may still be lurking 
there.

Here's the stack trace:

AspectJInstrumenter:weaveClass,org.apache.bcel.generic.ClassGenException: Not
targeting   36: aload_0[42](1)
AspectJInstrumenter:weaveClass,	at
org.apache.bcel.generic.Select.updateTarget(Select.java:213)
AspectJInstrumenter:weaveClass,	at
org.aspectj.weaver.bcel.ShadowRange.extractInstructionsInto
(ShadowRange.java:138)
AspectJInstrumenter:weaveClass,	at
org.aspectj.weaver.bcel.BcelShadow.extractMethod(BcelShadow.java:2002)
AspectJInstrumenter:weaveClass,	at
org.aspectj.weaver.bcel.BcelShadow.weaveAroundInline(BcelShadow.java:1436)
AspectJInstrumenter:weaveClass,	at
org.aspectj.weaver.bcel.BcelAdvice.implementOn(BcelAdvice.java:151)
AspectJInstrumenter:weaveClass,	at
org.aspectj.weaver.Shadow.implementMungers(Shadow.java:353)
AspectJInstrumenter:weaveClass,	at
org.aspectj.weaver.Shadow.implement(Shadow.java:325)
AspectJInstrumenter:weaveClass,	at
org.aspectj.weaver.bcel.BcelClassWeaver.implement(BcelClassWeaver.java:1161)
AspectJInstrumenter:weaveClass,	at
org.aspectj.weaver.bcel.BcelClassWeaver.weave(BcelClassWeaver.java:367)
AspectJInstrumenter:weaveClass,	at
org.aspectj.weaver.bcel.BcelClassWeaver.weave(BcelClassWeaver.java:80)
AspectJInstrumenter:weaveClass,	at
org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:724)
AspectJInstrumenter:weaveClass,	at
org.aspectj.weaver.bcel.BcelWeaver.weaveWithoutDump(BcelWeaver.java:689)
AspectJInstrumenter:weaveClass,	at
org.aspectj.weaver.bcel.BcelWeaver.weaveAndNotify(BcelWeaver.java:615)
AspectJInstrumenter:weaveClass,	at
org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:563)
AspectJInstrumenter:weaveClass,	at
com.acsera.javaagent.AspectJWeavingAdaptor.getWovenBytes
(AspectJWeavingAdaptor.java:244)
AspectJInstrumenter:weaveClass,	at
com.acsera.javaagent.AspectJWeavingAdaptor.weaveClass
(AspectJWeavingAdaptor.java:210)

And here's the patch:

void extractInstructionsInto(LazyMethodGen freshMethod, IntMap remap, boolean 
addReturn) {
	// XXX Darren
		// Find all the Select instructions in this list, and all of 
their targets.
		// Run through the targets and remove any Select targeters 
that aren't from this list.

		java.util.Set selectSet = new java.util.HashSet();
		java.util.Set targetSet = new java.util.HashSet();
		for ( InstructionHandle ih = start.getNext(); ih != end; ih = 
ih.getNext() ) {
			Instruction ii = ih.getInstruction();
			if ( ii instanceof Select ) {
				Select si = (Select) ii;
				selectSet.add( si );
				targetSet.add( si.getTarget() );
				InstructionHandle[] targets = si.getTargets();
				for ( int k = 0; k < targets.length; k++ ) {
					targetSet.add( targets[ k ] );
				}
			}
		}
		java.util.Iterator it = targetSet.iterator();
		while ( it.hasNext() ) {
			InstructionHandle ih = (InstructionHandle) it.next();
			InstructionTargeter[] its = ih.getTargeters();
			if ( its == null ) {
				continue;	// XXX internal consistency 
error?
			}
			for ( int k = 0; k < its.length; k++ ) {
				if ( its[k] instanceof Select ) {
					Select si = (Select) its[k];
					if ( ! selectSet.contains( si ) ) {
						// XXX System.out.println
( "ShadowRange:extractInstructionsInto: bogus Select " + si.toString() + " " + 
si.hashCode() );
						ih.removeTargeter( si );
					}
				}
			}
		}
		// XXX Darren
Comment 1 Adrian Colyer CLA 2005-08-26 11:39:21 EDT
for M4 investigation
Comment 2 Andrew Clement CLA 2005-09-15 05:26:26 EDT
Is there any way you can supply a program that exhibits the incorrect behaviour
when weaving?  I'm trying to hack some up myself but can't get it to fail.  I
did change some Select related stuff recently in BCEL for another bug - I've no
idea if it will affect this situation though.  I'd like to have a test program
before making a change like this.

If you can't supply the program, can you  at least tell me the pointcut/advice
declaration involved? so I can continue trying to recreate.  thanks.
Comment 3 Adrian Colyer CLA 2005-10-28 06:54:39 EDT
We'd like to fix this for 1.5.0 - but don't want to make a change without being able to reproduce first.

Do you have a test program that reproduces this we you could append please? 
Thanks.
Comment 4 Andrew Clement CLA 2005-11-09 03:58:10 EST
Hmmm - as I re-read this bug this morning, I remember something in my murky past
where I fixed something possibly related.  Given that this was raised against
1.2, take a look at bug 104720 - that was a problem in bcel to do with
extracting instructions containing a select.  The problem there did manifest at
runtime, rather than compile time as discussed in this bug, but it looks a
similar problem to do with the targets getting messed up.

"Exception in thread "main" java.lang.VerifyError: (class: Test, method:"
"newTest_aroundBody2 signature: (I)LTest;) Illegal default target in switch"

Can you possibly retry the failing scenario with a build of AspectJ 5?
Comment 5 Andrew Clement CLA 2005-11-14 11:28:02 EST
not seen on 1.5 ... delaying for investigation in 1.5.1
Comment 6 Andrew Clement CLA 2006-05-25 05:23:15 EDT
bug not seen in the last few months - presumed fixed. please reopen if you see it again.