[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Selective Load-Time Weaving with aop.xml and Java ClassLoader

On Fri, Jun 16, 2006 at 09:38:37AM +0100, Matthew Webster wrote:

> Greg,
> 
> WRT your aj/aj5 problem it is difficult to tell what is going on without 
> some more information. Which JDK are you using? What is the exact version 
> of AspectJ? How are configuring aj: are you just using CLASSPATH or 
> ASPECTPATH as well. I suggest you open a bug report and append the verbose 
> output you have collected along with configuration details.
> 

Overall, I take your response to indicate that indeed it should be
possible to use the include in the manner that I described in the
previous fashion.  Let me fill you in on several other points of
interest about my configuration.  There is quite a bit of code and
scripts besides the AspectJ portion and so I will try to narrow it
down without excluding anything important.

Operating System Details:

uname -a
Linux massah 2.6.9-1.667 #1 Tue Nov 2 14:41:25 EST 2004 i686 i686 i386 
GNU/Linux

java -version
java version "1.5.0_04"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_04-b05)
Java HotSpot(TM) Client VM (build 1.5.0_04-b05, mixed mode, sharing)

Application Information:

I am building a test coverage monitoring system that constructs a
special type of calling context tree (CCT) when JUnit and DBUnit test
suites are executed.  The case study applications can be instrumented
in either a "static" or a "dynamic" fashion.

The "static" approach uses ajc to place all of the instrumentation
before the test suite is executed.  The "dynamic" approach makes a
simple .jar file that just contains the aspects and it introduces the
instrumentation at test suite execution time.

I based my aspects (a long time ago!) on the tracing example that was
provided with AspectJ 1.2.1.  The MonitorTestCoverage aspect is
abstract and the TraceMonitoringTestCoverage contains concrete
implementations of the aspects and can be used to build the different
CCTs.  

All of the code in the diatoms.monitor package is part of the
instrumentation that is introduced by ajc.  I will provide more
details about this later in the message.

This command executes the ajc script when I want to perform static
instrumentation.  The .lst file contains a pointer to the .java files
for all of the case study applications and for the .java files that
contain my aspects.  

This works correctly with either AspectJ 1.2.1 or AspectJ 1.5.  Note
that the only .class files that are included are those related to the
within() specifications as described in my pointcuts later in the
message.

/usr/bin/time ajc @AllApplicationsTestCoverageMonitoring.lst -outjar 
TestCoverageMonitor.jar

jar tvf TestCoverageMonitor.jar
    55 Sat Jun 10 23:20:22 EDT 2006 META-INF/MANIFEST.MF
 10002 Sat Jun 10 23:20:26 EDT 2006 diatoms/monitor/MonitorTestCoverage.class
 81493 Sat Jun 10 23:20:26 EDT 2006 diatoms/monitor/TraceMonitorTestCoverage.class
  3045 Sat Jun 10 23:20:26 EDT 2006 diatoms/monitor/CallingContextTree.class
  1790 Sat Jun 10 23:20:26 EDT 2006 diatoms/monitor/DynamicCallTree.class
  5516 Sat Jun 10 23:20:26 EDT 2006 diatoms/monitor/HybridCallTree.class
  4196 Sat Jun 10 23:20:26 EDT 2006 diatoms/monitor/CallTree.class
  4070 Sat Jun 10 23:20:26 EDT 2006 diatoms/monitor/CallTreeNode.class
  7446 Sat Jun 10 23:20:26 EDT 2006 diatoms/monitor/MonitorConfiguration.class
   635 Sat Jun 10 23:20:26 EDT 2006 diatoms/monitor/CallTreeStorage.class
  1941 Sat Jun 10 23:20:26 EDT 2006 diatoms/monitor/CallTreePerformance.class
  5506 Sat Jun 10 23:20:26 EDT 2006 diatoms/difference/RelationalDifferenceCreator.class
  4180 Sat Jun 10 23:20:26 EDT 2006 diatoms/difference/RelationalDifferenceCreator$Base.class
  1731 Sat Jun 10 23:20:26 EDT 2006 diatoms/difference/RelationalDifferenceCreator$NormalPrint.class
 46282 Sat Jun 10 23:20:26 EDT 2006 org/hsqldb/sample/FindFile.class
 36703 Sat Jun 10 23:20:26 EDT 2006 org/hsqldb/sample/TestFindFile.class
  3933 Sat Jun 10 23:20:26 EDT 2006 org/hsqldb/sample/DatabaseExport.class
  3070 Sat Jun 10 23:20:26 EDT 2006 org/hsqldb/sample/FindFileDatabaseCreator.class
  3666 Sat Jun 10 23:20:26 EDT 2006 org/hsqldb/sample/DatabaseDescription.class
  7965 Sat Jun 10 23:20:26 EDT 2006 org/hsqldb/jdbc/jdbcStatement.class
  4902 Sat Jun 10 23:20:26 EDT 2006 gradebook/AllTests.class
  3610 Sat Jun 10 23:20:26 EDT 2006 gradebook/DatabaseDescription.class
  4620 Sat Jun 10 23:20:26 EDT 2006 gradebook/GradeBookConstants.class
 37347 Sat Jun 10 23:20:26 EDT 2006 gradebook/GradeBookCreator.class
  2222 Sat Jun 10 23:20:26 EDT 2006 gradebook/GradeBookDataException.class
