Section 14.2. AN OVERVIEW OF BYTECODE TRANSFORMATION


14.2. AN OVERVIEW OF BYTECODE TRANSFORMATION

Bytecode transformation is an example of a late code modification technique [21], targeting an executable program after compilation. Traditional late code modification systems suffer for lack of certain useful information available only in source code. However, Java classfiles retain symbolic information that enables a wide range of transformations. Additionally, bytecode transformation can be used on code for which source is not available.

Bytecode transformation can make a wide array of changes to a target class, including adding or removing fields, methods, or constructors; changing the superclass, changing the types or signatures of fields or methods, redirecting method invocations to new targets, and inserting new code into methods at arbitrary points.

Bytecode transformation can take place at any point, from initial class creation by the compiler to class loading. This section discusses transformation at two important stages in the lifecycle: static transformation, performed immediately after compilation when the entire program is complete, present, and visible, and dynamic transformation, performed at load time, one class at a time at the client. Static transformation allows transformations based on knowledge of the entire program, while dynamic transformation enables transformations that are aware of the run-time environment.

14.2.1. Static Transformation

Static transformation occurs after compilation and operates on class files on disk, writing the changes back and thus making them durable until the classes are recompiled. The entire program might be present when the system applies the transformation (the "closed-world" assumption). This means that no unseen classes subclass application classes and that the application does not dynamically load new classes. If so, a range of more sophisticated inter-method and inter-class optimizations and analyses is possible. This is similar to link-time optimizers [19], which use whole-program analysis to enable the optimizations they perform. Even without the closed-world assumption, the transformer can use information present in the classfile to determine and manipulate the class hierarchy. Interprocedural analysis can reveal valid targets for inlining or parameter elimination; dead code removal can remove unused code, methods, or even classes.

Transforming statically, rather than during the loading process, shifts transformation out of the critical path. Running the transformation at this point makes it unnecessary to run at load time; if the developer is certain that the transformation is necessary, then performing the transformation after compiling is advantageous.

14.2.2. Dynamic Transformation

Dynamic transformation operates at some time between the JVM request for a class and the loading of that class. Dynamic transformation may occur at the server as specific clients request the class, at an intermediate proxy that transforms classes as they pass through the network [17], or at load time as the classes enter the JVM.

The classloader architecture provided in Java provides a convenient mechanism to alter the semantics of loading a class. A classloader is a user-defined object in Java responsible for locating and obtaining classfiles and handing them to the JVM. While classloaders are intended to enable programmers to control the source location or time of class, they also provide an opportunity for transformation.

Performing the transformation at load time is the only way to guarantee transformation of foreign code, such as applets or servlets loaded from the network. It can apply whole-program transformations to such applications.

In addition to ensuring that every application class supports a given feature, a transformation can also be restrictive, guaranteeing that no application class uses a forbidden feature. For example, a restrictive transformer can limit access to a secure resource by simply disallowing any code that references that resource. The transformer can then safely add its own calls to that resource. Given Java's type-safety, all calls to that resource are guaranteed to be legitimate. (However, see the discussion later on reflection).

Load-time transformation is incremental: The transformer processes individual classes one at a time as they are loaded. The transformer does not control the load order of the classes, and most current JVMs do not allow modification or reloading of already-loaded classes. Transformers thus have only one chance to transform classes and often must do so with incomplete information about the entire application.

This constraint limits the applications for load-time transformation. For example, a dynamic transformer cannot, in general, apply optimizations requiring interprocedural analysis (such as leaf method removal) because the transformation may operate on a call site before the matching method is loaded. Transformer control over the class load order would improve the generality of dynamic transformation but would not solve the problem. For method invocations for which the transformer cannot determine the run-time type of the object, the classloader would require all possible descendents of that object to determine the safety of that method invocation. The current specification of the classfile does not provide that information, and in general, new subclasses may dynamically appear.



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