200 likes | 351 Views
Retroactive API Extensions Through Bytecode Weaving . Jevgeni Kabanov PhD student, University of Tartu. WHAT?. API Extensions Application programming interface New APIs, changed APIs Bytecode Weaving Bytecode : stack-based Java-like language Weaving: runtime program rewriting
E N D
Retroactive API Extensions Through Bytecode Weaving Jevgeni Kabanov PhD student, University of Tartu
WHAT? • API Extensions • Application programming interface • New APIs, changed APIs • Bytecode Weaving • Bytecode: stack-based Java-like language • Weaving: runtime program rewriting • Retroactive • Abstraction after the fact • Without access to source code
WHY? • Java EE is implemented by application containers each with specific extensions • Frameworks and applications need a unified access to container-specific features
EXAMPLE • JavaScript, DOM, abstraction libraries • GWT • Prototype • jQuery • Ext JS • Spring (Java framework) • Abstraction over some common Java EE features for applications
BEHIND THE SCENES MyClass MyClass’ MyClass_3 MyObject.class MyObject.class
IDEs Servers Frameworks Open-Source API
Class loader API publicabstractclassClassLoader { public Class loadClass(String name); protected Class defineClass(byte[] b); public URL getResource(String name); public Enumeration getResources(String name); publicClassLoadergetParent() }
API Extensions • Change loadClass() to include the classes we provide to it • Add a method getChildResources() that returns the resources hierarchically
Java Execution Model Local variables Operand stack Throwing an exception Calling a method Frame Execution stack
Instruction Example Instruction: opcode arguments Operands stack when applying the instruction: apply
Hello, World! in Bytecode publicclassHelloWorld { public<init>()V ALOAD 0 INVOKESPECIAL Object.<init>()V RETURN publicstaticmain([LString;)V GETSTATIC System.out : LPrintStream; LDC "Hello, World!" INVOKEVIRTUAL PrintStream.println(LString;)V RETURN }
REWRITING IS EASY • ASM • Visitor API • Low level • Javassist • String-embedded Java DSL • High-level, but adjustable
PROBLEM 1: TRANSPARENCY • If the result of an API call is altered, how do we access the original from our framework? • E.g. ClassLoader.loadClass()
PROBLEM 2: OPTIONAL • What if the features we want to support are optional or implemented differently among implementers? • E.g. ClassLoader.getChildResources()
PROBLEM 3: VERSIONING • What if we have several versions of an implementation? • NB! In Java the class files are not versioned and detecting versions may be challenging
PROBLEM 4: GLOBAL STATE • What if implementer state dictates that calls are legal in some states and illegal in others? • E.g. ClassLoaderclasspath is often constructed incrementally
PROBLEM 5: SYNCHRONIZATION • What if implementer does synchronization? • Synchronized in Java is a reentrant mutex • ClassLoader.loadClass() is synchronized, ClassLoader.getResource() usually not