Bug 114083 - Use reflection instead of byte-code to resolve types during LTW
Summary: Use reflection instead of byte-code to resolve types during LTW
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows XP
: P3 enhancement (vote)
Target Milestone: 1.5.2   Edit
Assignee: Adrian Colyer CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-10-28 06:49 EDT by Matthew Webster CLA
Modified: 2012-04-03 16:14 EDT (History)
2 users (show)

See Also:


Attachments
implementation of LTWWorld (7.61 KB, patch)
2005-11-22 04:22 EST, Ron Bodkin CLA
aclement: iplog+
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Matthew Webster CLA 2005-10-28 06:49:15 EDT
Using byte-code for type resolution greatly increases the footprint for LTW. 
It persists because we never release it and the approach does not scale in 
environments with large numbers of class loaders e.g. Tomcat or very large 
numbers e.g. OSGi. Using the ReflectionBasedReferenceTypeDelegate instead, 
which uses Class.forName(), will improve performance and reduce footprint.

There have been a number of discussions 
(http://dev.eclipse.org/mhonarc/lists/aspectj-dev/msg01847.html, 
http://dev.eclipse.org/mhonarc/lists/aspectj-users/msg04857.html) and bugs 
(https://bugs.eclipse.org/bugs/show_bug.cgi?id=35547, 
https://bugs.eclipse.org/bugs/show_bug.cgi?id=112817) on the subject. However 
care must be taken:
1.	Until the weaver is deemed re-entrant byte-code must continue to be 
used for classes defined by the class loader with which the weaver is 
associated
2.	Byte-code must be used for resolving aspects when using a JDK prior to 
1.5 and only in JDK 1.5 when the MAP is available because cross-cutting meta-
data is not available through  vanilla Java reflection
3.	Non-delegating web application class loaders are problematic. For this 
reason it may only be safe, at least initially, to use reflection for the boot 
loader. This should still provide a considerable benefit.
Comment 1 Matthew Webster CLA 2005-10-28 06:50:46 EDT
This should be target 1.5.1
Comment 2 Ron Bodkin CLA 2005-11-22 04:16:51 EST
I have started working on an implementation of LTWWorld; see the attached patch for what I have so far. This code is better than any previous attempts to implement this because it's now checking parent hierarchies for already defined classes using resource URL's to check for delegation. 

However, I'm hitting 4 problems, at least 3 of which look like bugs in the AJ 1.5 reflection delegates implementation. I think that the next step to making this work is more tests on the reflection cases....

1. One Matthew and I hit before. In UnresolvedType, there are cases where it is calling nameToSignature on a signature. This seems to happen predicably if you call getDeclaredMethods() on the delegate for anything that defines an array of generic types, E.g., javax.servlet.http.HttpServlet. Matthew was able to isolate a problem like this by replacing one of the reflection reference type delegate test cases to test behavior on Class instead of on Object.

I worked around this problem by just returning the signature:
    private static String nameToSignature(String name) {
...
        if (name.length() != 0) {
        	// lots more tests could be made here...

        	// check if someone is calling us with something that is a signature already
        	if (name.charAt(0)=='[') {
        		//XXX hack
        		System.err.println("still need hack");
        		return name;
        		//throw new BCException("Do not call nameToSignature with something that looks like a signature (descriptor): '"+name+"'");
        	}

2. The other looks like a problem from calling getDeclaredMethods() on a raw type. I get this stack trace for a number of collection types. I tried commenting out the isRawType() case in ReferenceType:397 and it seems to avoid the problem
		if (isParameterizedType()) {// || isRawType()) {

Can't ask to parameterize a member of a non-generic type
java.lang.IllegalStateException: Can't ask to parameterize a member of a non-generic type
	at org.aspectj.weaver.ResolvedMemberImpl.parameterizedWith(ResolvedMemberImpl.java:605)
	at org.aspectj.weaver.ResolvedMemberImpl.parameterizedWith(ResolvedMemberImpl.java:590)
	at org.aspectj.weaver.ReferenceType.getDeclaredMethods(ReferenceType.java:402)
	at org.aspectj.weaver.ResolvedType.addAndRecurse(ResolvedType.java:252)
	at org.aspectj.weaver.ResolvedType.addAndRecurse(ResolvedType.java:266)
	at org.aspectj.weaver.ResolvedType.getMethodsWithoutIterator(ResolvedType.java:247)
	at org.aspectj.weaver.ResolvedType.lookupResolvedMember(ResolvedType.java:365)
	at org.aspectj.weaver.JoinPointSignatureIterator.findSignaturesFromSupertypes(JoinPointSignatureIterator.java:167)
	at org.aspectj.weaver.JoinPointSignatureIterator.hasNext(JoinPointSignatureIterator.java:68)
	at org.aspectj.weaver.patterns.SignaturePattern.matches(SignaturePattern.java:285)
	at org.aspectj.weaver.patterns.KindedPointcut.matchInternal(KindedPointcut.java:105)
	at org.aspectj.weaver.patterns.Pointcut.match(Pointcut.java:145)
	at org.aspectj.weaver.patterns.AndPointcut.matchInternal(AndPointcut.java:57)
	at org.aspectj.weaver.patterns.Pointcut.match(Pointcut.java:145)
	at org.aspectj.weaver.patterns.AndPointcut.matchInternal(AndPointcut.java:55)
	at org.aspectj.weaver.patterns.Pointcut.match(Pointcut.java:145)
	at org.aspectj.weaver.patterns.AndPointcut.matchInternal(AndPointcut.java:55)
	at org.aspectj.weaver.patterns.Pointcut.match(Pointcut.java:145)
	at org.aspectj.weaver.patterns.AndPointcut.matchInternal(AndPointcut.java:55)
	at org.aspectj.weaver.patterns.Pointcut.match(Pointcut.java:145)
	at org.aspectj.weaver.ShadowMunger.match(ShadowMunger.java:64)
	at org.aspectj.weaver.Advice.match(Advice.java:109)
	at org.aspectj.weaver.bcel.BcelAdvice.match(BcelAdvice.java:105)
	at org.aspectj.weaver.bcel.BcelClassWeaver.match(BcelClassWeaver.java:2113)
	at org.aspectj.weaver.bcel.BcelClassWeaver.matchInvokeInstruction(BcelClassWeaver.java:2100)
	at org.aspectj.weaver.bcel.BcelClassWeaver.match(BcelClassWeaver.java:1882)
	at org.aspectj.weaver.bcel.BcelClassWeaver.match(BcelClassWeaver.java:1708)
	at org.aspectj.weaver.bcel.BcelClassWeaver.weave(BcelClassWeaver.java:455)
	at org.aspectj.weaver.bcel.BcelClassWeaver.weave(BcelClassWeaver.java:102)
	at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:1534)
	at org.aspectj.weaver.bcel.BcelWeaver.weaveWithoutDump(BcelWeaver.java:1485)
	at org.aspectj.weaver.bcel.BcelWeaver.weaveAndNotify(BcelWeaver.java:1266)
	at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:1088)
	at org.aspectj.weaver.tools.WeavingAdaptor.getWovenBytes(WeavingAdaptor.java:267)
	at org.aspectj.weaver.tools.WeavingAdaptor.weaveClass(WeavingAdaptor.java:199)
	at org.aspectj.weaver.loadtime.Aj.preProcess(Aj.java:67)
	at org.aspectj.weaver.loadtime.ClassPreProcessorAgentAdapter.transform(ClassPreProcessorAgentAdapter.java:52)
...

3. I also get a similar error as in #2 from ReferenceType.getDeclaredMethods on overridden methods. E.g., int java.util.Map.hashCode() appears as a declared method on the ReferenceType for java.util.Map<java.lang.Object,java.lang.Object>, but its declaring type, java.util.Map is raw. This if test on ReferenceType:403 works around this problem:

				if (delegateMethods[i].getDeclaringType().equals(this)) {
					parameterizedMethods[i] = delegateMethods[i].parameterizedWith(parameters,this,isParameterizedType());
				}

4. However, I now get this NPE when looking for aMember representing java.lang.Object java.util.AbstractMap.put(K, java.lang.Object), with an array of null parameterizedMethods (probably because of my workaround to #3

java.lang.NullPointerException
	at org.aspectj.weaver.ResolvedType.lookupResolvedMember(ResolvedType.java:373)
	at org.aspectj.weaver.JoinPointSignatureIterator.findSignaturesFromSupertypes(JoinPointSignatureIterator.java:167)
	at org.aspectj.weaver.JoinPointSignatureIterator.findSignaturesFromSupertypes(JoinPointSignatureIterator.java:197)
	at org.aspectj.weaver.JoinPointSignatureIterator.findSignaturesFromSupertypes(JoinPointSignatureIterator.java:165)
	at org.aspectj.weaver.JoinPointSignatureIterator.findSignaturesFromSupertypes(JoinPointSignatureIterator.java:197)
	at org.aspectj.weaver.JoinPointSignatureIterator.hasNext(JoinPointSignatureIterator.java:68)
	at org.aspectj.weaver.patterns.SignaturePattern.matches(SignaturePattern.java:285)
	at org.aspectj.weaver.patterns.KindedPointcut.matchInternal(KindedPointcut.java:105)
	at org.aspectj.weaver.patterns.Pointcut.match(Pointcut.java:145)
	at org.aspectj.weaver.patterns.AndPointcut.matchInternal(AndPointcut.java:57)
	at org.aspectj.weaver.patterns.Pointcut.match(Pointcut.java:145)
	at org.aspectj.weaver.patterns.AndPointcut.matchInternal(AndPointcut.java:55)
	at org.aspectj.weaver.patterns.Pointcut.match(Pointcut.java:145)
	at org.aspectj.weaver.patterns.AndPointcut.matchInternal(AndPointcut.java:55)
	at org.aspectj.weaver.patterns.Pointcut.match(Pointcut.java:145)
	at org.aspectj.weaver.patterns.AndPointcut.matchInternal(AndPointcut.java:55)
	at org.aspectj.weaver.patterns.Pointcut.match(Pointcut.java:145)
	at org.aspectj.weaver.ShadowMunger.match(ShadowMunger.java:64)
	at org.aspectj.weaver.Advice.match(Advice.java:109)
	at org.aspectj.weaver.bcel.BcelAdvice.match(BcelAdvice.java:105)
	at org.aspectj.weaver.bcel.BcelClassWeaver.match(BcelClassWeaver.java:2113)
	at org.aspectj.weaver.bcel.BcelClassWeaver.matchInvokeInstruction(BcelClassWeaver.java:2100)
	at org.aspectj.weaver.bcel.BcelClassWeaver.match(BcelClassWeaver.java:1882)
	at org.aspectj.weaver.bcel.BcelClassWeaver.match(BcelClassWeaver.java:1708)
	at org.aspectj.weaver.bcel.BcelClassWeaver.weave(BcelClassWeaver.java:455)
	at org.aspectj.weaver.bcel.BcelClassWeaver.weave(BcelClassWeaver.java:102)
	at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:1534)
	at org.aspectj.weaver.bcel.BcelWeaver.weaveWithoutDump(BcelWeaver.java:1485)
	at org.aspectj.weaver.bcel.BcelWeaver.weaveAndNotify(BcelWeaver.java:1266)
	at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:1088)
	at org.aspectj.weaver.tools.WeavingAdaptor.getWovenBytes(WeavingAdaptor.java:267)
	at org.aspectj.weaver.tools.WeavingAdaptor.weaveClass(WeavingAdaptor.java:199)
	at org.aspectj.weaver.loadtime.Aj.preProcess(Aj.java:67)
	at org.aspectj.weaver.loadtime.ClassPreProcessorAgentAdapter.transform(ClassPreProcessorAgentAdapter.java:52)
	at sun.instrument.TransformerManager.transform(TransformerManager.java:122)
...
Comment 3 Ron Bodkin CLA 2005-11-22 04:22:25 EST
Created attachment 30363 [details]
implementation of LTWWorld

still pending more testing
Comment 4 Andrew Clement CLA 2005-11-22 04:36:00 EST
Over the last few weeks I've hit all of the problems Ron is describing (whilst investigating other stuff...) and I've not done any LTW or used a reflection world - I think there are just bugs in that code and we don't have enough test programs for generic types (whether they are referred to in RAW form or not).  I will write a few and see what comes out...
Comment 5 Ron Bodkin CLA 2005-11-22 23:20:20 EST
Interesting...

See also bug #117622 with some tests and bug #117624 with one fix. The unit test for bug #117622 exhibits the same failure as item 1 below and with the same work-around, the same failure as item 2 below, with that work-around it exhibits failure 3. I have submitted a new tracking bug #117628 for this specific problem.
Comment 6 Andrew Clement CLA 2006-06-19 10:53:33 EDT
is this now resolved with LTWWorld in use for LTW?
Comment 7 Andrew Clement CLA 2006-06-27 10:38:48 EDT
anyone going to reply to my previous comment? I'll close this soon if no-one says otherwise...
Comment 8 Matthew Webster CLA 2006-06-29 08:32:16 EDT
I have opened Bug 149140.