a powerful back-end for aspect-oriented programming - citeseer

25
1 C H A P T E R 9 JMangler – A Powerful Back-End for Aspect-Oriented Programming Günter Kniesel 1 , Pascal Costanza 1 and Michael Austermann 2 1 University of Bonn, Computer Science Dept. III, Römerstr. 164, D-53117 Bonn, Germany [email protected] , [email protected] 2 SCOOP GmbH, Am Kielshof 29, D-51105 Köln, Germany, [email protected] AOSD improves separation of concerns in software development by enabling the modular expression of crosscutting aspects. However, modular implementation of an as- pect requires techniques for “weaving” the aspect into the code of all classes that require it. Often, weaving is complicated by the unavailability or dynamic creation of source code. We present JMangler, a freely available framework for load-time transformation of compiled Java programs. We introduce the notions of generic class file interception and order-independent composition and explain JMangler’s contribution in these areas. Then we show how JMangler can be used for load-time weaving and for injecting hooks that en- able run-time weaving. JMangler enables behaviors beyond the ability of current high-level AOSD languages and systems. 9.1. INTRODUCTION AOSD improves separation of concerns by enabling the modular expression of crosscutting concerns. Modular implementation of a concern as one aspect 1 requires techniques to “weave” this implementation back into the code of all classes which require the concern. For in- stance, logging behavior expressed in one aspect must be “woven” into all the classes of a system whose activities should be recorded. 9.1.1. Challenges for Aspect Weaving A general solution for aspect weaving must deal different times and development contexts. Weaving can be performed before a program starts (compile-time or static weaving), at load-time (load-time weaving) or after a class was loaded (dynamic weaving). Static 1 We use aspect as a generic term for a module that encapsulates the implementation of one concern, abstracting from the particular language concepts of AspectJ [28], ComposeJ [7, 43], DJ [36], Hyper/J [38, 37], and other AOSD systems. Final version to appear in: R. Filman, T. Elrad, S. Clarke, M. Aksit (Eds.): „Aspect-oriented Software Development“, Prentice Hall, 2004.

Upload: others

Post on 11-Feb-2022

0 views

Category:

Documents


0 download

TRANSCRIPT

1

C H A P T E R 9

JMangler – A Powerful Back-End for Aspect-Oriented Programming Günter Kniesel1, Pascal Costanza1 and Michael Austermann2 1 University of Bonn, Computer Science Dept. III, Römerstr. 164, D-53117 Bonn, Germany [email protected], [email protected] 2 SCOOP GmbH, Am Kielshof 29, D-51105 Köln, Germany, [email protected]

AOSD improves separation of concerns in software development by enabling the modular expression of crosscutting aspects. However, modular implementation of an as-pect requires techniques for “weaving” the aspect into the code of all classes that require it. Often, weaving is complicated by the unavailability or dynamic creation of source code.

We present JMangler, a freely available framework for load-time transformation of compiled Java programs. We introduce the notions of generic class file interception and order-independent composition and explain JMangler’s contribution in these areas. Then we show how JMangler can be used for load-time weaving and for injecting hooks that en-able run-time weaving. JMangler enables behaviors beyond the ability of current high-level AOSD languages and systems.

9.1. INTRODUCTION

AOSD improves separation of concerns by enabling the modular expression of crosscutting concerns. Modular implementation of a concern as one aspect1 requires techniques to “weave” this implementation back into the code of all classes which require the concern. For in-stance, logging behavior expressed in one aspect must be “woven” into all the classes of a system whose activities should be recorded.

9.1.1. Challenges for Aspect Weaving

A general solution for aspect weaving must deal different times and development contexts. Weaving can be performed before a program starts (compile-time or static weaving),

at load-time (load-time weaving) or after a class was loaded (dynamic weaving). Static 1 We use aspect as a generic term for a module that encapsulates the implementation of one concern, abstracting from the particular language concepts of AspectJ [28], ComposeJ [7, 43], DJ [36], Hyper/J [38, 37], and other AOSD systems.

Final version to appear in: R. Filman, T. Elrad, S. Clarke, M. Aksit (Eds.): „Aspect-oriented Software Development“, Prentice Hall, 2004.

2 JMangler – A Powerful Back-End for Aspect-Oriented Pro gramming

weaving has the advantage of adding no unnecessary run-time penalty to a program’s exe-cution. However, in a dynamic class loading context, static weaving has the weakness that it cannot enforce aspect application to dynamically loaded classes. With static weaving, we have to trust the programmer to identify the classes that belong to a program. In Java2, the only way to be sure of which classes are actually used by a program is by checking during dynamic class loading.

Weaving might be applied in fully controlled contexts or in partly controlled contexts, depending how the weaved entities are created, stored and in which format they are avail-able. A program can be available as source code or compiled form. Source code and com-piled code can be entirely available beforehand or parts of it can be generated at run-time. Code can be stored locally or on a remote host. Full control means that every part of the program is available as source code and the code is stored locally and entirely available beforehand. Otherwise, we have only partial control. These relationships are illustrated in Table 9-1. Table 9-1 Contexts of weaving

controlled uncontrolled

Format source code compiled code

Creation beforehand during run-time

Storage local remote

Another challenge for weaving is managing variants. Not every incarnation of a sys-tem requires every aspect. In general, the number of possible variants grows exponentially with the number of possible adaptations. Depending on its context of use, an application might or might not need to integrate a logging aspect; might or might not apply an observer aspect for monitoring different subsets of the program state [24]; might or might not need to apply various security, synchronization exception handling policies [7]; and so forth. In his discussion of “jumping aspects,” for instance, Brichau [7] shows that different excep-tion handling policies are required if an application is deployed standalone or as a compo-nent of another application.

It could be prohibitive to generate all these variants statically and in advance. For these reasons, we need means for instrumenting the code base “on the fly,” depending on the actual needs of an application in a concrete deployment scenario.

9.1.2. Promises of Load-time Analysis and Transform ation (LAT)

Processing binaries at load-time makes it possible to address many of the challenges men-tioned above. Load-time analysis and transformation of class files (subsequently called LAT) can be used to implement load-time weaving or to insert code that performs run-time weav-

2 Since JMangler targets Java class files, all our discussions are in the context of the Java language (and conservative extensions thereof).

9.1. Introduction 3

ing. With a tool that can store transformed classes, LAT can also be used for static weaving of binary code.

LAT is inherently applicable to black-box components delivered by third parties in bi-nary format and is oblivious of the local or remote origin of binaries and of their static or dynamic creation.

LAT processes only classes relevant in a given application context. It can further pre-vent static version proliferation by taking advantage of dynamic information for selection of relevant transformations and for their specialization to current run-time conditions.

9.1.3. Aspect-oriented LAT with JMangler

The advantages of load-time transformation have motivated the development of various LAT tools and frameworks for Java class files. JMangler differs from other approaches in four main regards:

� It provides “generic interception” of application class files, allowing transforma-tion of any application classes independent of a custom JVM and of whether the transformed application uses own class loaders [33]. Therefore, it enables load-time adaptation in environments like application servers, which make heavy use of custom class loaders [31].

� As of version 3, JMangler has an open architecture that facilitates the integration of “weavers,” which perform the real transformation of Java class files. Weavers inherit JMangler’s generic interception ability, so they can be implemented on top of all existing class file transformation frameworks [5, 9, 10, 12, 13, 34, 35], including those that were not designed for load-time use.

� JMangler extends the Java class loading model by providing nested class loading: while loading and transforming a class, it is possible to load, analyze and trans-form further classes. This enables non-local load-time transformations, which depend on the contents of multiple class files.

