Bug 92630 - Null Pointer Exception thrown by ajc compiler
Summary: Null Pointer Exception thrown by ajc compiler
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: 1.5.0M2   Edit
Hardware: Macintosh Mac OS X - Carbon (unsup.)
: P3 critical (vote)
Target Milestone: ---   Edit
Assignee: Adrian Colyer CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-04-25 15:26 EDT by Manjula Jayaraman CLA
Modified: 2005-08-25 05:40 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 Manjula Jayaraman CLA 2005-04-25 15:26:05 EDT
Hi,

I wrote my first aspect using aspect J as follows to enable logging:

package com.apple.ist.espresso.aspects;


import com.apple.ist.espresso.util.EspressoLogger;

public class EspressoTrace {

        private static EspressoLogger logger = null;


        public static void initLogger(EspressoLogger l) {
                logger = l;
        }

        public static void TraceEntry(String message) {
                logger.debug("Entering : " + message);
        }

        public static void TraceExit(String message) {
                logger.debug("Exiting : " + message);
        }
}


My aspect is in the file EspressoTraceAspect.java as follows:

package com.apple.ist.espresso.aspects;

aspect EspressoTraceAspect {

        pointcut traceCall() : execution(public * com.apple.ist.espresso..*.*(..));

        before() : traceCall {
                Trace.traceEntry("" + thisJointPointStaticPart.getSignature());
        }

        after() : traceCall {
                Trace.traceExit("" + thisJointPointStaticPart.getSignature());
        

        public static void main(String[] args) {
                Trace.initStream(EspressoLogger.getLogger(TraceAspect.class));
        }
}


When i compiled it using the following target: (init target that sets the required variables are done as 
shown in the example build.xml file and are NOT shown here)

      <target name="Ajx" depends="init">
                <iajc destdir="${build.dir}/classes" fork="true" forkclasspath="${aspectjtools.jar}" 
argfiles="${list}">
                    <src path="${src.dir}"/>
                    <src path="${sharedsrc.dir}"/>
                    <src path="${gensrc.dir}"/>
                        <classpath>
                                <path refid="classpath"/>
                                <path refid="aspectj.lib"/>
                        </classpath>
                </iajc>

        </target>

i'm getting the following exception.

[error] Internal compiler error
     [iajc] java.lang.NullPointerException
     [iajc]     at org.aspectj.weaver.bcel.UnwovenClassFile.deleteRealFile(UnwovenClassFile.java:170)
     [iajc]     at org.aspectj.ajdt.internal.core.builder.AjState.deleteClassFile(AjState.java:413)
     [iajc]     at org.aspectj.ajdt.internal.core.builder.AjState.noteResult(AjState.java:450)
     [iajc]     at org.aspectj.ajdt.internal.core.builder.AjBuildManager$3.acceptResult(AjBuildManager.java:
704)
     [iajc]     at 
org.aspectj.ajdt.internal.compiler.AjCompilerAdapter.afterProcessing(AjCompilerAdapter.java:144)
     [iajc]     at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:373)
     [iajc]     at 
org.aspectj.ajdt.internal.core.builder.AjBuildManager.performCompilation(AjBuildManager.java:683)
     [iajc]     at org.aspectj.ajdt.internal.core.builder.AjBuildManager.doBuild(AjBuildManager.java:168)
     [iajc]     at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:102)
     [iajc]     at org.aspectj.ajdt.ajc.AjdtCommand.doCommand(AjdtCommand.java:109)
     [iajc]     at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:60)
     [iajc]     at org.aspectj.tools.ajc.Main.run(Main.java:291)
     [iajc]     at org.aspectj.tools.ajc.Main.runMain(Main.java:227)
     [iajc]     at org.aspectj.tools.ajc.Main.main(Main.java:80)

     [iajc] (no source information available)
     [iajc] /Users/manjulajayaraman/projects/JADE/jadecvs/NewEspresso/ServerDevelopment/Phase1/
