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
|
[[ltw]]
== Load-Time Weaving
[[ltw-introduction]]
=== Introduction
The AspectJ weaver takes class files as input and produces class files
as output. The weaving process itself can take place at one of three
different times: compile-time, post-compile time, and load-time. The
class files produced by the weaving process (and hence the run-time
behaviour of an application) are the same regardless of the approach
chosen.
* Compile-time weaving is the simplest approach. When you have the
source code for an application, ajc will compile from source and produce
woven class files as output. The invocation of the weaver is integral to
the ajc compilation process. The aspects themselves may be in source or
binary form. If the aspects are required for the affected classes to
compile, then you must weave at compile-time. Aspects are required,
e.g., when they add members to a class and other classes being compiled
reference the added members.
* Post-compile weaving (also sometimes called binary weaving) is used to
weave existing class files and JAR files. As with compile-time weaving,
the aspects used for weaving may be in source or binary form, and may
themselves be woven by aspects.
* Load-time weaving (LTW) is simply binary weaving defered until the
point that a class loader loads a class file and defines the class to
the JVM. To support this, one or more "weaving class loaders", either
provided explicitly by the run-time environment or enabled through a
"weaving agent" are required.
You may also hear the term "run-time weaving". We define this as the
weaving of classes that have already been defined to the JVM (without
reloading those classes). AspectJ 5 does not provide explicit support
for run-time weaving although simple coding patterns can support
dynamically enabling and disabling advice in aspects.
==== Weaving class files more than once
As of AspectJ 5 aspects (code style or annotation style) and woven
classes are reweavable by default. If you are developing AspectJ
applications that are to be used in a load-time weaving environment with
an older version of the compiler you need to specify the `-Xreweavable`
compiler option when building them. This causes AspectJ to save
additional state in the class files that is used to support subsequent
reweaving.
[[ltw-rules]]
=== Load-time Weaving Requirements
All load-time weaving is done in the context of a class loader, and
hence the set of aspects used for weaving and the types that can be
woven are affected by the class loader delegation model. This ensures
that LTW complies with the Java 2 security model. The following rules
govern the interaction of load-time weaving with class loading:
[arabic]
. All aspects to be used for weaving must be defined to the weaver
before any types to be woven are loaded. This avoids types being
"missed" by aspects added later, with the result that invariants across
types fail.
. All aspects visible to the weaver are usable. A visible aspect is one
defined by the weaving class loader or one of its parent class loaders.
All concrete visible aspects are woven and all abstract visible aspects
may be extended.
. A class loader may only weave classes that it defines. It may not
weave classes loaded by a delegate or parent class loader.
[[ltw-configuration]]
=== Configuration
New in AspectJ 5 are a number of mechanisms to make load-time weaving
easy to use. The load-time weaving mechanism is chosen through JVM
startup options. Configuration files determine the set of aspects to be
used for weaving and which types will be woven. Additional diagnostic
options allow the user to debug the configuration and weaving process.
==== Enabling Load-time Weaving
AspectJ 5 supports several ways of enabling load-time weaving for an
application: agents, a command-line launch script, and a set of
interfaces for integration of AspectJ load-time weaving in custom
environments.
Agents::
AspectJ 5 ships with a load-time weaving agent that enables load-time
weaving. This agent and its configuration is execution environment
dependent. Configuration for the supported environments is discussed
later in this chapter.
+
Using Java 5 JVMTI you can specify the
`-javaagent:pathto/aspectjweaver.jar` option to the JVM.
+
Since AspectJ 1.9.7, the obsolete Oracle/BEA JRockit agent is no
longer part of AspectJ. JRockit JDK never supported Java versions
higher than 1.6. Several JRockit JVM features are now part of HotSpot
and tools like Mission Control available for OpenJDK and Oracle JDK.
Command-line wrapper scripts `aj`::
The `aj` command runs Java programs in Java 1.4 or later by setting up
`WeavingURLClassLoader` as the system class loader. For more
information, see xref:#aj[`aj`, the AspectJ load-time weaving launcher].
+
The `aj5` command runs Java programs in Java 5 by using the
`-javaagent:pathto/aspectjweaver.jar` option described above. For more
information, see xref:#aj[`aj`, the AspectJ load-time weaving launcher].
Custom class loader::
A public interface is provided to allow a user written class loader to
instantiate a weaver and weave classes after loading and before
defining them in the JVM. This enables load-time weaving to be
supported in environments where no weaving agent is available. It also
allows the user to explicitly restrict by class loader which classes
can be woven. For more information, see xref:#aj[`aj`, the AspectJ load-time weaving launcher] and the API
documentation and source for `WeavingURLClassLoader` and
`WeavingAdapter`.
[[configuring-load-time-weaving-with-aopxml-files]]
==== Configuring Load-time Weaving with aop.xml files
The weaver is configured using one or more `META-INF/aop.xml` files
located on the class loader search path. Each file may declare a list of
aspects to be used for weaving, type patterns describing which types
should woven, and a set of options to be passed to the weaver. In
addition AspectJ 5 supports the definition of concrete aspects in XML.
Aspects defined in this way must extend an abstract aspect visible to
the weaver. The abstract aspect may define abstract pointcuts (but not
abstract methods). The following example shows a simple aop.xml file:
[source, xml]
....
<aspectj>
<aspects>
<!-- declare two existing aspects to the weaver -->
<aspect name="com.MyAspect"/>
<aspect name="com.MyAspect.Inner"/>
<!-- define a concrete aspect inline -->
<concrete-aspect name="com.xyz.tracing.MyTracing"
extends="tracing.AbstractTracing"
precedence="com.xyz.first, *">
<pointcut name="tracingScope" expression="within(org.maw.*)"/>
</concrete-aspect>
<!-- Of the set of aspects declared to the weaver
use aspects matching the type pattern "com..*" for weaving. -->
<include within="com..*"/>
<!-- Of the set of aspects declared to the weaver
do not use any aspects with the @CoolAspect annotation for weaving -->
<exclude within="@CoolAspect *"/>
</aspects>
<weaver options="-verbose">
<!-- Weave types that are within the javax.* or org.aspectj.*
packages. Also weave all types in the foo package that do
not have the @NoWeave annotation. -->
<include within="javax.*"/>
<include within="org.aspectj.*"/>
<include within="(!@NoWeave foo.*) AND foo.*"/>
<!-- Do not weave types within the "bar" pakage -->
<exclude within="bar.*"/>
<!-- Dump all types within the "com.foo.bar" package
to the "./_ajdump" folder on disk (for diagnostic purposes) -->
<dump within="com.foo.bar.*"/>
<!-- Dump all types within the "com.foo.bar" package and sub-packages,
both before are after they are woven,
which can be used for byte-code generated at runtime
<dump within="com.foo.bar..*" beforeandafter="true"/>
</weaver>
</aspectj>
....
The DTD defining the format of this file is available here:
https://www.eclipse.org/aspectj/dtd/aspectj.dtd.
An aop.xml file contains two key sections: `aspects` defines one or more
aspects to the weaver and controls which aspects are to be used in the
weaving process; `weaver` defines weaver options and which types should
be woven.
The simplest way to define an aspect to the weaver is to specify the
fully-qualified name of the aspect type in an aspect element. You can
also declare (and define to the weaver) aspects inline in the aop.xml
file. This is done using the `concrete-aspect` element. A
concrete-aspect declaration must provide a pointcut definition for every
abstract pointcut in the abstract aspect it extends. This mechanism is a
useful way of externalizing configuration for infrastructure and
auxiliary aspects where the pointcut definitions themselves can be
considered part of the configuration of the service. Refer to the next
section for more details.
The `aspects` element may optionally contain one or more `include` and
`exclude` elements (by default, all defined aspects are used for
weaving). Specifying include or exclude elements restricts the set of
defined aspects to be used for weaving to those that are matched by an
include pattern, but not by an exclude pattern. The `within` attribute
accepts a type pattern of the same form as a within pcd, except that &&
and || are replaced by 'AND' and 'OR'.
Note that `include` and `exclude` elements affect all aspects declared
to the weaver including those in other aop.xml files. To help avoid
unexpected behaviour a lint warning is issued if an aspect is not
declared as a result of of applying these filters. Also note `aspect`
and `concrete-aspect` elements must be used to declare aspects to the
weaver i.e. `include` and `exclude` elements cannot be used find aspects
on the class loader search path.
The `weaver` element is used to pass options to the weaver and to
specify the set of types that should be woven. If no include elements
are specified then all types visible to the weaver will be woven. In
addition the `dump` element can be used capture on disk byte-code of
woven classes for diagnostic purposes both before, in the case of those
generated at runtime, and after the weaving process.
When several configuration files are visible from a given weaving class
loader their contents are conceptually merged. The files are merged in
the order they are found on the search path (with a regular
`getResourceAsStream` lookup) according to the following rules:
* The set of available aspects is the set of all declared and defined
aspects (`aspect` and `concrete-aspect` elements of the `aspects`
section).
* The set of aspects used for weaving is the subset of the available
aspects that are matched by at least one include statement and are not
matched by any exclude statements. If there are no include statements
then all non-excluded aspects are included.
* The set of types to be woven are those types matched by at least one
weaver `include` element and not matched by any weaver `exclude`
element. If there are no weaver include statements then all non-excluded
types are included.
* The weaver options are derived by taking the union of the options
specified in each of the weaver options attribute specifications. Where
an option takes a value e.g. `-warn:none` the most recently defined
value will be used.
It is not an error for the same aspect to be defined to the weaver in
more than one visible `META-INF/aop.xml` file. However, if the same
concrete aspect is defined in more than one aop.xml file then an error
will be issued. A concrete aspect defined in this way will be used to
weave types loaded by the class loader that loaded the aop.xml file in
which it was defined.
A `META-INF/aop.xml` can be generated by using either the `-outxml` or
`-outxmlfile` options of the AspectJ compiler. It will simply contain a
(possibly empty) set of aspect elements; one for each abstract or
concrete aspect defined. When used in conjuction with the `-outjar`
option a JAR is produced that can be used with the `aj5` command or a
load-time weaving environment.
[[concrete-aspect]]
==== Using Concrete Aspects
It is possible to make an abstract aspect concrete by means of the
`META-INF/aop.xml` file. This is useful way to implement abstract
pointcuts at deployment time, and also gives control over precedence
through the `precedence` attribute of the `concrete-aspect` XML element.
Consider the following:
[source, java]
....
package mypack;
@Aspect
public abstract class AbstractAspect {
// abstract pointcut: no expression is defined
@Pointcut
abstract void scope();
@Before("scope() && execution(* *..doSome(..))")
public void before(JoinPoint jp) {
// ...
}
}
....
This aspect is equivalent to the following in code style:
[source, java]
....
package mypack;
public abstract aspect AbstractAspect {
// abstract pointcut: no expression is defined
abstract pointcut scope();
before() : scope() && execution(* *..doSome(..)) {
// ...
}
}
....
This aspect (in either style) can be made concrete using
`META-INF/aop.xml`. It defines the abstract pointcut `scope()`. When
using this mechanism the following rules apply:
* The parent aspect must be abstract. It can be an @AspectJ or a regular
code style aspect.
* Only a simple abstract pointcut can be implemented i.e. a pointcut
that doesn't expose state (through `args(), this(), target(), if()`). In
@AspectJ syntax as illustrated in this sample, this means the method
that hosts the pointcut must be abstract, have no arguments, and return
void.
* The concrete aspect must implement all inherited abstract pointcuts.
* The concrete aspect may not implement methods so the abstract aspect
it extends may not contain any abstract methods.
_A limitation of the implementation of this feature in AspectJ 1.5.0 is
that aspects defined using aop.xml are not exposed to the weaver. This
means that they are not affected by advice and ITDs defined in other
aspects. Support for this capability will be considered in a future
release._
If more complex aspect inheritance is required use regular aspect
inheritance instead of XML. The following XML definition shows a valid
concrete sub-aspect for the abstract aspects above:
[source, xml]
....
<aspectj>
<aspects>
<concrete-aspect name="mypack.__My__AbstractAspect" extends="mypack.AbstractAspect">
<pointcut name="scope" expression="within(yourpackage..*)"/>
</concrete-aspect>
<aspects>
</aspectj>
....
It is important to remember that the `name` attribute in the
`concrete-aspect` directive defines the fully qualified name that will
be given to the concrete aspect. It must a valid class name because the
aspect will be generated on the fly by the weaver. You must also ensure
that there are no name collisions. Note that the concrete aspect will be
defined at the classloader level for which the aop.xml is visible. This
implies that if you need to use the `aspectof` methods to access the
aspect instance(s) (depending on the perclause of the aspect it extends)
you have to use the helper API `org.aspectj.lang.Aspects.aspectOf(..)`
as in:
[source, java]
....
// exception handling omitted
Class myConcreteAspectClass = Class.forName("mypack.__My__AbstractAspect");
// here we are using a singleton aspect
AbstractAspect concreteInstance = Aspects.aspectOf(myConcreteAspectClass);
....
[[concrete-aspect-precedence]]
==== Using Concrete Aspects to define precedence
As described in the previous section, the `concrete-aspect` element in
`META-INF/aop.xml` gives the option to declare the precedence, just as
`@DeclarePrecedence` or `declare precedence` do in aspect source code.
Sometimes it is necessary to declare precedence without extending any
abstract aspect. It is therefore possible to use the `concrete-aspect`
element without the `extends` attribute and without any `pointcut`
nested elements, just a `precedence` attribute. Consider the following:
[source, xml]
....
<aspectj>
<aspects>
<concrete-aspect name="mypack.__MyDeclarePrecedence"
precedence="*..*Security*, Logging+, *"/>
</aspects>
</aspectj>
....
This deployment time definitions is only declaring a precedence rule.
You have to remember that the `name` attribute must be a valid fully
qualified class name that will be then reserved for this concrete-aspect
and must not conflict with other classes you deploy.
[[weaver-options]]
==== Weaver Options
The table below lists the AspectJ options supported by LTW. All other
options will be ignored and a warning issued.
[cols=",",options="header",]
|===
|Option |Purpose
|`-verbose` |Issue informational messages about the weaving process.
Messages issued while the weaver is being bootstrapped are accumulated
until all options are parsed. If the messages are required to be output
immediately you can use the option `-Daj.weaving.verbose=true` on the
JVM startup command line.
|`-debug` |Issue a messages for each class passed to the weaver
indicating whether it was woven, excluded or ignored. Also issue
messages for classes defined during the weaving process such as around
advice closures and concrete aspects defined in `META-INF/aop.xml`.
|`-showWeaveInfo` |Issue informational messages whenever the weaver
touches a class file. This option may also be enabled using the System
property `-Dorg.aspectj.weaver.showWeaveInfo=true`.
|`-Xlintfile:pathToAResource` |Configure lint messages as specified in
the given resource (visible from this aop.xml file' classloader)
|`-Xlint:default, -Xlint:ignore, ...` |Configure lint messages, refer to
documentation for meaningfull values
|`-nowarn, -warn:none` |Suppress warning messages
|`-Xreweavable` |Produce class files that can subsequently be rewoven
|`-XnoInline` |Don't inline around advice.
|`-XmessageHandlerClass:...` |Provide alternative output destination to
stdout/stderr for all weaver messages. The given value must be the full
qualified class name of a class that implements the
`org.aspectj.bridge.IMessageHandler` interface and is visible to the
classloader with which the weaver being configured is associated.
Exercise caution when packaging a custom message handler with an
application that is to be woven. The handler (as well as classes on
which it depends) cannot itself be woven by the aspects that are
declared to the same weaver.
|===
[[ltw-specialcases]]
=== Special cases
The following classes are not exposed to the LTW infrastructure
regardless of the `aop.xml` file(s) used:
* All `org.aspectj.*` classes (and subpackages) - as those are needed by
the infrastructure itself
* All `java.*` and `javax.*` classes (and subpackages)
* All `sun.reflect.*` classes - as those are JDK specific classes used
when reflective calls occurs
Despite these restrictions, it is perfectly possible to match call join
points for calls to these types providing the calling class is exposed
to the weaver. Subtypes of these excluded types that are exposed to the
weaver may of course be woven.
Note that dynamic proxy representations are exposed to the LTW
infrastructure and are not considered a special case.
Some lint options behave differently when used under load-time weaving.
The `adviceDidNotMatch` won't be handled as a warn (as during compile
time) but as an info message.
[[ltw-packaging]]
=== Runtime Requirements for Load-time Weaving
To use LTW the `aspectjweaver.jar` library must be added to the
classpath. This contains the AspectJ 5 runtime, weaver, weaving class
loader and weaving agents. It also contains the DTD for parsing XML
weaving configuration files.
[[ltw-agents]]
=== Supported Agents
==== JVMTI
When using Java 5 the JVMTI agent can be used by starting the JVM with
the following option (adapt according to the path to aspectjweaver.jar):
[source, text]
....
-javaagent:pathto/aspectjweaver.jar
....
[[jrockit]]
==== JRockit with Java 1.3/1.4 (use JVMTI on Java 5)
Since AspectJ 1.9.7, the obsolete Oracle/BEA JRockit agent is no longer
part of AspectJ. JRockit JDK never supported Java versions higher than
1.6. Several JRockit JVM features are now part of HotSpot and tools like
Mission Control available for OpenJDK and Oracle JDK.
|