Bug 119657 - IllegalAccessError with around advice on interface method call
Summary: IllegalAccessError with around advice on interface method call
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: DEVELOPMENT   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 1.5.0RC1   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-12-07 10:21 EST by Matthew Webster CLA
Modified: 2005-12-12 08:50 EST (History)
0 users

See Also:


Attachments
Testcase (7.42 KB, application/octet-stream)
2005-12-07 12:18 EST, Matthew Webster CLA
no flags Details
Testcases and fix (6.34 KB, application/octet-stream)
2005-12-09 12:54 EST, Matthew Webster CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Matthew Webster CLA 2005-12-07 10:21:42 EST
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();
	}
}
Comment 1 Andrew Clement CLA 2005-12-07 10:53:23 EST
Err ? Wheres the rest of the program? It is no doubt peculiar to the join point and the type that is being affected...
Comment 2 Matthew Webster CLA 2005-12-07 12:18:32 EST
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
Comment 3 Matthew Webster CLA 2005-12-08 08:43:03 EST
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().
Comment 4 Matthew Webster CLA 2005-12-08 12:37:38 EST
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).
Comment 5 Matthew Webster CLA 2005-12-09 11:35:32 EST
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.
Comment 6 Matthew Webster CLA 2005-12-09 12:54:11 EST
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
Comment 7 Andrew Clement CLA 2005-12-12 06:16:02 EST
fixes checked in.
Comment 8 Andrew Clement CLA 2005-12-12 08:50:06 EST
fix available