aboutsummaryrefslogtreecommitdiffstats
path: root/docs/dist/doc/README-12.adoc
blob: 0cbc3b93ceb01a4e4d09c319b5209ca5176e4f7b (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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
== AspectJ 1.2

_© Copyright 2003,2004 Contributors. All rights reserved._

The definition of the AspectJ language is unchanged in the 1.2 release.
Instead, AspectJ 1.2 provides major improvements to the functionality of
the supporting tools and enforces some language limits that went
unchecked before. This document describes the tools differences between
AspectJ versions 1.2 and 1.1.1. Users new to AspectJ need only read the
link:progguide/index.html[AspectJ Programming Guide] since it describes
the 1.2 language. Users familiar with AspectJ 1.1 may find this document
a quicker way to learn what changed in the tools, and should use it as a
guide for porting programs from 1.1 to 1.2, together with porting.html.

This document first summarizes changes from the 1.1.1 release in

* xref:#compiler[the compiler],
* xref:#tools[the support tools],
* xref:#runtime[the runtime],
* xref:#devenv[the development environment support],

then xref:#details[details] some of the changes, and finally points
readers to the bug database for xref:#allchanges[all the changes].

'''''

[[compiler]]
=== The Compiler

Compared to AspectJ 1.1.1, the AspectJ 1.2 compiler...

* xref:#WEAVE_TIME[Is faster], with weaving completing in less than half
the time it used to take in many cases.
[#WEAVE_CHART]#image:images/AspectJ11v12.JPG[image]#.
* Supports the xref:#LAZY_TJP[-XlazyTjp option] which produces code that
runs faster and uses less memory in some common cases.
* Has xref:#INCREMENTAL[much better support for incremental
compilation].
* Produces xref:#ERROR_MESSAGES[better error messages].
* Has some xref:#LINT[new lint warnings] to catch common mistakes and
changes to serializability.
* Supports the xref:#REWEAVABLE[-Xreweavable option] that allows classes
to be woven more than once.
* {blank}
* Supports the xref:#INPATH[-inpath option] which allows both
directories and jars containing class files to be specified as input to
the weaver.
* xref:#COMPLIANCE[Changes the default compiler compliance mode] from
-1.3 to -1.4.

A short description of the options ajc accepts is available with
"`ajc -help`". Longer descriptions are available in the
link:devguide/ajc-ref.html[Development Environment Guide section on
ajc].

'''''

[[tools]]
=== Support Tools

AspectJ 1.2 contains two important changes to the supporting tools:

* xref:#AJDOC[ajdoc] is back
* A sample script is supplied for xref:#LTW[load-time weaving] from the
command-line.

'''''

[[runtime]]
=== The Runtime Library

This release has minor updates to the runtime library classes. As with
any release, you should compile and run with the runtime library that
came with your compiler, and you may run with a later version of the
library without recompiling your code.

* xref:#SOFTEX[`SoftException`] now supports `getCause()`.
* Although not part of `aspectjrt.jar` this release also provides a new
set of tools APIs in the xref:#LTW2[`org.aspectj.weaver.tools`] that
provide a weaving class loader and an adapter that can be used to
integrate load-time weaving into an existing class loader hierarchy.
* Cflow stack management has been modified to use thread local storage
on JVMs that support this feature. This improves performance in terms of
heap usage for multi-threaded applications that use cflow.

'''''

[[devenv]]
=== The AJDE Tools

The AJDE based tools for JBuilder, NetBeans and Emacs continue to be
independent SourceForge projects. The AspectJ 1.2 distribution includes
an updated version of the AjBrowser tool that benefits from all the
enhancements made in the 1.2 compiler.

The 1.2 release of AspectJ also lays a lot of the groundwork for a much
better AspectJ IDE experience that we hope to surface initially through
AJDT (AspectJ support for Eclipse). Amongst the many improvements, we
will have full eager parsing support that avoids the need to keep the
whole structure model of a project in memory, hopefully making AJDT much
less memory hungry and much slicker to use. For more details see the
https://www.eclipse.org/ajdt[AJDT project website].

'''''

[[details]]
=== Details of some compiler changes

[[WEAVE_TIME]]
==== Compilation (weave) times reduced.

Our benchmark suite shows that AspectJ 1.2 is at least twice as fast in
the weaving phase as AspectJ 1.1.1 for matches based on a variety of
pointcut expressions (see the xref:#WEAVE_CHART[chart above]). We've
also made the base incremental compilation implementation in AspectJ 1.2
approximately twice as fast as in AspectJ 1.1.1, so when this is
combined with the weave time improvements you should see speed-ups of up
to 4x for incremental compilation.

In addition, AspectJ 1.2 maintains only weak references to some of its
recoverable data structures, allowing the JVM to optimise between
performance and memory usage. Experiments forcing GC showed that we can
achieve about a 20% memory usage reduction in this manner if needed.

[[LAZY_TJP]]
==== The -XlazyTjp option.

Under AspectJ 1.1.1, if the body of an advice contained a reference to a
non-statically determinable portion of `thisJoinPoint` (such as for
example a call to `getArgs()`), then a JoinPoint object was always
creating before entering the advice. This was the case even if the
advice was guarded with an `if()` pointcut that evaluated to false.

AspectJ 1.2 now supports the `-XlazyTjp` option that only creates the
JoinPoint object just before dispatching to the advice body. By
promoting the guard to a test in an `if()` pointcut, the creation of the
JoinPoint object can be avoided altogether in the case where the test
returns false.

Consider a simple tracing aspect as follows:

[source, java]
....
public aspect Tracing {

  public static boolean enabled = false;

  pointcut toBeTraced() : execution(* *(..)) || execution(new(..));

  before() : toBeTraced() && if(enabled) {
    Object[] args = thisJoinPoint.getArgs();
    // format args and print out entry trace record etc....
  }
}
....

The most important consideration is the system overhead when tracing is
turned off. Using the `-XlazyTjp` option makes the program above run
10-100x faster, even when running a small test case with minimal GC
issues. The optimization is disabled at join points advised by around
advice, and an Xlint warning will be displayed in these cases.

[[INCREMENTAL]]
==== Improvements to incremental compilation.

AspectJ 1.2 provides more complete incremental compilation support than
AspectJ 1.1.1. Firstly, incremental compilation resulting from a change
to a source file is now approximately twice as fast as it was under
1.1.1 (even before taking the improvements to weaving time into
account). Secondly, the incremental coverage now takes into account
changes to resources, classes and jars on the inpath, injars, and
aspectpath. The new `inpath` option in AspectJ 1.2 allows directories to
be specified in addition to jars (just like a classpath) as input to the
weaver. Any update, addition or deletion of a class file in a directory
on the inpath will cause incremental (re)weaving.

Changes to a jar file on the inpath, injars or aspectpath will now be
detected, but will trigger a full rebuild, as will any change to the
paths used to control compilation.

[[ERROR_MESSAGES]]
==== Improved error messages.

AspectJ 1.1.1 did not provide source context information for messages
produced during the weaving phase, even in the case where source files
were passed to the compiler. For example, an error message arising as a
result of a `declare error` statement might look as follows under
AspectJ 1.1.1:

[source, text]
....
BadClass.java:6 should not be calling bad methods
....

whereas in AspectJ 1.2 you will see:

[source, text]
....
BadClass.java:6 error should not be calling bad methods
new C().bad();
^^^^^^^^^^^^^^
     method-call(void C.bad())
     see also: DeclareError.java:5
....

There are four new things to note about this error message. Firstly,
errors and warnings are now prefixed with the word "error", or "warning"
as appropriate. Secondly, the offending line of source is shown if
source code is available. Thirdly, in the case of weaver messages
arising as a result of `declare error` and `declare warning` statements,
AspectJ now shows not only the location of the error or warning, but
also the location of the `declare` statement itself. Finally, note that
messages produced as a result of `declare error` and `declare warning`
statements now also display the matched join point at the location of
the error:

When source code is not available, the messages show the binary input
source (class file or jar file) in which the error or warning was
detected:

[source, text]
....
BadClass.java:6 error should not be calling bad methods
(no source information available)
       method-call(void C.bad())
       see also: C:\...\DeclareError.java:5
       see also: C:\...\bin-input.jar
....

This error message tells us that `BadClass.class` contained in a jar on
the inpath called `bin-input.jar`, and originally compiled from a source
file called `BadClass.java`, contains a join point
(`method-call(void C.bad())` matched by a `declare error` statement on
line 5 of the file `DeclareError.java`.

[[LINT]]
==== New lint warnings.

Consider the program:

[source, java]
....
/*01*/ class A {
/*02*/   public void doIt() {...};
/*03*/ }
/*04*/
/*05*/ class B extends A {
/*06*/   public void doThisToo() {...};
/*07*/ }
/*08*/
/*09*/
/*10*/ public class CallsAandB {
/*11*/
/*12*/  public static void main(String[] args) {
/*13*/    B b = new B();
/*14*/    A bInDisguise = new B();
/*15*/
/*16*/    b.doIt();               // AspectJ 1.2 matches here
/*17*/    bInDisguise.doIt();     // this is never matched
/*18*/  }
/*19*/
/*20*/ }
/*21*/
/*22*/ aspect CallPCDMatchingExample {
/*23*/
/*24*/   before() : call(* B.doIt(..)) {
/*25*/     System.out.println("About to call B.doIt(...)");
/*26*/   }
/*27*/
/*28*/ }
....

Because the static type of `bInDisguise` is `A` (line 14), the call on
line 17 is never matched by the pointcut expression on 24, even though
the runtime type of `bInDisguise` is `B`. Type patterns matched in
`call` pointcut designators are matched based on static type matching.
Some users have found this static type matching confusing, and AspectJ
1.2 has a new Xlint warning (`unmatchedSuperTypeInCall`) which is
enabled by default.

The compiler will now produce a warning whenever a call pointcut
designator does not match at a join point, and a user may have expected
it to. Compiling the above program using AspectJ 1.2 produces the
following compiler output:

[source, text]
....
CallsAandB.java:24 warning does not match because declaring type is A, if match desired use target(B) [Xlint:unmatchedSuperTypeInCall]
before() : call(* B.doIt(..)) {
           ^^^^^^^^^^^^^^^
    see also: CallsAandB.java:17

1 warning
....

The warning is telling us that the call pointcut associated with the
before advice on line 24 of the source file does not match at a join
point where the user may have expected it to. The source location
corresponding to the unmatched join point is indicated by the "see also"
line - in this case line 17 of the source file. At line 17 we find a
call to `bInDisguise.doIt()`. Since the static type of `bInDisguise` is
`A`, this call will never be matched. The warning also tells us a
possible solution if we intended the pointcut to match at this join
point: use `call(* doIt(..) && target(B)`.

If you find warnings of this kind coming out when you use the AspectJ
1.2 compiler, the recommended fix is to switch to using the `target`
designator in place of a type pattern in the `call` pointcut expression.
Note that there is no loss of runtime efficiency here - runtime tests
are only added in the cases where it cannot be determined at compile
time whether the type of the receiver will match the type specified in
the `target` expression. Also note that `target` cannot be used in
`declare` statements.

A new Xlint warning, `needsSerialVersionUIDField` (disabled by default)
will produce a warning at compile time if the process of weaving changes
the default `serialVersionUID` of a serializable class, and the class
does not define a `serialVersionUID`. By defining a `serialVersionUID`
field, the programmer can ensure that objects serialized without the
aspect present can be read by a version of the program in which the
aspect is present, and vice-versa.

A complimentary Xlint warning, `brokeSerialVersionCompatibility`
(disabled by default) will produce a warning at compile time if the
process of weaving makes an incompatible change to a serializable class
(for example, through the addition of an inter-type declared field).

[[REWEAVABLE]]
==== The -Xreweavable option.

The new `-Xreweavable` option produces class files that contain enough
additional information in them that they can be rewoven. In time we hope
that this can become a standard option, replacing the current
`-Xnoweave` option. Using reweavable produces class files that can be
legally loaded by a JVM, whereas with noweave, it is too easy to produce
class files that will result in a verify error at runtime. The
reweavable option makes it easy to weave code many times without having
to decide which weave is the final one. In a future version of the
AspectJ compiler, producing reweavable class files may become the
default option. The trade-off at the moment is that reweavable class
files are currently approximately twice the size of their non-reweavable
counterparts.

To ensure consistent semantics when reweaving, the AspectJ compiler
requires that all aspects that have previously modified a class file
during weaving be present in the system during a reweave. An error will
be issued if any are missing.

[[INPATH]]
==== The -inpath option.

The new `-inpath` option replaces the `-injars` option (which is still
supported for backwards compatibility). It allows both directories and
jar files to be specified using path separators to separate entries in
the path. This option makes it easy for class files produced as the
result of building one project to become binary input to the compilation
of a second project.

[[COMPLIANCE]]
==== The default compliance mode of the compiler has changed from -1.3 to -1.4.

The default AspectJ compiler compliance level is now 1.4 (whereas in
previous releases the default compliance level was 1.3). This has a
number of implications:

* class files generated by the compiler are now JRE v1.2 and upwards
compatible. (At compliance level 1.3, AspectJ generated class files that
were compatible with JRE 1.1 also).
* `call` pointcuts may match more join points than in the same program
compiled at compliance level 1.3.

The AspectJ compiler can be restored to 1.3 compliance settings by
specifying the "-1.3" option on the command-line.

Consider again the following example program which illustrates the
differences in join point matching with the `call` pointcut designator
between 1.4 and 1.3 compliance levels.

[source, java]
....
/*01*/ class A {
/*02*/   public void doIt() {...};
/*03*/ }
/*04*/
/*05*/ class B extends A {
/*06*/   public void doThisToo() {...};
/*07*/ }
/*08*/
/*09*/
/*10*/ public class CallsAandB {
/*11*/
/*12*/  public static void main(String[] args) {
/*13*/    B b = new B();
/*14*/    A bInDisguise = new B();
/*15*/
/*16*/    b.doIt();               // AspectJ 1.2 matches here
/*17*/    bInDisguise.doIt();     // this is never matched
/*18*/  }
/*19*/
/*20*/ }
/*21*/
/*22*/ aspect CallPCDMatchingExample {
/*23*/
/*24*/   before() : call(* B.doIt(..)) {
/*25*/     System.out.println("About to call B.doIt(...)");
/*26*/   }
/*27*/
/*28*/ }
....

When this program is compiled with AspectJ 1.2 using the default
compiler options, it will produce one line of output when it is
executed:

`About to call B.doIt(...)`

The same program compiled under AspectJ 1.1 (or using AspectJ 1.2 with
the -1.3 flag specified) does not produce any output when it is run. The
reason for the additional call pcd match is that prior to compliance
level 1.4, Java compilers produced bytecodes that call A.doIt() (the
defining type of the method), rather than B.doIt() (the declared type in
the program text). The generated call to A.doIt() is not matched by the
call pcd used in the before advice. At compliance level 1.4, the
bytecodes retain the declared type of the receiver in the program
source, generating a call to B.doIt(), which _is_ matched by the call
pcd.

This is a good example of why the recommended style is to use
`call(* doIt(..)) && target(B)`, which always matches based on the
actual type of the receiver.

'''''

[[AJDOC]]
==== The ajdoc tool makes a comeback in the AspectJ 1.2 distribution.

`ajdoc` (the AspectJ replacement for the `javadoc` tool) is once again
included in the AspectJ distribution. The `ajdoc` tool produces regular
javadoc that also shows advises and advised by relationships next to
methods and advice. A future enhancement will show inter-type
declarations in the target class too.

*Known limitations:* Please note that `ajdoc` documents advice and
pointcut members, shows where advice applies and links affected members
back to the advice.  It currently does not document or add structural
links for any inter-type declarations or other declare forms.

Run the "ajdoc.bat" script just as you run javadoc.  For a list of
accepted parameters run "ajdoc -help".  For example, to document
everything in the Spacewar example run: +
> cd examples +
> ajdoc -d doc -private spacewar coordination

`ajdoc` sample output for an aspect source file:

image:images/ajdoc1.JPG[image]

`ajdoc` sample output for advised methods:

image:images/ajdoc2.JPG[image]

[[LTW]]
==== A sample script is supplied that supports load-time weaving from the command-line

The AspectJ 1.2 distribution ships with sample scripts for Windows and
Unix platforms that exploit AspectJ's binary weaving capabilities at
application load time. You will find these scripts in the
`doc/examples/ltw` directory of your AspectJ installation.

The scripts allow you to set an environment variable, `ASPECTPATH`,
containing a path-separator delimited list of aspect-library jar files.
A Java application can then be launched using the "`aj`" script ("`aj`"
is to "`ajc`" as "`java`" is to "`javac`"). If the `ASPECTPATH` is unset
or empty, "`aj`" behaves exactly the same as "`java`", but if the
`ASPECTPATH` contains one or more aspect libraries, the aspects in the
library will be linked (woven) with the application code as it is
loaded.

The `doc/examples/ltw` directory of your AspectJ installation contains a
sample application that demonstrates these capabilities. Following the
instructions in the `README` file in that directory, running
"`aj tracing.ExampleMain`" with `ASPECTPATH` unset produces the output:

[source, text]
....
c1.perimeter() = 12.566370614359172
c1.area() = 12.566370614359172
s1.perimeter() = 4.0
s1.area() = 1.0
c2.distance(c1) = 4.242640687119285
s1.distance(c1) = 2.23606797749979
s1.toString(): Square side = 1.0 @ (1.0, 2.0)
....

If you set `ASPECTPATH` to include `../jars/tracingLib.jar`, and run
"`aj tracing.ExampleMain`" again, the output will be:

[source, text]
....
  --> tracing.TwoDShape(double, double)
  <-- tracing.TwoDShape(double, double)
  --> tracing.Circle(double, double, double)
  <-- tracing.Circle(double, double, double)
  --> tracing.TwoDShape(double, double)
  <-- tracing.TwoDShape(double, double)
  --> tracing.Circle(double, double, double)
  <-- tracing.Circle(double, double, double)
  --> tracing.Circle(double)
  <-- tracing.Circle(double)
  --> tracing.TwoDShape(double, double)
  <-- tracing.TwoDShape(double, double)
  --> tracing.Square(double, double, double)
  <-- tracing.Square(double, double, double)
  --> tracing.Square(double, double)
  <-- tracing.Square(double, double)
  --> double tracing.Circle.perimeter()
  <-- double tracing.Circle.perimeter()
c1.perimeter() = 12.566370614359172
  --> double tracing.Circle.area()
  <-- double tracing.Circle.area()
c1.area() = 12.566370614359172
  --> double tracing.Square.perimeter()
  <-- double tracing.Square.perimeter()
s1.perimeter() = 4.0
  --> double tracing.Square.area()
  <-- double tracing.Square.area()
s1.area() = 1.0
  --> double tracing.TwoDShape.distance(TwoDShape)
    --> double tracing.TwoDShape.getX()
    <-- double tracing.TwoDShape.getX()
    --> double tracing.TwoDShape.getY()
    <-- double tracing.TwoDShape.getY()
  <-- double tracing.TwoDShape.distance(TwoDShape)
  etc...
....

The scripts only support JDK 1.4 and above - attempting to use them with
a 1.3 or lower JDK will most likely produce `NoClassDefFound` errors. We
welcome contributions from users to improve these scripts.

'''''

[[SOFTEX]]
==== SoftException now supports getCause()

`org.aspectj.lang.SoftException` now supports the `getCause()` method,
which returns the original exception wrapped by the `SoftException`.
This means that exception chains will print correctly on 1.4 and later
JREs.

[[LTW2]]
==== org.aspectj.weaver.tools package added

A new set of public APIs are exported by the
link:api/index.html[`org.aspectj.weaver.tools`] package that can be used
to integrate load-time weaving into an existing class loader hierachy.
The package implementation is included in `aspectjtools.jar`. For an
example of how to use these APIs, see the
`org.aspectj.weaver.WeavingURLClassLoader` implementation.

'''''

[[allchanges]]
=== All changes are listed in the bug database

For a complete list of changes in the 1.2 release, search for
`target 1.2` in the bug database:
https://bugs.eclipse.org/bugs/buglist.cgi?product=AspectJ&component=Compiler&target_milestone=1.2