aboutsummaryrefslogtreecommitdiffstats
path: root/docs/progGuideDB/implementation.xml
diff options
context:
space:
mode:
authorehilsdal <ehilsdal>2003-12-02 19:31:52 +0000
committerehilsdal <ehilsdal>2003-12-02 19:31:52 +0000
commit9f8fdd6e73ae4995d195cc5637307ee7b5d9b057 (patch)
tree052207e2a17b62ba31efbe65ca95b19828489ee0 /docs/progGuideDB/implementation.xml
parent4880b54e69fcd225590fce7079a84d2b17a6ee62 (diff)
downloadaspectj-9f8fdd6e73ae4995d195cc5637307ee7b5d9b057.tar.gz
aspectj-9f8fdd6e73ae4995d195cc5637307ee7b5d9b057.zip
Fix for Bugzilla 37899: Document or address limitations on handler pointcut/joinpoints
* changed "Implementation Limitations" to "Implementation Notes" inside ProgGuide * added section on bytecode limitations, headed by handler issues.
Diffstat (limited to 'docs/progGuideDB/implementation.xml')
-rw-r--r--docs/progGuideDB/implementation.xml178
1 files changed, 178 insertions, 0 deletions
diff --git a/docs/progGuideDB/implementation.xml b/docs/progGuideDB/implementation.xml
new file mode 100644
index 000000000..314c574f9
--- /dev/null
+++ b/docs/progGuideDB/implementation.xml
@@ -0,0 +1,178 @@
+<appendix id="implementation" xreflabel="Implementation Notes">
+
+ <title>Implementation Notes</title>
+
+<sect1>
+ <title>Compiler Notes</title>
+
+ <para>
+ The initial implementations of AspectJ have all been
+ compiler-based implementations. Certain elements of AspectJ's
+ semantics are difficult to implement without making modifications
+ to the virtual machine, which a compiler-based implementation
+ cannot do. One way to deal with this problem would be to specify
+ only the behavior that is easiest to implement. We have chosen a
+ somewhat different approach, which is to specify an ideal language
+ semantics, as well as a clearly defined way in which
+ implementations are allowed to deviate from that semantics. This
+ makes it possible to develop conforming AspectJ implementations
+ today, while still making it clear what later, and presumably
+ better, implementations should do tomorrow.
+ </para>
+
+ <para>
+ According to the AspectJ language semantics, the declaration
+ </para>
+
+<programlisting><![CDATA[
+ before(): get(int Point.x) { System.out.println("got x"); }
+]]></programlisting>
+
+ <para>
+ should advise all accesses of a field of type int and name x from
+ instances of type (or subtype of) Point. It should do this
+ regardless of whether all the source code performing the access
+ was available at the time the aspect containing this advice was
+ compiled, whether changes were made later, etc.
+ </para>
+
+ <para>
+ But AspectJ implementations are permitted to deviate from this in
+ a well-defined way -- they are permitted to advise only accesses
+ in <emphasis>code the implementation controls</emphasis>. Each
+ implementation is free within certain bounds to provide its own
+ definition of what it means to control code.
+ </para>
+
+ <para>
+ In the current AspectJ compiler, ajc, control of the code means
+ having bytecode for any aspects and all the code they should
+ affect available during the compile. This means that if some class
+ Client contains code with the expression <literal>new
+ Point().x</literal> (which results in a field get join point at
+ runtime), the current AspectJ compiler will fail to advise that
+ access unless Client.java or Client.class is compiled as well. It
+ also means that join points associated with code in native methods
+ (including their execution join points) cannot be advised.
+ </para>
+
+ <para>
+ Different join points have different requirements. Method and
+ constructor call join points can be advised only if ajc controls
+ the bytecode for the caller. Field reference or assignment join
+ points can be advised only if ajc controls the bytecode for the
+ "caller", the code actually making the reference or assignment.
+ Initialization join points can be advised only if ajc controls the
+ bytecode of the type being initialized, and execution join points
+ can be advised only if ajc controls the bytecode for the method or
+ constructor body in question.
+ The end of an exception handler is underdetermined in bytecode,
+ so ajc will not implement after or around advice on handler join
+ points.
+ Similarly, ajc cannot implement around advice on initialization
+ or preinitialization join points.
+ In cases where ajc cannot implement advice, it will emit a
+ compile-time error noting this as a compiler limitation.
+ </para>
+
+ <para>
+ Aspects that are defined <literal>perthis</literal> or
+ <literal>pertarget</literal> also have restrictions based on
+ control of the code. In particular, at a join point where the
+ bytecode for the currently executing object is not available, an
+ aspect defined <literal>perthis</literal> of that join point will
+ not be associated. So aspects defined
+ <literal>perthis(Object)</literal> will not create aspect
+ instances for every object unless <literal>Object</literal>is part
+ of the compile. Similar restrictions apply to
+ <literal>pertarget</literal> aspects.
+ </para>
+
+ <para>
+ Inter-type declarations such as <literal>declare parents</literal>
+ also have restrictions based on control of the code. If the
+ bytecode for the target of an inter-type declaration is not
+ available, then the inter-type declaration is not made on that
+ target. So, <literal>declare parents : String implements
+ MyInterface</literal> will not work for
+ <literal>java.lang.String</literal> unless
+ <literal>java.lang.String</literal> is part of the compile.
+ </para>
+
+ <para>
+ Other AspectJ implementations, indeed, future versions of ajc, may
+ define <emphasis>code the implementation controls</emphasis> more
+ liberally or restrictively.
+ </para>
+
+ <para>
+ The important thing to remember is that core concepts of AspectJ,
+ such as the join point, are unchanged, regardless of which
+ implementation is used. During your development, you will have to
+ be aware of the limitations of the ajc compiler you're using, but
+ these limitations should not drive the design of your aspects.
+ </para>
+</sect1>
+
+<sect1>
+ <title>Bytecode Notes</title>
+
+ <para>The end of exception handlers cannot reliably be found in Java
+ bytecode. Instead of removing the handler join point entirely, the
+ current AspectJ compiler restricts what can be done with the handler
+ join point:
+ </para>
+
+ <itemizedlist>
+ <listitem>After and around advice cannot apply to handler
+ join points.</listitem>
+
+ <listitem>The control flow of a handler join point cannot be
+ detected. </listitem>
+ </itemizedlist>
+
+ <para>
+ The first of these is relatively straightforward. If any piece of
+ after advice (returning, throwing, or "finally") would normally
+ apply to a handler join point, it will not in code output by the
+ current AspectJ compiler. A compiler warning is generated whenever
+ this is detected to be the case. Before advice is allowed.
+ </para>
+
+ <para> The second is that the control flow of a handler join point
+ is not picked out. For example, the following pointcut
+ </para>
+
+<programlisting><![CDATA[
+ cflow(call(void foo()) || handler(java.io.IOException))
+]]></programlisting>
+
+ <para> will capture all join points in the control flow of a call to
+ <literal>void foo()</literal>, but it will <emphasis>not</emphasis>
+ capture those in the control flow of an
+ <literal>IOException</literal> handler. It is equivalent to
+ <literal>cflow(call(void foo()))</literal>. In general,
+ <literal>cflow(handler(<replaceable>Type</replaceable>))</literal>
+ will pick out no join points.
+ </para>
+
+ <para> This does not restrict programs from placing before advice on
+ handlers inside <emphasis>other</emphasis> control flows. This
+ advice, for example, is perfectly fine:
+ </para>
+
+<programlisting><![CDATA[
+ before(): handler(java.io.IOException) && cflow(void parse()) {
+ System.out.println("about to handle an exception while parsing");
+ }
+]]></programlisting>
+
+ <para>
+ A source-code implementation of AspectJ (such as AspectJ 1.0.6) is
+ able to detect the endpoint of a handler join point, and as such
+ will likely have fewer such restrictions.
+ </para>
+
+</sect1>
+
+</appendix>