Bug 44586

Summary: After throwing advice on ctors doesn't execute for inter-type decls
Product: [Tools] AspectJ Reporter: Ron Bodkin <rbodkin+LISTS>
Component: CompilerAssignee: Jim Hugunin <jim-aj>
Status: RESOLVED FIXED QA Contact:
Severity: major    
Priority: P2    
Version: 1.1.1   
Target Milestone: 1.2   
Hardware: PC   
OS: Windows XP   
Whiteboard:

Description Ron Bodkin CLA 2003-10-09 13:53:43 EDT
The following code doesn't work in Ajc 1.1.1, in Ajc built from CVS HEAD (as 
of yesterday), nor in Ajc 1.0.6:

Output:
C:\devel\test\excHandling>java AfterThrowingCtor
Exception in thread "main" java.lang.IllegalStateException: crash
        at Foo.initVal(AfterThrowingCtor.java:21)
        at AfterThrowingCtor.ajc$interFieldInit$AfterThrowingCtor$Foo$val
(AfterT
hrowingCtor.java:9)
        at Foo.<init>(AfterThrowingCtor.java:13)
        at AfterThrowingCtor.main(AfterThrowingCtor.java:6)

Correct Output:
threw java.lang.IllegalStateException: crash at execution(Foo())
Exception in thread "main" java.lang.IllegalStateException: crash
        at Foo.initVal(AfterThrowingCtor.java:21)
        at AfterThrowingCtor.ajc$interFieldInit$AfterThrowingCtor$Foo$val
(AfterT
hrowingCtor.java:9)
        at Foo.<init>(AfterThrowingCtor.java:13)
        at AfterThrowingCtor.main(AfterThrowingCtor.java:6)

Input source:
public aspect AfterThrowingCtor {
    after() throwing (Throwable t) : execution(Foo.new(..)) {
	System.err.println("threw "+t+" at "+thisJoinPointStaticPart);
    }
    public static void main(String args[]) {
	new Foo();
    }

    private Object Foo.val = Foo.initVal();
}

class Foo {
    Foo() { 
    }

    // if you uncomment this line and comment out the inter-type decl.
    // the advice runs correctly
    //private Object val = initVal();

    static Object initVal() {
	throw new IllegalStateException("crash"); 
    }
}
---

AspectJ 1.1.1 runs the after throwing advice correctly if the field is 
declared normally (AspectJ 1.0.6 fails to do even this).
Comment 1 Adrian Colyer CLA 2004-01-13 11:16:52 EST
This is a subtle problem.

The issue surrounds the treatment of field initialization with respect to the 
scope of execution and initialization join points. 

Field initialization within a class was considered part of the constructor 
execution join point with the change to 1.1 (see
http://dev.eclipse.org/viewcvs/indextech.
cgi/~checkout~/aspectj-home/doc/README-11.html#CONSTRUCTOR_EXECUTION_IS_BIGGER
) as there was no principled way in bytecode to detect otherwise.

Field initialization outside of the class is not considered part of the 
constructor execution join point (the field belongs to the aspect), so it is 
correct that the advice does not run. Changing the advice to initialization 
rather than execution will cause it to execute in both cases.

See the test case in tests/bugs/AfterThrowingCtor.java for an example that 
illustrates both of these cases.