src/com/apple/ist/espresso/aspects/EspressoTrace.java:6 [error] The type EspressoTrace is already 
defined
     [iajc] public class EspressoTrace {
     [iajc]              ^^^^^^^^^^^^
     [iajc] ABORT
     [iajc] 
     [iajc] Exception thrown from AspectJ 1.5.0M2

     [iajc] This might be logged as a bug already -- find current bugs at
     [iajc]   http://bugs.eclipse.org/bugs/buglist.cgi?product=AspectJ&component=Compiler

     [iajc] Bugs for exceptions thrown have titles File:line from the top stack, 
     [iajc] e.g., "SomeFile.java:243"

     [iajc] If you don't find the exception below in a bug, please add a new bug
     [iajc] at http://bugs.eclipse.org/bugs/enter_bug.cgi?product=AspectJ
     [iajc] To make the bug a priority, please include a test program
     [iajc] that can reproduce this exception.
     [iajc] null
     [iajc] java.lang.NullPointerException
     [iajc]     at org.aspectj.weaver.bcel.UnwovenClassFile.deleteRealFile(UnwovenClassFile.java:170)
     [iajc]     at org.aspectj.ajdt.internal.core.builder.AjState.deleteClassFile(AjState.java:413)
     [iajc]     at org.aspectj.ajdt.internal.core.builder.AjState.noteResult(AjState.java:450)
     [iajc]     at org.aspectj.ajdt.internal.core.builder.AjBuildManager$3.acceptResult(AjBuildManager.java:
704)
     [iajc]     at 
org.aspectj.ajdt.internal.compiler.AjCompilerAdapter.afterProcessing(AjCompilerAdapter.java:144)
     [iajc]     at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:373)
     [iajc]     at 
org.aspectj.ajdt.internal.core.builder.AjBuildManager.performCompilation(AjBuildManager.java:683)
     [iajc]     at org.aspectj.ajdt.internal.core.builder.AjBuildManager.doBuild(AjBuildManager.java:168)
     [iajc]     at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:102)
     [iajc]     at org.aspectj.ajdt.ajc.AjdtCommand.doCommand(AjdtCommand.java:109)
     [iajc]     at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:60)
     [iajc]     at org.aspectj.tools.ajc.Main.run(Main.java:291)
     [iajc]     at org.aspectj.tools.ajc.Main.runMain(Main.java:227)
     [iajc]     at org.aspectj.tools.ajc.Main.main(Main.java:80)


     [iajc] 1 fail|abort, 2 errors

BUILD FAILED



Could someone please let me know  what's the problem and how do i proceed now?

Thanks,
Manjula
Comment 1 Andrew Clement CLA 2005-04-26 08:45:24 EDT
The failure occurs on a line that is processing a list of files, the list is
null.  The list was created by a call to File.listFiles() for a particular
directory and the code is trying to find <blah>$Ajc<blah> class files that
should be deleted.  The caller allows for the this method to fail with an
IOException - I suspect the difference is in the implementation of listFiles on
the MAC.  The spec for listFiles says it returns:

"An array of abstract pathnames denoting the files and directories in the
directory denoted by this abstract pathname. The array will be empty if the
directory is empty. Returns null if this abstract pathname does not denote a
directory, or if an I/O error occurs."

It could be that what windows considers an IO error is just returned as a Null
on the MAC.  Due to the caller of the method not minding if it fails I propose
to just guard on null and return from the deleteRealFile() method.

The fix will be in an imminent dev build.  

I'm hoping the other message in this bug report:

"The type EspressoTrace is already defined"

