diff options
Diffstat (limited to 'docs/devguide/ltw.adoc')
-rw-r--r-- | docs/devguide/ltw.adoc | 482 |
1 files changed, 482 insertions, 0 deletions
diff --git a/docs/devguide/ltw.adoc b/docs/devguide/ltw.adoc new file mode 100644 index 000000000..81d25ee3c --- /dev/null +++ b/docs/devguide/ltw.adoc @@ -0,0 +1,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. |