summaryrefslogtreecommitdiffstats
path: root/docs/progGuideDB
diff options
context:
space:
mode:
authorwisberg <wisberg>2006-10-05 17:01:58 +0000
committerwisberg <wisberg>2006-10-05 17:01:58 +0000
commitc0ef7c724322530a361686fade5607ed0577bb87 (patch)
tree5b79d0d678a923416223f7a4f158a0dc3629a97d /docs/progGuideDB
parentc315f9d9a754d01ea608d6d1ae020889d4018fc6 (diff)
downloadaspectj-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.xml16
-rw-r--r--docs/progGuideDB/semantics.xml75
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>