Community
Participate
Working Groups
Created attachment 133162 [details] Eclipse java project demonstrating bug I am trying to extract a value from an annotation and pass it into my advice but I am not having much luck. Here is the exception generated by my test project: Exception in thread "main" java.lang.VerifyError: (class: aspectj/pointcut/annotation/bug/AspectTargetClass, method: aspectTargetMethod signature: ()V) Incompatible argument to function at aspectj.pointcut.annotation.bug.TestPointcutAnnotationAspect.main(TestPointcutAnnotationAspect.java:7) This simple example works if I run with the jvm -noverify flag, however my real-world case fails with a different error when I try to do that (the ApiDescriptor argument value passed into AnnotationAspect.monitorMethodPerformancePartialAnnotation is the wrong type -- it's the object that the pointcut matched). I can investigate that more should the resolution of the VerifyError bug not completely take care of the problem. I am using version 1.6.3.20090122141228 of the AspectJ Development Tools plug-in and I have tried JDK 1.5.0_16 and JDK 1.6.0_07. My eclipse version is 3.4.0. Here is the article I used as a reference: http://andrewclement.blogspot.com/2009/02/aspectj-optimized-annotation-value.html
Few things uncovered here... I can make it work in code style (I shortened the package to p for readability): pointcut p(ApiDescriptor api): if(true) && execution(@MonitorableMethod public * p..*(..)) && @annotation(MonitorableMethod(api)); Object around(ApiDescriptor api): p(api) { System.out.println("Descriptor value: " + api.number); return proceed(api); } however, that proceed(api) isn't right - there shouldn't be a need to pass api. Not passing it causes this error: "too few arguments to proceed, expected 1" Going back to annotation style and trying the same solution (passing api): return pjp.proceed(new Object[]{api}); gives this nasty problem: C:\temp\ajcSandbox\aspectj16_2\ajcTest30146.tmp\AnnotationAspect.java:0::0 Internal compiler error java.lang.ArrayIndexOutOfBoundsException: 1 at org.aspectj.weaver.bcel.BcelWeaver.validateSingleBranchRecursion(BcelWeaver.java:808) at org.aspectj.weaver.bcel.BcelWeaver.validateSingleBranchRecursion(BcelWeaver.java:791) And as Jonathan says, not passing anything on proceed in a pure annotation style aspect gives: junit.framework.AssertionFailedError: Exception thrown by p.TestPointcutAnnotationAspect.main(String[]) :java.lang.VerifyError: (class: p/AspectTargetClass, method: aspectTargetMethod signature: ()V) Incompatible argument to function at junit.framework.Assert.fail(Assert.java:47) at org.aspectj.tools.ajc.AjcTestCase.run(AjcTestCase.java:655) at org.aspectj.testing.RunSpec.execute(RunSpec.java:62) at org.aspectj.testing.AjcTest.runTest(AjcTest.java:72) a few things to sort out...
ok - let's ignore for now that it wants the annotation value passing in again and look at the verifyerror. Here is the problem code: public void aspectTargetMethod(); org.aspectj.weaver.MethodDeclarationLineNumber: length = 0x8 00 00 00 07 00 00 00 FFFFFF85 Code: Stack=5, Locals=2, Args_size=1 0: getstatic #41; //Field ajc$tjp_0:Lorg/aspectj/lang/JoinPoint$StaticPart; 3: aload_0 4: aload_0 5: invokestatic #47; //Method org/aspectj/runtime/reflect/Factory.makeJP:(Lorg/aspectj/lang/JoinPoint$StaticPart;Ljava/lang/Object;Ljava/lang/Object;)Lorg/aspectj/lang/JoinPoint; 8: astore_1 9: aload_0 10: invokestatic #93; //Method p/AnnotationAspect.adviseIfMonitoringPartialAnnotation:(Lp/ApiDescriptor;)Z 13: ifeq 30 16: aload_0 17: aload_1 18: invokestatic #81; //Method p/AnnotationAspect.aspectOf:()Lp/AnnotationAspect; 21: aload_1 22: getstatic #83; //Field p/ApiDescriptor.TARGET_CLASS_TARGET_METHOD:Lp/ApiDescriptor; 25: invokestatic #87; //Method aspectTargetMethod_aroundBody1$advice:(Lp/AspectTargetClass;Lorg/aspectj/lang/JoinPoint;Lp/AnnotationAspect;Lorg/aspectj/lang/ProceedingJoinPoint;Lp/ApiDescriptor;)Ljava/lang/Object; 28: pop 29: return 30: aload_0 31: aload_1 32: invokestatic #89; //Method aspectTargetMethod_aroundBody0:(Lp/AspectTargetClass;Lorg/aspectj/lang/JoinPoint;)V 35: return 36: nop this bit looks to blame: 9: aload_0 10: invokestatic #93; //Method p/AnnotationAspect.adviseIfMonitoringPartialAnnotation:(Lp/ApiDescriptor;)Z as it tries to call adviseIfMonitoringPartialAnnotation(ApiDescriptor), passing an AspectTargetClass instance. That represents invocation of the if() pointcut code "return true". And indeed if we remove if the 'if() &&' from the annotation style pointcut (and change the pointcut to return void) then the aspect works.
My real use case also succeeds following removal of the if() clause in the pointcut. I can move the logic from my adviseIfMonitoring method into the advice itself as a temporary workaround.
Verify Error is now fixed. New generated code accesses the field of the annotation before calling the if() 8: astore_1 9: getstatic #83; //Field p/ApiDescriptor.TARGET_CLASS_TARGET_METHOD:Lp/ApiDescriptor; 12: invokestatic #93; //Method p/AnnotationAspect.adviseIfMonitoringPartialAnnotation:(Lp/ApiDescriptor;)Z test and fix committed. I have raised bug 273655 to cover the other wierdness discovered during investigating this bug.