136008 Sat Jun 10 23:20:28 EDT 2006 gradebook/GradeBook.class
  7186 Sat Jun 10 23:20:28 EDT 2006 gradebook/TestBeforeAllTests.class
  5479 Sat Jun 10 23:20:28 EDT 2006 gradebook/TestGradeBookCreator.class
 16596 Sat Jun 10 23:20:28 EDT 2006 gradebook/TestGradeBookCreatorWithFullDataSet.class
 54515 Sat Jun 10 23:20:28 EDT 2006 gradebook/TestGradeBook.class
  2648 Sat Jun 10 23:20:28 EDT 2006 reminder/ReminderConstants.class
 22996 Sat Jun 10 23:20:28 EDT 2006 reminder/ReminderCreator.class
  2211 Sat Jun 10 23:20:28 EDT 2006 reminder/ReminderDataException.class
  7079 Sat Jun 10 23:20:28 EDT 2006 reminder/TestBeforeAllTests.class
 35618 Sat Jun 10 23:20:28 EDT 2006 reminder/Reminder.class
  5532 Sat Jun 10 23:20:28 EDT 2006 reminder/TestReminderCreator.class
 22889 Sat Jun 10 23:20:28 EDT 2006 reminder/TestReminder.class
  3603 Sat Jun 10 23:20:28 EDT 2006 reminder/DatabaseDescription.class
  4688 Sat Jun 10 23:20:28 EDT 2006 reminder/AllTests.class

[ ... the rest of the listing was removed, but I think that this should
  explain the structure of the JAR file. ]

This command executes the ajc script when I want to perform the dynamic
instrumentation.  If I understand correctly, AspectJ 1.2.1 did not 
support the -outxml flag and thus the following command only 
works with AspectJ 1.5.  The .lst file only contains:

MonitorTestCoverage.java
TraceMonitorTestCoverage.java
MonitorConfiguration.java

/usr/bin/time ajc @AllApplicationsTestCoverageMonitoringRuntime.lst -outxml -outjar TestCoverageMonitorRuntime.jar 

jar tvf TestCoverageMonitorRuntime.jar
     0 Thu Jun 15 15:01:26 EDT 2006 META-INF/
    44 Thu Jun 15 15:01:26 EDT 2006 META-INF/MANIFEST.MF
     0 Thu Jun 15 15:01:26 EDT 2006 META-INF/
    55 Thu Jun 15 15:01:26 EDT 2006 META-INF/MANIFEST.MF
   487 Thu Jun 15 15:01:26 EDT 2006 META-INF/aop.xml
     0 Thu Jun 15 15:01:26 EDT 2006 diatoms/
     0 Thu Jun 15 15:01:26 EDT 2006 diatoms/monitor/
 10002 Thu Jun 15 15:01:26 EDT 2006 diatoms/monitor/MonitorTestCoverage.class
 81493 Thu Jun 15 15:01:26 EDT 2006 diatoms/monitor/TraceMonitorTestCoverage.class
  7446 Thu Jun 15 15:01:26 EDT 2006 diatoms/monitor/MonitorConfiguration.class

These are the only files that are inside of this .jar file.  I then
decompress this archive and exchange the default aop.xml file for a
separate file that I wrote myself after consulting the AspectJ
load-time weaving documentation.  The aop.xml file looks like:

