Bug 260384 - Exception occurred when compiling spring-framework-2.5.6
Summary: Exception occurred when compiling spring-framework-2.5.6
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: 1.6.2   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: 1.6.4   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 268727 (view as bug list)
Depends on:
Blocks:
 
Reported: 2009-01-08 07:51 EST by Yueqi Li CLA
Modified: 2009-03-16 11:50 EDT (History)
2 users (show)

See Also:


Attachments
Eclipse automatically included the libs (200.22 KB, image/png)
2009-01-08 22:50 EST, Yueqi Li CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Yueqi Li CLA 2009-01-08 07:51:21 EST
java.lang.NullPointerException
at org.aspectj.weaver.Shadow.getGenericArgTypes(Shadow.java:175)
at org.aspectj.weaver.patterns.ArgsPointcut.getArgumentsToMatchAgainst(ArgsPointcut.java:88)
at org.aspectj.weaver.patterns.ArgsPointcut.matchInternal(ArgsPointcut.java:76)
at org.aspectj.weaver.patterns.Pointcut.match(Pointcut.java:146)
at org.aspectj.weaver.patterns.AndPointcut.matchInternal(AndPointcut.java:52)
at org.aspectj.weaver.patterns.Po ... actGenericLabeledEnum.getLabel())
  end public String getLabel()
Comment 1 Andrew Clement CLA 2009-01-08 11:41:53 EST
can you give me more details on how you are compiling spring?  Are you really using AspectJ 1.6.2 (in your other bug you mentioned AspectJ 1.6.1rc1)?  Are you able to try with 1.6.3?

I would like to investigate this further if you can give me a few more details on what you are doing.
Comment 2 Yueqi Li CLA 2009-01-08 11:50:35 EST
I tried to compile Sprint in Eclipse with aspectj.
Both 1.6.1 and 1.6.2 of eclipse plugins produced the same bug.
What I did is:
1. unpack spring-framework-2.5.6.
2. create a java project called spring-framework-2.5.6, as project name is the same as the directory that contains sprint, the source is automatically recognized by eclipse 
3. start compile sprint, in fact eclipse started to compile it automatically.
Comment 3 Andrew Clement CLA 2009-01-08 13:07:26 EST
ok, I have AJDT 1.6.2 (from January 5th) installed.

I downloaded spring-framework-2.5.6-with-dependencies.zip

I extracted it.

I created a new Eclipse project and defined its source folder to be the spring-framework-2.5.6\src folder.

This resulted in 12000 errors because the libraries were not defined for the project so I extracted all the jars from the lib folder to one directory and put that on the project classpath. 

The project then compiled clean.

Were you seeing the error before the libraries are added to the classpath?  This is important as it will indicate whether it is a problem due to continuing with weaving once a compile error has occurred.

It may be due to you being on linux and me on windows - let me try it on a unix box.
Comment 4 Yueqi Li CLA 2009-01-08 22:50:36 EST
Created attachment 122054 [details]
Eclipse automatically included the libs

When creating the project, Eclipse automatically included the jars in lib directory of sprint. I think that is enough to compile.
Comment 5 Andrew Clement CLA 2009-01-09 13:30:27 EST
Ok, I see the mismatch - there are multiple source folders in spring framework that the new project wizard recognizes - so I need to compile more than just 'src'.  When I attempted an AspectJ build of it in eclipse I see the following 3 problems (one of which is the reported one):



java.lang.NumberFormatException
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.<init>(Unknown Source)
at org.aspectj.asm.internal.JDTLikeHandleProvider.getCount(JDTLikeHandleProvider.java:207)
at org.aspectj.asm.internal.JDTLikeHandleProvider.createHandleIdentifier(JDTLikeHandleProvider.java:118)
at org.aspectj.asm.internal.JDTLikeHandleProvider.creat ...   end public Object doInHibernate(org.hibernate.Session)
end final class org.springframework.orm.hibernate3.HibernateTransactionManagerTests$16$2$1