� JMangler includes a weaver that provides a partial solution to the problem of as-pect interference. For a certain class of transformations it can guarantee that their joint use will not lead to undesired effects (interferences) even if the transforma-tions have been developed independently [33].

JMangler and its relation to other LAT tools are described in [11, 33]. Details of its use and various features that go beyond the scope of this paper are described in the tutorial that is available online and as part of the JMangler distribution [1]. A commercial devel-opment tool built with JMangler is presented in [31].

In Section 9.2 we introduce the notion of generic interception and explain how JMan-gler achieves generic interception. Then we present its open architecture, which enables other frameworks to use be used as plug-ins for JMangler (Section 9.3) and describe the treatment of non-local dependencies (Section 9.4).

In Section 9.5 we introduce the concepts behind the weaver included in JMangler, as far as necessary to understand its use in different AOSD scenarios. In Section 9.6 we dis-cuss a few typical application scenarios: development of higher-level aspect tools, load-time weaving, run-time weaving, and applications beyond the expressive power of existing

4 JMangler – A Powerful Back-End for Aspect-Oriented Pro gramming

high-level AOSD languages. In Section 9.8 we summarize ongoing and future work before concluding.

9.2. GENERIC INTERCEPTION

One of the main challenges in the design of JMangler was to hook into the class loading system in a way that ensures interception of all application class files without compro-mising portability. In this section, we first review related approaches in order to explain why this is an issue. Then we present the solution used by JMangler. The class loading archi-tecture and the resulting interception options are illustrated in Figure 9-1.

9.2.1. Java’s Class Loader Architecture

Java’s class loading mechanism [20, 21, 36] is implemented partly in the JVM – which contains the native implementation of the bootstrap class loader – and partly in the Java APIs – which contain the pure Java class java.lang.ClassLoader and subclasses thereof (Figure 9-1). The bootstrap class loader is responsible for loading system classes (that is, all classes that are part of the Java Development Kit and of standard extensions). The class ClassLoader is the common superclass of all class-loaders for application-specific classes.

Programmers can customize the class loading system by writing their own subclasses of ClassLoader. Custom class loaders are used for two reasons:

Customization Custom class loaders can customize the class loading process to fit the special needs of an application (e.g. remote or mobile code). Preproc-essing of loaded class files also falls into this category.

Name spaces Every class loader instance provides a separate name space. Even if different copies of the same class are loaded by different class loaders, they live in different name spaces and are treated as different classes by the JVM. So more than one “subapplication” can run in the same host application on the same JVM, without interfering with each other. This is a typical scenario in application servers.

9.2.2. Class-Loader Dependent Interception

The common way of intercepting class files at load-time is by writing a custom subclass of ClassLoader. For instance, BCEL, Javassist and JOIE include a custom class loaders.

The applicability of this approach is limited by the name space mechanism. Loading a class with one class loader automatically excludes processing the same copy of that class with another class loader. Therefore, class-loader–dependent interception is not possible in applications that have their own custom class loader(s). Common uses of custom class-loaders include application servers, distributed applications, and mobile code.

9.2. Generic Interception 5

9.2.3. JVM Dependent Interception

Class-loader–independent interception is achieved by Keller and Hölzle’s Binary Compo-nent Adaptation (BCA) [26, 27, 28, 29]. This was the first approach that enabled modifying compiled Java classes at load-time. However, BCA is implemented as a customized ver-sion of the Java Virtual Machine of JDK 1.1 for Solaris. It is therefore JVM dependent.

Figure 9-1 Four ways of intercepting classes at load-time: use of a custom class loader, extension of the class java.lang.ClassLoader, use of a custom JVM implementation, and use of a custom I/O DLL. Only the second option provides portable generic interception.

9.2.4. Platform Dependent Interception

Duncan and Hölzle [19] propose a non-intrusive alternative to BCA, library-based load time adaptation. They avoid having to customize the JVM by supplying a modified version of the dynamically-linked standard C library. To make their approach work with all JVMs on a given platform, they modify each file routine to check for class files. Unfortunately, library based adaptation requires a custom DLL to be provided for every operating system. Therefore, it is platform specific.

9.2.5. Portable Generic Interception

In contrast to the previous approaches, JMangler provides a portable and generic intercep-tion facility. JMangler achieves this by providing a modified version of the final method defineClass() in the class java.lang.ClassLoader. Because the modified behavior is en-forced for every subclass of ClassLoader, JMangler is activated whenever an application-specific class is loaded. This way, interception of all loaded application classes is possible, independent of a custom JVM or a platform-specific DLL. The limitation of this approach

6 JMangler – A Powerful Back-End for Aspect-Oriented Pro gramming

compared to BCA and DLL based load-time adaptation is that JMangler cannot transform system classes.

Every version of JMangler (1 through 3) is an alternative implementation scheme for this same basic idea. Version 1 provides the modification statically and enforces its utiliza-tion by prepending it to Java’s BootstrapClassPath when starting the JVM. Version 2 does not modify java.lang.ClassLoader. However, it achieves the same effect by intercepting all instantiations of concrete subclasses of java.lang.ClassLoader and by replacing them with instantiation of adapted versions these classes. Analysis and replacement of calls as well as creation of adapted version of class loaders is done at load time. Versions 3 and higher use the “HotSwap” API for Java3 [16, 17], to replace java.lang.ClassLoader with a version cre-ated at runtime. Discussion of further implementation issues, including the tradeoff be-tween the different schemes, is outside the scope of this paper.

9.3. OPEN ARCHITECTURE

JMangler (version 3 and higher) is more than just a load time transformation framework. It has an open architecture, which lets existing class file transformation frameworks transpar-ently take advantage of its generic interception mechanism. Thus it is a generic enabler for the load-time use of existing frameworks. Figure 9-2 illustrates the essential parts of the architecture. Key items include

Hook The “hook” implements the generic interception mechanism and extends Java’s linear class loading scheme by nested class loading (see Section 9.4). It manages intercepted class files as byte streams.

Weavers Weavers provide the real weaving functionality. Because generic in-terception is already performed by the hook, weavers can be implemented on top of all existing class file transformation frameworks [5, 9, 10, 12, 13, 34, 35], in-cluding those that were not designed for load-time use. Weavers are not con-strained in any way. In the simplest case, a weaver is a few classes that imple-ment the weaver interface on the basis of a particular transformation framework. However, weavers can provide arbitrary additional functionality beyond the one supported by the underlying framework. For instance, the JMangler distribution includes a weaver based on BCEL [5, 12, 13]. In addition to the functionality of BCEL, it provides specific support for controlling the weaving process to enable composition of independently developed transformer components (see Section 9.5). Other researchers have already expressed their interest in implementing weavers for ASM [9] and Javassist [10].

Weaver Interface The weaver interface is a collection of Java interfaces that establish the connection between the hook and the weavers. They mediate pass-ing of class file representations from the hook to the weavers and back again.

3 HotSwap provides dynamic class exchange as an extension of the Java Platform Debugger Architecture (JPDA). See http://java.sun.com/j2se/1.4/docs/guide/jpda/enhancements.html

9.4. Support for Non-Local Transformations 7

Figure 9-2 JMangler’s open architecture makes its generic interception mechanism available to every class file transformation framework.

9.4. SUPPORT FOR NON-LOCAL TRANSFORMATIONS

The class loading mechanism of Java is linear: every class is loaded completely, be-fore another class starts loading. Figure 9-3 illustrates the corresponding flow of raw class files from the hook to the active weaver. The weaver creates a higher-level representation and transforms this representation before converting it back to a byte stream for the JVM.

