Load-Time Weaving Introduction The AspectJ 5 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. 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. 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 By default a class file that has been woven by the AspectJ compiler cannot subsequently be rewoven (passed as input to the weaver). If you are developing AspectJ applications that are to be used in a load-time weaving environment, 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. All abstract and concrete aspects visible to the weaver are available for extending (abstract aspects) and using for weaving. A visible aspect is one defined by the weaving class loader or one of its parent class loaders. A class loader may only weave classes that it defines. It may not weave classes loaded by a delegate or parent class loader. Configuration AspectJ 5 supports a number of mechanisms designed to make load-time weaving as easy to use as possibe. 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 three different 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 number of load-time weaving agents that enable load-time weaving. These agents and their configuration are execution environment dependent. Using Java 5 for example, you can specify the "-javaagent" option to the JVM. Configuration for the supported environments is discussed later in this chapter. AspectJ 5 has several agents including those that use JVMTI, and the JRockit MAPI. Command line AspectJ includes a script "aj" that allows programs executed at the command line to take advantage of load-time weaving. The script is customized when AspectJ is installed depending on the chosen JDK. For example, for JDK 1.4 the script uses the -Djava.system.class.loader system property to replace the system class loader with a weaving class loader allowing classes loaded from the CLASSPATH to be woven. For JDK 1.5 the JVMTI weaving agent is used allowing classes loaded by all class loaders to be woven. Versions of the JDK prior to 1.3 are not supported by the "aj" mechanism. Custom Integration 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 explicity restrict by class loader which classes can be woven. 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 define a list of concrete 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: ]]> 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. 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'. 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 seen by the weaver will be woven. When several configuration files are visible from a given weaving class loader their contents are conceptually merged (this applies to both aop.xml files and to aop.properties files as described in the next section). The files are merged in the order they are found on the search path (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 a declarative concrete aspect is declared in more than 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 file will automatically be generated when using the -outjar option of the AspectJ compiler. It will simply contain a (possibly empty) set of aspect elements, one for each concrete aspect included in the JAR. Configuring Load-time Weaving with Properties Files For memory constrained environments or those without support for XML a simple Java Properties file can be used to configure LTW. Just like XML files, META-INF/aop.properties files are loaded from the class loader search path. Everything that can be configured through XML can be configured using a Properties file, with the exception of declarative concrete aspects. For example: Weaver Options The table below lists the AspectJ options supported by LTW. All other options will be ignored and a warning issued. Option Purpose -1.5 Run the weaver in 1.5 mode (supports autoboxing in join point matching) -XlazyTjp Performance optimization for aspects making use of thisJoinPoint (non-static parts) -nowarn, -warn:none Suppress warning messages -proceedOnError Continue weaving even if errors occur (for example, "... already woven" errors) -verbose Issue informational messages about the weaving process -Xreweavable Produce class files that can subsequently be rewoven -Xnoinline Don't inline around advice. -showWeaveInfo Issue informational messages whenever the weaver touches a class file -XmessageHolderClass Provide alternative output destination to stderr for all weaver messages 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 JDK 1.5 the JVMTI agent can be used by starting the JVM with the following option: JRockit The JRockit agent is configured with the following JVM option: