Bug 28895 - NullPointerException using execution(new(..)) in pointcut
Summary: NullPointerException using execution(new(..)) in pointcut
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Docs (show other bugs)
Version: unspecified   Edit
Hardware: PC Linux
: P3 major (vote)
Target Milestone: ---   Edit
Assignee: Erik Hilsdale CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2002-12-29 02:18 EST by brian wallis CLA
Modified: 2003-01-14 16:01 EST (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description brian wallis CLA 2002-12-29 02:18:45 EST
AspectJ version 1.1B2 
Mandrake Linux 9.0 
Sun JDK 1.3.1_01 and 1.4.1_01 
 
The code below works with aspectj 1.0.6. If "execution" in the pointcut is 
replaced with "call" the example executes as normal. 
 
When run, an exception reported: java.lang.ExceptionInInitializerError 
and cause is NullPointerException as follows: 
 
> Exception in thread "main" java.lang.ExceptionInInitializerError 
> 	at au.com.blackcat.client.Client.<init>(Client.java:3) 
> 	at au.com.blackcat.client.Client.main(Client.java:8) 
> Caused by: java.lang.NullPointerException 
> 	at au.com.blackcat.client.Watchcall.<init>(Watchcall.java:3) 
> 	at au.com.blackcat.client.Watchcall.ajc$clinit(Watchcall.java) 
> 	at au.com.blackcat.client.Watchcall.<clinit>(Watchcall.java:3) 
> 	... 2 more 
 
compiled using 
> ajc @files.lst 
 
where files.lst contains 
> src/au/com/blackcat/client/Client.java 
> src/au/com/blackcat/client/Watchcall.java 
 
environment var CLASSPATH is 
> /opt/aspectj1.1/lib/aspectjtools.jar:/opt/aspectj1.1/lib/aspectjrt.jar 
 
Run with: 
> java -cp . au.com.blackcat.client.Client 
 
Client.java: 
> package au.com.blackcat.client; 
>  
> public class Client 
> { 
>  
>     public static void main(String[] args) 
>     { 
> 	Client c = new Client(); 
>     } 
>  
> } 
 
Watchcall.java: 
> package au.com.blackcat.client; 
>  
> public aspect Watchcall { 
>  
>     pointcut myConstructor(): execution(new(..)); 
>  
>     before(): myConstructor() { 
>         System.err.println("Entering Constructor"); 
>     } 
> }
Comment 1 Erik Hilsdale CLA 2003-01-14 16:01:57 EST
This is actually the correct behavior masked by throwing a very badly chosen
Exception.  In the current CVS compiler, this has now been changed to throw 

org.aspectj.lang.NoAspectBoundException
	
I've also written an extensive usage note on the problem which will appear in
README-11.html in the next release, using your test proggram.  Here's what it says:

  In AspectJ 1.0.6, we made an effort to hide some complications with Aspect
instantiation from the user. In particular, the following code compiled and ran: 

      public class Client
      {
          public static void main(String[] args) {
              Client c = new Client();
          }
      }

      aspect Watchcall {
          pointcut myConstructor(): execution(new(..));

          before(): myConstructor() {
              System.err.println("Entering Constructor");
          }
      }
      
But there's a conceptual problem with this code: The before advice should run
before the execution of all constructors in the system. It must run in the
context of an instance of the Watchcall aspect. The only way to get such an
instance is to have Watchcall's default constructor execute. But before that
executes, we need to run the before advice...

AspectJ 1.0.6 hid this circularity through the ad-hoc mechanism of preventing an
aspect's advice from matching join points that were within the aspect's
definition, and occurred before the aspect was initialized. But even in AspectJ
1.0.6, this circularity could be exposed: 

      public class Client
      {
          public static int foo() { return 3; }
          public static void main(String[] args) {
              Client c = new Client();
          }
      }

      aspect Watchcall {
          int i = Client.foo();
          pointcut myConstructor():
              execution(new(..)) || execution(int foo());

          before(): myConstructor() {
              System.err.println("Entering Constructor");
          }
      }
      
This program would throw a NullPointerException when run, since Client.foo() was
called before the Watchcall instance could be instantiated. 

In AspectJ 1.1, we have decided that half-hiding the problem just leads to
trouble, and so we are no longer silently hiding some join points before aspect
initialization. However, we have provided a better exception than a
NullPointerException for this case. In AspectJ 1.1, both of the above programs
will throw org.aspectj.lang.NoAspectBoundException.