Figure 9-3 Linear loading of class files: every class gets loaded and transformed completely, before another class can be loaded.

This scheme is sufficient for the implementation of local analyzes and transfor-mations, which need information just about one class at a time. Examples include the in-troduction of accessor methods or access counters in a class, and simple before, after, and around advice.

8 JMangler – A Powerful Back-End for Aspect-Oriented Pro gramming

Figure 9-4 JMangler provides nested class loading: while loading and transforming a class, it is pos-sible to load, analyze and transform further classes. All transformed classes are stored for later non-local analyzes. The numbers in the figure indicate the sequence of steps per-formed.

However, many analyzes and transformations are non-local, because they depend on the contents of multiple class files. For instance, addition of forwarding methods requires information about the interface of the class being forwarded to.

Non-local dependencies impose problems for load-time weaving. On one hand, the in-strumentation of one class must be completed before handing the class over to the JVM (as the HotSwap API of JDK 1.4 does not support addition of methods and fields at run-time). On the other hand, instrumentation of a class cannot be completed before further classes, on which it depends, are loaded and analyzed. This is not possible with the linear class loading model of Java.

To resolve this problem, JMangler extends the Java class loading model by providing nested class loading: while loading and transforming a class, it is possible to load, analyze and transform other classes. As illustrated in Figure 9-4, classes loaded and transformed during the processing of another class are stored and only passed to the JVM after comple-tion of the suspended class loading process. Storage of transformed classes also enables their use for later non-local analyzes (without having to repeat the same transformations again).

Nested loading is implemented in the MemoryClassLoaderHook of JMangler. It is thus available to every plug-in. Linear class loading is supported by the SieveClassLoaderHook to avoid the overhead of nested loading when it is not required. Applications can choose the preferred loading model simply by setting an option in a configuration file.

9.5. THE BCEL WEAVER

In addition to the generic interception and nested loading functionality available to every weaver, JMangler also includes a fully functional weaver. The BCEL weaver provided with JMangler offers an API for the implementation of transformers components (or simply, transformers), and the ability to load sets of transformers and apply their transformations to all classes of a program. Added benefits over the direct use of BCEL [5, 12, 13] are the no-

9.5. The BCEL Weaver 9

tion of transformer components, the simple composition of such components based on a textual configuration file, support for enforcing binary compatibility of transformations, and support for conflict-free automatic composition of independently developed trans-former components (see Section 9.5).

9.5.1. Transformations and Aspects

Weaving can be seen as transformation of classes. Accordingly, an aspect can be in-terpreted as the specification of such a transformation that determines what is to be trans-formed and how it should be transformed. This can be generalized as the specification of conditions, interface transformations and code transformations.

Conditions. Conditions are arbitrary Java Boolean expressions. Conditions enable implementation of the filter conditions of ComposeJ [8, 45] and the pointcut definitions of AspectJ [30].

Interface transformations. By default, JMangler supports all transformation of class files that do not violate binary compatibility [22]

� Addition of classes, interfaces, fields and methods

� Changes of a method’s throws clause

� Changes of a class’s extends clause that do not reduce the set of direct and indi-rect superclasses

� Changes of a class’s implements clause that do not reduce the set of direct and indirect superinterfaces

� Addition and changes of annotations that respect binary compatibility,

These transformations allow implementing the interface modifications expressible in current aspect languages, e.g. the introductions of AspectJ [30] or the hypermodule defini-tions of Hyper/J [39, 40]. If desired, the system can also perform transformations that break binary compatibility, e.g. removal of methods.

Code transformations. Code transformations are changes of method code. They al-low expressing the advices of AspectJ, traversals of DJ [38], filter actions of Composition Filters [8, 45] and method combination rules of Hyper/J.

9.5.2. Transformers

Conditions and transformations that conceptually belong together can be implemented in one transformer component.

Transformers are Java classes that implement specific interfaces (InterfaceTrans-former and CodeTransformer). A transformer component that implements the operations of the InterfaceTransformer interface can perform one or many related interface transforma-tions. The same is true for code transformations. A transformer can play both roles by im-plementing both interfaces. Thus it is possible for one component to provide a consistent set of related interface and code transformations. For instance, an accessor transformer needs interface transformations to create the accessor methods and code transformations to enforce their invocation in place of direct variable accesses.

10 JMangler – A Powerful Back-End for Aspect-Oriented Programming

9.5.3. Use of Transformers

Transformers are the basic unit of deployment and composition in the BCEL weaver. The transformers that should be applied to the classes of a program are specified in a configura-tion file that is passed as parameter to the invocation of JMangler along with the main class of the program and the program arguments (see Appendix A).

This scheme eases transformer component deployment in two ways: there is no need to write any code in order to apply and compose transformers and the application of trans-formers is independent of the base programs to which they should be applied.

9.5.4. Unanticipated Composition of Transformers

Multiple transformers can be applied jointly to the same program by listing them together in one configuration file and by specifying the desired order of execution. This provides a simple way of composing existing transformers. However, it also raises one of the main challenge in the design of JMangler and of aspect systems in general: unanticipated composi-tion of independently developed transformers.

The main issue here is that an execution order cannot be specified for transformers that have been developed independently without their being specifically designed for joint use. Whenever independently developed transformers are provided as black boxes (which is the core idea of component oriented development), the composer most likely does not have enough knowledge of their design and implementation in order to decide on the proper composition order. The same is true for independently developed aspects.

In this context, the problem is to determine automatically in which order transformers should be combined to achieve the intended semantics while avoiding unwanted side ef-fects.

In the current version, JMangler does not have any way of determining order auto-matically4. However, we have reduced the scope of the problem by identifying a class of transformations for which order is irrelevant. It is possible to apply them iteratively until a fixpoint is reached. In particular, iterative application of a set of positively triggered, monotonic interface transformations5 is guaranteed to produce a unique fixpoint, inde-pendent of the order in which the transformations are applied. Section 9.5.6 presents a short example that illustrates the effect of fixpoint iteration. A detailed one is contained in [33].

This insight has influenced the design of JMangler in three ways

1. There is a conceptual and API-level separation of interface transforma-tions and code transformations.

2. JMangler supports by default only interface transformations that pre-serve binary compatibility, which is a different way of saying that it supports only monotonic interface transformations.

4We have developed an automatic conflict detection and ordering mechanism [4, 30]. However, its integration into JMangler is a topic for fu-

ture work. 5 A transformation is positively triggered, if it is initiated by the existence of a particular property of a program, but must not be caused by the absence of a property. A transformation is monotonic if it only adds properties to a program but does not remove properties.

9.5. The BCEL Weaver 11

3. JMangler provides the ability to iterate interface transformations until a fixpoint is reached.

9.5.5. The Transformation Process

Figure 9-5 illustrates the above transformation process. The transformers specified in the configuration file passed as parameter to JMangler are applied to every loaded class. The transformation proceeds in two phases.

In the first phase, interface transformers are activated:

� Each interface transformer analyzes the classes under consideration, decides which transformations are to be carried out and re-quests these transformations from the BCEL weaver.

� The weaver collects the transformation requests of all interface transformers, checks the validity of the requested transformations (with respect to binary com-patibility / monotonicity), and performs the transformations (in an arbitrary or-der).

� This process is repeated until no further interface modification requests are is-sued. If an illegal transformation is detected the process is aborted.

In the second phase, the code transformers are activated. They are executed exactly in the order indicated in the configuration file. Each code transformer analyzes the classes un-der consideration, decides which transformations are to be carried out and performs these transformations directly, using the BCEL API [5, 12, 13].

