| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> |
| <html> <head> |
| <title>AspectJ 1.1 Readme</title> |
| <style type="text/css"> |
| <!-- |
| P { margin-left: 20px; } |
| PRE { margin-left: 20px; } |
| LI { margin-left: 20px; } |
| H4 { margin-left: 20px; } |
| H3 { margin-left: 10px; } |
| --> |
| </style> |
| </head> |
| |
| <body> |
| <div align="right"><small> |
| © Copyright 2002 Palo Alto Research Center, Incorporated, |
| 2003 Contributors. |
| All rights reserved. |
| </small></div> |
| |
| |
| <h1>AspectJ 1.1 Readme</h1> |
| |
| <p> This is the initial release of AspectJ 1.1. It includes a small |
| number of new language features as well as major improvements to the |
| functionality of the tools. </p> |
| |
| <p> |
| This document describes the differences between |
| AspectJ versions 1.1 and 1.0.6. |
| Users new to AspectJ need only read |
| the <a href="progguide/index.html">AspectJ Programming Guide</a> |
| since it describes the 1.1 language. |
| Users familiar with AspectJ 1.0 may find this document |
| a quicker way to learn what changed in the language |
| and tools, and should use it as a guide for porting |
| programs from 1.0 to 1.1. |
| </p> |
| |
| <p>This document first summarizes changes from the 1.0 release in |
| </p> |
| |
| <ul> |
| <li><a href="#language">the language</a>,</li> |
| <li><a href="#compiler">the compiler</a>,</li> |
| <li><a href="#tools">the support tools</a>,</li> |
| <li><a href="#runtime">the runtime</a>,</li> |
| <li><a href="#devenv">the development environment support</a>,</li> |
| <li><a href="#sources">the sources</a>, and</li> |
| <li><a href="#distribution">the distribution</a>,</li> |
| </ul> |
| |
| <p> then <a href="#details">details</a> some of the language |
| and compiler changes, |
| and finally points readers to the bug database for any |
| <a href="#knownLimitations">known limitations</a>. |
| </p> |
| |
| <!-- ============================== --> |
| <hr> |
| <h2><a name="language">The Language</a></h2> |
| |
| <p> AspectJ 1.1 is a slightly different language than AspectJ 1.0. |
| In all but a few cases, programs written in AspectJ 1.0 should |
| compile correctly in AspectJ 1.1. In many cases, there are |
| new or preferred forms in AspectJ 1.1. However, some AspectJ 1.0 |
| features have changed in 1.1, so some 1.0 programs |
| will not compile or will run differently in 1.1. |
| The corresponding features are marked below as compile-time |
| or run-time incompatible (<em>CTI</em> or <em>RTI</em>, respectively). |
| When the language change involves a move in the static shadow effective |
| at run-time but also apparent at compile-time (e.g., in declare |
| error or warning statements), it is marked <em>CRTI</em>. |
| Programs using run-time incompatible forms should be verified that |
| they are behaving as expected in 1.1. |
| </p> |
| |
| <p> |
| Most changes to the language are additions to expressibility |
| requested by our users: |
| </p> |
| |
| <ul> |
| <li><a href="#THROWS_PATTERN">Matching based on throws</a>: You can |
| now make finer discriminations between methods based on declared |
| exceptions. </li> |
| |
| <li><a href="#NEW_PCDS">New kinded pointcut designators</a>: Now |
| every kind of join point has a corresponding kinded pointcut |
| designator. </li> |
| </ul> |
| |
| <p> Some are have different behavior in edge cases but offer |
| improved power and clarity: </p> |
| |
| <ul> |
| <li><a href="#ASPECT_PRECEDENCE">New aspect precedence form</a>: |
| AspectJ 1.1 has a new declare form, <code>declare |
| precedence</code>, that replaces the "dominates" |
| clause on aspects. (<em>CTI</em>) </li> |
| |
| <li>The order of <a href="#SUPER_IFACE_INITS">initialization join |
| points for super-interfaces</a> has been clarified. (<em>RTI</em>) </li> |
| </ul> |
| |
| <p> But in order to support weaving into bytecode effectively, |
| several incompatible changes had to be made to the language: </p> |
| |
| <ul> |
| <li>A class's default constructor may |
| <a href="#DEFAULT_CONSTRUCTOR_CONFLICT">conflict</a> with an |
| inter-type constructor. (<em>CTI</em>) </li> |
| |
| <li><a href="#NO_CALLEE_SIDE_CALL">No callee-side call join |
| points</a>: The AspectJ 1.1 compiler does not expose call join |
| points unless it is given the calling code. (<em>CRTI</em>) </li> |
| |
| <li><a href="#SINGLE_INTERCLASS_TARGET">One target for intertype |
| declarations</a>. (<em>CTI</em>) </li> |
| |
| <li><a href="#UNAVAILABLE_JOIN_POINTS">No initializer execution join |
| points</a>. (<em>RTI</em>)</li> |
| |
| <li><a href="#AFTER_HANDLER">No after or around advice on handler |
| join points</a>. (<em>CTI</em>) </li> |
| |
| <li><a href="#CONSTRUCTOR_EXECUTION_IS_BIGGER">Initializers run |
| inside constructor execution join points</a>. (<em>RTI</em>)</li> |
| |
| <li><a href="#INTER_TYPE_FIELD_INITIALIZERS">inter-type field |
| initializers</a> run before class-local field initializers. (<em>RTI</em>) </li> |
| |
| <li><a href="#WITHIN_MEMBER_TYPES">Small limitations of the within |
| pointcut.</a> (<em>CRTI</em>)</li> |
| |
| <li><a href="#WITHIN_CODE">Small limitations of the withincode |
| pointcut.</a> (<em>CRTI</em>)</li> |
| |
| <li><a href="#INSTANCEOF_ON_WILD">Can't do instanceof matching on |
| type patterns with wildcards</a>. (<em>CTI</em>) </li> |
| |
| <li><a href="#NO_SOURCE_COLUMN">SourceLocation.getColumn() is |
| deprecated and will always return 0</a>. (<em>RTI</em>) </li> |
| |
| <li>The interaction between aspect instantiation and advice has been |
| <a href="#ASPECT_INSTANTIATION_AND_ADVICE">clarified</a>. (<em>RTI</em>) </li> |
| |
| <li><a href="#STRINGBUFFER">The String + operator is now correctly advised</a>. |
| (<em>CRTI</em>) </li> |
| </ul> |
| |
| <p><a name="NEW_LIMITATIONS">There</a> are a couple of language |
| limitations for things that are rarely used that make the |
| implementation simpler, so we have restricted the language accordingly. |
| </p> |
| |
| <ul> |
| <li><a href="#VOID_FIELD_SET">Field set join points now have a |
| <code>void</code> return type.</a> This will require |
| porting of code that uses the <code>set</code> PCD in conjunction |
| with after-returning or around advice. (<em>CTI</em>) <p></p></li> |
| |
| <li>'declare soft: TYPE: POINTCUT;' - AspectJ 1.1 only |
| accepts TYPE rather than a TYPE_PATTERN. |
| This limitation makes declare soft |
| much easier to implement efficiently. (<em>CTI</em>) <p></p></li> |
| |
| <li>Inter-type field declarations only allow a single field per |
| line, i.e. this is now illegal 'int C.field1, D.field2;' This must |
| instead be, 'int C.field1; int D.field2;' (<em>CTI</em>) <p></p></li> |
| |
| <li>We did not implement the handling of more than one |
| <code>..</code> wildcard in args PCD's (rarely encountered in the |
| wild) because we didn't have the time. This might be available |
| in later releases if there is significant outcry. (<em>CTI</em>) </li> |
| |
| </ul> |
| |
| <p>We did not implement the long-awaited <a href="#PER_TYPE">new |
| pertype aspect specifier</a> in this release, but it may well |
| be in a future release.</p> |
| |
| |
| <!-- ============================== --> |
| <hr> |
| <h2><a name="compiler">The Compiler</a></h2> |
| |
| <p> The compiler for AspectJ 1.1 is different than the compiler for |
| AspectJ 1.0. While this document describes the differences in the |
| compiler, it's worthwhile noting that much effort has been made to |
| make sure that the interface to ajc 1.1 is, as much as possible, the |
| same as the interface to ajc 1.0. There are two important changes |
| under the hood, however. </p> |
| |
| <p> First, the 1.1 compiler is implemented on top of the |
| open-source Eclipse compiler. This has two benefits: It allows us |
| to concentrate on the AspectJ extensions to Java and let the Eclipse |
| team worry about making sure the Java edge cases work, and it allows |
| us to piggyback on Eclipse's already mature incremental compilation |
| facilities. </p> |
| |
| <p> Second, ajc now cleanly delineates compilation of source code |
| from assembly (or "weaving") of bytecode. The compiler still |
| accepts source code, but internally it transforms it into bytecode |
| format before weaving. </p> |
| |
| <p> This new architecture, and other changes to the compiler, allows |
| us to implement some features that were defined in the AspectJ 1.0 |
| language but not implementable in the 1.1 compiler. It also makes |
| some new features available: </p> |
| |
| <ul> |
| <li><a href="#SOURCEROOT">The -sourceroots option</a> |
| takes one or more directories, and indicates that all the source |
| files in those directories should be passed to the compiler. </li> |
| |
| <li><a href="#BYTECODE_WEAVING">The -injars option</a> |
| takes one or more jar files, and indicates that all the classfiles |
| in the jar files should be woven into. </li> |
| |
| <li><a href="#BINARY_ASPECTS">The -aspectpath option</a> |
| takes one or more jar files, and weaves any aspects in .class form |
| into the sources.</li> |
| |
| <li><a href="#OUTJAR">The -outjar option</a> indicates |
| that the result classfiles of compiling and weaving should be placed |
| in the specified jar file. </li> |
| |
| <li><a href="#XLINT">The -Xlint option</a> allows control over |
| warnings.</li> |
| |
| <li><a href="#OTHER_X_OPTIONS">Various -X options</a> changed.</li> |
| |
| <li><a href="#INCREMENTAL">The -incremental option</a> tells the |
| AspectJ 1.1 compiler to recompile only as necessary. </li> |
| </ul> |
| |
| <p> Some other features we wanted to support for 1.1, but did not make |
| it into this release: </p> |
| |
| <ul> |
| <li><a href="#ERROR_MESSAGES">Error messages will sometimes be scary</a></li> |
| <li><a href="#MESSAGE_CONTEXT">Source code context is not shown |
| for errors and warnings detected during bytecode weaving</a></li> |
| </ul> |
| |
| <p> But some features of the 1.0 compiler are not supported in the |
| 1.1 compiler: </p> |
| |
| <ul> |
| <li><a href="#NO_SOURCE">The source-related options</a> -preprocess, |
| -usejavac, -nocomment and -workingdir</li> |
| |
| <li><a href="#NO_STRICT_LENIENT">The -strict and -lenient options</a> |
| </li> |
| |
| <li><a href="#NO_PORTING">The -porting option</a></li> |
| |
| <li><a href="#13_REQUIRED">J2SE 1.2 is not supported; |
| J2SE 1.3 or later is required.</a></li> |
| </ul> |
| |
| <p> A short description of the options ajc accepts is available with |
| "<code>ajc -help</code>". |
| Longer descriptions are available in the |
| <a href="devguide/ajc-ref.html">Development Environment Guide |
| section on ajc</a>. </p> |
| <p> </p> |
| |
| |
| <p> Some changes to the implementation are almost entirely |
| internal: |
| </p> |
| |
| <ul> |
| <li>The behavior of the compiler in |
| <a href="#TARGET_TYPES_MADE_PUBLIC">lifting the visibility</a> of |
| the target types of some declares and pointcuts to public has been |
| clarified. </li> |
| </ul> |
| |
| <p> Also, it is worth noting that because AspectJ now works on bytecode, |
| it is somewhat sensitive to how different compilers generate |
| bytecode, especially when compiling with and without <a |
| href="#ONE_FOUR_METHOD_SIGNATURES">the -1.4 flag</a>. </p> |
| |
| |
| |
| <!-- ============================== --> |
| <hr> |
| <h2><a name="tools">Support Tools</a></h2> |
| |
| <p>This release includes an Ant task for old-style 1.0 build |
| scripts, a new task for all the new compiler options, and a |
| CompilerAdapter to support running <code>ajc</code> with the Javac |
| task by setting the <code>build.compiler</code> property. |
| The new task can automatically copy input resources to output |
| and work in incremental mode using a "tag" file. |
| </p> |
| |
| <p>This release does not include <code>ajdoc</code>, the |
| documentation tool for AspectJ sources. |
| Ajdoc is deeply dependent on the |
| abstract syntax tree classes from the old compiler, so it needs a |
| bottom-up rewrite. We think it best to use this opportunity to |
| implement more general API's for publishing and rendering static |
| structure. Because those API's are last to settle in the new |
| architecture, and because the compiler itself is a higher priority, |
| we are delaying work on ajdoc until after the 1.1 release.</p> |
| |
| <p>AspectJ 1.1 will not include <tt>ajdb</tt>, the AspectJ |
| stand-alone debugger. It is no longer necessary for two reasons. |
| First, the -XnoInline flag will tell the compiler to generate |
| code without inlining that should work correctly with any Java |
| debugger. For code generated with inlining enabled, more |
| third-party debuggers are starting to work according to JSR 45, |
| "Debugging support for other languages," which is supported by |
| AspectJ 1.0. We aim to support JSR-45 in AspectJ 1.1, but |
| support will not be in the initial release. Consider using |
| the -XnoInline flag until support is available.</p> |
| |
| <!-- ============================== --> |
| <hr> |
| <h2><a name="runtime">The Runtime Library</a></h2> |
| |
| <p>This release has minor additions to the runtime library classes. |
| As with any release, you should compile and run with the runtime |
| library that came with your compiler, and you may run with |
| a later version of the library without recompiling your code.</p> |
| |
| <p> In one instance, however, runtime classes behave differently this release. |
| Because the AspectJ 1.1 compiler does its weaving through |
| bytecode, column numbers of source locations are not available. |
| Therefore, <code>thisJoinPoint.getSourceLocation().getColumn()</code> |
| is deprecated and will always return 0. </p> |
| |
| <!-- ============================== --> |
| <hr> |
| <h2><a name="devenv">The AJDE Tools</a></h2> |
| |
| <p> The AspectJ Browser supports incremental compilation and running |
| programs. AJDE for JBuilder, AJDE for NetBeans, and AJDE for Emacs |
| are now independent SourceForge projects (to keep their licenses). |
| They use the batch-build mode of the new compiler. |
| </p> |
| |
| <!-- ============================== --> |
| <hr> |
| <h2><a name="sources">The Sources and the Licenses</a></h2> |
| |
| <p> The AspectJ tools sources are available under the |
| <a href="http://eclipse.org/legal/cpl-v10.html">Common Public |
| License</a> in the CVS repository |
| at <a href="http://eclipse.org/aspectj">http://eclipse.org/aspectj</a>. |
| For more information, see the FAQ entry on |
| <a href="faq.html#q:buildingsource">building sources</a>. |
| </p> |
| |
| |
| <!-- ============================== --> |
| <hr> |
| <h2><a name="distribution">The AspectJ distribution</a></h2> |
| |
| <p> AspectJ 1.0 had many distributions - for the tools, |
| the documentation, each IDE support package, |
| their respective sources, and the Ant tasks - |
| because they came under different licenses. |
| All of AspectJ 1.1 is licensed under the CPL 1.0, |
| so the tools, Ant tasks, and documentation are all |
| in one distribution available from |
| <a href="http://eclipse.org/aspectj"> |
| http://eclipse.org/aspectj</a>. |
| To retain their MPL 1.1 license, |
| Ajde for |
| <a href="http://aspectj4emacs.sourceforge.net/">Emacs</a>, |
| <a href="http://aspectj4netbean.sourceforge.net/">NetBeans</a> and |
| <a href="http://aspectj4jbuildr.sourceforge.net/">JBuilder</a> |
| are now independent SourceForge projects. </p> |
| |
| </p> |
| |
| |
| <!-- ============================== --> |
| <hr> |
| <hr> |
| <h2><a name="details">Details</a> of some language and compiler changes</h2> |
| |
| <h3><a name="ASPECT_INSTANTIATION_AND_ADVICE">Aspect Instantiation |
| and Advice</a></h3> |
| |
| <p> 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: |
| </p> |
| |
| <PRE> |
| 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"); |
| } |
| } |
| </PRE> |
| |
| <p> 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...</p> |
| |
| <p> 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: |
| </p> |
| |
| <PRE> |
| 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"); |
| } |
| } |
| </PRE> |
| |
| <p>This program would throw a NullPointerException when run, since |
| Client.foo() was called before the Watchcall instance could be |
| instantiated. </p> |
| |
| <p> 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. |
| </p> |
| |
| <h3><a name="THROWS_PATTERN">Matching based on throws</a></h3> |
| |
| <p> Type patterns may now be used to pick out methods and |
| constructors based on their throws clauses. This allows the |
| following two kinds of extremely wildcarded pointcuts: </p> |
| |
| <pre> pointcut throwsMathlike(): |
| // each call to a method with a throws clause containing at least |
| // one exception with "Math" in its name. |
| call(* *(..) throws *..*Math*); |
| |
| pointcut doesNotThrowMathlike(): |
| // each call to a method with a throws clause containing no |
| // exceptions with "Math" in its name. |
| call(* *(..) throws !*..*Math*); |
| </pre> |
| |
| <p> The longwinded rules are that a method or constructor pattern |
| can have a "throws clause pattern". Throws clause patterns look |
| like: </p> |
| |
| <pre> ThrowsClausePattern: |
| ThrowsClausePatternItem ("," ThrowsClausePatternItem)* |
| |
| ThrowsClausePatternItem: |
| ["!"] TypeNamePattern |
| </pre> |
| |
| <p> A ThrowsClausePattern matches the ThrowsClause of any code |
| member signature. To match, each ThrowsClausePatternItem must |
| match the throws clause of the member in question. If any item |
| doesn't match, then the whole pattern doesn't match. This rule is |
| unchanged from AspectJ 1.0. </p> |
| |
| <p> If a ThrowsClausePatternItem begins with "!", then it matches |
| a particular throws clause if and only if <em>none</em> of the |
| types named in the throws clause is matched by the |
| TypeNamePattern. </p> |
| |
| <p> If a ThrowsClausePatternItem does not begin with "!", then it |
| matches a throws clause if and only if <em>any</em> of the types |
| named in the throws clause is matched by the TypeNamePattern.</p> |
| |
| <p> These rules are completely backwards compatible with |
| AspectJ 1.0. The rule for "!" matching has one potentially |
| surprising property, in that the two PCD's shown below will have |
| different matching rules. </p> |
| |
| <pre> [1] call(* *(..) throws !IOException) |
| [2] call(* *(..) throws (!IOException)) |
| |
| void m() throws RuntimeException, IOException {} |
| </pre> |
| |
| <p> [1] will NOT match the method m(), because method m's throws |
| clause declares that it throws IOException. [2] WILL match the |
| method m(), because method m's throws clause declares the it |
| throws some exception which does not match IOException, |
| i.e. RuntimeException. </p> |
| |
| <h3><a name="NEW_PCDS">New kinded pointcut designators</a></h3> |
| |
| <p> AspectJ 1.0 does not provide kinded pointcut designators for |
| two (rarely used) join points: preinitialization (the code that |
| runs before a super constructor call is made) and advice |
| execution. AspectJ 1.1 does not change the meaning of the join |
| points, but provides two new pointcut designators to pick out |
| these join points, thus making join points and pointcut |
| designators more parallel. </p> |
| |
| <p> <code>adviceexectuion()</code> will pick out advice execution |
| join points. You will usually want to use <code>adviceexecution() |
| && within(Aspect)</code> to restrict it to only those pieces of |
| advice defined in a particular aspect. <br> |
| <code>preinitialization(<var>ConstructorPattern</var>)</code> will |
| pick out pre-initialization join points where the initialization |
| process is entered through |
| <code><var>ConstructorPattern</var></code>. </p> |
| |
| <h3><a name="PER_TYPE">New pertype aspect specifier</a> (not in 1.1)</h3> |
| |
| <p>We strongly considered adding a pertype aspect kind to 1.1. |
| This is somewhat motivated by the new |
| <a href="#SINGLE_INTERCLASS_TARGET">restrictions on inter-type |
| declarations<a>. This is also motivated by many previous request |
| to support a common logging idiom. Here's what pertype would look |
| like:</p> |
| |
| <pre> /** One instance of this aspect will be created for each class, |
| * interface or aspect in the com.bigboxco packages. |
| */ |
| aspect Logger pertype(com.bigboxco..*) { |
| /* This field holds a logger for the class. */ |
| Log log; |
| |
| /* This advice will run for every public execution defined by |
| * a type for which a Logger aspect has been created, i.e. |
| * any type in com.bigboxco..* |
| */ |
| before(): execution(public * *(..)) { |
| log.enterMethod(thisJoinPoint.getSignature().getName()); |
| } |
| |
| /* We can use a special constructor to initialize the log field */ |
| public Logger(Class myType) { |
| this.log = new Log(myType); |
| } |
| } |
| |
| /** External code could use aspectOf to get at the log, i.e. */ |
| Log l = Logger.aspectOf(com.bigboxco.Foo.class).log; |
| </pre> |
| |
| <p>The one open question that we see is how this should interact |
| with inner types. If a pertype aspect is created for an outer |
| type should advice in that aspect run for join points in inner |
| types? That is the behavior of the most common uses of this |
| idiom. </p> |
| |
| <p> In any case, this feature will not be in AspectJ 1.1. |
| </p> |
| |
| <h3><a name="SINGLE_INTERCLASS_TARGET">One target for intertype |
| declarations</a></h3> |
| |
| <p> Intertype declarations (once called "introductions") in |
| AspectJ 1.1 can only have one target type. So the following code |
| intended to declare that there is a void doStuff() method on all |
| subtypes of Target is not legal AspectJ 1.1 code. |
| </p> |
| |
| <pre> aspect A { |
| public void Target+.doStuff() { ... } |
| } |
| </pre> |
| |
| <p> The functionality of "multi-intertype declarations" can be |
| recovered by using a helper interface. |
| </p> |
| |
| <pre> aspect A { |
| private interface MyTarget {} |
| declare parents: Target+ implements MyTarget; |
| public void MyTarget.doStuff() { ... } |
| } |
| </pre> |
| |
| <p> We believe this is better style in AspectJ 1.0 as well, as it |
| makes clear the static type of "this" inside the method body. |
| </p> |
| |
| <p> The one piece of functionality that can not be easily |
| recovered is the ability to add static fields to many classes. We |
| believe that the <a href="#PER_TYPE">pertype proposal</a> provides |
| this functionality in a much more usable form.</p> |
| |
| <h3><a name="UNAVAILABLE_JOIN_POINTS">No initializer execution join |
| points</a></h3> |
| |
| <p> AspectJ 1.1 does not consider initializer execution a |
| principled join point. The collection of initializer code (the |
| code that sets fields with initializers and the code in non-static |
| initializer blocks) is something that makes sense only in Java |
| source code, not in Java bytecode. </p> |
| |
| <h3><a name="AFTER_HANDLER"></a>No after or around advice on handler |
| join points</h3> |
| |
| <p> The end of an exception handler is underdetermined in bytecode, |
| so ajc will not implement after or around advice on handler join |
| points, instead signaling a compile-time error.</p> |
| |
| <h3><a name="CONSTRUCTOR_EXECUTION_IS_BIGGER">Initializers run |
| inside constructor execution join points</a></h3> |
| |
| <p> The code generated by the initializers in Java source code now |
| runs inside of constructor execution join points. This changes |
| how before advice runs on constructor execution join points. |
| Consider: </p> |
| |
| <pre> class C { |
| C() { } |
| String id = "identifier"; // this assignment |
| // has to happen sometime |
| } |
| aspect A { |
| before(C c) this(c) && execution(C.new()) { |
| System.out.println(c.id.length()); |
| } |
| } |
| </pre> |
| |
| <p> In AspectJ 1.0, this will print "10", since id is assigned its |
| initial value prior to the before advice's execution. However, in |
| AspectJ 1.1, this will throw a NullPointerExcception, since "id" |
| does not have a value prior to the before advice's execution. |
| </p> |
| |
| <p> Note that the various flavors of after returning advice are |
| unchanged in this respect in AspectJ 1.1. Also note that this |
| only matters for the execution of constructors that call a |
| super-constructor. Execution of constructors that call a |
| this-constructor are the same in AspectJ 1.1 as in AspectJ 1.0. |
| </p> |
| |
| <p> We believe this difference should be minimal to real programs, |
| since programmers using before advice on constructor execution |
| must always assume incomplete object initialization, since the |
| constructor has not yet run. </p> |
| |
| <h3><a name="INTER_TYPE_FIELD_INITIALIZERS">Inter-type field initializers</a></h3> |
| |
| <p> The initializer, if any, of an inter-type field definition runs |
| before the class-local initializers of its target class. </p> |
| |
| <p> In AspectJ 1.0.6, such an initializer would run after the |
| initializers of a class but before the execution of any of its |
| constructor bodies. As already discussed in the sections about |
| <a href="#UNAVAILABLE_JOIN_POINTS">initializer execution join |
| points</a> and <a href="#CONSTRUCTOR_EXECUTION_IS_BIGGER">constructor |
| execution</a>, the point in code between the initializers of a class |
| and its constructor body is not principled in bytecode. So we had a |
| choice of running the initializer of an inter-type field definition at |
| the beginning of initialization (i.e., before initializers from |
| the target class) or at the end (i.e., just before its called |
| constructor exits). We chose the former, having this pattern in mind: |
| </p> |
| |
| <PRE> |
| int C.methodCount = 0; |
| before(C c): this(c) && execution(* *(..)) { c.methodCount++; } |
| </PRE> |
| |
| <p> We felt there would be too much surprise if a constructor called a |
| method (thus incrementing the method count) and then the field was |
| reset to zero after the constructor was done. |
| </p> |
| |
| <h3><a name="WITHIN_MEMBER_TYPES">Small limitations of the within |
| pointcut</a></h3> |
| |
| <p>Because of the guarantees made (and not made) by the Java |
| classfile format, there are cases where AspectJ 1.1 cannot |
| guarantee that the within pointcut designator will pick out all |
| code that was originally within the source code of a certain |
| type. |
| </p> |
| |
| <p> The non-guarantee applies to code inside of anonymous and |
| local types inside member types. While the within pointcut |
| designator behaves exactly as it did in AspectJ 1.0 when given a |
| package-level type (like C, below), if given a member-type (like |
| C.InsideC, below), it is not guaranteed to capture code in |
| contained local and anonymous types. For example: </p> |
| |
| <pre> class C { |
| Thread t; |
| class InsideC { |
| void setupOuterThread() { |
| t = new Thread( |
| new Runnable() { |
| public void run() { |
| // join points with code here |
| // might not be captured by |
| // within(C.InsideC), but are |
| // captured by within(C) |
| System.out.println("hi"); |
| } |
| }); |
| } |
| } |
| } |
| </pre> |
| |
| <p> We believe the non-guarantee is small, and we haven't verified |
| that it is a problem in practice. </p> |
| |
| <h3><a name="WITHIN_CODE">Small limitations of the withincode |
| pointcut</a></h3> |
| |
| <p>The withincode pointcut has similar issues to those described |
| above for within. |
| </p> |
| |
| <h3><a name="INSTANCEOF_ON_WILD">Can't do instanceof matching on |
| type patterns with wildcard</a></h3> |
| |
| <p>The pointcut designators this, target and args specify a |
| dynamic test on their argument. These tests can not be performed |
| on type patterns with wildcards in them. The following code that |
| compiled under 1.0 will be an error in AspectJ-1.1:</p> |
| |
| <pre> pointcut oneOfMine(): this(com.bigboxco..*); |
| </pre> |
| |
| <p>The only way to implement this kind of matching in a modular |
| way would be to use the reflection API at runtime on the Class of |
| the object. This would have a very high performance cost and |
| possible security issues. There are two good work-arounds. If |
| you control the source or bytecode to the type you want to match |
| then you can use declare parents, i.e.:</p> |
| |
| <pre> private interface OneOfMine {} |
| declare parents: com.bigboxco..* implements OneOfMine; |
| pointcut oneOfMine(): this(OneOfMine); |
| </pre> |
| |
| <p>If you want the more dynamic matching and are willing to pay |
| for the performance, then you should use the Java reflection API |
| combined with if. That would look something like:</p> |
| |
| <pre> pointcut oneOfMine(): this(Object) && |
| if(classMatches("com.bigboxco..*", |
| thisJoinPoint.getTarget().getClass())); |
| |
| static boolean classMatches(String pattern, Class _class) { |
| if (patternMatches(pattern, _class.getName())) return true; |
| ... |
| } |
| </pre> |
| |
| <p>Note: wildcard type matching still works in all other PCD's that |
| match based on static types. So, you can use |
| 'within(com.bigboxco..*+)' to match any code lexically within one |
| of your classes or a subtype thereof. This is often a good |
| choice.</p> |
| </p> |
| |
| |
| <h3><a name="NO_SOURCE_COLUMN">SourceLocation.getColumn()</a></h3> |
| |
| <p>The Java .class file format contains information about the |
| source file and line numbers of its contents; however, it has no |
| information about source columns. As a result, we can not |
| effectively support the access of column information in the |
| reflection API. So, any calls to |
| thisJoinPoint.getSourceLocation().getColumn() will be marked as |
| deprecated by the compiler, and will always return 0.</p> |
| |
| <h3><a name="ASPECT_PRECEDENCE">Aspect precedence</a></h3> |
| |
| <p> AspectJ 1.1 has a new declare form: |
| </p> |
| |
| <pre> declare precedence ":" TypePatternList ";" |
| </pre> |
| |
| <p> This is used to declare advice ordering constraints on join |
| points. For example, the constraints that (1) aspects that have |
| Security as part of their name should dominate all other aspects, and |
| (2) the Logging aspect (and any aspect that extends it) should |
| dominate all non-security aspects, can be expressed by: </p> |
| |
| <pre> declare precedence: *..*Security*, Logging+, *; |
| </pre> |
| |
| <p> In the TypePatternList, the wildcard * means "any type not matched |
| by another type in the declare precedence". </p> |
| |
| <h4>Various cycles</h4> |
| |
| <p> It is an error for any aspect to be matched by more than one |
| TypePattern in a single declare precedence, so: </p> |
| |
| <pre> declare precedence: A, B, A ; // error |
| </pre> |
| |
| <p> However, multiple declare precedence forms may legally have this |
| kind of circularity. For example, each of these declare precedence is |
| perfectly legal: |
| </p> |
| |
| <pre> declare precedence: B, A; |
| declare precedence: A, B; |
| </pre> |
| |
| <p> And a system in which both constraints are active may also be |
| legal, so long as advice from A and B don't share a join point. So |
| this is an idiom that can be used to enforce that A and B are strongly |
| independent. </p> |
| |
| <h4>Applies to concrete aspects</h4> |
| |
| <p> Consider the following library aspects: |
| </p> |
| |
| <pre> abstract aspect Logging { |
| abstract pointcut logged(); |
| |
| before(): logged() { |
| System.err.println("thisJoinPoint: " + thisJoinPoint); |
| } |
| } |
| |
| aspect MyProfiling { |
| abstract pointcut profiled(); |
| |
| Object around(): profiled() { |
| long beforeTime = System.currentTimeMillis(); |
| try { |
| return proceed(); |
| } finally { |
| long afterTime = System.currentTimeMillis(); |
| addToProfile(thisJoinPointStaticPart, |
| afterTime - beforeTime); |
| } |
| } |
| abstract void addToProfile( |
| org.aspectj.JoinPoint.StaticPart jp, |
| long elapsed); |
| } |
| </pre> |
| |
| <p> In order to use either aspect, they must be extended with |
| concrete aspects, say, MyLogging and MyProfiling. In AspectJ |
| 1.0, it was not possible to express that Logging's advice (when |
| concerned with the concrete aspect MyLogging) dominated |
| Profiling's advice (when concerned with the concrete aspect |
| MyProfiling) without adding a dominates clause to Logging |
| itself. In AspectJ 1.1, we can express that constraint with a |
| simple: </p> |
| |
| <pre> declare precedence: MyLogging, MyProfiling; |
| </pre> |
| |
| <h4>Changing order of advice for sub-aspects</h4> |
| |
| <p> By default, advice in a sub-aspect has more precedence than |
| advice in a super-aspect. One use of the AspectJ 1.0 dominates |
| form was to change this precedence: |
| </p> |
| |
| <pre> abstract aspect SuperA dominates SubA { |
| pointcut foo(): ... ; |
| |
| before(): foo() { |
| // in AspectJ 1.0, runs before the advice in SubA |
| // because of the dominates clause |
| } |
| } |
| |
| aspect SubA extends SuperA { |
| before(): foo() { |
| // in AspectJ 1.0, runs after the advice in SuperA |
| // because of the dominates clause |
| } |
| } |
| </pre> |
| |
| <p> This no longer works in AspectJ 1.1, since declare precedence only |
| matters for concrete aspects. Thus, if you want to regain this kind |
| of precedence change, you will need to refactor your aspects. |
| </p> |
| |
| <h3><a name="SOURCEROOT">The -sourceroots option</a></h3> |
| |
| <p> The AspectJ 1.1 compiler now accepts a -sourceroots option used to |
| pass all .java files in particular directories to the compiler. It |
| takes either a single directory name, or a list of directory names |
| separated with the CLASSPATH separator character (":" for various |
| Unices, ";" for various Windows). </p> |
| |
| <p> So, if you have your project separated into a gui module and a |
| base module, each of which is stored in a directory tree, you might |
| use one of |
| </p> |
| |
| <pre> ajc -sourceroots /myProject/gui:/myProject/base |
| ajc -sourceroots d:\myProject\gui;d:\myProject\base |
| </pre> |
| |
| <p> This option may be used in conjunction with lst files, listing |
| .java files on the command line, and the -injars option. |
| </p> |
| |
| <h3><a name="BYTECODE_WEAVING">The -injars option</a></h3> |
| |
| <p> The AspectJ 1.1 compiler now accepts an -injars option used to |
| pass all .class files in a particular jar file to the compiler. It |
| takes either a single directory name, or a list of directory names |
| separated with the CLASSPATH separator character (":" for various |
| Unices, ";" for various Windows). </p> |
| |
| <p> So, if MyTracing.java defines a trace aspect that you want to |
| apply to all the classes in myBase.jar and myGui.jar, you would use |
| one of: </p> |
| |
| <pre> ajc -injars /bin/myBase.jar:/bin/myGui.jar MyTracing.java |
| ajc -injars d:\bin\myBase.jar;d:\bin\myGui.jar MyTracing.java |
| </pre> |
| |
| <p> The class files in the input jars must not have had advice woven |
| into them, since AspectJ enforces the requirement that advice is woven |
| into a particular classfile only once. So if the classfiles in the |
| jar file are to be created with the ajc compiler (as opposed to a pure |
| Java compiler), they should not be compiled with any non-abstract |
| aspects. </p> |
| |
| <p> This option may be used in conjunction with lst files, listing |
| .java files on the command line, and the -sourceroots option. |
| </p> |
| |
| <h3><a name="OUTJAR">The -outjar option</a></h3> |
| |
| <p> The -outjar option takes the name of a jar file into which the |
| results of the compilation should be put. For example: |
| |
| <pre> ajc -injars myBase.jar MyTracing.java -outjar myTracedBase.jar |
| </pre> |
| |
| <p> No meta information is placed in the output jar file. </p> |
| |
| <h3><a name="INCREMENTAL">Incremental compilation</a></h3> |
| |
| <p> The AspectJ 1.1 compiler now supports incremental compilation. |
| When ajc is called with the -incremental option, it must also be |
| passed a -sourceroots option specifying a directory to incrementally |
| compile. Once the initial compile is done, ajc waits for console |
| input. Every time it reads a new line (i.e., every time the user |
| hits return) ajc recompiles those input files that need recompiling. |
| </p> |
| |
| <h4>Limitations</h4> |
| |
| <p> This new functionality is still only lightly tested. </p> |
| |
| <h3><a name="XNOWEAVE">-XnoWeave, a compiler option to suppress |
| weaving</a></h3> |
| |
| <p> The -XnoWeave option suppresses weaving, and generates |
| classfiles and that can be passed to ajc again (through the |
| -injars option) to generate final, woven classfiles. </p> |
| |
| <p> This option was originally envisioned to be the primary way to |
| generate binary aspects that could be linked with other code, and |
| so it was previously (in AspectJ 1.1beta1) named |
| <code>-noweave</code>. We feel that using the |
| <code><a href="#BINARY_ASPECTS">-aspectpath</a></code> option is a |
| much better option. There may still be use cases for unwoven |
| classfiles, but we've moved the flag to experimental status. |
| </p> |
| |
| <h3><a name="BINARY_ASPECTS">-aspectpath, working with aspects in .class/.jar |
| form</a> </h3> |
| |
| <p> When aspects are compiled into classfiles, they include all |
| information necessary for the ajc compiler to weave their advice |
| and deal with their inter-type declarations. In order for these |
| aspects to have an effect on a compilation process, they must be |
| passed to the compiler on the -aspectpath. Every .jar file on |
| this path will be searched for aspects and any aspects that are |
| found will be enabled during the compilation. The binary forms of |
| this aspects will be untouched. </p> |
| |
| <h3><a name="NO_CALLEE_SIDE_CALL">Callee-side call join |
| points</a></h3> |
| |
| <p> The 1.0 implementation of AspectJ, when given: |
| </p> |
| |
| <pre> class MyRunnable implements Runnable { |
| public void run() { ... } |
| } |
| |
| aspect A { |
| call(): (void run()) && target(MyRunnable) { |
| // do something here |
| } |
| } |
| </pre> |
| |
| <p> would cause A's advice to execute even when, say, java.lang.Thread |
| called run() on a MyRunnable instance. |
| </p> |
| |
| <p> With the new compiler, two things have happened in regard to |
| callee-side calls: |
| </p> |
| |
| <ol> |
| <li>because the programmer has access to more code (i.e., |
| bytecode, not just source code), callee-side calls are much |
| less important to have.</li> |
| |
| <li>because compilation is more modular, allowing and |
| encouraging separate compilation, callee-side calls are much |
| more difficult to implement</li> |
| </ol> |
| |
| <p> With these two points in mind, advice in an aspect will not be |
| applied to call join points whose call site is completely |
| unavailable to the aspect. </p> |
| |
| <ol> |
| <li>One reason (though not the only reason) we worked so hard in |
| the <em>implementation</em> of 1.0.6 to expose call join |
| points, even if we only had access to the callee's code, was |
| that otherwise users couldn't get access to call join points |
| where the call was made from bytecode. This is no longer the |
| case. In short, the implementation controls much more code (or |
| has the capability to) than ever before.</li> |
| |
| <li>The implementation model for the AspectJ 1.1 compiler is to |
| separate the compilation of aspects/advice from their |
| weaving/linking. A property of the model is that the |
| compilation requires no access to "target" code, only the |
| weaving/linking does, and weaving/linking is inherently |
| per-class local: No action at weaving/linking time depends on |
| the coordinated mangling of multiple classfiles. Rather, all |
| weaving is done on a per classfile basis. This is an essential |
| property for the current separate compilation model. <br> |
| |
| However, allowing implementation of call advice on either |
| side requires simultaneous knowledge of both sides. If we first |
| have access to a call, we can't decide to simply put the advice |
| on the call site, since later we may decide to implement on the |
| callee.</li> |
| </ol> |
| |
| <p>This implementation decision is completely in the letter and |
| the spirit of the AspectJ language. From the semantics guide |
| describing code the implementation controls:</p> |
| |
| <blockquote> |
| But AspectJ implementations are permitted to deviate from this |
| in a well-defined way -- they are permitted to advise only |
| accesses in <em>code the implementation |
| controls</em>. Each implementation is free within certain |
| bounds to provide its own definition of what it means to control |
| code. |
| </blockquote> |
| |
| <p>And about a particular decision about the 1.0.6 |
| implementation:</p> |
| |
| <blockquote> |
| Different join points have different requirements. Method call |
| join points can be advised only if ajc controls |
| <em>either</em> the code for the caller or the code |
| for the receiver, and some call pointcut designators may |
| require caller context (what the static type of the receiver |
| is, for example) to pick out join points. |
| </blockquote> |
| |
| <p> The 1.1 implementation makes a different design decision: |
| Method call join points can be advised only if ajc (in compiler or |
| linker form) controls the code for the caller. </p> |
| |
| <p>What does 1.1 gain from this?</p> |
| |
| <ul> |
| <li>a clear (and implemented) separate compilation model (see |
| point 2, above)</li> |
| |
| <li>a less confusing interaction between call join points and |
| the thisJoinPoint reflective object: We still get bug reports |
| about source information sometimes existing and sometimes not |
| existing at call join points.</li> |
| </ul> |
| |
| <p> What does 1.1 lose from this?</p> |
| |
| <ul> |
| <li>The ability to capture all calls to Runnable.run() from |
| anywhere to code ajc has access too, even from Thread, even if |
| you don't compile java.lang with ajc.</li> |
| |
| <li>The ability to, without access to the caller, capture entry to |
| a particular method, but not super calls.</li> |
| |
| <li>A code-size-improvement performance optimization.</li> |
| </ul> |
| |
| <p> What are the possibilities for the future?</p> |
| |
| <ul> |
| <li>AspectJ 1.1.1 could expand its capture of call join points, |
| possibly at the expense of separate compilation clarity, |
| possibly not. </li> |
| |
| <li>AspectJ 1.1.1 could re-introduce reception join points from |
| AspectJ 0.7 (what callee-side call join points actually are): |
| though they would never ever be taught in a tutorial or |
| entry-level description of the model, they may have specialized |
| uses.</li> |
| </ul> |
| |
| <p> How will this affect developers?</p> |
| <ul> |
| <li>When using the call PCD but only supplying the callee |
| code, supply the calling code or use the execution PCD instead. |
| </li> |
| </ul> |
| |
| <h3><a name="OTHER_X_OPTIONS">Various -X options</a></h3> |
| |
| <p> The AspectJ 1.0 compiler supported a number of options that |
| started with X, for "experimental". Some of them will not be |
| supported in 1.1, either because the "experiment" succeeded (in |
| which case it's part of the normal functionality) or failed. |
| Others will be supported as is (or nearly so) in 1.1: |
| </p> |
| |
| <ul> |
| <li>-XOcodeSize: This is no longer necessary because inlining |
| of around advice is on by default. We support its inverse, |
| <a href="#XNOINLINE"><code>-XnoInline</code></a>. |
| </li> |
| |
| <li><a href="#XNOWEAVE">-XnoWeave, a compiler option to suppress |
| weaving</a></li> |
| |
| <li>-XtargetNearSource: Not supported in this release. </li> |
| |
| <li>-XserializableAspects: Supported. </li> |
| |
| <li>-XaddSafePrefix: This option will not be supported in 1.1 at |
| all because we're now always using (what we believe to be) safe |
| prefixes. </li> |
| |
| <li>-Xlint: Still supported, with <a href="#XLINT">various |
| options</a>. </li> |
| </ul> |
| |
| <h3><a name="ERROR_MESSAGES">Some confusing error messages</a></h3> |
| |
| <p>Building on the eclipse compiler has given us access to a very |
| sophisticated problem reporting system as well as highly optimized |
| error messages for pure Java code. Often this leads to noticeably |
| better error messages than from ajc-1.0.6. However, when we don't |
| handle errors correctly this can sometimes lead to cascading error |
| messages where a single small syntax error will produce dozens of |
| other messages. Please report any very confusing error messages as |
| bugs.</p> |
| |
| |
| <h3><a name="MESSAGE_CONTEXT">Source code context is not shown |
| for errors and warnings detected during bytecode weaving</a></h3> |
| |
| <p>For compiler errors and warnings detected during bytecode weaving, |
| source code context will not be displayed. In particular, for declare |
| error and declare warning statements, the compiler now only emits the |
| file and line. We are investigating ways to overcome this in cases |
| where the source code is available; in cases where source code is |
| not available, we might specify the signature of the offending code. |
| For more information, see bug 31724.</p> |
| |
| |
| <h3><a name="XLINT">The -Xlint option</a></h3> |
| |
| <p><code>-Xlint:ignore,error,warning</code> will set the level for |
| all Xlint warnings. <code>-Xlint</code>, alone, is an |
| abbreviation for <code>-Xlint:warning</code>.</p> |
| |
| <p>The <code>-Xlintfile:lint.properties</code> allows fine-grained |
| control. In tools.jar, see |
| <code>org/aspectj/weaver/XlintDefault.properties</code> for the |
| default behavior and a template to copy. </p> |
| |
| <p> More <code>-Xlint</code> warnings are supported now, and |
| we may add disabled warnings in subsequent bug-fix releases of 1.1. |
| Because the configurability allows users to turn off |
| warnings, we will be able to warn about more potentially |
| dangerous situations, such as the potentially unsafe casts used by |
| very polymorphic uses of proceed in around advice. </p> |
| |
| <h3><a name="NO_SOURCE">Source-specific options</a></h3> |
| |
| <p> Because AspectJ 1.1 does not generate source code after |
| weaving, the source-code-specific options -preprocess, -usejavac, |
| -nocomment and -workingdir options are meaningless and so not |
| supported. </p> |
| |
| <h3><a name="NO_STRICT_LENIENT">The -strict and -lenient |
| options</a></h3> |
| |
| <p> Because AspectJ 1.1 uses the Eclipse compiler, which has its |
| own mechanism for changing strictness, we no longer support the |
| -strict and -lenient options. </p> |
| |
| <h3><a name="NO_PORTING">The -porting option</a></h3> |
| |
| <p> AspectJ 1.1 does not have a -porting option.</p> |
| |
| <h3><a name="13_REQUIRED">J2SE 1.3 required</a></h3> |
| |
| <p>Because we build on Eclipse, the compiler will no longer run |
| under J2SE 1.2. You must run the compiler (and all tools based on |
| the compiler) using J2SE 1.3 or later. The code generated by the |
| compiler can still run on Java 1.1 or later VM's if compiled against |
| the correct runtime libraries.</p> |
| |
| <h3><a name="DEFAULT_CONSTRUCTOR_CONFLICT">Default |
| constructors</a></h3> |
| |
| <p> AspectJ 1.1 does not allow the inter-type definition of a |
| zero-argument constructor on a class with a visible default |
| constructor. So this is no longer allowed: </p> |
| |
| <PRE> |
| class C {} |
| |
| aspect A { |
| C.new() {} // was allowed in 1.0.6 |
| // is a "multiple definitions" conflict in 1.1 |
| } |
| </PRE> |
| |
| <p> In the Java Programming Language, a class defined without a |
| constructor actually has a "default" constructor that takes no |
| arguments and just calls <code>super()</code>. </p> |
| |
| <p> This default constructor is a member of the class like any other |
| member, and can be referenced by other classes, and has code generated |
| for it in classfiles. Therefore, it was an oversight that AspectJ |
| 1.0.6 allowed such an "overriding" inter-type constructor definition. |
| </p> |
| |
| <h3><a name="SUPER_IFACE_INITS">Initialization join points for |
| super-interfaces</a></h3> |
| |
| <p> In AspectJ, interfaces may have non-static members due to |
| inter-type declarations. Because of this, the semantics of AspectJ |
| defines the order that initializer code for interfaces is run. |
| </p> |
| |
| <p> In the semantics document for AspectJ 1.0.6, the following |
| promises were made about the order of this initialization: |
| </p> |
| |
| <ol> |
| <li>a supertype is initialized before a subtype</li> |
| <li>initialized code runs only once</li> |
| <li>initializers for supertypes run in left-to-right order</li> |
| </ol> |
| |
| <p> The first two properties are important and are preserved in |
| AspectJ 1.1, but the third property is and was ludicrous, and was |
| never properly implemented (and never could be) in AspectJ 1.0.6. |
| Consider: </p> |
| |
| <PRE> |
| interface Top0 {} |
| interface Top1 {} |
| interface I extends Top0, Top1 {} |
| interface J extends Top1, Top0 {} |
| |
| class C implements I, J {} |
| // I says Top0's inits must run before Top1's |
| // J says Top1's inits must run before Top0's |
| |
| aspect A { |
| int Top0.i = foo("I'm in Top0"); |
| int Top1.i = foo("I'm in Top1"); |
| static int foo(String s) { |
| System.out.println(s); |
| return 37; |
| } |
| } |
| </PRE> |
| |
| <p> This was simply a bug in the AspectJ specification. The correct |
| third rule is: |
| </p> |
| |
| <blockquote>the initializers for a type's superclass are run before the |
| initializers for its superinterfaces. |
| </blockquote> |
| |
| |
| <h3><a name="VOID_FIELD_SET">Field Set Join Points</a></h3> |
| |
| <p> In AspectJ 1.0.6, the join point for setting a field F had, as a |
| return type, F's type. This was "java compatible" because |
| field assignment in java, such as "Foo.i = 37", is in fact an |
| expression, and does in fact return a value, the value that the |
| field is assigned to. |
| </p> |
| |
| <p> This was never "java programmer compatible", however, largely |
| because programmers have absorbed the good style of rarely using an |
| assignment statement in a value context. Programmers typically expect |
| "Foo.i = 37" not to return a value, but to simply assign a value. </p> |
| |
| <p> Thus, programmers typically wanted to write something like: |
| </p> |
| |
| <PRE> |
| void around(): set(int Foo.i) { |
| if (theSetIsAllowed()) { |
| proceed(); |
| } |
| } |
| </PRE> |
| |
| <p> And were confused by it being a compile-time error. They weren't |
| confused for long, and soon adapted to writing: |
| </p> |
| |
| <PRE> |
| int around(): set(int Foo.i) { |
| if (theSetIsAllowed()) { |
| return proceed(); |
| } else { |
| return Foo.i; |
| } |
| } |
| </PRE> |
| |
| <p> But there was definitely a short disconnect. </p> |
| |
| <p> On top of that, we were never shown a convincing use-case for |
| returning an interesting value from a set join point. When we |
| revisited this issue, in fact, we realized we had a long-standing bug |
| in 1.0.6 dealing with the return value of pre-increment expressions |
| (such as ++Foo.i) that nobody had found because nobody cares about the |
| return value of such join points. |
| </p> |
| |
| <p> So, because it's easier to implement, and because we believe that |
| this is the last possibility to make the semantics more useful, we |
| have made set join points have a void return type in 1.1. </p> |
| |
| <h3><a name="XNOINLINE">The -XnoInline Option</a></h3> |
| |
| <p> The <code>-XnoInline</code> |
| option to indicate that no inlining of any kind should be done. This |
| is purely a compiler pragma: No program semantics (apart from stack |
| traces) will be changed by the presence or absence of this option. |
| </p> |
| |
| <h3><a name="TARGET_TYPES_MADE_PUBLIC">Target types made |
| public</a></h3> |
| |
| <p> Even in 1.0.6, the AspectJ compiler has occasionally needed to |
| convert the visibility of a package-level class to a public one. This |
| was previously done in an ad-hoc basis that took whole-program |
| analysis into account. With the incremental compilation model of |
| AspectJ 1.1, we can now specify the occasions when the compiler makes |
| these visibility changes. |
| </p> |
| |
| <p> In particular, the types used in the <code>this</code>, |
| <code>target</code>, and <code>args</code> pointcuts are made public, |
| as are the super-types from <code>declare parents</code> and the |
| exception type from <code>declare soft</code>. |
| </p> |
| |
| <p> We believe the visibility changes could be avoided in the future |
| with various implementation tricks if they become a serious |
| concern, but did not encounter them as such a concern when they were |
| done in the 1.0.6 implementation. </p> |
| |
| <h3><a name="STRINGBUFFER">String + now advised</a></h3> |
| |
| <p> In Java, the + operator sometimes results in StringBuffer objects |
| being created, appended to, and used to generate a new String. Thus, |
| </p> |
| |
| <PRE> |
| class Foo { |
| String makeEmphatic(String s) { |
| return s + "!"; |
| } |
| } |
| </PRE> |
| |
| <p> is approximately the same at runtime as |
| </p> |
| |
| <PRE> |
| class Foo { |
| String makeEmphatic(String s) { |
| return new StringBuffer(s).append("!").toString(); |
| } |
| } |
| </PRE> |
| |
| |
| <p> In the design process of AspectJ 1.0.6 we didn't expose those |
| StringBuffer methods and constructors as join points (though we did |
| discuss it), but in 1.1 we do. </p> |
| |
| <p> This change is likely to affect highly wildcarded aspects, and can |
| do so in surprising ways. In particular: |
| </p> |
| |
| <PRE> |
| class A { |
| before(int i): call(* *(int)) && args(i) { |
| System.err.println("entering with " + i); |
| } |
| } |
| </PRE> |
| |
| <p> may result in a stack overflow error, since the argument to |
| println is really </p> |
| |
| <PRE> |
| new StringBuffer("entering with ").append(i).toString() |
| </PRE> |
| |
| <p> which has a call to StringBuffer.append(int). In such cases, it's |
| worth restricting your pointcut, with something like one of: |
| </p> |
| |
| <PRE> |
| call(* *(int)) && args(i) && !within(A) |
| call(* *(int)) && args(i) && !target(StringBuffer) |
| </PRE> |
| |
| <h3><a name="ONE_FOUR_METHOD_SIGNATURES">The -1.4 flag and method signatures</a></h3> |
| |
| <p> Consider the following aspect |
| </p> |
| |
| <PRE> |
| public aspect SwingCalls { |
| |
| pointcut callingAnySwing(): call(* javax.swing..*+.*(..)); |
| |
| before(): callingAnySwing() { |
| System.out.println("Calling any Swing"); |
| } |
| } |
| </PRE> |
| |
| <p> And then consider the two statements |
| </p> |
| |
| <PRE> |
| JFrame frame = new JFrame(); |
| frame.setTitle("Title"); |
| </PRE> |
| |
| <p> According to the Java Language Specification version 2, the call |
| to <code>frame.setTitle("Title")</code> should always produce the |
| bytecode for a call to <code>javax.swing.JFrame.setTitle</code>. |
| However, older compilers (and eclipse when run without the |
| <code>-1.4</code> flag) will generate the bytecode for a call to |
| <code>java.awt.Frame.setTitle</code> instead since this method is not |
| overriden by JFrame. The AspectJ weaver depends on the correctly |
| generated bytecode in order to match patterns like the one you show |
| correctly. </p> |
| |
| <p> This is a good example of why the pattern <code>call(* *(..)) && |
| target(JFrame)</code> is the recommended style. In general, OO |
| programmers don't want to care about the static type of an object at a |
| call site, but only want to know the dynamic instanceof behavior which |
| is what the target matching will handle. </p> |
| |
| |
| <h2><a name="knownLimitations">Known limitations</a></h2> |
| |
| <p>The AspectJ 1.1.0 release contains a small number of known limitations |
| relative to the AspectJ 1.1 language. |
| For the most up-to-date information about known limitations in an |
| AspectJ 1.1 release, see the bug database at |
| <a href="http://bugs.eclipse.org/bugs">http://bugs.eclipse.org/bugs</a>, |
| especially the open bugs for the |
| <a href="http://bugs.eclipse.org/bugs/buglist.cgi?product=AspectJ&component=Compiler&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED"> |
| compiler</a>, |
| <a href="http://bugs.eclipse.org/bugs/buglist.cgi?product=AspectJ&component=IDE&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED"> |
| IDE support</a>, |
| <a href="http://bugs.eclipse.org/bugs/buglist.cgi?product=AspectJ&component=Doc&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED"> |
| documentation</a>, and |
| <a href="http://bugs.eclipse.org/bugs/buglist.cgi?product=AspectJ&component=Ant&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED"> |
| Ant tasks</a>. |
| Developers should know about bugs marked with the "info" keyword |
| because those bugs reflect failures to implement the 1.1 language perfectly. |
| These might be fixed during the 1.1 release cycle; find them using the query |
| <a href="http://bugs.eclipse.org/bugs/buglist.cgi?product=AspectJ&keywords=info"> |
| http://bugs.eclipse.org/bugs/buglist.cgi?product=AspectJ&keywords=info</a> |
| |
| For ajc's 1.1 implementation limitations, see |
| <a href="progguide/implementation.html"> |
| Programming Guide Appendix: "Implementation Notes"</a>. |
| |
| </p> |
| </body> </html> |