Community
Participate
Working Groups
If an @AspectJ aspect advises itself using after throwing advice that itself throws an exception running the resulting program causes a VerifyError: java.lang.VerifyError: (class: A, method: stop signature: ()V) catch_type not a subclass of Throwable at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Class.java:2365) at java.lang.Class.getMethod0(Class.java:2611) at java.lang.Class.getMethod(Class.java:1579) at org.aspectj.tools.ajc.AjcTestCase.run(AjcTestCase.java:608) at org.aspectj.testing.RunSpec.execute(RunSpec.java:56) at org.aspectj.testing.AjcTest.runTest(AjcTest.java:68) at org.aspectj.testing.XMLBasedAjcTestCase.runTest(XMLBasedAjcTestCase.java:111) at org.aspectj.systemtest.ajc150.Ajc150Tests.testError(Ajc150Tests.java:877) 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 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)
Created attachment 32514 [details] Testcase
I'm not sure this verify error only occurs when the @AfterReturning advice affects itself that throws an exception. I think it's to do with the extra JoinPoint argument in the list of method args. I've been able to reproduce the problem by running the following: --------------------------------------------------------------------------- import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; @Aspect public class A { public static void main(String[] args) { try { new B().start(); } catch (Exception e) { e.printStackTrace(); } } @AfterThrowing(pointcut = "execution(public void B.start())", throwing = "ex") public void handleException(JoinPoint jp, Exception ex) { } } class B implements I { public void start() throws Exception { throw new IllegalArgumentException(); } } interface I { public void start() throws Exception; } --------------------------------------------------------------------------------------------------- Changing the @AfterThrowing advice to: @AfterThrowing(pointcut = "execution(public void B.start())", throwing = "ex") public void handleException(Exception ex) { } and then rerunning does not result in a verify error. Looking at the output from decompiling B when there is a verify error, the Exception table for the start() method has Exception table: from to target type 9 17 17 Class org/aspectj/lang/JoinPoint which would result in a verify error saying that the type isn't a subclass of Throwable.
Created attachment 34912 [details] patch containing failing testcase Apply to the tests project. Testcase mentioned in previous comment.
The problem is that Advice.getExtraParameterType() returns the UnresolvedType corresponding to the first argument, so in the example aspect this is org.aspectj.lang.JoinPoint. The fix is to make allowances for the extra parameter corresponding to JoinPoint in the case of annotation style aspects. Advice.getExtraParameterType() is used in the processing of the extra parameter both for after throwing and after returning advice. Currently if used with the following advice: @AfterReturning(pointcut = "execution(public B1 B1.start())", returning = "r") public void afterJP(JoinPoint jp, B1 r) { r.stop(); } it results in a verify error of the form: Exception in thread "main" java.lang.VerifyError: (class: B1, method: start signature: ()LB1;) Incompatible argument to function at A1.main(A1.java:9)
Created attachment 34995 [details] patch containing failing testcase for @AfterThrowing and @AfterReturning Apply this patch to the tests project. This patch replaces the previously attached one as it improves on the tests for @AfterThrowing and adds tests for @AfterReturning.
Created attachment 34996 [details] patch containing proposed fix Apply to the weaver project. Patch containing proposed fix mentioned above.
fix committed.
fix available.