<aspectj>
<aspects>
<aspect name="diatoms.monitor.MonitorTestCoverage"/>
<aspect name="diatoms.monitor.TraceMonitorTestCoverage"/>
</aspects>
<weaver options="">
               <include within="org.hsqldb.sample.*"/>
               <include within="gradebook.*"/>
               <include within="com.runstate.pithy.*"/>
               <include within="reminder.*"/>
               <include within="student.*"/>
               <include within="TransactionAgent.*"/>
</weaver>
</aspectj>

My understanding of this file is that it will only apply the two
aspects to the union of the classes within the includes.  Is this
correct?

Now, at the point when a test suite is executed, and I want to perform
load-time weaving with the JVMTI-based approach I set the CLASSPATH to
contain the TestCoverageMonitorRuntime.jar and I also include this in
the ASPECTPATH.  The final script that actually executes the JVM looks
like (this is almost exactly the same as the one provided with
AspectJ, but I have changed the size of the maximum heap):

diatomsAj5_master:

if [ "$JAVA_HOME" = "" ] ; then JAVA_HOME=/usr/java/jdk1.5.0_04
fi
if [ "$ASPECTJ_HOME" = "" ] ; then ASPECTJ_HOME=/home/gkapfham/working/research/diatoms/tools/aspectj1.5
fi

echo $CLASSPATH
echo $ASPECTPATH

/usr/bin/time "$JAVA_HOME/bin/java" -classpath "$ASPECTJ_HOME/lib/aspectjweaver.jar:$CLASSPATH" "-javaagent:$ASPECTJ_HOME/lib/aspectjweaver.jar"  "-Xmx256m" "$@"

The above script is actually executed by another script which would 
make a call that looks like:

/home/gkapfham/working/research/diatoms/src/diatoms/monitor/diatomsAj5_master 
-Ddiatoms.monitor.configure=<some configuration file> 
-Daj.weaving.verbose=true <name of the case study application test suite>

In the end, this would produce output that shows me that the aop.xml
file is being found and then clearly explain that only the classes that 
I have specified are indeed being instrumented.  The only "info weaving"
messages that are produced are those that follow:

info AspectJ Weaver Version 1.5.0 built on Tuesday Dec 20, 2005 at 12:05:54 GMT
info register classloader sun.misc.Launcher$AppClassLoader@26099296
info using file:/home/gkapfham/working/research/diatoms/src/diatoms/monitor/TestCoverageMonitorRuntime.jar!/META-INF/aop.xml
info register aspect diatoms.monitor.MonitorTestCoverage
info register aspect diatoms.monitor.TraceMonitorTestCoverage
info weaving 'org/hsqldb/sample/TestFindFile'
.info weaving 'org/hsqldb/sample/DatabaseDescription'
info weaving 'org/hsqldb/sample/FindFile'

Alternatively, I can execute the test suite with a script that
performs the load-time weaving with the classloader mechanism.  This
script looks like.  This is again very similar to the one that is
provided with AspectJ.  This current version would work correctly for
ApsectJ 1.5, but not work for AspectJ 1.2.1 because the older version
uses org.aspectj.weaver.WeavingURLClassLoader and not the
org.aspectj.weaver.loadtime.WeavingURLClassLoader.

if [ "$JAVA_HOME" = "" ] ; then JAVA_HOME=/usr/java/jdk1.5.0_04
fi
if [ "$ASPECTJ_HOME" = "" ] ; then ASPECTJ_HOME=/home/gkapfham/working/research/diatoms/tools/aspectj1.5
fi

ASPECTPATH=/home/gkapfham/working/research/diatoms/src/diatoms/monitor/TestCoverageMonitorRuntime.jar

echo "$ASPECTJ_HOME/lib/aspectjweaver.jar:$CLASSPATH"

/usr/bin/time "$JAVA_HOME/bin/java" -classpath "$ASPECTJ_HOME/lib/aspectjweaver.jar" "-Djava.system.class.loader=org.aspectj.weaver.loadtime.WeavingURLClassLoader" "-Daj.class.path=$ASPECTPATH:$CLASSPATH" "-Daj.aspect.path=$ASPECTPATH" "-Xmx256m" "$@"

The above script would be executed by another script and the call looks 
like the following:

