Community
Participate
Working Groups
I get the eror when adding the following simple around advice but not when I use "-XnoInline": public aspect Recovery { Object around () : call(public * *(..)) && target(StockQuoteService) { System.out.println("Recovery.around() " + thisJoinPoint); return proceed(); } }
Err ? Wheres the rest of the program? It is no doubt peculiar to the join point and the type that is being affected...
Created attachment 31315 [details] Testcase The problem seems to lie with duplicate closures. When Recovery.aj is compiled a closure accounts.recovery.Recovery$AjcClosure1 is generated. This is loaded after services.account.StockQuoteServiceTest is woven but another is generated when accounts.recovery.Recovery is rewoven. We don't see this because the resulting LinkageError("duplicate class definition: accounts/recovery/Recovery$AjcClosure1") is being swallowed in Aj.defineClass(). For some reason the first closure doesn't work. LOADING SUITE: ..\tests\src\org\aspectj\systemtest\ajc150\ajc150.xml TEST: no IllegalAccessError with around advice on interface method call ...info register aspect accounts.recovery.Recovery info weaving 'services.account.StockQuoteServiceTest' weaveinfo Join point 'method-call(services.account.AccountReport services.account.StockQuoteServiceTest.getAccountReport(java.lang.String))' in Type 'services.account.StockQuoteServiceTest' (StockQuoteServiceTest.java:13) advised by around advice from 'accounts.recovery.Recovery' (Recovery.aj:7) [with runtime test] weaveinfo Join point 'method-call(java.lang.String services.accountdata.StockAccount.getSymbol())' in Type 'services.account.StockQuoteServiceTest' (StockQuoteServiceTest.java:19) advised by around advice from 'accounts.recovery.Recovery' (Recovery.aj:7) [with runtime test] weaveinfo Join point 'method-call(float services.stockquote.StockQuoteService.getQuote(java.lang.String))' in Type 'services.account.StockQuoteServiceTest' (StockQuoteServiceTest.java:19) advised by around advice from 'accounts.recovery.Recovery' (Recovery.aj:7) weaveinfo Join point 'method-call(int services.accountdata.StockAccount.getQuantity())' in Type 'services.account.StockQuoteServiceTest' (StockQuoteServiceTest.java:19) advised by around advice from 'accounts.recovery.Recovery' (Recovery.aj:7) [with runtime test] WeavingClassFileProvider.acceptResult() className=services.account.StockQuoteServiceTest, length=6593 info weaving 'accounts.recovery.Recovery$AjcClosure1' WeavingClassFileProvider.acceptResult() className=accounts.recovery.Recovery$AjcClosure1, length=725 info weaving 'services.stockquote.StockQuoteService' WeavingClassFileProvider.acceptResult() className=services.stockquote.StockQuoteService, length=336 info weaving 'services.account.AccountReport' WeavingClassFileProvider.acceptResult() className=services.account.AccountReport, length=238 info weaving 'services.accountdata.StockAccount' WeavingClassFileProvider.acceptResult() className=services.accountdata.StockAccount, length=1127 info weaving 'services.stockquote.StockQuoteServiceImpl' WeavingClassFileProvider.acceptResult() className=services.stockquote.StockQuoteServiceImpl, length=575 info weaving 'accounts.recovery.Recovery' info processing reweavable type accounts.recovery.Recovery: C:\temp\ajcSandbox\ajcTest4475.tmp\accounts\recovery\Recovery.aj info successfully verified type accounts.recovery.Recovery exists. Originates from C:\temp\ajcSandbox\ajcTest4475.tmp\accounts\recovery\Recovery.aj weaveinfo Join point 'method-call(void java.io.PrintStream.println(java.lang.String))' in Type 'accounts.recovery.Recovery' (Recovery.aj:8) advised by around advice from 'accounts.recovery.Recovery' (Recovery.aj:7) [with runtime test] WeavingClassFileProvider.acceptResult() className=accounts.recovery.Recovery, length=3744 WeavingClassFileProvider.acceptResult() className=accounts.recovery.Recovery$AjcClosure1, length=725 Aj.defineClass() name=accounts.recovery.Recovery$AjcClosure1 java.lang.IllegalAccessError: tried to access method accounts.recovery.Recovery.println_aroundBody0(Laccounts/recovery/Recovery;Ljava/io/PrintStream;Ljava/lang/String;Lorg/aspectj/lang/JoinPoint;)V from class services.account.StockQuoteServiceTest at services.account.StockQuoteServiceTest.getQuote_aroundBody5$advice(StockQuoteServiceTest.java:108) at services.account.StockQuoteServiceTest.getAccountReport(StockQuoteServiceTest.java:19) at services.account.StockQuoteServiceTest.getAccountReport_aroundBody0(StockQuoteServiceTest.java:13) at services.account.StockQuoteServiceTest.main(StockQuoteServiceTest.java:13) 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 org.aspectj.tools.ajc.AjcTestCase.run(AjcTestCase.java:609) 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.testNoIllegalAccessErrorWithAroundAdvice_pr119657(Ajc150Tests.java:802)DONE 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) If "-XnoWeave" is used to compile the aspect no closure is generated at that point but several _are_ generated during LTW and the test passes: LOADING SUITE: ..\tests\src\org\aspectj\systemtest\ajc150\ajc150.xml TEST: no IllegalAccessError with around advice on interface method call ...info register aspect accounts.recovery.Recovery info weaving 'services.account.StockQuoteServiceTest' weaveinfo Join point 'method-call(services.account.AccountReport services.account.StockQuoteServiceTest.getAccountReport(java.lang.String))' in Type 'services.account.StockQuoteServiceTest' (StockQuoteServiceTest.java:13) advised by around advice from 'accounts.recovery.Recovery' (Recovery.aj:7) [with runtime test] weaveinfo Join point 'method-call(java.lang.String services.accountdata.StockAccount.getSymbol())' in Type 'services.account.StockQuoteServiceTest' (StockQuoteServiceTest.java:19) advised by around advice from 'accounts.recovery.Recovery' (Recovery.aj:7) [with runtime test] weaveinfo Join point 'method-call(float services.stockquote.StockQuoteService.getQuote(java.lang.String))' in Type 'services.account.StockQuoteServiceTest' (StockQuoteServiceTest.java:19) advised by around advice from 'accounts.recovery.Recovery' (Recovery.aj:7) weaveinfo Join point 'method-call(int services.accountdata.StockAccount.getQuantity())' in Type 'services.account.StockQuoteServiceTest' (StockQuoteServiceTest.java:19) advised by around advice from 'accounts.recovery.Recovery' (Recovery.aj:7) [with runtime test] WeavingClassFileProvider.acceptResult() className=services.account.StockQuoteServiceTest, length=4483 WeavingClassFileProvider.acceptResult() className=services.account.StockQuoteServiceTest$AjcClosure1, length=762 Aj.defineClass() name=services.account.StockQuoteServiceTest$AjcClosure1 WeavingClassFileProvider.acceptResult() className=services.account.StockQuoteServiceTest$AjcClosure3, length=775 Aj.defineClass() name=services.account.StockQuoteServiceTest$AjcClosure3 WeavingClassFileProvider.acceptResult() className=services.account.StockQuoteServiceTest$AjcClosure5, length=909 Aj.defineClass() name=services.account.StockQuoteServiceTest$AjcClosure5 WeavingClassFileProvider.acceptResult() className=services.account.StockQuoteServiceTest$AjcClosure7, length=855 Aj.defineClass() name=services.account.StockQuoteServiceTest$AjcClosure7 info weaving 'services.stockquote.StockQuoteService' WeavingClassFileProvider.acceptResult() className=services.stockquote.StockQuoteService, length=336 info weaving 'services.account.AccountReport' WeavingClassFileProvider.acceptResult() className=services.account.AccountReport, length=238 info weaving 'services.accountdata.StockAccount' WeavingClassFileProvider.acceptResult() className=services.accountdata.StockAccount, length=1127 info weaving 'services.stockquote.StockQuoteServiceImpl' WeavingClassFileProvider.acceptResult() className=services.stockquote.StockQuoteServiceImpl, length=575 info weaving 'accounts.recovery.Recovery' weaveinfo Join point 'method-call(void java.io.PrintStream.println(java.lang.String))' in Type 'accounts.recovery.Recovery' (Recovery.aj:8) advised by around advice from 'accounts.recovery.Recovery' (Recovery.aj:7) [with runtime test] WeavingClassFileProvider.acceptResult() className=accounts.recovery.Recovery, length=3745 WeavingClassFileProvider.acceptResult() className=accounts.recovery.Recovery$AjcClosure1, length=725 Aj.defineClass() name=accounts.recovery.Recovery$AjcClosure1 Recovery.around() call(float services.stockquote.StockQuoteService.getQuote(String)) DONE
If -XnoWeave works perhaps what we need to do is determine whether an aspect is reweavable when it is registered (BcelWeaver.addLibraryAspect()) and use the original unwoven byte-code. The fact that a closure may already exist will not matter because we will generate new ones and they will be used in preference to the one on disk (either through calling defineClass() or GeneratedClassHandler callback interface. We can use the logic from processReweavableStateIfPresent().
Unfortunately this causes TraceJarWeaveTestCase to fail because we now generate different byte-code for the woven classes: the aspect is no longer woven hence we cannot inline around advice. The real problem seems to be that an aspect that weaves itself in isolation and generates a closure then incorrectly weaves other classes during LTW (see stack trace).
The closure generated is identical whether an aspect is compiled alone or with the rest of the application that it affects. The problem only applies to aspects that advise themselves. We must use the unwoven version of an aspect for LTW as it may be woven by another aspect and until that point it cannot inline around advice in other types.
Created attachment 31483 [details] Testcases and fix 1. Modify BcelWeaver.addLibraryAspect() to use unwoven aspects 2. Testcases for LTW around advice closures and the new "info generating class ..." message 3. Move defineClass() from Aj to ClassLoaderWeavingAdaptor 4. Issue warnings when defining generated classes fails 5. New TraceJarHello.txt because we can't inline advice
fixes checked in.
fix available