-------------
org.aspectj.weaver.BCException
at org.aspectj.weaver.bcel.BcelRenderer.visit(BcelRenderer.java:205)
at org.aspectj.weaver.ast.Literal.accept(Literal.java:29)
at org.aspectj.weaver.bcel.BcelRenderer.recur(BcelRenderer.java:111)
at org.aspectj.weaver.bcel.BcelRenderer.renderTest(BcelRenderer.java:101)
at org.aspectj.weaver.bcel.BcelAdvice.getTestInstructions(BcelAdvice.java:581)
at org.aspectj.weaver.bcel.BcelAdvice.getAdviceInstructions ... indingAspectWithSingleArg, org.aspectj.lang.ProceedingJoinPoint, int)
end public class org.springframework.aop.framework.ReflectiveMethodInvocation
-----------------
java.lang.NullPointerException
at org.aspectj.weaver.Shadow.getGenericArgTypes(Shadow.java:175)
at org.aspectj.weaver.patterns.ArgsPointcut.getArgumentsToMatchAgainst(ArgsPointcut.java:88)
at org.aspectj.weaver.patterns.ArgsPointcut.matchInternal(ArgsPointcut.java:76)
at org.aspectj.weaver.patterns.Pointcut.match(Pointcut.java:146)
at org.aspectj.weaver.patterns.AndPointcut.matchInternal(AndPointcut.java:52)
at org.aspectj.weaver.patte ... enericLabeledEnum.getLabel())
  end public String getLabel()

end public abstract class org.springframework.core.enums.AbstractGenericLabeledEnum
---------------

When I build a subset on the commandline I see this 4th problem (I assume it is because I'm building an incomplete/inconsistent subset):

java.lang.NullPointerException
        at org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration.makeResolvedPointcutDefinition(PointcutDeclaration.java:221)
        at org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceType.fillDeclaredMembers(EclipseSourceType.java:244)
        at org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceType.getDeclaredPointcuts(EclipseSourceType.java:382)
        at org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration.buildInterTypeAndPerClause(AspectDeclaration.java:1033)
        at org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment.buildInterTypeAndPerClause(AjLookupEnvironment.java:539)
        at org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment.collectAllITDsAndDeclares(AjLookupEnvironment.java:387)
        at org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment.completeTypeBindings(AjLookupEnvironment.java:198)
        at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.internalBeginToCompile(Compiler.java:616)
        at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.beginToCompile(Compiler.java:357)
        at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:371)
Comment 6 Andrew Clement CLA 2009-01-09 16:00:13 EST
Exception 4 in previous entry now fixed (the NPE).  New NPE:

java.lang.NullPointerException
	at org.aspectj.weaver.MemberImpl.toString(MemberImpl.java:346)
	at java.lang.String.valueOf(Unknown Source)
	at java.lang.StringBuilder.append(Unknown Source)
	at org.aspectj.weaver.ResolvedTypeMunger.toString(ResolvedTypeMunger.java:135)
	at java.lang.String.valueOf(Unknown Source)
	at java.lang.StringBuilder.append(Unknown Source)
Comment 7 Andrew Clement CLA 2009-01-09 22:59:04 EST
Urgh this is a pain to debug as it takes so long for the problems to appear after kicking off a build.

At the:

java.lang.NullPointerException
at org.aspectj.weaver.Shadow.getGenericArgTypes(Shadow.java:175)

the shadow is:
method-call(java.lang.Comparable org.springframework.core.enums.AbstractGenericLabeledEnum.getCode())

and the enclosing shadow is:
method-execution(java.lang.String org.springframework.core.enums.AbstractGenericLabeledEnum.getLabel())

the signature is:
java.lang.Comparable org.springframework.core.enums.AbstractGenericLabeledEnum.getCode()
Comment 8 Andrew Clement CLA 2009-01-12 13:50:55 EST
Exception: org.aspectj.weaver.Shadow.getGenericArgTypes(Shadow.java:175)

getCode() is actually not implemented by the hierarchy.  it is merely declared in the top most interface and then all the classes in the hierarchy are abstract.

Here is a tiny program that will crash the compiler with the same exception:

interface I {
        void getCode();
}

abstract class C1 implements I {
}

abstract class C2 extends C1 {
  public void m() {
          getCode();
  }
}

aspect X {
        before(int i): args(i) { }
}

