310 likes | 654 Views
JavAssist. X.java. compile. X.class. load. JVM. Class Loader. My Loader. X. JavAssist enables preload byte code modification. What is Reflection?. If a program can inspect itself while running , it’s said that the runtime system is reflective with respect to that program.
E N D
JavAssist X.java compile X.class load JVM Class Loader My Loader X JavAssist enables preload byte code modification
What is Reflection? If a program can inspect itself while running, it’s said that the runtime system is reflective with respect to that program.
Levels of Reflection • Introspection. • No alteration, read only. • Behavioral Reflection. • Limited Alteration possible, such as method invocation. • In general : behavior of operations is changeable. • Structural Reflection. • The ability to change data structures used by the runtime system, such as Class for example.
Java, AspectJ, andJavAssist • Java provides Introspection: • getName. • AspectJ provides Behavioral Reflection: • Aspects + Point cuts are used. • Compile time Weaving process integrates behavioral changes to precompiled base code. • Javassist provides Structural Reflection: • Javassist API is in Java. • Customized runtime loader changes preloaded byte code.
How is Javassist implemented? CtClass c = new CtClass(“X.class”); //There’s nothing like Class X in the JVM so far! c.notFinal(); c.addField(…) c.addMethod(…) //c contains the altered byte code of X. c.load(); //Altered X is finally loaded into the JVM. JVM My Loader c X.class X’
Design Goals of Javassist • Source Level Abstraction. • No knowledge of byte code is needed. • API is purely in Java. • Efficient Structural Reflection. • Reduce runtime overheads due to class reconstruction. • Safe Structural Reflection. • Protect programmers from defected byte code composition.
Pursuing Javassist Design Goals. • Source Level Abstraction. • Class rename. • Efficient Structural Reflection. • Runtime compilation with addMethod. • Safe Structural Reflection. • Class member removal.
The Javassist API CtClass{ CtFields CtMethods CtMethods } Class{ Fields Constructors Methods } • Introspection • Alteration. • Adding a new Member. • Altering a Method Body. • Javassist Class Loader.
Example: addMethod 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 = new ClassMap(); map.put(“X” , ”java.lang.String”); c.addMethod(m, “addString”, map); Public void addString(java.lang.String e){ super.addElement(e); }
Example: setBody M( … ){ … Xclass xclass = new Xclass(3,4); … } CtMethod m = // method which body is to be changed CodeConverter conv = new CodeConverter(); Conv.replaceNew(Xclass, Yclass, “create” ); m.instrument(conv); M( … ){ … Yclass.create(3,4); … } Must be Static
Reflective Class Loader • JavAssist default loader. • User defined loader. • Web Server. • Off line.
Examples: Binary Code Adaptation. class X implements Writable{ public void write(PrintableStream s){..} } class X implements Printable{ public void (PrintableStream s){..} public void print(){write(System.out);} }
Examples: Binary Code Adaptation. class Exemplar implements Printable { public void write(PrintStream s) { /* dummy */ } public void print() { write(System.out); } } class Adaptor { // THE JOB IS DONE HERE public void adapt(CtClass c) { CtMethod printM = /* method print() in Exemplar */; CtClass[] interfaces = c.getInterfaces(); for (int i = 0; i < interfaces.length; ++i) if (interfaces[i].getName().equals("Writable")) { interfaces[i] = CtClass.forName("Printable"); c.setInterfaces(interfaces); c.addMethod(printM, new ClassMap()); return; } } }
Behavioral Reflection. public class MyMetaObject extends MetaObject { public Object trapMethodCall(String methodName, Object[] args) { /* called if a method call is intercepted. */ } public Object trapFieldRead(String fieldName) { /* called if the value of a field is read. */ } public void trapFieldWrite(String fieldName, Object value) { /* called if a field is set. */ } }
Behavioral Reflection. public class C{ public int f; public int m(int x){ return x+f;} } public class C implements MetaLevel { public int m(int x) { /* notify a MetaObject. */ } public int f; private MetaObject _MetaObject = new MyMetaObject(this); public MetaObject _getMetaObject() { return _MetaObject; } public int orig_m(int x) { return x + f; } public static int read_f(Object target) {/*notify a MetaObject. */ } public static void write_f(Object target, int value) { /*notify a MetaObject. */ } }
Behavioral Reflection. class Exemplar { private MetaObject _MetaObject; public Object trap(Object[] args, String methodName) { return _MetaObject.trapMethodcall(methodName, args); } public static Object trapRead(Object[] args, String name) { Metalevel target = (Metalevel)args[0]; return target._getMetaObject().trapFieldRead(name); } public static Object trapWrite(Object[] args, String name) { Metalevel target = (Metalevel)args[0]; Object value = args[1]; target._getMetaObject().trapFieldWrite(name, value); } }
Related Work:Reflection in Java. • MetaXa and Kava enable behavioral reflection in Java, whereas JavAssist enable structural reflection. • JavAssist can be used to achieve behavioral reflection, such as with MetaXa and Kava. • Kirby’s system, allows a class definition at load time. It doesn’t support class redefining.
Related Work:Compile-Time MetaObject Protocol. • Another architecture enabling structural reflection without modifying an existing runtime system is OpenJava. • OpenJava was designed mainly for off-line use at compile time.
Related Work:Compile-Time MetaObject Protocol. • OpenJava is source-code based. • OpenJava alterations are on source code level. • OpenJava involves a performance overhead due to source code manipulations. On the other hand it results with a fine-grained source code.
Related Work:Compile-Time MetaObject Protocol. • JavAssist is bytecode based and doesn’t need source code( which is not always available). • No performance overhead: the code is already compiled, therefore JavAssist achieves shorter loading time. • JavAssist runs 10 times faster than OpenJava.
Related Work: Bytecode Translators. • JOIE and JavaClass API provide functionality similar to JavAssist. • Using them, the programmer is required to have a deep understanding of the Java byte code. • JavAssist provides source-level abstraction for manipulating byte code in a safe manner.
Related Work: Others. • OpenJIT: allows a Java program to control how byte code is compiled into native code. It provides better flexibility with method body redefinition, but doesn’t allow to add a new method or field to the class.
Conclusions. • JavAssist is an extension to the Java reflection API. • It enables structural reflection in Java, allows to alter a given class definition and to dynamically define a new class. • Language extensions are more easily implemented with structural reflection than with behavioral reflection.
Conclusions (Cont.) • JavAssist is portable. • JavAssist provides source-level abstraction for manipulating byte code in a safe manner, while byte code translators, such as JOIE and the JavaClass API, provide no higher-level abstraction. • JavAssist processes byte code. • OpenJava processes source code.
Conclusions (Cont.) • The architecture of JavAssist can be applied to other object-oriented languages if a compiled binary program includes enough symbolic information to construct a class object. • API must be individually designed for each language to allow class alteration definition in a safe and meaningful manner.