The accelerating use of Java [GJS96] to enable transportable code over the Internet has created both the need and an opportunity to take a larger view of program development. The possibility that programs will consist of components loaded dynamically, possibly from multiple diverse sources, creates challenges for program developers: How can third-party code be adapted to local environments? How do we add functionality to ``shrink-wrapped'' code? Is it possible to insert new behaviors, such as recoverability, caching, or visualization, into existing implementations?
Fortunately, Java bears within itself the seeds of the solution. Java is an ideal environment for load-time transformation, a powerful technique in which user-specified transformers (possibly supplied by a third party) add, remove, or change fundamental details of transportable code as it is imported into the local Java Virtual Machine (JVM)[LY97]. Java has several properties that assist load-time transformation. Transportable Java code arrives from the network as compiled classfiles containing procedures (methods) and related data definitions for an object type (class): these classfiles retain a great deal of symbolic information, allowing the receiver to determine the structure of the class and to modify it on-the-fly. Secondly, methods are represented as JVM bytecodes: since bytecodes are stack instructions, it is relatively easy to splice new code into existing methods. Finally and most importantly, the JVM uses a user-extensible class loader to locate and load new classes on demand: the class loader can be modified to apply load-time transformations to every classfile brought into the local environment.
Load-time transformation has far-reaching implications for the balance of responsibility between class authors and users. In the traditional model, users run programs whose attributes are statically determined by the original authors. Load-time transformation enables a new model, one in which end users assemble and customize applications by chaining together combinations of original code and third-party transformers. The role of the transformers is to implement class features or extensions that the authors did not foresee or chose not to support directly in the original class. Our hypothesis is that many program behaviors are best applied by generic class transformers as needed, rather than hardwired into the class source. Broadly, transformers are useful for implementing any behavior that is orthogonal to the purpose of the class and can be specified independently. Moreover, support for transformers can improve reuse of existing code by providing a means to adapt it to local needs.
Table 1: Stages in the program development life cycle.
This paper describes load-time transformation using the Java Object Instrumentation Environment, or JOIE, a toolkit for specifying transformations for Java classes. JOIE transformers are written in Java and use JOIE primitives to analyze and modify classes. The JOIE toolkit includes an enhanced class loader that invokes transformers at load time. JOIE works with any JVM, and is available for download at https://www.cs.duke.edu/ari/joie/.
The remainder of the paper addresses four main questions that arise from the introduction of load-time transformation and its use in JOIE. What are its capabilities? How is it implemented? What are the useful applications? Can it compromise existing guarantees of security and safety?
Section 2 introduces load-time transformation within the context of the program lifecycle. Section 3 presents the environment and the capabilities JOIE offers to enable transformations. Section 4 examines some implementation details for Java transformations. Section 5 outlines some application areas for JOIE, and Section 6 presents in more detail the implementation of a specific transformer, Automatic Observable, which adds to classes the ability to detect state changes and report them to registered observers. Section 7 discusses issues arising from load-time transformation, including security, safety, debugging complexity, and legal concerns.