]> source.dussan.org Git - aspectj.git/commitdiff
bug 159390 Documenting long-known runtime ClassCastException from proceed
authorwisberg <wisberg>
Thu, 5 Oct 2006 17:01:58 +0000 (17:01 +0000)
committerwisberg <wisberg>
Thu, 5 Oct 2006 17:01:58 +0000 (17:01 +0000)
docs/progGuideDB/implementation.xml
docs/progGuideDB/semantics.xml

index f83e7dd8ce976e7a9e1a76757b5518f134c23ba9..52da14d9c011ab67f0972af2ad1ce89a22307577 100644 (file)
   </sect2>
 </sect1>
 
+<sect1>
+  <title>Annotation-style Notes</title>
+  <para>Writing aspects in annotation-style is subject to the same
+      bytecode limitations since the binary aspects take the same
+      form and are woven in the same way.  However, the implementation
+      differences (e.g., the mechanism for implementing around advice) 
+      may be apparent at runtime.  See the documentation on annotation-style 
+      for more information.
+  </para>
+</sect1>
 <sect1>
   <title>Summary of implementation requirements</title>
   <para>
                        <listitem>
                          <para>cflow and cflowbelow pointcuts work within a single thread.</para>
                        </listitem>
+                       <listitem>
+                         <para>
+                  Runtime <literal>ClassCastException</literal> may result 
+                  from supplying a supertype of the actual type as an argument
+                  to proceed(..) in around advice.</para>
+                       </listitem>
                </itemizedlist>
    </listitem>
  </itemizedlist>
index 6c2fb173a9489a3672b317191e11990eb842b218..fd282faecf2370e8747de76781f04d45ba94fc95 100644 (file)
@@ -1938,11 +1938,11 @@ ModifiersPattern =
       }
   }
 </programlisting>
-
-       <para>
-               Any occurence of <literal>proceed(..)</literal> within the body of
-               around advice is treated as the special proceed form (even if the
-               aspect defines a method named <literal>proceed</literal>) unless a 
+    
+    <para>
+               Any occurence of <literal>proceed(..)</literal> within the body of around 
+        advice is treated as the special proceed form (even if the
+               aspect defines a method named <literal>proceed</literal>), unless a 
                target other than the aspect instance is specified as the recipient of
                the call.
                For example, in the following program the first 
@@ -1986,6 +1986,71 @@ ModifiersPattern =
       parameters or return values of join points can be done by using around
       advice.
     </para>
+    <para>
+        With <literal>proceed(..)</literal> it is possible to change the values
+        used by less-precedent advice and the underlying join point by supplying
+        different values for the variables.  For example, this aspect replaces
+        the string bound to <literal>s</literal> in the named pointcut 
+        <literal>privateData</literal>:
+    </para>
+
+<programlisting>
+  aspect A {
+    Object around(String s): MyPointcuts.privateData(s) {
+      return proceed("private data");
+    }
+  }
+</programlisting>
+    <para>
+        If you replace an argument to <literal>proceed(..)</literal>, you can cause 
+        a <literal>ClassCastException</literal> at runtime when the argument
+        refers to a supertype of the actual type and you do not supply a 
+        reference of the actual type.  In the following aspect, the
+        around advice replaces the declared target <literal>List</literal> 
+        with an <literal>ArrayList</literal>.  This is valid code at
+        compile-time since the types match.  
+    </para>
+<programlisting>
+  import java.util.*;
+
+  aspect A {
+    Object around(List list): call(* List+.*()) <![CDATA[&&]]> target(list) {
+      return proceed(new ArrayList());
+    }
+  }
+</programlisting>
+    <para>
+        But imagine a simple program where the actual target is
+        <literal>LinkedList</literal>.  In this case, the advice would cause a
+        <literal>ClassCastException</literal> at runtime, and 
+        <literal>peek()</literal> is not declared in <literal>ArrayList</literal>.
+    </para>
+<programlisting>
+  public class Test {
+    public static void main(String[] args) {
+      new LinkedList().peek();
+    }
+  }
+</programlisting>
+    <para>
+        The <literal>ClassCastException</literal> can occur even in situations
+        where it appears to be unnecessary, e.g., if the program is changed to
+        call <literal>size()</literal>, declared in <literal>List</literal>:
+    </para>
+<programlisting>
+  public class Test {
+    public static void main(String[] args) {
+      new LinkedList().size();
+    }
+  }
+</programlisting>
+    <para>
+        There will still be a <literal>ClassCastException</literal> because
+        it is impossible to prove that there won't be a runtime binary-compatible
+        change in the hierarchy of <literal>LinkedList</literal> or some
+        other advice on the join point that requires a 
+        <literal>LinkedList</literal>.
+    </para>
 
     <sect2 id="advice-modifiers" xreflabel="advice-modifiers">
       <title>Advice modifiers</title>