/home/gkapfham/working/research/diatoms/src/diatoms/monitor/diatomsAj_master 
-Ddiatoms.monitor.configure=<some configuration file> 
-Daj.weaving.verbose=true <name of the application test suite>

When this is executed I produce output that contains many XLint messages 
and there is no indication that the aop.xml file was actually detected.
This is a sampling of the output:

info adding aspect library: '/home/gkapfham/working/research/diatoms/src/diatom\s/monitor/TestCoverageMonitorRuntime.jar'
info weaving 'org.hsqldb.sample.TestFindFile'
warning at /home/gkapfham/working/research/diatoms/src/diatoms/monitor/TraceMon\itorTestCoverage.java:531::0 advice defined in diatoms.monitor.TraceMonitorTest\Coverage has not been applied [Xlint:adviceDidNotMatch]
warning at /home/gkapfham/working/research/diatoms/src/diatoms/monitor/TraceMon\itorTestCoverage.java:612::0 advice defined in diatoms.monitor.TraceMonitorTest\Coverage has not been applied [Xlint:adviceDidNotMatch] warning at /home/gkapfham/working/research/diatoms/src/diatoms/monitor/TraceMon\itorTestCoverage.java:1187::0 advice defined in diatoms.monitor.TraceMonitorTes\tCoverage has not been applied [Xlint:adviceDidNotMatch]
warning at /home/gkapfham/working/research/diatoms/src/diatoms/monitor/TraceMon\itorTestCoverage.java:1755::0 advice defined in diatoms.monitor.TraceMonitorTes\tCoverage has not been applied [Xlint:adviceDidNotMatch]
info weaving 'org.dbunit.DatabaseTestCase'

Note that org.dbunit.DatabaseTestCase is not an example of a file that
was included by the aop.xml file.  I have also tried several things to
remove the Xlint messages but I was never able to do so.

> I would caution the use of  "<include within..." and "<exlude within..." 
> as a general programming model, it was never intended to be used for that 
> and can actually make your programs harder to understand. They were 
> intended to be used by non-programmers managing complex systems comprising 
> code from multiple sources as a way of dealing with potential problems. If 
> you don't intend to weave a class or package then write a pointcut. I know 
> you are not using Eclipse but at least you will get some feedback from the 
> compiler in terms of where an aspect is taking affect rather than waiting 
> until you run your program. If your were using Eclipse and AJDT then you 
> could have immediate knowledge.

I think that I can learn something here.  I would certainly be willing
to _not_ use the aop.xml file and instead write a more refined
pointcut.  I wrote my pointcut in the following fashion:

   pointcut myClass(): (within(gradebook.*) ||  
	within(org.hsqldb.sample.*) || within(reminder.*) ||
	within(com.runstate.pithy.*) || within(student.*) || 
	within(TransactionAgent.*)); 

The superaspect MonitorTestCoverage also contains a pointcut that
essentially look like:

    pointcut myMethod(): myClass() && execution(* *(..));
 
Later inside of the TraceMonitorTestCoverage.java file I also include
before, after, and around advice that essentially look like:

    before(): myMethod() && if(monitorEnabled)  
	{

	    if( tree.getRoot() == null )
		{

		    tree.callTo("mainMethodPreserveContext");

		}

	    tree.callTo(thisJoinPointStaticPart.getSignature().
 			toString() + " " + 
			thisJoinPointStaticPart.getSourceLocation());

	}

or 

    Statement around(): databaseCreateStatement()  
	{

		[... complicated code excluded ...]

       }

where the superaspect has already declared:

    pointcut databaseCreateStatement(): myClass() && 
	call(Statement createStatement()); 

Please let me know how I can improve these aspects to ensure that they
only apply to the classes specified in the myClass() during load-time
weaving.  (I'll provide more details about performance in a later
email, if time permits).

Thank you for your assistance!  I know that this is a very long email
message with many details to digest.  I hope that I have included
enough details to help you to better understand the problem.  I am
certainly not an AspectJ expert so it is likely that I have made some
mistakes along the way.

Kind Regards,

greg

-- 
Gregory M. Kapfhammer, Instructor
Department of Computer Science 
Allegheny College
Office: 814-332-2880
gkapfham(at)allegheny(dot)edu
http://cs.allegheny.edu/~gkapfham/