is just a symptom of us failing with an NPE.  I suppose a possible workaround
would be to construct the output directory for the ant task (make sure it
exists) before running the task - does that make any difference?  Was it already
defined?
Comment 2 Manjula Jayaraman CLA 2005-04-27 01:22:45 EDT
(In reply to comment #1)
> The failure occurs on a line that is processing a list of files, the list is
> null.  The list was created by a call to File.listFiles() for a particular
> directory and the code is trying to find <blah>$Ajc<blah> class files that
> should be deleted.  The caller allows for the this method to fail with an
> IOException - I suspect the difference is in the implementation of listFiles on
> the MAC.  The spec for listFiles says it returns:
> 
> "An array of abstract pathnames denoting the files and directories in the
> directory denoted by this abstract pathname. The array will be empty if the
> directory is empty. Returns null if this abstract pathname does not denote a
> directory, or if an I/O error occurs."
> 
> It could be that what windows considers an IO error is just returned as a Null
> on the MAC.  Due to the caller of the method not minding if it fails I propose
> to just guard on null and return from the deleteRealFile() method.
> 
> The fix will be in an imminent dev build.  
> 
> I'm hoping the other message in this bug report:
> 
> "The type EspressoTrace is already defined"
> 
> is just a symptom of us failing with an NPE.  I suppose a possible workaround
> would be to construct the output directory for the ant task (make sure it
> exists) before running the task - does that make any difference?  Was it already
> defined?


Thanks for the quick response.  I've just two files EspressoTrace.java and EspressoTraceAspect.java 
When i move those files under ASPECTJ examples dir (examples/trace) and build it using the build.xml 
provided in the examples dir (after making necessary modifications in the build.xml), my sample aspect 
code works. But when moved these two files under a package in my project, i see this NullPointer 
Exception.

Here's my project folder hierarchy

Phase1/src/com/apple/ist/espresso/aspects

I've two files under this folder

EspressoTrace.java
 EspressoTraceAspect.java

There are other packages under com/apple/ist/espresso which needs to be intercepted through AOP.

Shared/src/com/apple/ist/espresso/  ------> Source  code shared by more than 1 projects.

Under Shared/src/com/apple/ist/espresso/xmlparser

I've files.lst as follows:

RequestXmlParser.java
../../../../../../../Phase1/src/com/apple/ist/espresso/aspects/EspressoTrace.java
../../../../../../../Phase1/src/com/apple/ist/espresso/aspects/EspressoTraceAspect.java


To start with i wanted to intercept just RequestXmlParser.java


I've another files.lst under Phase1 where i also have build.xml

Here's the Phase1/files.lst

@../Shared/src/com/apple/ist/espresso/xmlparser/files.lst


Here are some aspectj related targets in my build.xml files:



         <target name="init.variables" description="init variables">

            <!-- build.compiler value to pick up our CompilerAdapter for javac -->
              <property name="ajc.adapter" value="org.aspectj.tools.ant.taskdefs.Ajc11CompilerAdapter"/
>

             <!-- required libraries - install or predefine -->
              <property name="aspectjrt.jar" location="${aspectj.lib.dir}/aspectjrt.jar"/>
              <property name="aspectjtools.jar" location="${aspectj.lib.dir}/aspectjtools.jar"/>
              <property name="aspectjweaver.jar" location="${aspectj.lib.dir}/aspectjweaver.jar"/>

             <!-- checking required libraries -->
              <available file="${aspectjtools.jar}" property="aspectjtools.jar.available"/>
              <available file="${aspectjrt.jar}" property="aspectjrt.jar.available"/>

        </target>

          <target name="init.taskdefs" depends="init.variables, aspectjtools.jar.available, 
aspectjrt.jar.available"
                 unless="taskdefs.init">

                  <!-- sets name of new task to iajc, old task to ajc -->
              <taskdef resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties">
                  <classpath>
                    <pathelement path="${aspectjtools.jar}"/>
                  </classpath>
              </taskdef>
                  <property name="taskdefs.init" value="true"/>
            </target>


           <!-- targets to fail unless required libraries available -->

            <target name="aspectjrt.jar.available" depends="init.variables" unless="aspectjrt.jar.available" 
>
              <fail message="expecting aspectjrt.jar at ${aspectjrt.jar}"/>
            </target>

          <target name="aspectjtools.jar.available" depends="init.variables" 
unless="aspectjtools.jar.available" >
              <fail message="expecting aspectjtools.jar at ${aspectjtools.jar}"/>
            </target>

<path id="aspectj.lib">
                <fileset dir="./jars" includes="aspectjrt.jar"/>
        </path>

<target name="Ajx" depends="init">
                <iajc destdir="${build.dir}/classes" fork="true" forkclasspath="${aspectjtools.jar}" 
argfiles="${list}">
                    <src path="${src.dir}"/>
                    <src path="${sharedsrc.dir}"/>
                        <classpath>
                                <path refid="aspectj.lib"/>
                                <path refid="classpath"/>
                        </classpath>
                </iajc>

        </target>

 <target name="compile" description="Compile main source tree java files">
       <antcall target="clean"/>
        <mkdir dir="${build.dir}/classes"/>
        <antcall target="Ajx">
                <param name="list" value="files.lst"/>
        </antcall>
        <!-- compile tests -->
        <mkdir dir="${test.dir}/classes"/>
        <antcall target="test-ajx">
                <param name="list" value="files.list"/>
        </antcall>
       </target>

<target name="clean" description="Clean output directories">
        <delete dir="${build.dir}"/>
        <delete dir="${coverage.dir}"/>
            <delete quiet="on">
                <fileset dir="${build.dir}/classes" includes="**/*.ajesym"/>
              </delete>
            
    </target>

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


when i run compile target, i get NullPointerException. I'm VERY SURE that AspectJ is able to find the files 
listed in files.lst. The reason i say is that if i provide incorrect path in the files.lst, it provides me some 
other error.  


So, i still don't understand what's the mistake from my part.

Thanks for any help in advance,
Manjula
Comment 3 Manjula Jayaraman CLA 2005-04-29 17:59:03 EDT
I tried to create the output directory before ajc compiler starts. I still get the same NPE.

I'm still stuck with this issue and couldn't make any progress. Could someone please help?

Thanks,
Manjula

(In reply to comment #2)
> (In reply to comment #1)
> > The failure occurs on a line that is processing a list of files, the list is
> > null.  The list was created by a call to File.listFiles() for a particular
> > directory and the code is trying to find <blah>$Ajc<blah> class files that
> > should be deleted.  The caller allows for the this method to fail with an
> > IOException - I suspect the difference is in the implementation of listFiles on
> > the MAC.  The spec for listFiles says it returns:
> > 
> > "An array of abstract pathnames denoting the files and directories in the
> > directory denoted by this abstract pathname. The array will be empty if the
> > directory is empty. Returns null if this abstract pathname does not denote a
> > directory, or if an I/O error occurs."
> > 
> > It could be that what windows considers an IO error is just returned as a Null
> > on the MAC.  Due to the caller of the method not minding if it fails I propose
> > to just guard on null and return from the deleteRealFile() method.
> > 
> > The fix will be in an imminent dev build.  
> > 
> > I'm hoping the other message in this bug report:
> > 
> > "The type EspressoTrace is already defined"
> > 
> > is just a symptom of us failing with an NPE.  I suppose a possible workaround
> > would be to construct the output directory for the ant task (make sure it
> > exists) before running the task - does that make any difference?  Was it already
> > defined?
> 
> 
> Thanks for the quick response.  I've just two files EspressoTrace.java and EspressoTraceAspect.java 
> When i move those files under ASPECTJ examples dir (examples/trace) and build it using the 
build.xml 
> provided in the examples dir (after making necessary modifications in the build.xml), my sample 
aspect 
> code works. But when moved these two files under a package in my project, i see this NullPointer 
> Exception.
> 
> Here's my project folder hierarchy
> 
> Phase1/src/com/apple/ist/espresso/aspects
> 
> I've two files under this folder
> 
> EspressoTrace.java
>  EspressoTraceAspect.java
> 
> There are other packages under com/apple/ist/espresso which needs to be intercepted through AOP.
> 
> Shared/src/com/apple/ist/espresso/  ------> Source  code shared by more than 1 projects.
> 
> Under Shared/src/com/apple/ist/espresso/xmlparser
> 
> I've files.lst as follows:
> 
> RequestXmlParser.java
> ../../../../../../../Phase1/src/com/apple/ist/espresso/aspects/EspressoTrace.java
> ../../../../../../../Phase1/src/com/apple/ist/espresso/aspects/EspressoTraceAspect.java
> 
> 
> To start with i wanted to intercept just RequestXmlParser.java
> 
> 
> I've another files.lst under Phase1 where i also have build.xml
> 
> Here's the Phase1/files.lst
> 
> @../Shared/src/com/apple/ist/espresso/xmlparser/files.lst
> 
> 
> Here are some aspectj related targets in my build.xml files:
> 
> 
> 
>          <target name="init.variables" description="init variables">
> 
>             <!-- build.compiler value to pick up our CompilerAdapter for javac -->
>               <property name="ajc.adapter" 
value="org.aspectj.tools.ant.taskdefs.Ajc11CompilerAdapter"/
> >
> 
>              <!-- required libraries - install or predefine -->
>               <property name="aspectjrt.jar" location="${aspectj.lib.dir}/aspectjrt.jar"/>
>               <property name="aspectjtools.jar" location="${aspectj.lib.dir}/aspectjtools.jar"/>
>               <property name="aspectjweaver.jar" location="${aspectj.lib.dir}/aspectjweaver.jar"/>
> 
>              <!-- checking required libraries -->
>               <available file="${aspectjtools.jar}" property="aspectjtools.jar.available"/>
>               <available file="${aspectjrt.jar}" property="aspectjrt.jar.available"/>
> 
>         </target>
> 
>           <target name="init.taskdefs" depends="init.variables, aspectjtools.jar.available, 
> aspectjrt.jar.available"
>                  unless="taskdefs.init">
> 
>                   <!-- sets name of new task to iajc, old task to ajc -->
>               <taskdef resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties">
>                   <classpath>
>                     <pathelement path="${aspectjtools.jar}"/>
>                   </classpath>
>               </taskdef>
>                   <property name="taskdefs.init" value="true"/>
>             </target>
> 
> 
>            <!-- targets to fail unless required libraries available -->
> 
>             <target name="aspectjrt.jar.available" depends="init.variables" 
unless="aspectjrt.jar.available" 
> >
>               <fail message="expecting aspectjrt.jar at ${aspectjrt.jar}"/>
>             </target>
> 
>           <target name="aspectjtools.jar.available" depends="init.variables" 
> unless="aspectjtools.jar.available" >
>               <fail message="expecting aspectjtools.jar at ${aspectjtools.jar}"/>
>             </target>
> 
> <path id="aspectj.lib">
>                 <fileset dir="./jars" includes="aspectjrt.jar"/>
>         </path>
> 
> <target name="Ajx" depends="init">
>                 <iajc destdir="${build.dir}/classes" fork="true" forkclasspath="${aspectjtools.jar}" 
> argfiles="${list}">
>                     <src path="${src.dir}"/>
>                     <src path="${sharedsrc.dir}"/>
>                         <classpath>
>                                 <path refid="aspectj.lib"/>
>                                 <path refid="classpath"/>
>                         </classpath>
>                 </iajc>
> 
>         </target>
> 
>  <target name="compile" description="Compile main source tree java files">
>        <antcall target="clean"/>
>         <mkdir dir="${build.dir}/classes"/>
>         <antcall target="Ajx">
>                 <param name="list" value="files.lst"/>
>         </antcall>
>         <!-- compile tests -->
>         <mkdir dir="${test.dir}/classes"/>
>         <antcall target="test-ajx">
>                 <param name="list" value="files.list"/>
>         </antcall>
>        </target>
> 
> <target name="clean" description="Clean output directories">
>         <delete dir="${build.dir}"/>
>         <delete dir="${coverage.dir}"/>
>             <delete quiet="on">
>                 <fileset dir="${build.dir}/classes" includes="**/*.ajesym"/>
>               </delete>
>             
>     </target>
> 
> ------------------------------------------------
> 
> 
> when i run compile target, i get NullPointerException. I'm VERY SURE that AspectJ is able to find the 
files 
> listed in files.lst. The reason i say is that if i provide incorrect path in the files.lst, it provides me 
some 
> other error.  
> 
> 
> So, i still don't understand what's the mistake from my part.
> 
> Thanks for any help in advance,
> Manjula
Comment 4 Manjula Jayaraman CLA 2005-04-29 18:43:42 EDT
Hi,

When i removed the following lines from the Ajx task, the Null Pointer Exception disappeared.

<src path="${src.dir}"/>
                    <src path="${sharedsrc.dir}"/>
                    <src path="${gensrc.dir}"

Still, i'm not sure why should it be a NPE?

Thanks,
Manjula
Comment 5 Andrew Clement CLA 2005-05-04 11:41:49 EDT
It is interesting that you are using 'src path' as we don't document that it is
supported in the AspectJ manuals (however, it does work..).  

<iajc destdir="${build.dir}/classes" fork="true" 
  forkclasspath="${aspectjtools.jar}" 
  argfiles="${list}">
  <src path="${src.dir}"/>
  <src path="${sharedsrc.dir}"/>
  <src path="${gensrc.dir}"/>
  <classpath>
    <path refid="classpath"/>
    <path refid="aspectj.lib"/>
  </classpath>
</iajc>

You also seem to be mixing your methods of referring to what you want compiled -
you specify a list of files for building from an argfile and then supply three
source paths that will contain files - which want do you want the compiler to use?  

I have just recreated a scenario like yours with multiple input src folders and
I get the errors I'd expect - if I use a .lst and specify <src path> entries as
well then AspectJ tells me it is seeing duplicates (since the files are being
found as referenced twice - once in the .lst and once through the <src path>
entries).

I don't see an NPE and I still believe that is due to what I mentioned in
comment #1 where the MAC is interpreting an error differently to Windows.  The
bug is fixed but I am still having problems creating a development build
containing the fix.
Comment 6 Andrew Clement CLA 2005-05-06 08:43:38 EDT
Fix available, see AspectJ download page:
aspectj-DEVELOPMENT-20050506112715.jar
Comment 7 Adrian Colyer CLA 2005-08-25 05:40:50 EDT
This was fixed in May as per last comment on this  bug, but we forgot to close
out the report. Tidying that up now...