Bug 345345 - Compile error: IllegalStateException thrown: Unable to pack method, jump (with opcode=161) is too far
Summary: Compile error: IllegalStateException thrown: Unable to pack method, jump (wit...
Status: NEW
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows XP
: P3 major (vote)
Target Milestone: ---   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-05-10 18:26 EDT by art y CLA
Modified: 2011-05-20 15:05 EDT (History)
1 user (show)

See Also:


Attachments
Exception stack traces (3.93 KB, text/plain)
2011-05-10 18:30 EDT, art y CLA
no flags Details
Eclipse project for repro (1.70 MB, application/zip)
2011-05-13 03:25 EDT, art y CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description art y CLA 2011-05-10 18:26:20 EDT
Build Identifier: 20100218-1602

Hit the java.lang.IllegalStateException at org.aspectj.apache.bcel.generic.InstructionBranch.updatePosition(InstructionBranch.java:176) when args designator token inside cflow like 
	@After( value="cflow( executingAbstractBeanFactoryGetBean( String) && args( beanName))")

It would be hard to guess what caused this problem only from the exception information if I had made multiple source code changes and had hit this issue. Hence, hope that AJDT provides more helpful information like which statement in source code caused this problem.


Reproducible: Always

Steps to Reproduce:
1. I have the pointcuts and the advises like:
	@Pointcut( 
			"execution( * org.springframework.beans.factory.support.AbstractBeanFactory+" +
			".getBean( String, Class)) && args( beanName) && if()"
			)
	public static boolean executingAbstractBeanFactoryGetBean( String beanName) {
		if ( beanName.equals( AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME)) 
		{
			return true;
		}
		return false;
	}

	@Before( 
			value="cflow( executingAbstractBeanFactoryGetBean( String)) " +
					"&& args( beanName)"
			)
	public void beforeExecutingAbstractBeanFactoryGetBean(
			JoinPoint joinPoint, JoinPoint.EnclosingStaticPart enclosingStaticPart, String beanName) {
		logger.info( 
				String.format( 
						"Before point cut -----------------------------------------------------------------%n" +
						"%1$s" + 
						"----------------------------------------------------------------------------------",
						Util.getJoinPointInfo( joinPoint, enclosingStaticPart)
						)
				);
	}
	@After( 
			value="cflow( executingAbstractBeanFactoryGetBean( String)) " +
			"&& args( beanName)"
			)
	public void afterExecutingAbstractBeanFactoryGetBean(
			JoinPoint joinPoint, JoinPoint.EnclosingStaticPart enclosingStaticPart, String beanName) {
		
		logger.info( 
				String.format( 
						"After point cut -----------------------------------------------------------------%n" +
						"%1$s" + 
						"----------------------------------------------------------------------------------",
						Util.getJoinPointInfo( joinPoint, enclosingStaticPart)
						)
				);
	}

2. I changed the before-advise and after-advise like:
	@Before( value="cflow( executingAbstractBeanFactoryGetBean( String) && args( beanName))")
	...

	@After( value="cflow( executingAbstractBeanFactoryGetBean( String) && args( beanName))")
	...

(Note: If I made the change only on the before-advise, then it didn't hit this exception.)
Comment 1 art y CLA 2011-05-10 18:30:12 EDT
Created attachment 195283 [details]
Exception stack traces
Comment 2 Andrew Clement CLA 2011-05-11 15:15:02 EDT
> Unable to pack method, jump (with opcode=161) is too far: 35461

This is telling us that the act of weaving the method has made a jump destination too far away from us and we can't represent it.

The opcode 161 is IF_ICMPLT (if int compare less than).  And the jump destination is a two byte signed relative destination.  Given that it is 2byte signed we can only jump 32767 bytes further down the method.  The weaving has increased the amount of code inside the method to such a degree that the destination we were going to jump to is now 35461 and we now can't express where we want to go.  We probably need to rewrite it such that we branch somewhere close and do a wide jump/goto to the destination, but currently AspectJ doesn't do that.

It is a really poor error message that doesn't tell us which method it couldn't pack!  If it did it may be possible to simply exclude that method from weaving for now (it may have nothing to do with what you are trying to achieve with the aspect).  if you want to try this route I'll enhance the message so we can discover which woven method is proving tricky.

As you change the advice it will reduce the amount of change in the woven code, possibly bring the jump destination close enough to represent in 2bytes.
Comment 3 art y CLA 2011-05-12 19:24:55 EDT
Thanks Andy for checking this.

>we branch somewhere close and do a wide jump/goto to the destination, but currently AspectJ doesn't do that.
It would be great if AspectJ could do. 
But, even if you only enforce the message at least, I think that will be great help.

>It is a really poor error message that doesn't tell us which method it couldn't
pack! 
It would be also great if AJDT can put the error on which advise encountered this.

>if you want to try this route I'll enhance the message so we can
discover which woven method is proving tricky.
I encountered this accidentally at trying to get the logic trace from getBean method of Spring's AbstractBeanFactory in the attempt of finding out the cause of the problem with ReloadableResourceBundleMessageSource bean on Spring Web Flow.
I may be able to make a small Eclipse project to repro this symptom and attach to this bug. Let me see and I will get back to you.
Comment 4 art y CLA 2011-05-13 03:25:42 EDT
Created attachment 195560 [details]
Eclipse project for repro

Attached IllegalStateExceptionByFarIntJump.zip for repro.
Please, after expand it at local, open it as a project on Eclipse, and try to compile. It should re-produce that exception.
Comment 5 Andrew Clement CLA 2011-05-19 19:27:07 EDT
thanks for the test program.

First change is committed, now we see the offending method:

java.lang.IllegalStateException: Unexpected problem whilst preparing bytecode for org.springframework.beans.BeanWrapperImpl.setPropertyValue(Lorg/springframework/beans/BeanWrapperImpl$PropertyTokenHolder;Lorg/springframework/beans/PropertyValue;)V
	at org.aspectj.apache.bcel.generic.MethodGen.getMethod(MethodGen.java:699)
	at org.aspectj.weaver.bcel.LazyMethodGen.getMethod(LazyMethodGen.java:463)
	at org.aspectj.weaver.bcel.LazyClassGen.writeBack(LazyClassGen.java:492)
	at org.aspectj.weaver.bcel.LazyClassGen.getJavaClassBytesIncludingReweavable(LazyClassGen.java:674)
	at org.aspectj.weaver.bcel.BcelWeaver.getClassFilesFor(BcelWeaver.java:1436)
	at org.aspectj.weaver.bcel.BcelWeaver.weaveAndNotify(BcelWeaver.java:1398)
	at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:1180)
	at org.aspectj.ajdt.internal.compiler.AjPipeliningCompilerAdapter.weaveQueuedEntries(AjPipeliningCompilerAdapter.java:514)
	at org.aspectj.ajdt.internal.compiler.AjPipeliningCompilerAdapter.queueForWeaving(AjPipeliningCompilerAdapter.java:447)
	at org.aspectj.ajdt.internal.compiler.AjPipeliningCompilerAdapter.afterProcessing(AjPipeliningCompilerAdapter.java:432)
	at org.aspectj.ajdt.internal.compiler.CompilerAdapter.ajc$after$org_aspectj_ajdt_internal_compiler_CompilerAdapter$5$6b855184(CompilerAdapter.aj:98)
	at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.process(Compiler.java:652)
	at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:392)
	at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performCompilation(AjBuildManager.java:1021)
	at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performBuild(AjBuildManager.java:268)
	at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:181)
	at org.aspectj.ajdt.ajc.AjdtCommand.doCommand(AjdtCommand.java:114)
	at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:60)
	at org.aspectj.tools.ajc.Main.run(Main.java:371)
	at org.aspectj.tools.ajc.Main.runMain(Main.java:248)
	at org.aspectj.tools.ajc.Main.main(Main.java:84)
