Bug 363985 - advising a private constructor generates an extra ctor that is also advised
Summary: advising a private constructor generates an extra ctor that is also advised
Status: NEW
Alias: None
Product: AspectJ
Classification: Tools
Component: Runtime (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows XP
: P3 major (vote)
Target Milestone: ---   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-11-16 19:10 EST by Pepe CLA
Modified: 2011-11-17 16:29 EST (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Pepe CLA 2011-11-16 19:10:06 EST
Build Identifier: 20110615-0604

When advising a private constructor a new constructor seems to be created.
The problem is that that new ctor is also advised if the pointcut uses new(..).

The code in "steps to reproduce" generates,

-if the ctor is not private:
before 0
Hi
after 0

-if the ctor is private:
before 0
Hi
after 0
before 1
null
after 1
null



Reproducible: Always

Steps to Reproduce:
package org.aspectj.bugs;

public aspect bug {

	static private class A {
		private A() {
			System.out.println("Hi");
		}
	}
	
	pointcut insert(A a) : this(a) && execution(A.new(..));

	before(A a) : insert(a) {
		System.out.println("before " + thisJoinPoint.getArgs().length);
		if(thisJoinPoint.getArgs().length == 1) {
			System.out.println(thisJoinPoint.getArgs()[0]);
		}
	}
	
	after(A a) : insert(a) {
		System.out.println("after " + thisJoinPoint.getArgs().length);
		if(thisJoinPoint.getArgs().length == 1) {
			System.out.println(thisJoinPoint.getArgs()[0]);
		}
	}
	
	public static void main(String[] args) {
		new A();
	}
	
}
Comment 1 Andrew Clement CLA 2011-11-17 16:29:35 EST
The generation of the secondary constructor is not AspectJ, it is how the eclipse compiler chooses to implement private inner class constructors (if the outer class needs to be able to see into the type, the compiler creates a second ctor of package visibility and tries to kind of 'hide it' by making it synthetic and giving it an unusual argument).  javac does things differently - it does generate the extra ctor but the parameter is of a different type.  This code compiled with javac or plain eclipse will show bytecode containing two ctors (for class B):

public class A {
  static private class B {
    private B() {
    }
  }

  public void m() {
    new B();
  }
}

Anyway, the AspectJ weaver sees the bytecode and all it sees are two different constructors, it doesn't know/recognize what the compiler did to create them, so it is kind of working-as-designed that both are advised.

In your advice you can exclude synthetic constructors:

execution(!synthetic A.new(..));