Bug 106554 - Problem in staticinitialization with pertypewithin aspect
Summary: Problem in staticinitialization with pertypewithin aspect
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.0 M4   Edit
Assignee: Andrew Clement CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-08-09 16:25 EDT by Ron Bodkin CLA
Modified: 2005-09-14 03:05 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 Ron Bodkin CLA 2005-08-09 16:25:56 EDT
Here is a small test case that illustrates the problem I'm seeing with the 
AspectJ in CVS HEAD (it also affects 1.5.0 M2):

The program should output 1 but it outputs null instead. 

public aspect AspectStatic {
    public interface Iface {
    }

    private static Class[] managedInterfaces = { Iface.class };
    private static Object assembler = initAssembler();
    private static Object initAssembler() {
            return new Integer(1);
    }

    public static void main(String args[]) {
        System.out.println("test = "+assembler);
    }
}

aspect StopsInit pertypewithin(AspectStatic) {
    before() : staticinitialization(*) {
    }
}
Comment 1 Adrian Colyer CLA 2005-08-26 11:53:46 EDT
for investigation in M4
Comment 2 Andrew Clement CLA 2005-09-12 10:07:50 EDT
Hmmm...

if you compile this program 'ajc AspectStatic.aj' and run it, you get 'null'.
 
If you compile this program 'ajc -1.5 AspectStatic.aj' and run it, you get '1'.
Comment 3 Andrew Clement CLA 2005-09-12 10:12:16 EDT
It is this line that causes us to fail when compiling without -1.5:

private static Class[] managedInterfaces = { Iface.class };

commenting *out* that line and compiling 'ajc AspectStatic.aj', it runs OK. 
(or,  as the bug suggests, commenting out the advice in the sub-aspect, also
makes it work).

managedInterfaces is obviously initialized via a static initializer block.

Comment 4 Andrew Clement CLA 2005-09-12 11:33:20 EDT
yuck.

Modified program: 
---
public aspect A {
  interface I { }

  static Class[] classes = { I.class };

  static Object f = new Integer(1);

  public static void main(String args[]) {
    System.out.println("test = "+f);
    System.err.println("A:"+A.aspectOf());
  }
}

aspect StopsInit pertypewithin(A) {
  before() : staticinitialization(*) {}
}
---
Compiling and running this (no -1.5) will fail with:
test = null
Exception in thread "main" org.aspectj.lang.NoAspectBoundException: Exception 
while initializing A: java.lang.IncompatibleClassChangeError
        at A.aspectOf(A.aj)
        at A.main(A.aj:10) 
  Caused by: java.lang.IncompatibleClassChangeError
        at A$I.<clinit>(A.aj:1)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:164)
        at A.<clinit>(A.aj:4)


If you change the declaration of the inner type from 'interface I' to 'class I'
then it compiles and runs OK !

The 'bang' that occurs during initialization prevents us executing the code that
sets the field (hence it is null).  The aspectOf() call enables us to see the
exception that occurred during initialization.
Comment 5 Andrew Clement CLA 2005-09-13 04:16:53 EDT
The difference when the code is compiled with '-1.5' is the bytecode for
initializing:

   private static Class[] managedInterfaces = { Iface.class };

When it fails (no -1.5):
static {};
  Code:
   Stack=5, Locals=1, Args_size=0
   0:	ldc	#104; //String A
   2:	invokestatic	#135; //Method
StopsInit.ajc$createAspectInstance:(Ljava/lang/String;)LStopsInit;
   5:	putstatic	#122; //Field ajc$StopsInit$ptwAspectInstance:LStopsInit;
   8:	invokestatic	#126; //Method ajc$StopsInit$localAspectOf:()LStopsInit;
   11:	invokevirtual	#131; //Method StopsInit.ajc$before$StopsInit$1$ee91c721:()V
   14:	iconst_1
   15:	anewarray	#20; //class java/lang/Class
   18:	dup
   19:	iconst_0
   20:	getstatic	#22; //Field class$0:Ljava/lang/Class;
   23:	dup
   24:	ifnonnull	52
   27:	pop
   28:	ldc	#24; //String A$I
   30:	invokestatic	#28; //Method
java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
   33:	dup
   34:	putstatic	#22; //Field class$0:Ljava/lang/Class;
   37:	goto	52
   40:	new	#30; //class java/lang/NoClassDefFoundError
   43:	dup_x1
   44:	swap
   45:	invokevirtual	#36; //Method
