Bug 71372 - NoSuchMethodError calling private method from around advice in inner aspect
Summary: NoSuchMethodError calling private method from around advice in inner aspect
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: 1.2   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 1.2.1   Edit
Assignee: Adrian Colyer CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-08-04 09:29 EDT by Matthew Webster CLA
Modified: 2004-10-21 04:32 EDT (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Matthew Webster CLA 2004-08-04 09:29:43 EDT
Static inner classes and aspects are permitted to call private static methods 
in the enclosing class. In the case of aspects this should apply to both 
methods and advice. However while the following testcase will compile it fails 
to run:

package bug_nnnn;

public class InnerAspectCallsPrivateMethod {

	public void test () {
		foo("test");
	}
	
	private static void foo (String from) {
		System.out.println("? foo() " + from);
	}
	
	public static void main(String[] args) {
		new InnerAspectCallsPrivateMethod().test();
	}
	
	private static aspect Aspect {
		
		public Aspect () {
			foo("Aspect.<init>");
		}
		
		pointcut execTest () :
			execution(* InnerAspectCallsPrivateMethod.test());
		
		before () :  execTest () {
			foo("before");
		}
		
		void around () :  execTest () {
			foo("around");
		}
	}
}

java.lang.NoSuchMethodError: bug_nnnn.InnerAspectCallsPrivateMethod$Aspect.foo
(Ljava/lang/String;)V
? foo() Aspect.<init>
? foo() before
	at 
bug_nnnn.InnerAspectCallsPrivateMethod$Aspect.ajc$inlineAccessMethod$bug_nnnn_I
nnerAspectCallsPrivateMethod$Aspect$bug_nnnn_InnerAspectCallsPrivateMethod$Aspe
ct$foo(InnerAspectCallsPrivateMethod.java)
	at bug_nnnn.InnerAspectCallsPrivateMethod.test_aroundBody1$advice
(InnerAspectCallsPrivateMethod.java:43)
	at bug_nnnn.InnerAspectCallsPrivateMethod.test
(InnerAspectCallsPrivateMethod.java)
	at bug_nnnn.InnerAspectCallsPrivateMethod.main
(InnerAspectCallsPrivateMethod.java:26)
Exception in thread "main"
Comment 1 Andrew Clement CLA 2004-08-13 05:31:38 EDT
The interesting bit of AJ source relating to this bug is in:

AccessForInlineVisitor.getAccessibleMethod()

which is called with a binding of 'void foo(java.lang.String)' and a receiver
Type of 'Aspect'.  See comments relating to this bug, prefixed 'Andy' below:

{
  if (!binding.isValidBinding()) return binding;
		
  makePublic(receiverType);  //???
  if (isPublic(binding)) return binding;
  if (binding instanceof InterTypeMethodBinding) return binding;

  if (binding.isPrivate() &&  binding.declaringClass != inAspect.binding) {
// Andy: This is where we end up in the case where foo() is a private
// Andy: method.  We raise its visibility.

    binding.modifiers = AstUtil.makePackageVisible(binding.modifiers);
  }
	
// Andy: We then create a ResolvedMember in the *aspect* for the foo method
// Andy: which never has its body generated (called something like 
// Andy: PrivateCall$Aspect.foo() - where PrivateCall is the name of the 
// Andy: class containing foo().
  ResolvedMember m = EclipseFactory.makeResolvedMember(binding, receiverType);
  if (inAspect.accessForInline.containsKey(m)) 
    return (MethodBinding)inAspect.accessForInline.get(m);
// Andy: Now we generate an inline accessor method that calls foo() and 
// Andy: we use it in the advice.  Of course this method will be generated 
// Andy: but its body will call the method PrivateCall$Aspect.foo() which is
// Andy: never generated.
  MethodBinding ret = world.makeMethodBinding(
    AjcMemberMaker.inlineAccessMethodForMethod(inAspect.typeX, m));
  inAspect.accessForInline.put(m, ret);
  return ret;
}

The solution is to raise the visibility and just return the newly accessible
method binding as it will then be completely visible to the advice (there is
no need for an accessor method).

I'm thinking there are a whole bunch of related tests that could be written in
this area and currently puzzling through which are likely to break with the
change above.  

Question for Matthew:
Do we think it is allowed for around advice in the inner aspect to call a
private method foo() in the enclosing class and yet have that around advice
affect something in a completely different type?  

In this case the inlining may cause my change to break (but I suspect we are
already broken so I haven't made it worse...)
Comment 2 Andrew Clement CLA 2004-08-13 10:51:51 EDT
Ok.  I fixed it properly and have covered all cases with tests - even the case
when you inline the around advice into an entirely different type.

Waiting for build before closing
Comment 3 Andrew Clement CLA 2004-08-15 05:15:40 EDT
Fix available:

BUILD COMPLETE -  build.340
Date of build: 08/14/2004 10:57:39
Time to build: 92 minutes 0 seconds
Last changed: 08/14/2004 09:08:57
Latest good AspectJ jar available at:
download.eclipse.org/technology/ajdt/dev/aspectj-DEVELOPMENT.jar
Comment 4 Adrian Colyer CLA 2004-10-21 04:32:09 EDT
Fix released as part of AspectJ 1.2.1