pptx

handslustyInternet and Web Development

Dec 14, 2013 (3 years and 9 months ago)

100 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

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


MyObject.class

MyObject.class

MyClass_3

MyClass


MyClass

IDEs

Servers

Frameworks

Open
-
Source API

Class loader API

public

abstract

class

ClassLoader

{


public

Class
loadClass
(String

name);


protected

Class
defineClass
(
byte
[]
b
);



public

URL
getResource
(String

name);


public

Enumeration
getResources
(String

name);



public

ClassLoader

getParent
()

}

API Extensions

Change
loadClass
() to include the classes
we provide to it


Add a method
getChildResources
() that
returns the resources hierarchically

Java
Class
Definition

Modifiers, name, super class, interfaces

Enclosing class reference

Annotation*

Inner class*

Name

Field*

Modifiers, name, type

Annotation*

Method*

Modifiers, name, return and parameter types

Annotation*

Compiled code

Java Execution Model

Method B

Method
A

Main

L0

L1

L2

L3

O1

O2

L0

L1

L2

O1

O2

O3

L0

L1

O
1

Local variables

Operand stack

Execution stack

Frame

Calling a method

Throwing an exception

Instruction Example

INVOKEINTERFACE

java/util/List

get

(I)
LObject
;

opcode

argumen
ts

...

java.util.List

int

...

java.util.List.get(int)

apply

Operan
ds stack when applying the instruction
:

Instru
ction
:

Hello, World! in
Bytecode

public

class

HelloWorld

{


public

<init>()V


ALOAD 0


INVOKESPECIAL

Object.<init>()V


RETURN


public

static

main([
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.
ClassLoader

classpath

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

Questions?