BCEL weaver

sequential

execution

fixpointiteration

... ...

BCEL weaver

sequential

execution

fixpointiteration

... ...

Figure 9-5 Transformation process implemented in JMangler’s BCEL weaver: First the interface transformations are applied iteratively until a fixpoint is reached, then the code transform-ers are applied sequentially in the order specified in the configuration file.

12 JMangler – A Powerful Back-End for Aspect-Oriented Programming

9.5.6. An Example

Consider a logging transformer, whose purpose is to log execution of all methods that call certain security sensitive methods. It can be implemented as a combined interface and code transformer.

Assume method m in class class should be logged. Then the interface transformer part creates a method m_log in class, which calls m after performing logging actions. The code transformer replaces calls to the original method m by calls to m_log at every joinpoint where logging should be performed.

Now assume another, independently developed interface transformer that adds a method to the program, say more2Log, which also fulfils the criterion for being logged.

Iterative execution of the two interface transformers guarantees that there exists a more2Log_log method when the logging code transformer is activated. Thus the invariant assumed by the code transformer is fulfilled.

If each transformer were executed just once, their user would need to know enough of their internal working in order to determine that the second transformer needs to be acti-vated before the first one. Even worse, if the transformers were mutually dependent there would be no way of using them together without iterative application [33].

public class MyTransformer implements InterfaceTransformerComponent { // the interface to be added private String interfaceName = "java.lang.Serializable"; // this method will be invoked by JMangler to compute the interface // transformations requested by this transformer component public ExtensionSet transformInterface(UnextendableClassSet cs) { ExtensionSet es = new ExtensionSet(); // ananlyse and tranform all classes in the class set: Iterator iter = cs.getIteratorForTransformableClasses(); while (iter.hasNext()) { // the BCEL representation of a class file ClassGen clas = (ClassGen)iter.next(); // the conditional transformation if (!Condition.implementsInterface(clas, interfaceName)) { es.addInterfaceToClass(this,clas.getClassName(),interfaceName); } } return es; // give JMangler the collected transformation requests } }

Figure 9-6 An interface transformer that adds the interface java.lang.Serializable to each class that does not implement it already.

This example illustrates that fixpoint iteration provides the guarantee that each in-terface transformation is applied to the entire program including parts added by other inter-face transformers. Code transformers can therefore rely on the fact that the invariants they assume are indeed met throughout the program.

Now that we know how to compose and apply existing transformers with JMangler and understand the transformation process, the only missing part of the picture is how to write transformers. This is explained separately for interface and code transformers.

9.6. Usage Scenarios 13

9.5.7. Creation of Interface Transformers

From a technical point of view an interface transformer is a Java class that implements the interface InterfaceTransformerComponent. The main method in this interface,

ExtensionSet transformInterface(UnextendableClassSet6)

analyzes a set of classes and determines a set of extensions that should be performed on these classes.

For instance, the transformer shown in Figure 9-6 requests addition of the interface java.lang.Serializable to each class in the class set passed as parameter.

A complete version of this and of many other transformers can be found on the JMan-gler website and in the samples package of the JMangler distribution. The samples can be taken as templates for writing interface transformers. This is easily done after a short study of the classes ClassGen and ExtensionSet. The class ClassGen is part of the BCEL library [5, 12, 13] and provides the basic operations to analyze and transform a class file. All monotonic interface modifications listed in Section 9.5.1 have their counterparts as meth-ods of the ExtensionSet set class whose purpose is to collect transformation requests and execute them under the control of JMangler as described in Section 9.5.5.

9.5.8. Creation of Code Transformers

A code transformer is a Java class that implements the interface CodeTransformerComponent. The main method in this interface,

transformCode(UnextendableClassSet)

analyzes the set of classes passed as parameter and modifies them directly using the BCEL API.

Creating code transformations requires an above-average understanding of the internal workings of the Java Virtual Machine, its instruction set, its class file format and the BCEL library. However, since many tasks follow quite fixed idioms, learning to program at this level is not as difficult as it may appear. A tool that is very helpful in this context is the BCELifier [4]. From a plain Java method it creates the BCEL code that will create exactly the input method, when executed. BCELifier is provided on the BCEL website and is also included in the JMangler 3 release.

An example of an advanced application, code coverage, that can be conveniently ex-pressed in about one page of code is presented in Appendix B. The implementation of the example is explained in detail in Appendix A. A short introduction to code coverage is given in Section 9.6.3.2.

9.6. USAGE SCENARIOS

In this section we discuss typical application scenarios for JMangler: load-time weaving (Section 9.6.1), run-time weaving (Section 9.6.2), and applications beyond the expressive power of existing high-level AOSD languages (Section 9.6.3).

6 An UnextendableClassSet is unextendable just in the sense that transformers cannot add or remove classes from it. However, they can

modify its classes and the framework can add new classes that get loaded during the transformation process.

14 JMangler – A Powerful Back-End for Aspect-Oriented Programming

9.6.1. Load-time Weaving with JMangler

The straightforward use of JMangler for AOSD development is implementation of load-time weaving. We talk about load-time weaving if functionality is introduced at load-time into an application and activated permanently for the current run of the application.

In the simplest case, the introduced functionality is the intended functionality of an aspect, e.g. tracing behavior. The examples given in the previous section all fall into this category, so we do not go here into further details. Instead, we pick the ObjectTeams pro-ject as an interesting large application that uses JMangler for load-time weaving. Ob-jectTeams [25, 37, 44] is a programming model that builds on research and experience concerning several recent approaches, mostly from the field of aspect-oriented software development.

The compiler for ObjectTeams/Java adapts classes of the system core at load time us-ing JMangler (with the BCEL weaver). This enables running several ObjectTeams applica-tions with different adaptations to shared modules, although shared modules exist only as a single jar file. No source code is needed, nor are different adapted variants stored in the file system, thus significantly relieving configuration management and deployment.

Thus, on the one hand, ObjectTeams fully exploits the benefits of load-time weaving with JMangler. On the other hand programmers using ObjectTeams/Java need not know about JMangler since input for transformations is generated by the compiler and invocation of JMangler is encapsulated in the command for starting the Java Virtual Machine.

9.6.2. Run-time Weaving with JMangler

An advanced use of load-time weaving is to create a system that performs run-time weav-ing. In such a scenario, it is not the logging code that is weaved at load-time but the code that enables dynamic inclusion of logging and other “aspects”. This is the way how As-pectWerkz [2] uses load-time waving to provide a dynamic, aspect-oriented system with a high, user friendly abstraction level. In order to be generally applicable, AspectWerkz adopted (and adapted) the generic interception approach of JMangler.

Yet another variant of this idea is described in [42]. Starting from the formal seman-tics of a core language which includes method call interception (MCI), different implemen-tation models are examined regarding expressiveness, simplicity, and efficiency. One sug-gested alternative is to perform static weaving of code that enables dynamic method call interception and to eliminate at load-time the hooks that are not relevant for that particular invocation of a program. In this scenario, the load-time transformation is used to unweave code that only slows down the application without providing any functional benefit. Thus the load-time transformer behaves as an optimizer for the statically weaved code that per-forms dynamic weaving.

9.6.3. Advanced Features

For the sake of simplicity, ease of use, or avoidance of conceptual problems, AOSD lan-guages abstract away some of the expressive power available at the byte code level. We discuss here two cases: (1) parametric and (2) fine-grained analysis and transformation.

9.6. Usage Scenarios 15

9.6.3.1. Parametric Introductions and Advices

The logging example in Section 9.5.6 illustrates that one transformer can compactly ex-press interface and code transformations that are parametric with respect to the exact name of the manipulated entities. The italic style of the method name m (see Section 9.5.6) indi-cates that this is a variable ranging over the names of all methods that fulfill the conditions for being logged. Correspondingly, the name m_log is a template for names of logging methods to be created. For instance, if the transformer determines at run-time that the methods meth1, …, methn should be logged, the template expands to meth1_log, ..., methn_log.

In AspectJ terminology, our logging example expresses a possibly infinite number of consistent “introductions” and “advices” in one single transformer. This is impossible in AspectJ, which does support only a limited for of parametric names in pointcuts but does not support parametric names in introductions and advices. Put differently, AspectJ can perform wildcard matching of existing names, but it offers no mechanism to create new names that depend on the matched ones. Instead, one has to know statically all names of methods to be logged and write the same introduction code (up to names) for each and every method.

The step from AspectJ’s wildcard substitution to “parametric aspects” is a significant change in expressiveness [23]. Moving from statically known names to name variables means making the step from a closed to an open world. This results in extended applicabil-ity and expressiveness but also raises additional interference problems, as illustrated by the logging example in Section 9.5.6. The lack of mechanisms for dealing with aspect interfer-ence in open worlds is one important reason that prevents many aspect systems from offer-ing parametric transformations.

Disregarding aspect interference, ComposeJ [45] could support a similar functionality by means of meta filters [6]. However, meta filters are not yet implemented. For Hyper/J [39, 40], parametricity seems to be difficult to achieve, due to its declarative completeness requirement (every name referred to must be declared in the referring module).

It seems that the only aspect systems that already provide parametric introductions and advices are systems based on logic programming, e.g. TyRuBa [13, 14] and SOUL [41]. An interesting new contribution in this context is the concept of “parametric introductions” in Sally [23]. It is interesting to note that these systems are similar to JMangler in that the backtracking mechanism of logic programming is another way of implementing fixpoint iteration.

9.6.3.2. Code Coverage

The common abstraction supported by AOSD languages is interception of variable ac-cesses and method calls. In [19] Filman and Havelund consider the ability to “intercept” finer-grained structures as a desirable improvement to aspect languages. In this section we give an example application where “interception” at the level of individual statements or individual lines of code is essential: code coverage.

Code coverage is a measure for the percentage of a program exercised (“covered”) by the tests run on that program. Coverage is reported on the basis of metrics. For instance, statement coverage reports the percentage of statements in a program that have been exe-

16 JMangler – A Powerful Back-End for Aspect-Oriented Programming

cuted during testing. A good coverage tool will also indicate the places in a program that have not been covered.

In showing how JMangler can be used to implement a coverage tool we concentrate on line coverage, the percentage of lines of code covered by tests.

A code transformer for collecting line coverage information is listed and explained in detail in the appendices A and B. CC4J, a full-fledged, commercial code coverage tool de-ployed in large scale industrial software projects is described in [31]. Its core is a similar transformer for the BCEL weaver of JMangler (Figure 9-7). Unlike the vanilla version pre-sented in the appendix, it supports collecting coverage information from multiple test runs and their user-friendly presentation that immediately directs programmers to the untested spots of the application. Also, it is considerably more efficient.

Java Virtual Machine

instrumentedclass files

class files config

Class LoaderSystem

CC4J GUICC4J GUICC4J ReportGenerator

CC4J ReportGenerator

CC4J MergerCC4J Merger

coverage files of other test runs

CCFCCF

CCFCCF

CCFCCFCCFCCF

JMangler CC4JTransformer

CC4JTransformer

CCFCCF

code coverage files with info

about executed lines of code

Java Virtual Machine

instrumentedclass files

class files config

Class LoaderSystem

CC4J GUICC4J GUICC4J ReportGenerator

CC4J ReportGenerator

CC4J MergerCC4J Merger

coverage files of other test runs

CCFCCF

CCFCCF

CCFCCFCCFCCF

CC4J GUICC4J GUICC4J ReportGenerator

CC4J ReportGenerator

CC4J MergerCC4J Merger

coverage files of other test runs

CCFCCF

CCFCCF

CCFCCFCCFCCF

JManglerJMangler CC4JTransformer

CC4JTransformer

CC4JTransformer

CC4JTransformer

CCFCCF

code coverage files with info

about executed lines of code

CCFCCFCCFCCF

code coverage files with info

about executed lines of code

Figure 9-7 Architecture of CC4J, a commercial code coverage tool implemented with JMangler.

Summarizing, JMangler offers considerable expressive power but is clearly a tool for “experts.” It is typically used as a back-end for the implementation of easier to use, high-level aspect tools and systems. This is reflected in all the case studies presented in this sec-tion.

9.7. RELATED WORK

JMangler has often been described as a class file transformation framework and has conse-quently been compared to similar tools [33]. However, JMangler version 3, described in this paper, clearly separates the concerns of generic class file interception, nested class loading, control of the weaving process and class file manipulation. Its contributions to the state of the art address the first three concerns. Its open architecture makes the system in-dependent of a particular transformation framework. This is a step forward compared to the work we reported in [10, 33].

9.8. Conclusions and Future Work 17

Related to the generic interception mechanism, we know of only one recently started similar project. As of May 2003, the BeeSee system (http://besee.sourceforge.net/) is being redesigned to provide a generic interception mechanism “largely inspired by JMangler 3.x” (see the javadoc of class “Starter”). The aim of the development is to provide a light-weight version of JMangler’s basic mechanisms at the price of eliminating support for more advanced features like nested class loading and iterative application of transformers.

Related to nested class loading we know of no similar work yet. Related to weaving control, effects similar to the iterative application of transformers

can be achieved in systems based on logic programming (e.g., SOUL) [14, 41], due to their inherent backtracking mechanism. JMangler’s iteration mechanism is a means of resolving potential conflicts between differ-ent transformations. Dounce et al. present a more advanced approach to detection and reso-lution of aspect-aspect conflicts [17]. Their work is based on an event model of aspect-oriented programming and additional annotations of aspect programs. Bardey and Kniesel’s work provides a similar effect based on detection of dependencies among conditional pro-gram transformations [3, 32]. Störzer and Krinke present an approach to aspect-base inter-ference based on traditional program analysis techniques in [43].

9.8. CONCLUSIONS AND FUTURE WORK

In this paper we have discussed why load-time analysis and transformation is a promising approach to various challenges of aspect weaving: missing source code of base entities, their dynamic creation and version proliferation.

We have introduced JMangler, a framework that enables interception and transforma-tion of all loaded application classes. The generic interception mechanism is portable across operating systems, independent of a custom JVM implementation and effective also in applications that use custom class loaders (application servers, for instance). JMangler provides nested class loading as an extension of the linear Java class loading model, thus enabling load time transformations that are dependent on the contents of multiple classes. It supports the integration of weavers implemented on top of different class file transforma-tion frameworks and provides a complete weaver implemented using BCEL.

The BCEL weaver enables composition and joint use of transformers components that have been developed independently. Automatic order-independent composition is possible for positively triggered, monotonic interface transformations. Only the order of code trans-formations has to be specified explicitly, since it is essential for the behavior of the result-ing code.

An AOSD system can translate its aspects to JMangler transformer components and let them be applied at load-time. Load-time transformation can be used to weave applica-tion-level functionality or to inject code that performs run-time weaving. Load-time weaving with JMangler is able to process also classes that are created and loaded dynamically, from an arbitrary local or remote origin. Since weaving is done at load-time only the aspects get weaved that are useful for that particular invocation of a pro-gram. Thus static creation of potentially unnecessary variants is avoided.

If desired, variants created at load-time can be stored for later use. JMangler trans-formers allow the implementation of “parametric aspects” that express compactly a poten-tially infinite number of “introductions” and “advices”. It is possible to define “pointcuts”

18 JMangler – A Powerful Back-End for Aspect-Oriented Programming

at the level of individual statements or line numbers. This enables very fine grained control over a program’s behavior, as exemplified by the CC4J code coverage system.

Recent follow-up work has focused on improving automatic handling of aspect inter-ference. We have developed a tool that allows automatic detection and resolution of inter-ferences between transformations [3, 32]. The integration of the interference checking tool with JMangler is a topic of ongoing work.

Information on the most recent state of JMangler can be found at http://javalab.cs.unibonn.de/research/jmangler/.

Acknowledgements

We want to thank Robert Filman, Shigeru Chiba, and Tzilla Elrad, who have provided many critical remarks on an earlier draft of this paper. Their knowledgeable comments have significantly contributed to the quality of its presentation. All remaining errors are, of course, ours.

Discussions with the participants of the JMangler tutorial and demonstration at AOSD 2003 have provided much encouragement and sharpened our understanding of current needs and relevant future work. In this context, thanks go in particular to Andrew Clement, Bruno Harbulot, Eric Hilsdale, Mik Kersten, Renaud Pawlak, Andrei Popovici, Christa Schwanninger, Lionel Seinturier, and Matthew Webster.

We also want to thank Lodewijk Bergmanns and Stephan Herrmann for providing in-formation about the JMunger and ObjectTeams projects early during their development. Stephan Herrmann has also provided a lot of helpful feedback on bugs and possible im-provements in various versions of JMangler.

Most of this work has been performed within the TAILOR project, directed by profes-sor A. B. Cremers and partly supported by Deutsche Forschungsgemeinschaft (DFG) under grant CR 65/13.

APPENDIX 9.A. SIMPLE CODE COVERAGE

In Section 9.6.3.2 we presented code coverage as an example of an application that requires ”interception“ at the line or statement level. Here we show how a tool that collects line coverage information can be implemented easily as a code transformer.

In the following text, line numbers in brackets refer to the source code shown in Ap-pendix B. The example is fully functional. It can be downloaded from the JMangler web-site along with other sample transformers (see http://javalab.cs.uni-bonn.de/research/jmangler/).

9.A.1. Implementation of the CodeCoverTransformer

First of all, we need to implement a class CodeCoverTransformer that implements the inter-face CodeTransformerComponent (9). Inside the CodeCoverTransformer class we provide all the necessary ingredients for our tool, including the actual recordCoveredLine method (11-12). It is called at run time while all the other elements of CodeCoverTransformer are exe-

Appendix 9.A. Simple Code Coverage 19

cuted at load time. In our simple code coverage tool, recordCoveredLine just prints a mes-sage to the standard output stream.

The most interesting method required by the CodeTransformerComponent interface is transform-

Code (43ff) that is called by the JMangler framework at load time (according to the Holly-wood principle: “Don’t call us, we’ll call you!”). JMangler passes an UnextendableClassSet to transformCode that contains all the classes loaded by a class loader within a session. The getItera-

torForTransformableClasses method allows us to iterate over all classes in that set that still need to be transformed, which is what we want to do (45-46). At each step, the iterator returns an instance of ClassGen7 (47).

From each ClassGen instance we request the following information that we need later on:

� Its name (48);

� Its constant pool (51), a standard ingredient of java class files that contains all the constant data used within a class;8

� An instruction factory (52), a BCEL utility class that allows the creation of com-plex bytecode instructions in a convenient way;

� Its methods as declared in the corresponding Java source file (53).

Before we proceed we perform a sanity check in order to prevent the CodeCoverTrans-former to transform itself (49). We then iterate over all non-native and non-abstract meth-ods of the current transformable class (55-57) - that is, all the methods that are actually im-plemented, in Java bytecode. We create an instance of MethodGen for each of those methods in order to be able to modify it (59). Next, we request an InstructionList instance (60) and the line number table (61) from the current method. The instruction list is a modifiable data structure that represents the actual method code.

The line number table [36] allows us to determine the positions in the instruction list for each line of the original Java source code. For instance, in Table 9-2, the statements implementing line 3 start at program counter value 0.

Table 9-2 A sample line number table

Source file Byte code

1 public class Sample { 2 void sayHello() { 3 System.out.println("Hello"); 4 return; 5 } 6 }

Method void sayHello() 0 getstatic #8 3 ldc #1 5 invokevirtual #9 8 return

Line number Program counter

3 0

7 This class is part of the BCEL library and represents a Java class as a modifiable data structure. BCEL distinguishes between modifi-able entities that end in ...Gen (like ClassGen, MethodGen, FieldGen and so on) and their non-modifiable counterparts. 8 This includes constant numbers and string literals, but also class, method and field names, for example.

20 JMangler – A Powerful Back-End for Aspect-Oriented Programming

So we iterate over the line number table (63-64) and call the auxiliary method addRe-cordCaller (65-66) to perform the modification at each step (see below).

Since calls to recordCoveredLine make use of the Java operand stack, we need to call setMaxStack for each MethodGen instance afterwards (68) in order to let BCEL determine its correct (static) size. Then we convert the MethodGen instance back to its non-modifiable form (as required by BCEL) (69), and finally write all the modified methods back to the ClassGen instance (71).

The remaining actions required by BCEL and the Java class loader framework are all performed by JMangler, so we have completed all the necessary steps by now.

The addRecordCaller method (21ff) works as follows. First, it creates the call se-quence by generating a new instruction list (26-36). This instruction list consists of first pushing the name of the current class onto the operand stack (LDC_W9) (28-29), then pushing the line number onto the operand stack (also LDC_W) (31), and finally calling recordCovered-Line (33-36) which pops the two arguments from the operand stack. The latter call is gen-erated by createInvoke in InstructionFactory that takes some meta information about re-

cordCoveredLine (the name of its defining class, its own name and its return and parameter types) and the INVOKESTATIC instruction for class method invocations; createInvoke also takes care of the correct handling of the constant pool.

This new call sequence is inserted into the instruction list (38). We insert the new call sequence before the given position, so that a source line is recorded even when it throws an exception (which may be the correct specified behavior of your program at that line). Be-cause the current line possibly is the branch target of other instructions (for example of an if/then/else statement), we finally need to redirect all the branches from the old position to the start of the new call sequence in order to have the line number recorded in all cases (39).

9.A.2. Activation

In order to activate the CodeCoverTransformer described in the previous section, we need to define a configuration file for JMangler as partly explained in Section 9.5.3. For our pur-poses, the following three lines are sufficient.

transformer CodeCoverTransformer { name = org.cs3.jmangler.samples.codecoverage.CodeCoverTransformer; }

The first line of the configuration file assigns a short name to the fully qualified class name given in the second line.10 This declaration also activates the named transformer.

The scheme of using configuration files for transformer activation eases deployment in two ways: there is no need to write any code in order to apply a certain transformer, and the application of a transformer is independent of the base program to which it should be applied. The configuration file containing the above lines, say codecover.config, can be used on arbitrary Java programs.

jmangler --cf codecover.config AnArbitraryJavaProgram

9 Load Constant with wide index – wide index is an index into the constant pool possibly greater than 255 10 Such short names are convenient in more sophisticated configuration files that, for example, express relationships between different transformers.

Appendix 9.A. Simple Code Coverage 21

This invocation starts the JVM, loads JMangler and the transformers specified in the con-figuration file, and then initiates execution of the program passed as a command line pa-rameter.

Now suppose we are given the slightly more interesting variant of “Hello, World”: 1: public class HelloWorld { 2: public static void main(String[] args) { 3: if (args.length > 0) 4: {System.out.println(args[0]);} 5: else 6: {System.out.println("Hello, World!");} 7: } 8: }

We start the CodeCoverTransformer on an invocation of “HelloWorld” that has no arguments and observe the output.

>> jmangler --cf codecover.config HelloWorld covered line 3 in class HelloWorld covered line 6 in class HelloWorld Hello, World! covered line 7 in class HelloWorld

11

Obviously, line 4 has not been covered. So we conclude that in order to guarantee complete coverage of all possible branches we need to extend our test suite by a call of the “Hello, World” application that has a non-empty argument.

We hope that this example conveys the following facts. On the one hand, a JMangler user needs an above-average understanding of the internal workings of the Java Virtual Machine, its instruction set, its class file format and a class file transformation framework like the BCEL library. So JMangler is clearly a tool for experts. On the other hand, JMan-gler allows one to implement powerful transformers in a relatively convenient way, as il-lustrated by the compact and straightforward code given in Appendix B.

9.A.3 Source Code for the Code Coverage Tool

1: import de.fub.bytecode.*; 2: import de.fub.bytecode.generic.*; 3: import de.fub.bytecode.classfile.*; 4: import org.cs3.jmangler.*; 5: import org.cs3.jmangler.tau.*; 6: import org.cs3.jmangler.supplier.*; 7: import java.util.*; 8: 9: public class CodeCoverTransformer implements CodeTransformerComponent { 10: 11: public static void recordCoveredLine(String className, int line) 12: {System.out.println("covered line "+line+" in class "+className);} 13: 14: private static String recorderMethName = "recordCoveredLine"; 15: private static Type recorderReturnType = Type.VOID; 16: private static Type[] recorderArgTypes = new Type[2]; 17: {recorderArgTypes[0] = Type.STRING; 18: recorderArgTypes[1] = Type.INT;} 19:

11 Line 7 is covered because the Java compiler places the implicit return statement for method main at that line.

22 JMangler – A Powerful Back-End for Aspect-Oriented Programming

20: 21: public void addRecordCaller 22: (ClassGen classGen, ConstantPoolGen poolGen, 23: InstructionFactory factory, int lineNo, 24: InstructionList intoList, InstructionHandle beforeHandle) 25: { 26: InstructionList recordCaller = new InstructionList(); 27: 28: InstructionHandle callHandle = recordCaller.append( 29: new LDC_W(poolGen.addString(classGen.getClassName()))); 30: 31: recordCaller.append(new LDC_W(poolGen.addInteger(lineNo))); 32: 33: recordCaller.append( 34: factory.createInvoke("CodeCoverTransformer", recorderMethName, 35: recorderReturnType, recorderArgTypes, 36: Constants.INVOKESTATIC)); 37: 38: intoList.insert(beforeHandle, recordCaller); 39: intoList.redirectBranches(beforeHandle, callHandle); 40: } // addRecordCaller 41: 42: 43: public void transformCode(UnextendableClassSet classSet) 44: { 45: Iterator classIterator = classSet.getIteratorForTransformableClasses(); 46: while (classIterator.hasNext()) 47: {ClassGen classGen = (ClassGen)classIterator.next(); 48: String className = classGen.getClassName(); 49: if (className.equals(this.getClass().getName())) continue; 50: 51: ConstantPoolGen poolGen = classGen.getConstantPool(); 52: InstructionFactory factory = new InstructionFactory(classGen); 53: Method[] methods = classGen.getMethods(); 54: 55: for (int methInd = 0; methInd < methods.length; methInd++) 56: {Method meth = methods[methInd]; 57: if (meth.isNative() || meth.isAbstract()) continue; 58: 59: MethodGen methGen = new MethodGen(meth, className, poolGen); 60: InstructionList instList = methGen.getInstructionList(); 61: LineNumberGen[] lines = methGen.getLineNumbers(); 62: 63: for (int lineInd = 0; lineInd < lines.length; lineInd++) 64: {LineNumberGen line = lines[lineInd]; 65: addRecordCaller(classGen, poolGen, factory, line.getSourceLine(), 66: instList, line.getInstruction());} 67: 68: methGen.setMaxStack(); 69: methods[methInd] = methGen.getMethod();} 70: 71: classGen.setMethods(methods);} 72: } // transformCode 73: 74: 75: public void sessionStart() {} 76: public void sessionEnd() {} 77: public String verboseMessage() {return toString();} 78: 79: } // CodeCoverTransformer

Appendix 9.A. Simple Code Coverage 23

REFERENCES

1. AK�IT, M., Ed. 2003. 2nd Int'l Conf. Aspect-Oriented Software Development (AOSD), (Boston). ACM.

2. AspectWerkz. AspectWerkz homepage. http:aspectwerkz.codehaus.org/.

3. BARDEY, U. 2003. Abhängigkeitsanalyse für Programm-Transformationen (in German). Diploma thesis, Uni-versity of Bonn.

4. BCEL. BCEL homepage. http://jakarta.apache.org/bcel/.

5. BERGMANS, L. AND AK�IT, M. 2001. Composing crosscutting concerns using composition filters. Comm. ACM 44, 10 (Oct.), 51–57.

6. BERGMANS, L., AK�IT, M., AND TEKINERDO�AN, B. 2001. Aspect composition using composition filters. In Software Architectures and Component Technology, M. Ak�it, Ed. Kluwer Academic Publishers, Boston, 357–382.

7. BRICHAU, J., MEUTER, W. D., AND DE VOLDER, K. 2000. Jumping aspects. In Workshop on Aspects and Dimen-sions of Concerns (ECOOP) (Cannes, France). http://trese.cs.utwente.nl/Workshops/adc2000/papers/Brichau.pdf.

8. BRUNETON, E., LENGLET, R., AND COUPAYE, T. 2002. ASM: A code manipulation tool to implement adaptable systems. In Adaptable and extensible component systems (Grenoble, France). http://asm.objectweb.org/current/asm-eng.pdf.

9. CHIBA, S. 2000. Load-time structural reflection in Java. In ECOOP 2000—Object-Oriented Programming: 14th European Conference (Cannes, France), E. Bertino, Ed. LNCS, vol. 1850. Springer-Verlag, Berlin, 313–336.

10. COSTANZA, P., KNIESEL, G., AND AUSTERMANN, M. 2001. Independent extensibility for aspect-oriented systems. In Workshop on Advanced Separation of Concerns (ECOOP), (Budapest). http://trese.cs.utwente.nl/Workshops/adc2000/papers/Constanza.pdf

11. DAHM , M. 1999. Byte code engineering. In Java-Informations-Tage. Springer-Verlag, Berlin, 267–277.

12. DAHM , M. 1999. Byte code engineering with the JavaClass API. Tech. Rep. B-17-98, Freie Universitt Berlin, Institut für Informatik.

13. DE VOLDER, K. 1998. Aspect-oriented logic meta programming. In Workshop on Aspect Oriented Program-ming (ECOOP), (Brussels). http://trese.cs.utwente.nl/aop-ecoop98/papers/DeVolder.pdf

14. DE VOLDER, K. AND D'HONDT, T. 1999. Aspect-oriented logic meta programming. In Meta-Level Architectures and Reflection, 2nd Int'l Conf. Reflection, P. Cointe, Ed. LNCS, vol. 1616. Springer Verlag, Berlin, 250–272.

15. DMITRIEV , M. 2001. Towards flexible and safe technology for runtime evolution of Java language applications. In Workshop on Engineering Complex Object-Oriented Systems for Evolution (ECOOSE), (OOPSLA), (Tampa, Florida). http://www.dsg.cs.tcd.ie/ecoose/oopsla2001/ecoose_papers.zip.

16. DMITRIEV , M. 2002. Hotswap technology application for advanced profiling. In 1st Int'l Workshop on Unan-ticipated Software Evolution (USE), (ECOOP), (Malaga, Spain). http://joint.org/use/2002/sub/.

17. DOUENCE, R., FRADET, P., AND SÜDHOLT, M. 2002. A framework for the detection and resolution of aspect in-teractions. In 1st ACM Conf. Generative Programming and Component Engineering GPCE), (Pittsburgh). LNCS, vol. 2487. Springer-Verlag, Berlin, 173–188.

18. DUNCAN, A. AND HÖLZLE, U. 1999. Load-time adaptation: Efficient and non-intrusive language extension for virtual machines. Tech. Rep. TRCS99-09, Department of Computer Science, University of California.

19. FILMAN , R. E. AND HAVELUND , K. 2002. Source-code instrumentation and quantification of events. In Founda-tions of Aspect-Oriented Languages (FOAL, AOSD), (Enschede, The Netherlands), G . T. Leavens and R. Cy-tron, Eds. 45–49. Department of Computer Science, Iowa State Univ., ftp://ftp.cs.iastate.edu/pub/technreports/TR02-06/TR.pdf.

24 JMangler – A Powerful Back-End for Aspect-Oriented Programming

20. GONG, L. 1999. Inside Java 2 Platform Security Architecture, API Design, and Implementation. Addison-Wesley, Reading, Massachusetts.

21. GONG, L. 1999. Securely loading classes. In Inside Java 2 Platform Security Architecture, API Design, and Im-plementation. Addison-Wesley, Reading, Massachusetts, 71–83.

22. GOSLING, J., JOY, B., STEELE, G., AND BRACHA, G. 2000. Java Language Specification, 2nd Ed.. Addison-Wesley, Reading, Massachusetts.

23. HANENBERG, S. AND UNLAND , R. 2003. Parametric introductions. In 2nd Int' Conf. Aspect-Oriented Software Development (AOSD), (Boston), M. Ak�it, Ed. ACM, 80–89.

24. HANNEMANN , J. AND KICZALES, G. 2002. Design pattern implementation in Java and AspectJ. In 17th Conf. Ob-ject-oriented Programming, Systems, Languages, and Applications (OOPSLA), (Seattle). ACM, 161–173.

25. HERRMANN, S. 2002. Object teams: Improving modularity for crosscutting collaborations. In Net.Object Days 2002 (Erfurt, Germany), M. Ak�it and M. Mezini, Eds. LNCS, vol. 2591. Springer-Verlag, Berlin, 248–264.

26. JMangler. JMangler homepage. http://javalab.cs.uni-bonn.de/research/jmangler/.

27. KELLER, R. AND HÖLZLE, U. 1997. Supporting the integration and evolution of components through binary component adaptation. Tech. Rep. TRCS97-15, University of California, Santa Barbara. Sept.

28. KELLER, R. AND HÖLZLE, U. 1998. Binary code adaptation. In ECOOP'98 Object-Oriented Programming, 12th European Conference, E. Jul, Ed. LNCS, vol. 1445. Springer-Verlag, Berlin, 307–329.

29. KELLER, R. AND HÖLZLE, U. 1998. Implementing binary component adaptation for Java. Tech. Rep. TRCS98-21, University of California, Santa Barbara.

30. KICZALES, G., HILSDALE, E., HUGUNIN, J., KERSTEN, M., PALM , J., AND GRISWOLD, W. G. 2001. An overview of AspectJ. In ECOOP 2001—Object-Oriented Programming, 15th European Conference, (Budapest), J. L. Knudsen, Ed. LNCS, 2072. Springer-Verlag, Berlin, 327–353.

31. KNIESEL, G. AND AUSTERMANN, M. 2002. CC4J—code coverage for Java—a load-time adaptation success story. In Component Deployment - IFIP/ACM Working Conference, (Berlin). LNCS, vol. 2370. Springer-Verlag, Berlin, 155–169.

32. KNIESEL, G. AND BARDEY, U. 2003. Static dependency analysis for conditional program transformations. Tech. Rep. IAI-TR-03-03, ISSN 0944-8535, CS Dept. III, University of Bonn, Germany.

33. KNIESEL, G., COSTANZA, P., AND AUSTERMANN, M. 2001. JMangler—a framework for load-time transformation of Java class files. In 1st IEEE Int'l Workshop on Source Code Analysis and Manipulation (SCAM 2001) (Flor-ence). http://www.informatik.uni-bonn.de/\~costanza/SCAM_jmangler.pdf.

34. LAFFRA, C. 2000. Jikes bytecode toolkit. http://www.alphaworks. ibm.com/tech/jikesbt.

35. LEE, H. B. AND ZORN, B. G. 1997. BIT: A tool for instrumenting Java bytecodes. In Symp. Internet Technolo-gies and Systems (Monterey, California). USENIX, 73–82.

36. LINDHOLM , T. AND YELLIN , F. 1999. The Java Virtual Machine Specification (2nd Ed). Addison-Wesley, Read-ing, Massachusetts.

37. Object Teams. Object Teams homepage. http://www.ObjectTeams.org.

38. ORLEANS, D. AND LIEBERHERR, K. 2001. DJ: Dynamic adaptive programming in Java. In Metalevel Architec-tures and Separation of Crosscutting Concerns 3rd Int'l Conf. (Reflection 2001), (Kyoto), A. Yonezawa and S. Matsuoka, Eds. LNCS, vol. 2192. Springer-Verlag, Berlin, 73–80.

39. OSSHER, H. AND TARR, P. 1999. Multi-dimensional separation of concerns using hyperspaces. Tech. Rep. 21452, IBM Research Report.

40. OSSHER, H. AND TARR, P. 2001. The shape of things to come: Using multi-dimensional separation of concerns with Hyper/J to (re)shape evolving software. Comm. ACM 44, 10 (Oct.), 43–50.

Appendix 9.A. Simple Code Coverage 25

41. SOUL. Soul homepage. http://prog.vub.ac.be/research/DMP/soul/.

42. STENZEL, C. 2002. Implementation models for method call interception based on formal semantics (in German: Implementationsmodelle für Methodenaufrufabfang basierend auf formaler Semantik). Diploma thesis, Univer-sity of Rostock. http://www.informatik.uni-rostock.de/~stenzel/.

43. STÖRZER, M. AND KRINKE, J. 2003. Interference analysis for AspectJ. In FOAL: Foundations of Aspect-Oriented Languages (AOSD), (Boston). http://www.cs.iastate.edu/~leavens/FOAL/papers-2003/stoerzer-krinke.pdf.

44. VEIT, M. AND HERRMANN, S. 2003. Model-view-controller and Object Teams: A perfect match of paradigms. In 2nd Int' Conf. Aspect-Oriented Software Development (AOSD) (Boston), M. Ak�it, Ed. ACM, 140–149.

45. WICHMAN , J. C. 1999. The development of a preprocessor to facilitate composition filters in the Java language. M.S. thesis, University of Twente.