Bug 550494 - NullPointerException compiling aspect using @DeclareParents to implement interface
Summary: NullPointerException compiling aspect using @DeclareParents to implement inte...
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: 1.9.4   Edit
Hardware: PC Windows 10
: P3 normal (vote)
Target Milestone: 1.9.5   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-08-27 22:52 EDT by Alexander Kriegisch CLA
Modified: 2019-12-02 21:14 EST (History)
1 user (show)

See Also:


Attachments
Sample code (2.49 KB, application/x-zip-compressed)
2019-08-27 22:52 EDT, Alexander Kriegisch CLA
no flags Details
ajc core dump (9.01 KB, text/plain)
2019-08-27 22:52 EDT, Alexander Kriegisch CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Alexander Kriegisch CLA 2019-08-27 22:52:21 EDT
Created attachment 279695 [details]
Sample code

I bumped into this problem when answering a StackOverflow question. See here for more details:

https://stackoverflow.com/a/57684300/1082681

------------------------------------------------------------

package de.scrum_master.app;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;

public class BaseClass {
  public PrintWriter getLogWriter() throws SQLException { return null; }
  public void setLogWriter(PrintWriter out) throws SQLException {}
  public void setLoginTimeout(int seconds) throws SQLException {}
  public int getLoginTimeout() throws SQLException { return 0; }
  public Logger getParentLogger() throws SQLFeatureNotSupportedException { return null; }
  public <T> T unwrap(Class<T> iface) throws SQLException { return null; }
  public boolean isWrapperFor(Class<?> iface) throws SQLException { return false; }
  public Connection getConnection() throws SQLException { return null; }
  public Connection getConnection(String username, String password) throws SQLException { return null; }
}

------------------------------------------------------------

package de.scrum_master.app;

import javax.sql.DataSource;

public class SubClass extends BaseClass implements DataSource {}

------------------------------------------------------------

package de.scrum_master.app;

import java.sql.SQLException;

public class Application {
  public static void main(String[] args) throws SQLException {
    System.out.println("Aspect should not kick in without ITD, but should with ITD");
    new BaseClass().getConnection();
    new BaseClass().getConnection("user", "pw");

    System.out.println("Aspect should kick in");
    new SubClass().getConnection();
    new SubClass().getConnection("user", "pw");
  }
}

------------------------------------------------------------

package de.scrum_master.aspect;

import javax.sql.DataSource;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.DeclareParents;

@Aspect
public class DataSourceConnectionAspect {
  // This statement crashes the AspectJ compiler
  @DeclareParents("de.scrum_master.app.BaseClass")
  private DataSource dataSource;
  
  @Before("execution(public java.sql.Connection javax.sql.DataSource+.getConnection(..))")
  public void myAdvice(JoinPoint thisJoinPoint) {
    System.out.println(thisJoinPoint);
  }
}

------------------------------------------------------------

The same aspect in native syntax works:

------------------------------------------------------------

package de.scrum_master.aspect;

import javax.sql.DataSource;

import de.scrum_master.app.BaseClass;

public aspect DataSourceConnectionAspect {
  declare parents: BaseClass implements DataSource;

  before() : execution(public java.sql.Connection javax.sql.DataSource+.getConnection(..)) {
    System.out.println(thisJoinPoint);
  }
}

------------------------------------------------------------

---- AspectJ Properties ---
AspectJ Compiler 1.9.4 built on Friday May 10, 2019 at 08:43:10 PDT
---- Dump Properties ---
Dump file: ajcore.20190828.093602.273.txt
Dump reason: java.lang.NullPointerException
Dump on exception: true
Dump at exit condition: abort
---- Exception Information ---
java.lang.NullPointerException
	at java.base/java.io.DataOutputStream.writeUTF(DataOutputStream.java:347)
	at java.base/java.io.DataOutputStream.writeUTF(DataOutputStream.java:323)
	at org.aspectj.weaver.MethodDelegateTypeMunger.write(MethodDelegateTypeMunger.java:134)
	at org.aspectj.weaver.WeaverStateInfo.write(WeaverStateInfo.java:227)
	at org.aspectj.weaver.AjAttribute$WeaverState.write(AjAttribute.java:209)
	at org.aspectj.weaver.AjAttribute.getBytes(AjAttribute.java:59)
	at org.aspectj.weaver.bcel.Utility.bcelAttribute(Utility.java:714)
(...)

------------------------------------------------------------

I am attaching a source zip and an ajc core dump.
Comment 1 Alexander Kriegisch CLA 2019-08-27 22:52:55 EDT
Created attachment 279696 [details]
ajc core dump
Comment 2 Alexander Kriegisch CLA 2019-08-27 23:01:39 EDT
I forgot to mention: You can either compile with AJDT from Eclipse or like this from the console:

ajc -8 -sourceroots src -d bin -cp "c:\Program Files\Java\AspectJ\lib\aspectjrt.jar"

I used Java 8, but probably with newer Java versions it will be the same.
Comment 3 Andrew Clement CLA 2019-11-27 22:03:12 EST
Fixed up (I think!). Thanks for the tests (as usual)
Comment 4 Alexander Kriegisch CLA 2019-12-02 21:14:21 EST
I compiled via ajc and also manually patched my AJDT in Eclipse with the 1.9.5 aspectjrt and aspectjweaver JARs, renaming them to org.aspectj.runtime_1.9.2.201911072000.jar and org.aspectj.weaver_1.9.2.201911072000.jar in my Eclipse 2018-12 (sorry, not on a more recent version yet) installation's ~/.p2/pool/plugins directory. In both cases the error is fixed, so thank you very much, Andy. :-)