It would appear that the code to walk the hierarchy for getCode() is broken.  It doesn't cope with a method not being implemented in the class hierarchy.  Bit of a serious bug....

---

Side note:
I don't actually think AspectJ should be used to compile spring-framework like this - because the aspects are not written to be compiled with everything else and so are weaving/affecting hundreds of the other spring types.  However, I will fix the exceptions that are occurring here.
Comment 9 Andrew Clement CLA 2009-01-12 15:34:28 EST
Exception: org.aspectj.weaver.Shadow.getGenericArgTypes(Shadow.java:175)

I rewrote the hierarchy search logic.  It was using nested iterators and that was just too complicated to understand so I rewrote it with a couple of loops.  It is not *quite* as lazy as it was before but it is trivial to understand now and it works.  That code snippet now compiles just fine.  A related code snippet that has unexpected results is when the pointcut is like this:

pointcut p(): call(* *(..)) {}

That would have failed to match the method call silently.  Unlike the args() version it doesn't crash with an exception, it just silently doesn't intercept the invocation - to me this is even more serious than the crashing case.  Anyway, this is also fixed by the rewrite.
Comment 10 Andrew Clement CLA 2009-01-12 18:17:55 EST
Exception: org.aspectj.weaver.bcel.BcelRenderer.visit(BcelRenderer.java:205)

With a new AspectJ in AJDT, I now get this exception on first compile (one from a previous comment):

org.aspectj.weaver.BCException
at org.aspectj.weaver.bcel.BcelRenderer.visit(BcelRenderer.java:205)
at org.aspectj.weaver.ast.Literal.accept(Literal.java:29)
at org.aspectj.weaver.bcel.BcelRenderer.recur(BcelRenderer.java:111)
at org.aspectj.weaver.bcel.BcelRenderer.renderTest(BcelRenderer.java:101)


Unfortunately the debugger cant cope and so I can only get to the failure if I run the code normally - so I'm now using good old System.out.println() debugging, woo..
Comment 11 Andrew Clement CLA 2009-01-12 19:59:31 EST
Exception: org.aspectj.weaver.bcel.BcelRenderer.visit(BcelRenderer.java:205)

Finally, some state captured at the point of failure.

shadow is: method-call(java.lang.Object java.lang.Object.clone())

enclosing shadow is:
method-execution(org.aopalliance.intercept.MethodInvocation org.springframework.aop.framework.ReflectiveMethodInvocation.invocableClone(java.lang.Object[]))

advice is: 
(before: ((target(org.springframework.aop.aspectj.ThisAndTargetSelectionOnlyPointcutsAtAspectJTests$TestImpl) && this(org.springframework.aop.aspectj.ThisAndTargetSelectionOnlyPointcutsAtAspectJTests$TestInterface)) && persingleton(org.springframework.aop.aspectj.ThisAndTargetSelectionOnlyPointcutsAtAspectJTests$Counter))->void org.springframework.aop.aspectj.ThisAndTargetSelectionOnlyPointcutsAtAspectJTests$Counter.incrementThisAsInterfaceAndTargetAsClassCounter())


Also, some state for the exception:
java.lang.NumberFormatException
org.aspectj.asm.internal.JDTLikeHandleProvider.getCount(JDTLikeHandleProvider.java:207)

