diff options
author | wisberg <wisberg> | 2006-10-05 17:01:58 +0000 |
---|---|---|
committer | wisberg <wisberg> | 2006-10-05 17:01:58 +0000 |
commit | c0ef7c724322530a361686fade5607ed0577bb87 (patch) | |
tree | 5b79d0d678a923416223f7a4f158a0dc3629a97d /docs/progGuideDB | |
parent | c315f9d9a754d01ea608d6d1ae020889d4018fc6 (diff) | |
download | aspectj-c0ef7c724322530a361686fade5607ed0577bb87.tar.gz aspectj-c0ef7c724322530a361686fade5607ed0577bb87.zip |
bug 159390 Documenting long-known runtime ClassCastException from proceed
Diffstat (limited to 'docs/progGuideDB')
-rw-r--r-- | docs/progGuideDB/implementation.xml | 16 | ||||
-rw-r--r-- | docs/progGuideDB/semantics.xml | 75 |
2 files changed, 86 insertions, 5 deletions
diff --git a/docs/progGuideDB/implementation.xml b/docs/progGuideDB/implementation.xml index f83e7dd8c..52da14d9c 100644 --- a/docs/progGuideDB/implementation.xml +++ b/docs/progGuideDB/implementation.xml @@ -298,6 +298,16 @@ </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> This summarizes the requirements of our implementation of AspectJ. @@ -351,6 +361,12 @@ <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> diff --git a/docs/progGuideDB/semantics.xml b/docs/progGuideDB/semantics.xml index 6c2fb173a..fd282faec 100644 --- a/docs/progGuideDB/semantics.xml +++ b/docs/progGuideDB/semantics.xml @@ -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> |