aboutsummaryrefslogtreecommitdiffstats
path: root/docs/progGuideDB/limitations.xml
blob: b5d574738c122dedfeec81679a25f22fc82a5d6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<appendix id="limitations" xreflabel="Implementation Limitations">

  <title>Implementation Limitations</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.
  </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>

</appendix>