Load-Time Weaving
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.
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:
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.
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 .
The aj5 command runs Java programs in Java 5
by using the -javaagent:pathto/aspectjweaver.jar option
described above.
For more information, see .
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 and the
API documentation and source for
WeavingURLClassLoader and
WeavingAdapter.
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:
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.
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:
This aspect is equivalent to the following in code style:
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:
]]>
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:
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:
]]>
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
The table below lists the AspectJ options supported by LTW. All other options
will be ignored and a warning issued.
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.
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.
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.
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):
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.