Load Time Structural Reflection in Java Shigeru Chiba Institute of Information Science and Electronics University of Tsukuba Introduction • Reflection in java – Behavioral reflection – Structural reflection • Javassist, a class library enabling structural reflection in java Properties of Javassist • Portable • Provides source level abstraction • Does byte code transformation at compile time BCA class Calendar implements Writable { public void write(PrintStream s) { ... } } class Calendar implements Printable { public void write(PrintStream s) { ... } public void print() { write(System.out); } } • Implementation of BCA with behavioral reflection is not straightforward Javassist • Translates alterations by structural reflection into equivalent bytecode • It is used with a user class loader class MyLoader extends ClassLoader { public Class loadClass(String name) { byte[] bytecode = readClassFile(name); return resolveClass(defineClass(bytecode)); } private byte[] readClassFile(String name) { // read a class file from a resource. } } Javassist API • A CtClass object has to be created CtClass c = new CtClass(stream or string); • To obtain bytecode of altered class byte[] bytecode = c.toBytecode(); • Javassist allows to dynamically define a new class CtClass c2 = new CtNewClass(); Introspection • This part of Javassist is compatible with Java reflection API with the difference that Javassist does not provide methods for creating an instance or invoking a method because these are meaningless at load time Methods in CtClass for introspecting classes Alteration by Javassist • Principles governing alteration in Javassist – Source level abstraction for programmers – Execution of structural reflection efficiently – Type safety while performing Structural reflection Adding a new member void addMethod(CtMethod m, String name, ClassMap map) void addWrapper(int modifiers, CtClass returnType, String name,CtClass[] parameters, CtClass[] exceptions,CtMethod body, ConstParameter constParam) Replacing a Class name in the method body public class XVector extends java.util.Vector { public void add(X e) { super.addElement(e);}} CtMethod m = /* method add() in XVector */; CtClass c = /* class StringVector */; ClassMap map = new ClassMap(); map.put("X", "java.lang.String"); c.addMethod(m, "addString", map); public void addString(java.lang.String e) { super.addElement(e);} Altering a Method body void setBody(CtMethod m, ClassMap map) void setWrapper(CtMethod m, ConstParameter param) Reflective class loader • Javassist provides a reflective class loader which can be used to self-reflectively modify the bytecode Using Javassist with a Web server for (;;) { receive an http request from a web browser. CtClass c = new CtClass(the requested class); do structural reflection on c if needed. byte[] bytecode = c.toBytecode(); send the bytecode to the web browser. } Using Javassist Off line CtClass c =newCtClass("Rectangle"); do structural reflection on c if needed. c.compile(); writes bytecode on the original class file. • Now the over written class file can be loaded in the JVM without user class loader Use of Javassist • Binary Code Adaption • Remote Method Invocation Comparison of OpenJava and Javassist • Openjava needs source file of every processed class whereas Javassist needs just the class files of the classes • Javassist is much faster as it can move compilation penalties to an earlier stage Conclusion • Javassist is portable • Provides source level abstraction in a safe manner • Does not need source code • Can be extended to other object oriented languages with individually designed API for each language The Jalapeno Dynamic Optimizing Compiler for java Thomas J.Watson Research Center IBM Project overview • Jalapeno is a JVM built by IBM Research (initiated in December 1997) It takes a compile-only approach to program execution • Three different compilers to provide translations: – A “baseline” compiler that makes it easier to mix execution of un-optimized and optimized methods in the JVM – A “quick” compiler for a low level of code optimization – An optimizing compiler for computationally intensive code Motivation of the Project • To deliver high performance and scalability ofJava applications on SMP server machines • To support all Java features and semantics with respect to exceptions, garbage collection and threads Jalapeno JVM • Jalapeno JVM includes the following subsystems: - Dynamic Class Loader - Dynamic Linker - Object Allocator - Garbage Collector - Thread Scheduler - Profiler - Three dynamic compilers Jalapeno JVM • All subsystems implemented in Java • Self-bootstrapping • Can dynamically self-optimize the JVM itself Structure of Jalapeno Optimization system • Unlike traditional JVMs, Jalapeno is adaptive and dynamic – Automatically select a set of methods to optimize – Generate the best possible code for selected methods for a given compile-time budget – Reduce synchronization and other thread primitive Structure of Jalapeno adaptive Optimization system • Jalapeno Adaptive Optimization System includes: – On-Line Measurement (OLM) subsystem – Controller subsystem – Optimizing Compiler subsystem Online Measurment • OLM – Collect application and hardware performance information – Maintain Calling Context Graph (CCG) to keep track of context-sensitive information – Continuously monitor the methods, including those previously “optimized” Controller • Controller – Detect if certain performance threshold is reached – Use information collected from OLM to build an optimization plan (e.g. which methods need to be compiled and the optimization levels) Optimizing Compiler • The Optimizing Compiler can be used either as a static or dynamic compiler. • When used as a static compiler or a bytecode -tobytecode optimizer, it generates file for later execution ,used to bootstrap Jalapeno JVM Optimizing Compiler • When used as a dynamic compiler, it generates the best possible code given compile time budget • The Jalapeno Optimizing Compiler consists of an optimizer front-end and an optimizer backend Intermediate Representation (IR) • The Optimizing Compiler uses register-based intermediate representations • IR consists of an operator and some number of operands • Jalapeno uses 3 different types of IRs: – HIR (High-Level IR) – LIR (Low-Level IR) – MIR (Machine-Specific IR) IR • Operators such as NULL_CHECK and BOUNDS_CHECK operators are used to facilitate optimization • Control Flow Graph (CFG) and Basic Blocks (BB) are constructed as a by-product of BC2IR(Byte Code to Intermediate Representation) Front end of Optimizing compiler • The Front-End contains two parts: – BC2IR algorithm to translate byte code to HIR and perform on the fly optimizations – Additional optimization performed on the generated HIR Back end of Optimizer Compiler • The Back-End of the compiler translates – HIR to LIR – LIR to MIR – MIR to the final binary code • Different optimizations are performed during each phase HIR to LIR • HIR is lowered to low-level IR (LIR) • LIR expands instructions into operations that are specific to the Jalapeno JVM (such as object layouts or parameter-passing mechanism) • The expanded LIR may expose more opportunities for low-level optimizations Final Assembly • Emit the binary executable code into an instruction array • Convert offsets in the IR to offsets in the machine code • Store the instruction array (a Java array reference) into a field of the object instance for that method Inlining Method Calls • During BC2IR phase: – Static and final methods can be safely inlined. – “Inlining plan” is based on static code size and depth heuristics Implementation Status • OLM is in prototype stage, and the controller is in design phase • The Optimizing compiler can only be invoked as a static compiler or dynamically by the Jalapeno class loader to optimize all methods Performance Benchmark Enviroments • Four Java Environments: – IBM JDK 1.1.6 w/o JIT – IBM JDK 1.1.6 w IBM JIT v3.0 – Jalapeno Baseline – Use Jalapeno Baseline Compiler as a JIT for all classes dynamically loaded – Jalapeno Optimizer – Use Jalapeno Optimizing as JIT for all classes dynamically loaded Benchmark Programs • Benchmark Programs: – 9 “Micro-benchmark” Programs from Symantec – 4 “Macro-benchmark” programs from SPECjvm98suite Performance Results • Micro-Benchmark: – 3 of the 9 tests run faster with the Jalapeno Optimizing Compiler – Remaining cases are within 1.6 times slower of the standard IBM JIT compiler Performance Results • Macro-Benchmark: – 1.3 to 3.3 times slower than the “best” current commercial JVM" – With further improvements, Jalapeno (a pure Java JVM) may achieve performance competitive to a state-of-the-art JVM implemented in C Conclusion • First dynamic optimizing compiler for Java that is being used in JVM with a compile –only approach to program execution – Validated the “compile-only” approach to program execution – Demonstrated that a JVM implemented in Java can deliver performance comparable to a standard JIT compiler