Caused by: java.lang.IllegalStateException: Unable to pack method, jump (with opcode=161) is too far: 35461
	at org.aspectj.apache.bcel.generic.InstructionBranch.updatePosition(InstructionBranch.java:176)
	at org.aspectj.apache.bcel.generic.BranchHandle.updatePosition(BranchHandle.java:101)
	at org.aspectj.apache.bcel.generic.InstructionList.setPositions(InstructionList.java:901)
	at org.aspectj.apache.bcel.generic.InstructionList.setPositions(InstructionList.java:845)
	at org.aspectj.apache.bcel.generic.InstructionList.getByteCode(InstructionList.java:963)
	at org.aspectj.apache.bcel.generic.MethodGen.getMethod(MethodGen.java:697)
	... 20 more

However, that isn't a particularly large method implying the advice is doing something unusual, so I'll look at that next.

>>It is a really poor error message that doesn't tell us which method it couldn't pack! 
>It would be also great if AJDT can put the error on which advise encountered
this.

Can't really do this.  It will not usually be any one particular advice, it will be a bunch of them in combination.  If you have 10 advice, any 9 of them might weave ok but the 10th one will blow the limit, would we mark all 10 in that case?  You might then try to debug them but there is nothing wrong with any individual one...  better to fix it properly and not hit this exception.
Comment 6 art y CLA 2011-05-20 15:05:30 EDT
>However, that isn't a particularly large method implying the advice is doing
>something unusual, so I'll look at that next.
Thanks Andy for working on this.
Just in case, here's the source location of Spring: https://src.springframework.org/svn/spring-framework/tags/spring-framework-3.0.4.RELEASE/

>better to fix it properly and not hit this exception.
Understood.

Regards