From e1c9313a55965194e2f987d5fa5777747e068695 Mon Sep 17 00:00:00 2001 From: ehilsdal Date: Wed, 18 Dec 2002 06:09:31 +0000 Subject: [PATCH] Various fixes and completions. Should be 1.1beta2-ready apart from some verbiage about the ant tasks. --- build/products/tools/dist/README-11.html | 377 +++++++++++++++++++---- 1 file changed, 312 insertions(+), 65 deletions(-) diff --git a/build/products/tools/dist/README-11.html b/build/products/tools/dist/README-11.html index 1434df7f5..6901b25b5 100644 --- a/build/products/tools/dist/README-11.html +++ b/build/products/tools/dist/README-11.html @@ -53,7 +53,13 @@ release schedule closely, however, these are the changes since the points, and the -XserializableAspects experimental option.
  • Field set join points now have a - void return type.
  • XXX + void return type. This will require porting of code + that uses the set PCD in conjunction with after + returning or around advice. + +
  • Various StringBuffer methods and + constructors resulting from the Java Language string concatenation + operator + now result in join points.
  • Users now have more control over the -Xlint option.
  • @@ -65,16 +71,24 @@ release schedule closely, however, these are the changes since the
  • The -noweave option is now the -XnoWeave option.
  • -
  • A new option, -XnoInline, +
  • A new option, -XnoInline, is now supported to control some compiler behavior.
  • A class's default constructor may conflict with an inter-type constructor.
  • +
  • inter-type field + initializers run before class-local field initializers.
  • +
  • Some of the treatment of initialization join points for - super-interfaces have been clarified.
  • + super-interfaces have been clarified. + +
  • The behavior of the compiler in + lifting the visibility of + the target types of some declares and pointcuts to public has been + clarified.
  • The new pertype aspect specifier has been taken off the table for 1.1rc, though it may well be in a @@ -105,7 +119,7 @@ release schedule closely, however, these are the changes since the 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 are not yet implemented in 1.1, so many 1.0 programs + features are not yet implemented in 1.1, so some 1.0 programs will not compile in this release.

    @@ -120,9 +134,8 @@ release schedule closely, however, these are the changes since the exceptions.
  • New kinded pointcut designators: Now - every kind of pointcut has a corresponding kinded pointcut + every kind of join point has a corresponding kinded pointcut designator.
  • -

    Some are have different behavior in edge cases but offer @@ -130,8 +143,12 @@ release schedule closely, however, these are the changes since the

    But in order to support weaving into bytecode effectively, @@ -145,7 +162,7 @@ release schedule closely, however, these are the changes since the

  • No callee-side call join points: The AspectJ 1.1 compiler does not expose call join points unless it is given the calling code.
  • - +
  • One target for intertype declarations
  • @@ -155,6 +172,9 @@ release schedule closely, however, these are the changes since the
  • Initializers run inside constructor execution join points
  • +
  • inter-type field + initializers run before class-local field initializers
  • +
  • Small limitations of the within pointcut
  • @@ -176,6 +196,11 @@ release schedule closely, however, these are the changes since the the current compiler implementation.

    +

    And some changes to the implementation are almost entirely + internal: +

    + + +

    A short description of the options ajc accepts is available with - "ajc -help".

    + "ajc -help".

    @@ -331,12 +365,10 @@ release schedule closely, however, these are the changes since the

    The AJDE Tools

    -

    AJDE for JBuilder, AJDE for Netbeans, and AJDE for Emacs and the - AJBrowser have not changed much. They use the batch-build mode of - the new compiler. The beta compiler does not yet produce - crosscutting structure (for anything but method executions) so there are no inline - annotations in JBuilder or Emacs support and you only see a - declaration tree in the structure views. Incremental building and +

    The AspectJ Browser hasn't changed much, and apart from being + distributed from Sourceforge, AJDE for JBuilder, AJDE for Netbeans, + and AJDE for Emacs haven't changed much either. They use the + batch-build mode of the new compiler. Incremental building and bytecode weaving are not available in the AJDE tools in the beta release, but will be in a future release.

    @@ -437,9 +469,10 @@ release schedule closely, however, these are the changes since the advice defined in a particular aspect.
    preinitialization(ConstructorPattern) will pick out pre-initialization join points where the initializaiton - process is entered through ConstructorPattern.

    + process is entered through + ConstructorPattern.

    -

    New pertype aspect specifier

    +

    New pertype aspect specifier (not in 1.1)

    We strongly considered adding a pertype aspect kind to 1.1. This is somewhat motivated by the new @@ -519,7 +552,7 @@ release schedule closely, however, these are the changes since the

    No initializer execution join points

    -

    AspectJ 1.1 does not consider initializer execution as a +

    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 @@ -563,6 +596,34 @@ release schedule closely, however, these are the changes since the must always assume incomplete object initialization, since the constructor has not yet run.

    +

    Inter-type field initializers

    + +

    The initializer, if any, of an inter-type field definition runs + before the class-local initializers of its target class.

    + +

    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 + initializer execution join + points and constructor + execution, 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: +

    + +
    +    int C.methodCount = 0;
    +    before(C c): this(c) && execution(* *(..)) { c.methodCount++; }
    +    
    + +

    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. +

    +

    Small limitations of the within pointcut

    @@ -800,10 +861,6 @@ release schedule closely, however, these are the changes since the .java files on the command line, and the -injars option.

    -

    ALPHA: In the beta release of the compiler, - only one directory can be passed to the -sourceroots option. -

    -

    The -injars option

    The AspectJ 1.1 compiler now accepts an -injars option used to @@ -839,29 +896,29 @@ release schedule closely, however, these are the changes since the

        ajc -injars myBase.jar MyTracing.java -outjar myTracedBase.jar
         
    -

    No meta information is placed in the output jar file

    +

    No meta information is placed in the output jar file.

    Incremental compilation

    The AspectJ 1.1 compiler now supports incremental compilation. For the final release, this will work from the various IDE plugins we - ship, but for the Alpha release, it is only supported on the + ship, but for the 1.1beta2 release, it is only supported on the command-line compiler.

    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 + input. Every time it reads a new line (i.e., every time the user hits return) ajc recompiles those input files that need recompiling.

    Limitations for 1.1beta2

    -

    some changes to classes should force re-weaving, but are not +

    Some changes to classes should force re-weaving, but are not noticed

    -

    inter-type declarations, declare parents are not tracked +

    Inter-type declarations, declare parents are not tracked correctly

    -XnoWeave, a compiler option to suppress @@ -1043,11 +1100,13 @@ release schedule closely, however, these are the changes since the

    -
    -  inter-type constructors and default constructors conflict now
    -  
    +

    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:

    +
    +    class C {}
    +
    +    aspect A {
    +        C.new() {}  // was allowed in 1.0.6
    +                    // is a "multiple definitions" conflict in 1.1
    +    }
    +    
    + +

    In the Java Programming Language, a class defined without a + constructor actually has a "default" constructor that takes no + arguments and just calls super().

    + +

    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. +

    Initialization join points for super-interfaces

    - XXX -
    -  We promised to run super inits in L-R order.  This was, of course, totally ludricous.  We couldn't do it then and we can't do it now.
    -  It is undefined what order they go in, apart from the other promises made in that section (interfaces with members)
     
    +    

    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. +

    + +

    In the semantics document for AspectJ 1.0.6, the following + promises were made about the order of this initialization: +

    + +
      +
    1. a supertype is initialized before a subtype
    2. +
    3. initialized code runs only once
    4. +
    5. initializers for supertypes run in left-to-right order
    6. +
    + +

    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:

    + +
    +    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;
    +        }
    +    }
    +    
    + +

    This was simply a bug in the AspectJ specification. The correct + third rule is: +

    + +
    the initializers for a type's superclass are run before the + initializers for its superinterfaces. +
    - int C.methodCount = 0; - before(C c): this(c) && execution(* *(..)) { c.methodCount++; } - -- - this would have bizarre behavior if we didn't run initializers before constructors -

    Field Set Join Points

    - XXX -

    Are now void -

    +

    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. +

    + +

    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.

    + +

    Thus, programmers typically wanted to write something like: +

    + +
    +    void around(): set(int Foo.i) {
    +        if (theSetIsAllowed()) {
    +            proceed();
    +        }
    +    }
    +    
    + +

    And were confused by it being a compile-time error. They weren't + confused for long, and soon adapted to writing: +

    + +
    +    int around(): set(int Foo.i) {
    +        if (theSetIsAllowed()) {
    +            return proceed();
    +        } else {
    +            return Foo.i;
    +        }
    +    }
    +    
    + +

    But there was definitely a short disconnect.

    + +

    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. +

    -

    The -XnoInline Option

    -XXX +

    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.1beta2. + Please complain voiceferously if you believe this is wrong, and we + can revert for the final version.

    -

    Link to other X flags, in particular XblahBlah +

    The -XnoInline Option

    + +

    Though 1.1beta2 does not have code inlining turned on, we expect + that the final release will have inlining on for many cases of around + advice. Therefore, we are supporting the -XnoInline + 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. +

    + +

    Target types made + public

    + +

    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. +

    + +

    In particular, the types used in the this, + target, and args pointcuts are made public, + as are the super-types from declare parents and the + exception type from declare soft. +

    + +

    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.

    + +

    String + now advised

    + +

    In Java, the + operator sometimes results in StringBuffer objects +being created, appended to, and used to generate a new String. Thus,

    +
    +class Foo {
    +    String makeEmphatic(String s) {
    +        return s + "!";
    +    }
    +}
    +
    + +

    is approximately the same at runtime as +

    + +
    +class Foo {
    +    String makeEmphatic(String s) {
    +        return new StringBuffer(s).append("!").toString();
    +    }
    +}
    +
    + + +

    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.

    + +

    This change is likely to affect highly wildcarded aspects, and can +do so in surprising ways. In particular: +

    + +
    +class A {
    +    before(int i): call(* *(int)) && args(i) {
    +        System.err.println("entering with " + i);
    +    }
    +}
    +
    + +

    may result in a stack overflow error, since the argument to +println is really

    + +
    +new StringBuffer("entering with ").append(i).toString()
    +
    + +

    which has a call to StringBuffer.append(int). In such cases, it's +worth restricting your pointcut, with something like one of: +

    + +
    +call(* *(int)) && args(i) && !within(A)
    +call(* *(int)) && args(i) && !target(StringBuffer)
    +
    + - \ No newline at end of file + -- 2.39.5