Section 15.2. GENERIC INTERCEPTION


15.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 compromising 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 architecture and the resulting interception options are illustrated in Figure 15-1.

Figure 15-1. Four ways of intercepting classes at load time: Use of a custom classloader, 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.


15.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 (see Figure 15-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 classloaders 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). Preprocessing of loaded class files also falls into this category.

Namespaces. Every class loader instance provides a separate namespace. Even if different copies of the same class are loaded by different classloaders, they live in different namespaces 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.

15.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 custom classloaders.

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

15.2.3. JVM-Dependent Interception

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

15.2.4. Platform-Dependent Interception

Duncan and Hölzle [18] 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.

15.2.5. Portable Generic Interception

In contrast to the previous approaches, JMangler provides a portable and generic interception 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 enforced 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, independently of a custom JVM or a platform-specific DLL. The limitation of this approach 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 utilization 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 instantiations of adapted versions these classes. Analysis and replacement of calls as well as creation of adapted version of classloaders is done at load time. Versions 3 and higher use the "HotSwap" API for Java[3] [15, 16] to replace java.lang.ClassLoader with a version created at runtime. Discussion of further implementation issues, including the tradeoff between the different schemes, is outside the scope of this paper.

[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.



Aspect-Oriented Software Development
Aspect-Oriented Software Development with Use Cases
ISBN: 0321268881
EAN: 2147483647
Year: 2003
Pages: 307

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net