java/lang/Throwable.getMessage:()Ljava/lang/String;
   48:	invokespecial	#40; //Method
java/lang/NoClassDefFoundError."<init>":(Ljava/lang/String;)V
   51:	athrow
   52:	aastore
   53:	putstatic	#42; //Field classes:[Ljava/lang/Class;
   56:	new	#44; //class java/lang/Integer
   59:	dup
   60:	iconst_1
   61:	invokespecial	#47; //Method java/lang/Integer."<init>":(I)V
   64:	putstatic	#49; //Field f:Ljava/lang/Object;
   67:	invokestatic	#52; //Method ajc$postClinit:()V
   70:	goto	78
   73:	astore_0
   74:	aload_0
   75:	putstatic	#54; //Field ajc$initFailureCause:Ljava/lang/Throwable;
   78:	return

when it works (-1.5):
static {};
  Code:
   Stack=4, Locals=1, Args_size=0
   0:	ldc	#89; //String A
   2:	invokestatic	#121; //Method
StopsInit.ajc$createAspectInstance:(Ljava/lang/String;)LStopsInit;
   5:	putstatic	#108; //Field ajc$StopsInit$ptwAspectInstance:LStopsInit;
   8:	invokestatic	#112; //Method ajc$StopsInit$localAspectOf:()LStopsInit;
   11:	invokevirtual	#117; //Method StopsInit.ajc$before$StopsInit$1$ee91c721:()V
   14:	iconst_1
   15:	anewarray	#19; //class java/lang/Class
   18:	dup
   19:	iconst_0
   20:	ldc	#21; //class A$I
   22:	aastore
   23:	putstatic	#23; //Field classes:[Ljava/lang/Class;
   26:	new	#25; //class java/lang/Integer
   29:	dup
   30:	iconst_1
   31:	invokespecial	#29; //Method java/lang/Integer."<init>":(I)V
   34:	putstatic	#31; //Field f:Ljava/lang/Object;
   37:	invokestatic	#34; //Method ajc$postClinit:()V
   40:	goto	48
   43:	astore_0
   44:	aload_0
   45:	putstatic	#36; //Field ajc$initFailureCause:Ljava/lang/Throwable;
   48:	return

when Iface is a class rather than an interface (it works):
static {};
  Code:
   Stack=5, Locals=1, Args_size=0
   0:	ldc	#104; //String A
   2:	invokestatic	#135; //Method
StopsInit.ajc$createAspectInstance:(Ljava/lang/String;)LStopsInit;
   5:	putstatic	#122; //Field ajc$StopsInit$ptwAspectInstance:LStopsInit;
   8:	invokestatic	#126; //Method ajc$StopsInit$localAspectOf:()LStopsInit;
   11:	invokevirtual	#131; //Method StopsInit.ajc$before$StopsInit$1$ee91c721:()V
   14:	iconst_1
   15:	anewarray	#20; //class java/lang/Class
   18:	dup
   19:	iconst_0
   20:	getstatic	#22; //Field class$0:Ljava/lang/Class;
   23:	dup
   24:	ifnonnull	52
   27:	pop
   28:	ldc	#24; //String A$I
   30:	invokestatic	#28; //Method
java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
   33:	dup
   34:	putstatic	#22; //Field class$0:Ljava/lang/Class;
   37:	goto	52
   40:	new	#30; //class java/lang/NoClassDefFoundError
   43:	dup_x1
   44:	swap
   45:	invokevirtual	#36; //Method
java/lang/Throwable.getMessage:()Ljava/lang/String;
   48:	invokespecial	#40; //Method
java/lang/NoClassDefFoundError."<init>":(Ljava/lang/String;)V
   51:	athrow
   52:	aastore
   53:	putstatic	#42; //Field classes:[Ljava/lang/Class;
   56:	new	#44; //class java/lang/Integer
   59:	dup
   60:	iconst_1
   61:	invokespecial	#47; //Method java/lang/Integer."<init>":(I)V
   64:	putstatic	#49; //Field f:Ljava/lang/Object;
   67:	invokestatic	#52; //Method ajc$postClinit:()V
   70:	goto	78
   73:	astore_0
   74:	aload_0
   75:	putstatic	#54; //Field ajc$initFailureCause:Ljava/lang/Throwable;
   78:	return
Comment 6 Andrew Clement CLA 2005-09-13 11:11:55 EDT
test and fix checked in. waiting on build.
Comment 7 Andrew Clement CLA 2005-09-14 03:05:55 EDT
fix available in latest dev build.