123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- [[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.adoc#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.adoc#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.adoc#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.
|