existingHandle is:
=spring-framework-2.5.6/test<org.springframework.orm.hibernate3{HibernateTransactionManagerTests.java[HibernateTransactionManagerTests~testTransactionWithPropagationSupportsAndInnerTransaction[!2~doInTransaction~QTransactionStatus;[

suffixPosition is 193 and the problem is the data after the counter in the handle.  The problem class creating this situation is HibernateTransactionManagerTests.


Comment 12 Andrew Clement CLA 2009-01-13 12:10:38 EST
This code will cause the NumberFormatException:

public class C {
	SessionFactory sf;
	HT ht;
	
          public void m() {
        	  LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean() {
        		  protected SessionFactory newSessionFactory(Configuration config) throws Exception {
        			  return sf;
        		  }
        	  };
              final TT tt = new TT();
              tt.execute(new TransactionCallback() {
            	   public Object doInTransaction(TransactionStatus status) {
            		   System.out.println("X");
            		   ht.execute(new HibernateCallback() {
            			   public Object doInHibernate(Session session) {
            				   return null;
            			   }
            		   });
            		   tt.execute(new TransactionCallback() {
                    	   public Object doInTransaction(TransactionStatus status) {
                    		   System.out.println("X");
                    		   ht.execute(new HibernateCallback() {
                    			   public Object doInHibernate(Session session) {
                    				   return null;
                    			   }
                    		   });
                    		   return null;
                    	   }
            		   });
            		   return null;
            	   }
              });
          }
}

class TT { public void execute(Object o) {}}
class LocalSessionFactoryBean {}
class HT  { public void execute(Object o) {}}
class Session {}
class TransactionStatus {}
class SessionFactory {}
class Configuration {}
class TransactionCallback {}
class HibernateCallback {}


aspect X {
	before(): within(*) {}
}
Comment 13 Andrew Clement CLA 2009-01-13 12:34:29 EST
NumberFormatException now fixed.  Problem is when seeing an anonymous inner type within another anonymous inner type we would find the first '!' in the handle and process the data after it as a number.  For a method within an anon inner type there is already 'stuff' after the !<number> and so we crash with a NumberFormatException.  Really we should be looking for the correct '!' and I've fixed it to do that.

Final exception to sort out:
org.aspectj.weaver.BCException
at org.aspectj.weaver.bcel.BcelRenderer.visit(BcelRenderer.java:205)
at org.aspectj.weaver.ast.Literal.accept(Literal.java:29)
at org.aspectj.weaver.bcel.BcelRenderer.recur(BcelRenderer.java:111)
at org.aspectj.weaver.bcel.BcelRenderer.renderTest(BcelRenderer.java:101)
at org.aspectj.weaver.bcel.BcelAdvice.getTestInstructions(BcelAdvice.java:581)
at org.aspectj.weaver.bcel.BcelAdvice.getAdviceInstructions ...
indingAspectWithSingleArg, org.aspectj.lang.ProceedingJoinPoint, int)
end public class org.springframework.aop.framework.ReflectiveMethodInvocation
Comment 14 Andrew Clement CLA 2009-01-13 15:04:16 EST
OK, debugging this - why does the pointcut initially match if it then has a runtime test of FALSE (indicating advice will never get called).

That is because at the time we were checking whether it could possibly match we said MAYBE, but later we changed the conditions of the match slightly and that causes a match to be impossible.  it is all down to the stupid clone() method.

In BcelShadow we have a method called ensureTargetTypeIsCorrect() that is an attempt to deal with unhelpful bytecode put out by the compiler which indicates the target of clone() is Object even though it really isn't.  So we initially match target() when we think it is Object, then later we work out what it really is and in attempting to create an instanceof test we discover it can never be true.

Here is a program that crashes in the same way:

public class C {
        public void m() throws Exception {
                clone();
        }
}

class D {}

aspect X {
  before(): target(D) { }
}

I think the easiest thing to do here, given that clone calls don't happen very often is to cope with an instanceof that will never pass and so never call the advice.  It is only by accident of some test aspects applying across the whole of spring that this happens anyway... not a realistic scenaro.



Comment 15 Andrew Clement CLA 2009-01-13 15:31:01 EST
org.aspectj.weaver.bcel.BcelRenderer.visit(BcelRenderer.java:205) - now fixed.
Comment 16 Andrew Clement CLA 2009-01-13 15:56:21 EST
So...  all this is fixed and AspectJ 1.6.4 is better for it.  However I don't recommend that Spring Framework is built like this.  With all the source folders defined together in a single project, the test aspects in files like:

tiger/test/
org.springframework.aop.aspectj.ThisAndTargetSelectionOnlyPointcutsAtAspectJTests

are being matched EVERYWHERE across the whole framework and because interface types are being used they are actually matching in places they were never designed to.

It takes an eternity build because of all the matching and weaving. This advice:

ThisAndTargetSelectionOnlyPointcutsAtAspectJTests.incrementTargetAsInterfaceCounter

matches 65007 places - and that is with me compiling a subset of the code...



Comment 17 Andrew Clement CLA 2009-03-16 11:50:06 EDT
*** Bug 268727 has been marked as a duplicate of this bug. ***