JavAssist

28
JavAssist X.java X.class Class Loade r My Loader X compile lo ad sist enables preload byte code modific

description

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. - PowerPoint PPT Presentation

Transcript of JavAssist

Page 1: JavAssist

JavAssistX.java

X.class

ClassLoader

My Loader

X

compile

load

JavAssist enables preload byte code modification

Page 2: JavAssist

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.

Page 3: JavAssist

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.

Page 4: JavAssist

Java, AspectJ, and JavAssist

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

Page 5: JavAssist

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.

c X.class

X’

My Loader

Page 6: JavAssist

Design Goals of Javassist

1. Source Level Abstraction.No knowledge of byte code is needed.API is purely in Java.

2. Efficient Structural Reflection.Reduce runtime overheads due to class reconstruction.

3. Safe Structural Reflection.Protect programmers from defected byte code composition.

Page 7: JavAssist

Pursuing Javassist Design Goals.

1. Source Level Abstraction.Class rename.

2. Efficient Structural Reflection.Runtime compilation with addMethod.

3. Safe Structural Reflection.Class member removal.

Page 8: JavAssist

The Javassist API

•Introspection•Alteration.•Adding a new Member.•Altering a Method Body.•Javassist Class Loader.

Class{

Fields

Constructors

Methods{

CtClass{

CtFields

CtMethods

CtMethods{

Page 9: JavAssist

CtClass Introspection

Page 10: JavAssist

CtField & CtMethod Introspection

Page 11: JavAssist

Alteration

Page 12: JavAssist

Example: addMethodpublic class Xvector extends java.util.vector{

public void add(X e){super.addElement(e);

{{

CtMethod m = // method add() in XVector CtClass c = // class StringVectorClassmap = new ClassMap();map.put(“X” , ”java.lang.String”);c.addMethod(m, “addString”, map);

Public void addString(java.lang.String e){super.addElement(e);

{

Page 13: JavAssist

Example: setBody

CtMethod m = // method which body is to be changedCodeConverter conv = new CodeConverter();Conv.replaceNew(Xclass, Yclass, “create” );m.instrument(conv);

M( … ){…Xclass xclass = new Xclass(3,4);…

{

M( … ){…Yclass.create(3,4);…

{ Must be Static

Page 14: JavAssist

Reflective Class Loader

•JavAssist default loader.•User defined loader.•Web Server.•Off line.

Page 15: JavAssist

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);{{

Page 16: JavAssist

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;

}{

{

Page 17: JavAssist

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. */ }

}

Page 18: JavAssist

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 ./* { }

Page 19: JavAssist

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);

}

}

Page 20: JavAssist

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.

Page 21: JavAssist

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.

Page 22: JavAssist

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.

Page 23: JavAssist

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.

Page 24: JavAssist

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.

Page 25: JavAssist

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.

Page 26: JavAssist

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.

Page 27: JavAssist

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.

Page 28: JavAssist

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.