SlideShare a Scribd company logo
1 of 42
Playing with Java Classes
and Bytecode
What is a Class?
How it is loaded and used?
How to write a Java program that writes itself at runtime?
Yoav Abrahami
Wix.com
Java Classloading
• Why do we care?
– Because if we’re gonna write code at runtime, we’d better know
how to load and use it…
– Because we don’t really understand classes
• So… what identifies a class?
– Its name
– Its package
– Its classloader
• It means that
– We can have multiple instances of a class loaded at the same time
– Two instances of the same class from different classloaders are not compatible and not
assignable
– Static variables are static only in the context of a classloader, not globally as we’re
always told
Java Classloading
• So what is this classloader?
– A Java class (subclass of java.lang.ClassLoader), responsible for loading other classes
used by the JVM
– Classloaders are arranged as a tree
• Bootstrap classloader
– Loads the Java system
• jre/lib/resources.jar – series of resource files
• jre/lib/rt.jar – the java.*, javax.*, etc packages
• jre/lib/sunrsasign.jar
• jre/lib/jsse.jar – secure socket extension
• jre/lib/jce.jar – Java cryptography extension
• jre/lib/charsets.jar
• jre/classes
– The important stuff is in rt.jar – the base Java classes
Bootstrap
classloader
Ext
classloader
Application
/ System
classloader
Java Classloading
Commandline Java App Tomcat (6)
Bootstrap
classloader
Ext
classloader
Application
/ System
classloader
Application
/ System
classloader
Common
classloader
WAR 1
classloader
WAR 2
classloader
Java Classloading
Commandline Java App Tomcat (6)
Bootstrap
classloader
Ext
classloader
Application
/ System
classloader
Application
/ System
classloader
Common
classloader
WAR 1
classloader
WAR 2
classloader
Loads the Application Jars
from the classpath
Loads only
bootstrap.jar and
tomcat-juli.jar
Loads Tomcat
commons library jars
Loads jars in the
webapp lib directory
LETS TALK BUSINESS
Ok, we understand classes. Where is the cool stuff?
What we’re gonna talk about
• Aspect Oriented Programming
– Java Proxy
– Spring Aspects
– AspectJ Aspects
• Doing the really cool stuff
– The bootstrap classloader
– The javaagent and class instrumentation
– Writing bytecode at runtime
• All in context of when I’ve had to use them
The Java Proxy
• What does it do?
– Allows implementing one or more interfaces dynamically
• When do we use it?
– Generic implementation of an interface – such as in the case of a client calling a service.
The client uses an interface with a generic implementation that marshals the method
calls to whatever “on-the-wire” format. For instance, creating a SOAP client on the fly
using an interface and WSDL
– Simplistic AOP – to catch method calls, perform some pre/post/around logic and
delegate the call to the real implementation. Can be used for transaction handling,
logging, etc.
• Limitations
– Only supports Java interfaces
– Intercepts only calls to the proxy instance. Direct calls to the
delegate will not be intercepted (for instance, a call from one
delegate method to another)
The Java Proxy
• Example code
public interface SomeInterface {
public void doSomething();
public void doAnotherThing(String name);
}
Object p = Proxy.newProxyInstance(this.getClass().getClassLoader(),
new Class<?>[]{SomeInterface.class}, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("invoking method:" + method.getName());
if (args != null)
for (Object arg: args)
System.out.println(" arg: " + arg);
return null;
}
});
SomeInterface s = (SomeInterface)p;
s.doSomething();
s.doAnotherThing("hello");
Spring AOP
• What does it do?
– Allows intercepting method calls to Spring beans, with or without an interface
– Simpler code compared to the Java Proxy
– Based on the proxy model – Spring BeanFactory returns a proxy to the real bean
– Supports choosing the methods to intercept using AspectJ selectors
– Aspects are written using the AspectJ Java syntax
• When do we use it?
– AOP on Spring beans
– Transaction handling, logging, security handling – anything AOP is good for
• Limitations
– Only supports Spring beans
– Intercepts only calls to the proxy instance. Direct calls to the
delegate will not be intercepted (for instance, a call from one
delegate method to another)
– Supports only a subset of AspectJ selectors
Spring AOP
• Configuring Spring AOP
• Example Aspect
• Activating the Aspect
– Using Spring component scan, by adding the @Component annotation on the aspect
– Using Spring Beans XML
@Aspect
public class ExampleAspect {
@Around("@annotation(com.experiments.RequireLogin)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable
{
...
}
}
<bean class="com.experiments.ExampleAspect"/>
<aop:aspectj-autoproxy/>
AspectJ
• What does it do?
– Allows intercepting any JoinPoint such as method calls, exceptions, etc.
– Supports writing aspects using Java or AspectJ syntax
– Modifies the actual class bytecode
– Supports choosing the methods to intercept using AspectJ selectors
– Modify existing classes, adding methods, members and super-interfaces to them
– Weaves aspects on load time or compile time
• When do we use it?
– AOP on any Java class
– Transaction handling, logging, security – anything AOP is good for
– Introduce compiler-like coding rules
• Limitations
– For compile-time weaving – replaces the standard Java Compiler
– For load-time weaving – requires elaborate JVM configuration
AspectJ
• Configuration options
– Compile-time weaving
– Load-time weaving
– Load-time weaving with Spring
• Dependencies
– aspectjrt.jar must be in the classpath
• Configuring AspectJ load-time weaving with Spring
– Simple, isn’t it?
• Well, not so simple…
<aop:aspectj-autoproxy/>
<context:load-time-weaver/>
AspectJ
• Need to include META-INF/aop.xml
– declares the aspects for load-time weaving and the target packages to weave into
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<!-- only any class from the com.experiments package -->
<include within="com.experiments..*"/>
</weaver>
<aspects>
<!-- weave in just this aspect -->
<aspect name="com.experiments.ExampleAspect"/>
</aspects>
</aspectj>
AspectJ
• Per-platform configuration for class instrumentation
– Command line & JUnit applications – using the -javaagent to load instrumentation jars
• -javaagent:spring-instrument-<version>.jar -javaagent:aspectjweaver-<version>.jar
– Maven running JUnit – using the maven-surefire-plugin, passing it the javaagent args
– Note the two javaagent params must be at the same line
– Tomcat 6 –
• spring-instrument-tomcat-<version>.jar has to be copied to the Tomcat lib directory
• The webapp must have a context.xml file in WEB-INFcontent.xml, with the minimum content
– There are alternative locations for the context file. This is the location I find easiest to use.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.6</version>
<configuration>
<forkMode>once</forkMode>
<argLine> -javaagent:"${settings.localRepository}/org/springframework/spring-
instrument/${org.springframework.version}/spring-instrument-
${org.springframework.version}.jar"
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/
${org.aspectj.version}/aspectjweaver-${org.aspectj.version}.jar" </argLine>
<useSystemClassLoader>true</useSystemClassLoader>
</configuration>
</plugin>
<Context path="/">
<Loader loaderClass="org.springframework.instrument.classloading.tomcat.
TomcatInstrumentableClassLoader"/>
</Context>
ASPECTJ 101
As long as we’re talking about aspects…
AOP 101 – AspectJ Style
• Aspect – a concern that cuts across multiple classes. Examples are logging,
transaction handling, security, etc.
• Join Point – a point during the execution of a program. Examples are when
– A method is executed
– A method is called
– A constructor is executed
– A constructor is called
– An exception handler is executed
– An advice is executed
– Static initialization is executed
– Initialization and pre-initialization of an object
• Advice – an action taken by the aspect at a particular pointcut. Types of advice:
– Before, after returning, after throwing, after finally, around
• Pointcut – a selector of Join Points using predicates. An advice is associated with a
pointcut expression and runs on any point matched by the pointcut
AOP 101 – AspectJ Style
• More on pointcuts
– Pointcuts are query expressions on the code
– May be joined using the and (‘&&’), or (‘||’) or not (‘!’) operators
• Some pointcut predicates
– execution(…) – when a particular method body executes
– call(…) – when a method is called
– handler(….) – when a particular exception handler executes
– this(…) – when the currently executing object is of a certain type
– target(…) – when the target object is of type
– args(…) – when the method arguments match a certain type
– within(…) – when the executing code belongs to a certain class
– cflow(…) – when the program flow is in a certain method call (the method is a parent in
the stack)
– @annotation(…) – methods annotated with a certain annotation
– @target(…) – when the target executing object has a certain annotation
– @args(…) – when the runtime type of an argument has a certain annotation
– @within(…) – limits to pointcuts within a class that has a certain annotation
– bean(…) – a spring bean name
AOP 101 – AspectJ Style
• More on pointcuts
– Pointcuts are query expressions on the code
– May be joined using the and (‘&&’), or (‘||’) or not (‘!’) operators
• Some pointcut predicates
– execution(…) – when a particular method body executes
– call(…) – when a method is called
– handler(….) – when a particular exception handler executes
– this(…) – when the currently executing object is of a certain type
– target(…) – when the target object is of type
– args(…) – when the method arguments match a certain type
– within(…) – when the executing code belongs to a certain class
– cflow(…) – when the program flow is in a certain method call (the method is a parent in
the stack)
– @annotation(…) – methods annotated with a certain annotation
– @target(…) – when the target executing object has a certain annotation
– @args(…) – when the runtime type of an argument has a certain annotation
– @within(…) – limits to pointcuts within a class that has a certain annotation
– bean(…) – a spring bean name
Not
Supported by
Spring AOP
Only Spring
AOP
AOP 101 – AspectJ Style
• Some examples
– execution (int *())
• JoinPoints that are integer-returning method executions that do not take parameters
– @annotation(com.example.Log) && execution(* *(..))
• JoinPoints that are executions of methods annotated with the @Log annotation, regardless of
the method return type, class, name or parameters
– call(public * *(..))
• Call to any public method
– !this(Point) && call(int *(..))
• Any call to a method returning an integer when the executing object is of any type other
than Point
– cflow(P) && cflow(Q)
• All JoinPoint that are both in the control flow of P and in the control flow of Q
AOP 101 – AspectJ Style
• Coding Aspects using AspectJ Java Syntax
• The AspectJ syntax
@Aspect
public class MyAspect {
@Pointcut("within(com.springsource..*)")
public void inSpring() {}
@Pointcut("@Annotation(java.lang.Deprecated)")
public void inDepracated() {}
@Pointcut("inSpring() && inDepracated()")
public void deprecatedInSpring() {}
@Before("deprecatedInSpring()")
public void pointcutRef() {
...
}
@Before("within(com.springsource..*) && @Annotation(java.lang.Deprecated)")
public void pointcutInplace() {
...
}
}
aspect A {
pointcut fooPC(): execution(void Test.foo());
pointcut gooPC(): execution(void Test.goo());
pointcut printPC(): call(void java.io.PrintStream.println(String));
before(): cflow(fooPC()) && cflow(gooPC()) && printPC() && !within(A) {
System.out.println("should occur");
}
}
AOP 101 – AspectJ Style
• Adding code to existing classes using aspects (Inter-type declarations)
– Adding implemented interfaces
– Changing the superclass of a class
– Adding methods to a class
– Adding members to a class
– Implement Mix-ins in Java
• Using Join Points to raise custom compiler errors or warnings
• Privileged aspects
– Can access private, package and protected members of classes, bypassing the java
member visibility constraints
AOP 101 – AspectJ Style
• Example of an aspect modifying a class
aspect PointAssertions {
private boolean Point.assertX(int x) { return (x <= 100 && x >= 0); }
private boolean Point.assertY(int y) { return (y <= 100 && y >= 0); }
before(Point p, int x): target(p) && args(x) && call(void setX(int)) {
if (!p.assertX(x)) {
System.out.println("Illegal value for x");
return;
}
}
before(Point p, int y): target(p) && args(y) && call(void setY(int)) {
if (!p.assertY(y)) {
System.out.println("Illegal value for y");
return;
}
}
}
public class Point {
int x, y;
public void setX(int x) { this.x = x; }
public void setY(int y) { this.y = y; }
public static void main(String[] args) {
Point p = new Point();
p.setX(3);
p.setY(333);
}
}
BACK TO THE COOL STUFF
The bootstrap classloader
• What does it do?
– Allows replacing Java system classes
– Bypasses all Java security policies set by SecurityManager
• When do we use it?
– Meddling with the core Java APIs
– Terracotta uses it to replace the Java HashMap class with a distributed cache
implementation
• Limitations
– Classes loaded by the bootstrap classloader can’t load classes that are not included in
the bootstrap classpath
• Usage
– With the Java command line options
• –bootclasspath: - list of jars to use instead of the standard list
• –bootclasspath/a: - list of jars to append to the standard list
• –bootclasspath/p: - list of jars to prepend to the standard list
Javaagent and Instrument
• What does it do?
– Allows instrumenting / transforming / changing a class as it is loaded
• When do we use it?
– AspectJ uses it for load-time weaving
– To modify classes as we load them
• Limitations
– Works on the class file bytes – requires intimate knowledge of the class file structure
– Not very useful without a framework like AspectJ, BCEL, cglib, etc.
• Usage
– Using the –javaagent command line option to introduce an Agent jar
– The Agent jar has to have a premain method
• public static void premain(String agentArguments, Instrumentation
instrumentation)
– The Instrumentation class allows to redefine a class,
add & remove transformers, and re-transform a class.
– ClassFileTransformer has one method to transform a class
file bytes (as byte[]).
Writing Bytecode
• What does it do?
– Write new classes or modify existing classes at runtime
– Load the new/modified classes
– Instantiate them
– Use them as any other Java class
• When do we use it?
– Implementing Proxies on any class – Spring AOP and Hibernate do just that
– Hibernate uses bytecode manipulations of classes to introduce mechanisms for lazy-
loading of members
• My own experience
– Performance – when a mapping library (in my case XML to objects) was too slow due to
excessive use of reflection, coding simple mapping classes proved much faster
– Adaptor for Beans – a reporting framework used reflection on beans to read the field
definitions from a JavaObject datasource. When adapting a
Java query interface that returns map-like objects, we had to
generate wrapper classes adapting the map to the beans the
framework expected.
Writing Bytecode
• Limitations
– Hard to use
– Generated bytecode cannot be debugged normally – there’s no source code 
• BCEL – I’ve found using BCEL to be the easiest
• BCEL is included with JRE 1.6
– In package com.sun.org.apache.bcel
– However, the JRE version didn’t work for me
– Eventually, I’ve used the Apache version – BCEL 5.2
• Guidelines
– Keep the generated code small. Use helper methods / superclasses whenever you can.
Remember, you can debug helper classes or superclasses, but you can’t debug
generated bytecode
– Classes can be generated at build-time or runtime.
I’ve found runtime generation simpler to use
– Use class generation-by-example
Writing Bytecode
• Code generation or bytecode generation?
• Code generation
– Performed at build-time - inputs to the generation process must be available at
build time
– Easier to debug
– Tends to clutter the project source code
– Code-generation code tends to be longer than bytecode-generation code
– Hard to get the build right – separation of generated code from actual code
• Bytecode generation
– Performed at runtime – inputs to the generation process can be resolved at runtime
– Requires a higher skill level
– More complex to debug
• At the philosophical level
– If it can be generated, it’s not code!
– We’re just configuring the JVM, not coding
Writing Bytecode
• Class generation-by-example
– Write an example class of what you want to generate
– Compile it
– Run org.apache.bcel.util.BCELifier. It generates a factory class that generates your
example class bytecode
– Modify the generated factory class so that it generates the bytecode for the
classes you want
– Use a bytecode verifier to verify the generated classes
– Decompile generated files and verify method logic. I recommend that you set the
"annotate" option so you can see the bytecode instruction as comments.
– BCEL also provides a tool to generate HTML documentation for your example class
bytecode
• Class loading
– Code a new subclass of ClassLoader
– Use the defineClass (protected) method to define the new
generated class
– Remember to link your classloader to a parent classloader
Writing Bytecode
• Example – mapping objects from type A to type B
Using a superclass helper
public abstract class BaseMapper {
protected Object a;
protected Object b;
public BaseMapper(Object a, Object b) {
this.a = a;
this.b = b;
}
public abstract Object mapToB(Object a);
public abstract Object mapToA(Object b);
}
public class ExampleMappedClass extends BaseMapper{
public ExampleMappedClass(Person person, PersonDTO personDTO) {
super(person, personDTO);
}
@Override
public PersonDTO mapToB(Object a) {
Person person = (Person)a;
PersonDTO personDTO = new PersonDTO();
personDTO.name = person.name;
personDTO.lastName = person.lastName;
personDTO.id = Integer.toString(person.id);
return personDTO;
}
@Override public Person mapToA(Object b) {
PersonDTO personDTO = (PersonDTO)b;
Person person = new Person();
person.name = personDTO.name;
person.lastName = personDTO.lastName;
person.id = Integer.parseInt(personDTO.id);
return person;
}
}
The example class
Writing Bytecode
• Running BCELifier on the class
– BCELifier has a main method, accepting one parameter – the class name
• The created factory class
– Defining the class and the class members
public class ExampleMappedClassCreator implements Constants {
private InstructionFactory _factory;
private ConstantPoolGen _cp;
private ClassGen _cg;
public ExampleMappedClassCreator() {
_cg = new ClassGen("com.experiments.ExampleMappedClass", "com.experiments.BaseMapper",
"ExampleMappedClass.java", ACC_PUBLIC | ACC_SUPER, new String[] { });
_cp = _cg.getConstantPool();
_factory = new InstructionFactory(_cg, _cp);
}
public void create(OutputStream out) throws IOException {
createMethod_0();
createMethod_1();
createMethod_2();
createMethod_3();
createMethod_4();
_cg.getJavaClass().dump(out);
}
...
Writing Bytecode
• Creating the Factory class (continued)
– Creating the constructor
– Which generates bytecode for the constructor
private void createMethod_0() {
InstructionList il = new InstructionList();
MethodGen method = new MethodGen(ACC_PUBLIC, Type.VOID, new Type[] {
new ObjectType("com.experiments.Person"),
new ObjectType("com.experiments.PersonDTO") },
new String[] { "arg0", "arg1" },
"<init>", "com.experiments.ExampleMappedClass", il, _cp);
InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 0));
il.append(_factory.createLoad(Type.OBJECT, 1));
il.append(_factory.createLoad(Type.OBJECT, 2));
il.append(_factory.createInvoke("com.experiments.BaseMapper", "<init>",
Type.VOID, new Type[] { Type.OBJECT, Type.OBJECT }, Constants.INVOKESPECIAL));
InstructionHandle ih_6 = il.append(_factory.createReturn(Type.VOID));
method.setMaxStack();
method.setMaxLocals();
_cg.addMethod(method.getMethod());
il.dispose();
}
public ExampleMappedClass(Person person, PersonDTO personDTO) {
super(person, personDTO);
}
public PersonDTO mapToB(Object a) {
Person person = (Person)a;
PersonDTO personDTO = new PersonDTO();
personDTO.name = person.name;
personDTO.lastName = person.lastName;
personDTO.id = Integer.toString(person.id);
return personDTO;
}private void createMethod_1() {
InstructionList il = new InstructionList();
MethodGen method = new MethodGen(ACC_1PUBLIC, new ObjectType("com.experiments.PersonDTO"),
new Type[] { Type.OBJECT }, new String[] { "arg0" }, "mapToB", "com.experiments.ExampleMappedClass", il, _cp);
InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 1));
il.append(_factory.createCheckCast(new ObjectType("com.experiments.Person")));
il.append(_factory.createStore(Type.OBJECT, 2));
InstructionHandle ih_5 = il.append(_factory.createNew("com.experiments.PersonDTO"));
il.append(InstructionConstants.DUP);
il.append(_factory.createInvoke("com.experiments.PersonDTO", "<init>", Type.VOID, Type.NO_ARGS,
Constants.INVOKESPECIAL));
il.append(_factory.createStore(Type.OBJECT, 3));
InstructionHandle ih_13 = il.append(_factory.createLoad(Type.OBJECT, 3));
il.append(_factory.createLoad(Type.OBJECT, 2));
il.append(_factory.createFieldAccess("com.experiments.Person", "name", Type.STRING, Constants.GETFIELD));
il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "name", Type.STRING, Constants.PUTFIELD));
InstructionHandle ih_21 = il.append(_factory.createLoad(Type.OBJECT, 3));
il.append(_factory.createLoad(Type.OBJECT, 2));
il.append(_factory.createFieldAccess("com.experiments.Person", "lastName", Type.STRING, Constants.GETFIELD));
il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "lastName", Type.STRING, Constants.PUTFIELD));
InstructionHandle ih_29 = il.append(_factory.createLoad(Type.OBJECT, 3));
il.append(_factory.createLoad(Type.OBJECT, 2));
il.append(_factory.createFieldAccess("com.experiments.Person", "id", Type.INT, Constants.GETFIELD));
il.append(_factory.createInvoke("java.lang.Integer", "toString", Type.STRING, new Type[] { Type.INT },
Constants.INVOKESTATIC));
il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "id", Type.STRING, Constants.PUTFIELD));
InstructionHandle ih_40 = il.append(_factory.createLoad(Type.OBJECT, 3));
InstructionHandle ih_41 = il.append(_factory.createReturn(Type.OBJECT));
method.setMaxStack();
method.setMaxLocals();
_cg.addMethod(method.getMethod());
il.dispose();
}
Writing Bytecode
• Creating the Factory class (continued)
– Creating the mapToB method
public PersonDTO mapToB(Object a) {
Person person = (Person)a;
PersonDTO personDTO = new PersonDTO();
personDTO.name = person.name;
personDTO.lastName = person.lastName;
personDTO.id = Integer.toString(person.id);
return personDTO;
}private void createMethod_1() {
InstructionList il = new InstructionList();
MethodGen method = new MethodGen(ACC_1PUBLIC, new ObjectType("com.experiments.PersonDTO"),
new Type[] { Type.OBJECT }, new String[] { "arg0" }, "mapToB", "com.experiments.ExampleMappedClass", il, _cp);
InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 1));
il.append(_factory.createCheckCast(new ObjectType("com.experiments.Person")));
il.append(_factory.createStore(Type.OBJECT, 2));
InstructionHandle ih_5 = il.append(_factory.createNew("com.experiments.PersonDTO"));
il.append(InstructionConstants.DUP);
il.append(_factory.createInvoke("com.experiments.PersonDTO", "<init>", Type.VOID, Type.NO_ARGS,
Constants.INVOKESPECIAL));
il.append(_factory.createStore(Type.OBJECT, 3));
InstructionHandle ih_13 = il.append(_factory.createLoad(Type.OBJECT, 3));
il.append(_factory.createLoad(Type.OBJECT, 2));
il.append(_factory.createFieldAccess("com.experiments.Person", "name", Type.STRING, Constants.GETFIELD));
il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "name", Type.STRING, Constants.PUTFIELD));
InstructionHandle ih_21 = il.append(_factory.createLoad(Type.OBJECT, 3));
il.append(_factory.createLoad(Type.OBJECT, 2));
il.append(_factory.createFieldAccess("com.experiments.Person", "lastName", Type.STRING, Constants.GETFIELD));
il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "lastName", Type.STRING, Constants.PUTFIELD));
InstructionHandle ih_29 = il.append(_factory.createLoad(Type.OBJECT, 3));
il.append(_factory.createLoad(Type.OBJECT, 2));
il.append(_factory.createFieldAccess("com.experiments.Person", "id", Type.INT, Constants.GETFIELD));
il.append(_factory.createInvoke("java.lang.Integer", "toString", Type.STRING, new Type[] { Type.INT },
Constants.INVOKESTATIC));
il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "id", Type.STRING, Constants.PUTFIELD));
InstructionHandle ih_40 = il.append(_factory.createLoad(Type.OBJECT, 3));
InstructionHandle ih_41 = il.append(_factory.createReturn(Type.OBJECT));
method.setMaxStack();
method.setMaxLocals();
_cg.addMethod(method.getMethod());
il.dispose();
}
Writing Bytecode
• Creating the Factory class (continued)
– Creating the mapToB method
public
Return type
Input arguments
Class name
Method name
Input argument names
public PersonDTO mapToB(Object a) {
Person person = (Person)a;
PersonDTO personDTO = new PersonDTO();
personDTO.name = person.name;
personDTO.lastName = person.lastName;
personDTO.id = Integer.toString(person.id);
return personDTO;
}private void createMethod_1() {
InstructionList il = new InstructionList();
MethodGen method = new MethodGen(ACC_1PUBLIC, new ObjectType("com.experiments.PersonDTO"),
new Type[] { Type.OBJECT }, new String[] { "arg0" }, "mapToB", "com.experiments.ExampleMappedClass", il, _cp);
InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 1));
il.append(_factory.createCheckCast(new ObjectType("com.experiments.Person")));
il.append(_factory.createStore(Type.OBJECT, 2));
InstructionHandle ih_5 = il.append(_factory.createNew("com.experiments.PersonDTO"));
il.append(InstructionConstants.DUP);
il.append(_factory.createInvoke("com.experiments.PersonDTO", "<init>", Type.VOID, Type.NO_ARGS,
Constants.INVOKESPECIAL));
il.append(_factory.createStore(Type.OBJECT, 3));
InstructionHandle ih_13 = il.append(_factory.createLoad(Type.OBJECT, 3));
il.append(_factory.createLoad(Type.OBJECT, 2));
il.append(_factory.createFieldAccess("com.experiments.Person", "name", Type.STRING, Constants.GETFIELD));
il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "name", Type.STRING, Constants.PUTFIELD));
InstructionHandle ih_21 = il.append(_factory.createLoad(Type.OBJECT, 3));
il.append(_factory.createLoad(Type.OBJECT, 2));
il.append(_factory.createFieldAccess("com.experiments.Person", "lastName", Type.STRING, Constants.GETFIELD));
il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "lastName", Type.STRING, Constants.PUTFIELD));
InstructionHandle ih_29 = il.append(_factory.createLoad(Type.OBJECT, 3));
il.append(_factory.createLoad(Type.OBJECT, 2));
il.append(_factory.createFieldAccess("com.experiments.Person", "id", Type.INT, Constants.GETFIELD));
il.append(_factory.createInvoke("java.lang.Integer", "toString", Type.STRING, new Type[] { Type.INT },
Constants.INVOKESTATIC));
il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "id", Type.STRING, Constants.PUTFIELD));
InstructionHandle ih_40 = il.append(_factory.createLoad(Type.OBJECT, 3));
InstructionHandle ih_41 = il.append(_factory.createReturn(Type.OBJECT));
method.setMaxStack();
method.setMaxLocals();
_cg.addMethod(method.getMethod());
il.dispose();
}
Writing Bytecode
• Creating the Factory class (continued)
– Creating the mapToB method
Store the result as Object 2
Take Object 1 – the a parameter
(Object 0 is this)
Cast it to Person
public PersonDTO mapToB(Object a) {
Person person = (Person)a;
PersonDTO personDTO = new PersonDTO();
personDTO.name = person.name;
personDTO.lastName = person.lastName;
personDTO.id = Integer.toString(person.id);
return personDTO;
}private void createMethod_1() {
InstructionList il = new InstructionList();
MethodGen method = new MethodGen(ACC_1PUBLIC, new ObjectType("com.experiments.PersonDTO"),
new Type[] { Type.OBJECT }, new String[] { "arg0" }, "mapToB", "com.experiments.ExampleMappedClass", il, _cp);
InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 1));
il.append(_factory.createCheckCast(new ObjectType("com.experiments.Person")));
il.append(_factory.createStore(Type.OBJECT, 2));
InstructionHandle ih_5 = il.append(_factory.createNew("com.experiments.PersonDTO"));
il.append(InstructionConstants.DUP);
il.append(_factory.createInvoke("com.experiments.PersonDTO", "<init>", Type.VOID, Type.NO_ARGS,
Constants.INVOKESPECIAL));
il.append(_factory.createStore(Type.OBJECT, 3));
InstructionHandle ih_13 = il.append(_factory.createLoad(Type.OBJECT, 3));
il.append(_factory.createLoad(Type.OBJECT, 2));
il.append(_factory.createFieldAccess("com.experiments.Person", "name", Type.STRING, Constants.GETFIELD));
il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "name", Type.STRING, Constants.PUTFIELD));
InstructionHandle ih_21 = il.append(_factory.createLoad(Type.OBJECT, 3));
il.append(_factory.createLoad(Type.OBJECT, 2));
il.append(_factory.createFieldAccess("com.experiments.Person", "lastName", Type.STRING, Constants.GETFIELD));
il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "lastName", Type.STRING, Constants.PUTFIELD));
InstructionHandle ih_29 = il.append(_factory.createLoad(Type.OBJECT, 3));
il.append(_factory.createLoad(Type.OBJECT, 2));
il.append(_factory.createFieldAccess("com.experiments.Person", "id", Type.INT, Constants.GETFIELD));
il.append(_factory.createInvoke("java.lang.Integer", "toString", Type.STRING, new Type[] { Type.INT },
Constants.INVOKESTATIC));
il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "id", Type.STRING, Constants.PUTFIELD));
InstructionHandle ih_40 = il.append(_factory.createLoad(Type.OBJECT, 3));
InstructionHandle ih_41 = il.append(_factory.createReturn(Type.OBJECT));
method.setMaxStack();
method.setMaxLocals();
_cg.addMethod(method.getMethod());
il.dispose();
}
Writing Bytecode
• Creating the Factory class (continued)
– Creating the mapToB method
Store the result as Object 3
Create new PersonDTO
Invoke the personDTO constructor
public PersonDTO mapToB(Object a) {
Person person = (Person)a;
PersonDTO personDTO = new PersonDTO();
personDTO.name = person.name;
personDTO.lastName = person.lastName;
personDTO.id = Integer.toString(person.id);
return personDTO;
}private void createMethod_1() {
InstructionList il = new InstructionList();
MethodGen method = new MethodGen(ACC_1PUBLIC, new ObjectType("com.experiments.PersonDTO"),
new Type[] { Type.OBJECT }, new String[] { "arg0" }, "mapToB", "com.experiments.ExampleMappedClass", il, _cp);
InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 1));
il.append(_factory.createCheckCast(new ObjectType("com.experiments.Person")));
il.append(_factory.createStore(Type.OBJECT, 2));
InstructionHandle ih_5 = il.append(_factory.createNew("com.experiments.PersonDTO"));
il.append(InstructionConstants.DUP);
il.append(_factory.createInvoke("com.experiments.PersonDTO", "<init>", Type.VOID, Type.NO_ARGS,
Constants.INVOKESPECIAL));
il.append(_factory.createStore(Type.OBJECT, 3));
InstructionHandle ih_13 = il.append(_factory.createLoad(Type.OBJECT, 3));
il.append(_factory.createLoad(Type.OBJECT, 2));
il.append(_factory.createFieldAccess("com.experiments.Person", "name", Type.STRING, Constants.GETFIELD));
il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "name", Type.STRING, Constants.PUTFIELD));
InstructionHandle ih_21 = il.append(_factory.createLoad(Type.OBJECT, 3));
il.append(_factory.createLoad(Type.OBJECT, 2));
il.append(_factory.createFieldAccess("com.experiments.Person", "lastName", Type.STRING, Constants.GETFIELD));
il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "lastName", Type.STRING, Constants.PUTFIELD));
InstructionHandle ih_29 = il.append(_factory.createLoad(Type.OBJECT, 3));
il.append(_factory.createLoad(Type.OBJECT, 2));
il.append(_factory.createFieldAccess("com.experiments.Person", "id", Type.INT, Constants.GETFIELD));
il.append(_factory.createInvoke("java.lang.Integer", "toString", Type.STRING, new Type[] { Type.INT },
Constants.INVOKESTATIC));
il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "id", Type.STRING, Constants.PUTFIELD));
InstructionHandle ih_40 = il.append(_factory.createLoad(Type.OBJECT, 3));
InstructionHandle ih_41 = il.append(_factory.createReturn(Type.OBJECT));
method.setMaxStack();
method.setMaxLocals();
_cg.addMethod(method.getMethod());
il.dispose();
}
Writing Bytecode
• Creating the Factory class (continued)
– Creating the mapToB method
Pop the stack, writing the value to the name property of object 3
Load object 3 to the stack - Person
Read the name field from object 2 to the stack
Load object 2 to the stack - PersonDTO
Writing Bytecode
• Creating the Factory class (continued)
– Creating the mapToB method – we got a second mapToB method
– The first has signature PersonDTO mapToB(Object)
– The second has signature Object mapToB(Object)
– The second overrides the superclass mapToB method and calls the first
– Narrowing the return type of mapToB was apparently not a good idea, given that
generated classes loaded at runtime do not benefit from the narrowed type constraint
private void createMethod_4() {
InstructionList il = new InstructionList();
MethodGen method = new MethodGen(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, Type.OBJECT,
new Type[] { Type.OBJECT }, new String[] { "arg0" }, "mapToB",
"com.experiments.ExampleMappedClass", il, _cp);
InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 0));
il.append(_factory.createLoad(Type.OBJECT, 1));
il.append(_factory.createInvoke("com.experiments.ExampleMappedClass", "mapToB",
new ObjectType("com.experiments.PersonDTO"), new Type[] { Type.OBJECT }, Constants.INVOKEVIRTUAL));
InstructionHandle ih_5 = il.append(_factory.createReturn(Type.OBJECT));
method.setMaxStack();
method.setMaxLocals();
_cg.addMethod(method.getMethod());
il.dispose();
}
class MyClassLoader extends ClassLoader {
MyClassLoader(ClassLoader parent) {
super(parent);
}
public void defineClass(JavaClass javaClass) {
byte[] classBytes = javaClass.getBytes();
defineClass(javaClass.getClassName(), classBytes, 0, classBytes.length);
}
}
public JavaClass create() {
createMethod_0();
createMethod_1();
createMethod_2();
createMethod_3();
createMethod_4();
return _cg.getJavaClass();
}
MyClassLoader myClassLoader = new MyClassLoader(this.getClass().getClassLoader());
ExampleMappedClassCreator creator = new ExampleMappedClassCreator();
JavaClass javaClass = creator.create();
myClassLoader.defineClass(javaClass);
Class<?> clazz = myClassLoader.loadClass(javaClass.getClassName());
Constructor<?> constructor = clazz.getConstructor(Person.class, PersonDTO.class);
BaseMapper mapper = (BaseMapper)constructor.newInstance(new Person(), new PersonDTO());
Writing Bytecode• Using the generated class
– The Class loader
– Creating and loading the new class
– Add a method returning JavaClass to the factory class
– And use it
class MyClassLoader extends ClassLoader {
MyClassLoader(ClassLoader parent) {
super(parent);
}
public void defineClass(JavaClass javaClass) {
byte[] classBytes = javaClass.getBytes();
defineClass(javaClass.getClassName(), classBytes, 0, classBytes.length);
}
}
public JavaClass create() {
createMethod_0();
createMethod_1();
createMethod_2();
createMethod_3();
createMethod_4();
return _cg.getJavaClass();
}
MyClassLoader myClassLoader = new MyClassLoader(this.getClass().getClassLoader());
ExampleMappedClassCreator creator = new ExampleMappedClassCreator();
JavaClass javaClass = creator.create();
myClassLoader.defineClass(javaClass);
Class<?> clazz = myClassLoader.loadClass(javaClass.getClassName());
Constructor<?> constructor = clazz.getConstructor(Person.class, PersonDTO.class);
BaseMapper mapper = (BaseMapper)constructor.newInstance(new Person(), new PersonDTO());
Writing Bytecode• Using the generated class
– The Class loader
– Creating and loading the new class
– Add a method returning JavaClass to the factory class
– And use it
Create the classloader
Create the class factory
Create the class bytecode
Define the new class
Load the new class
Get the new class constructor
Call the constructor
IT IS THAT SIMPLE


More Related Content

What's hot

Java byte code presentation
Java byte code presentationJava byte code presentation
Java byte code presentationMahnoor Hashmi
 
Java virtual machine
Java virtual machineJava virtual machine
Java virtual machineNikhil Sharma
 
Java and Java platforms
Java and Java platformsJava and Java platforms
Java and Java platformsIlio Catallo
 
Java history, versions, types of errors and exception, quiz
Java history, versions, types of errors and exception, quiz Java history, versions, types of errors and exception, quiz
Java history, versions, types of errors and exception, quiz SAurabh PRajapati
 
Playing with Java Classes and Bytecode
Playing with Java Classes and BytecodePlaying with Java Classes and Bytecode
Playing with Java Classes and BytecodeYoav Avrahami
 
New Features Of JDK 7
New Features Of JDK 7New Features Of JDK 7
New Features Of JDK 7Deniz Oguz
 
Introduction to java
Introduction to javaIntroduction to java
Introduction to javaAjay Sharma
 
CS Lesson: Introduction to the Java virtual Machine
CS Lesson: Introduction to the Java virtual MachineCS Lesson: Introduction to the Java virtual Machine
CS Lesson: Introduction to the Java virtual MachineKatrin Becker
 
Understanding Java Dynamic Proxies
Understanding Java Dynamic ProxiesUnderstanding Java Dynamic Proxies
Understanding Java Dynamic ProxiesRafael Luque Leiva
 
Architecture diagram of jvm
Architecture diagram of jvmArchitecture diagram of jvm
Architecture diagram of jvmhome
 
Java Virtual Machine - Internal Architecture
Java Virtual Machine - Internal ArchitectureJava Virtual Machine - Internal Architecture
Java Virtual Machine - Internal Architecturesubnesh
 

What's hot (20)

Java introduction
Java introductionJava introduction
Java introduction
 
Java byte code presentation
Java byte code presentationJava byte code presentation
Java byte code presentation
 
Java Virtual Machine
Java Virtual MachineJava Virtual Machine
Java Virtual Machine
 
Java virtual machine
Java virtual machineJava virtual machine
Java virtual machine
 
Jvm Architecture
Jvm ArchitectureJvm Architecture
Jvm Architecture
 
Java and Java platforms
Java and Java platformsJava and Java platforms
Java and Java platforms
 
Java history, versions, types of errors and exception, quiz
Java history, versions, types of errors and exception, quiz Java history, versions, types of errors and exception, quiz
Java history, versions, types of errors and exception, quiz
 
Playing with Java Classes and Bytecode
Playing with Java Classes and BytecodePlaying with Java Classes and Bytecode
Playing with Java Classes and Bytecode
 
3. jvm
3. jvm3. jvm
3. jvm
 
New Features Of JDK 7
New Features Of JDK 7New Features Of JDK 7
New Features Of JDK 7
 
Introduction to java
Introduction to javaIntroduction to java
Introduction to java
 
Java &amp; advanced java
Java &amp; advanced javaJava &amp; advanced java
Java &amp; advanced java
 
CS Lesson: Introduction to the Java virtual Machine
CS Lesson: Introduction to the Java virtual MachineCS Lesson: Introduction to the Java virtual Machine
CS Lesson: Introduction to the Java virtual Machine
 
Understanding Java Dynamic Proxies
Understanding Java Dynamic ProxiesUnderstanding Java Dynamic Proxies
Understanding Java Dynamic Proxies
 
Invoke dynamics
Invoke dynamicsInvoke dynamics
Invoke dynamics
 
Architecture diagram of jvm
Architecture diagram of jvmArchitecture diagram of jvm
Architecture diagram of jvm
 
Java essential notes
Java essential notesJava essential notes
Java essential notes
 
Java basics notes
Java basics notesJava basics notes
Java basics notes
 
Java architecture
Java architectureJava architecture
Java architecture
 
Java Virtual Machine - Internal Architecture
Java Virtual Machine - Internal ArchitectureJava Virtual Machine - Internal Architecture
Java Virtual Machine - Internal Architecture
 

Viewers also liked

JVM, byte codes & jvm languages
JVM, byte codes & jvm languagesJVM, byte codes & jvm languages
JVM, byte codes & jvm languagesEdgar Espina
 
JavaOne 2010: Top 10 Causes for Java Issues in Production and What to Do When...
JavaOne 2010: Top 10 Causes for Java Issues in Production and What to Do When...JavaOne 2010: Top 10 Causes for Java Issues in Production and What to Do When...
JavaOne 2010: Top 10 Causes for Java Issues in Production and What to Do When...srisatish ambati
 
Mastering Java Bytecode With ASM - 33rd degree, 2012
Mastering Java Bytecode With ASM - 33rd degree, 2012Mastering Java Bytecode With ASM - 33rd degree, 2012
Mastering Java Bytecode With ASM - 33rd degree, 2012Anton Arhipov
 
JavaOne 2012 CON 3961 Innovative Testing Techniques Using Bytecode Instrument...
JavaOne 2012 CON 3961 Innovative Testing Techniques Using Bytecode Instrument...JavaOne 2012 CON 3961 Innovative Testing Techniques Using Bytecode Instrument...
JavaOne 2012 CON 3961 Innovative Testing Techniques Using Bytecode Instrument...PaulThwaite
 
Bytecode manipulation with Javassist and ASM
Bytecode manipulation with Javassist and ASMBytecode manipulation with Javassist and ASM
Bytecode manipulation with Javassist and ASMashleypuls
 
Java Bytecode For Discriminating Developers - GeeCON 2011
Java Bytecode For Discriminating Developers - GeeCON 2011Java Bytecode For Discriminating Developers - GeeCON 2011
Java Bytecode For Discriminating Developers - GeeCON 2011Anton Arhipov
 
OWASP SD: Deserialize My Shorts: Or How I Learned To Start Worrying and Hate ...
OWASP SD: Deserialize My Shorts: Or How I Learned To Start Worrying and Hate ...OWASP SD: Deserialize My Shorts: Or How I Learned To Start Worrying and Hate ...
OWASP SD: Deserialize My Shorts: Or How I Learned To Start Worrying and Hate ...Christopher Frohoff
 
Built in classes in java
Built in classes in javaBuilt in classes in java
Built in classes in javaMahmoud Ali
 
Inner Classes & Multi Threading in JAVA
Inner Classes & Multi Threading in JAVAInner Classes & Multi Threading in JAVA
Inner Classes & Multi Threading in JAVATech_MX
 
C sharp part 001
C sharp part 001C sharp part 001
C sharp part 001Ralph Weber
 
Make Java Profilers Lie Less
Make Java Profilers Lie LessMake Java Profilers Lie Less
Make Java Profilers Lie LessJaroslav Bachorik
 
GeeCon2016- High Performance Instrumentation (handout)
GeeCon2016- High Performance Instrumentation (handout)GeeCon2016- High Performance Instrumentation (handout)
GeeCon2016- High Performance Instrumentation (handout)Jaroslav Bachorik
 
Java Collections
Java CollectionsJava Collections
Java Collectionsparag
 
Esoft Metro Campus - Certificate in java basics
Esoft Metro Campus - Certificate in java basicsEsoft Metro Campus - Certificate in java basics
Esoft Metro Campus - Certificate in java basicsRasan Samarasinghe
 
Basic Concepts of OOPs (Object Oriented Programming in Java)
Basic Concepts of OOPs (Object Oriented Programming in Java)Basic Concepts of OOPs (Object Oriented Programming in Java)
Basic Concepts of OOPs (Object Oriented Programming in Java)Michelle Anne Meralpis
 

Viewers also liked (20)

JVM, byte codes & jvm languages
JVM, byte codes & jvm languagesJVM, byte codes & jvm languages
JVM, byte codes & jvm languages
 
JavaOne 2010: Top 10 Causes for Java Issues in Production and What to Do When...
JavaOne 2010: Top 10 Causes for Java Issues in Production and What to Do When...JavaOne 2010: Top 10 Causes for Java Issues in Production and What to Do When...
JavaOne 2010: Top 10 Causes for Java Issues in Production and What to Do When...
 
Mastering Java Bytecode With ASM - 33rd degree, 2012
Mastering Java Bytecode With ASM - 33rd degree, 2012Mastering Java Bytecode With ASM - 33rd degree, 2012
Mastering Java Bytecode With ASM - 33rd degree, 2012
 
JavaOne 2012 CON 3961 Innovative Testing Techniques Using Bytecode Instrument...
JavaOne 2012 CON 3961 Innovative Testing Techniques Using Bytecode Instrument...JavaOne 2012 CON 3961 Innovative Testing Techniques Using Bytecode Instrument...
JavaOne 2012 CON 3961 Innovative Testing Techniques Using Bytecode Instrument...
 
Bytecode manipulation with Javassist and ASM
Bytecode manipulation with Javassist and ASMBytecode manipulation with Javassist and ASM
Bytecode manipulation with Javassist and ASM
 
Oops concepts
Oops conceptsOops concepts
Oops concepts
 
Java Bytecode For Discriminating Developers - GeeCON 2011
Java Bytecode For Discriminating Developers - GeeCON 2011Java Bytecode For Discriminating Developers - GeeCON 2011
Java Bytecode For Discriminating Developers - GeeCON 2011
 
OWASP SD: Deserialize My Shorts: Or How I Learned To Start Worrying and Hate ...
OWASP SD: Deserialize My Shorts: Or How I Learned To Start Worrying and Hate ...OWASP SD: Deserialize My Shorts: Or How I Learned To Start Worrying and Hate ...
OWASP SD: Deserialize My Shorts: Or How I Learned To Start Worrying and Hate ...
 
JVM
JVMJVM
JVM
 
Built in classes in java
Built in classes in javaBuilt in classes in java
Built in classes in java
 
Inner Classes & Multi Threading in JAVA
Inner Classes & Multi Threading in JAVAInner Classes & Multi Threading in JAVA
Inner Classes & Multi Threading in JAVA
 
Java virtual machine
Java virtual machineJava virtual machine
Java virtual machine
 
C sharp part 001
C sharp part 001C sharp part 001
C sharp part 001
 
Java Inner Classes
Java Inner ClassesJava Inner Classes
Java Inner Classes
 
Make Java Profilers Lie Less
Make Java Profilers Lie LessMake Java Profilers Lie Less
Make Java Profilers Lie Less
 
GeeCon2016- High Performance Instrumentation (handout)
GeeCon2016- High Performance Instrumentation (handout)GeeCon2016- High Performance Instrumentation (handout)
GeeCon2016- High Performance Instrumentation (handout)
 
Java Collections
Java CollectionsJava Collections
Java Collections
 
Esoft Metro Campus - Certificate in java basics
Esoft Metro Campus - Certificate in java basicsEsoft Metro Campus - Certificate in java basics
Esoft Metro Campus - Certificate in java basics
 
Basic Concepts of OOPs (Object Oriented Programming in Java)
Basic Concepts of OOPs (Object Oriented Programming in Java)Basic Concepts of OOPs (Object Oriented Programming in Java)
Basic Concepts of OOPs (Object Oriented Programming in Java)
 
OOP java
OOP javaOOP java
OOP java
 

Similar to Playing with Java Classes and Bytecode: Understanding Classloading and AOP

The Art of Metaprogramming in Java
The Art of Metaprogramming in Java  The Art of Metaprogramming in Java
The Art of Metaprogramming in Java Abdelmonaim Remani
 
Learn Java with Dr. Rifat Shahriyar
Learn Java with Dr. Rifat ShahriyarLearn Java with Dr. Rifat Shahriyar
Learn Java with Dr. Rifat ShahriyarAbir Mohammad
 
Java For beginners and CSIT and IT students
Java  For beginners and CSIT and IT studentsJava  For beginners and CSIT and IT students
Java For beginners and CSIT and IT studentsPartnered Health
 
imperative programming language, java, android
imperative programming language, java, androidimperative programming language, java, android
imperative programming language, java, androidi i
 
1 java programming- introduction
1  java programming- introduction1  java programming- introduction
1 java programming- introductionjyoti_lakhani
 
Java Basics for selenium
Java Basics for seleniumJava Basics for selenium
Java Basics for seleniumapoorvams
 
java: basics, user input, data type, constructor
java:  basics, user input, data type, constructorjava:  basics, user input, data type, constructor
java: basics, user input, data type, constructorShivam Singhal
 
Java programming basics
Java programming basicsJava programming basics
Java programming basicsHamid Ghorbani
 
Manuel - SPR - Intro to Java Language_2016
Manuel - SPR - Intro to Java Language_2016Manuel - SPR - Intro to Java Language_2016
Manuel - SPR - Intro to Java Language_2016Manuel Fomitescu
 
Beginning Java for .NET developers
Beginning Java for .NET developersBeginning Java for .NET developers
Beginning Java for .NET developersAndrei Rinea
 
Java programing considering performance
Java programing considering performanceJava programing considering performance
Java programing considering performanceRoger Xia
 

Similar to Playing with Java Classes and Bytecode: Understanding Classloading and AOP (20)

oop unit1.pptx
oop unit1.pptxoop unit1.pptx
oop unit1.pptx
 
CS8392 OOP
CS8392 OOPCS8392 OOP
CS8392 OOP
 
Java and the JVM
Java and the JVMJava and the JVM
Java and the JVM
 
The Art of Metaprogramming in Java
The Art of Metaprogramming in Java  The Art of Metaprogramming in Java
The Art of Metaprogramming in Java
 
Learn Java with Dr. Rifat Shahriyar
Learn Java with Dr. Rifat ShahriyarLearn Java with Dr. Rifat Shahriyar
Learn Java with Dr. Rifat Shahriyar
 
Java For beginners and CSIT and IT students
Java  For beginners and CSIT and IT studentsJava  For beginners and CSIT and IT students
Java For beginners and CSIT and IT students
 
imperative programming language, java, android
imperative programming language, java, androidimperative programming language, java, android
imperative programming language, java, android
 
1 java programming- introduction
1  java programming- introduction1  java programming- introduction
1 java programming- introduction
 
Module 1.pptx
Module 1.pptxModule 1.pptx
Module 1.pptx
 
Java basics training 1
Java basics training 1Java basics training 1
Java basics training 1
 
Presentation on java
Presentation  on  javaPresentation  on  java
Presentation on java
 
Java Basics for selenium
Java Basics for seleniumJava Basics for selenium
Java Basics for selenium
 
java: basics, user input, data type, constructor
java:  basics, user input, data type, constructorjava:  basics, user input, data type, constructor
java: basics, user input, data type, constructor
 
Java JVM
Java JVMJava JVM
Java JVM
 
Introduction java programming
Introduction java programmingIntroduction java programming
Introduction java programming
 
Java programming basics
Java programming basicsJava programming basics
Java programming basics
 
Manuel - SPR - Intro to Java Language_2016
Manuel - SPR - Intro to Java Language_2016Manuel - SPR - Intro to Java Language_2016
Manuel - SPR - Intro to Java Language_2016
 
java basic .pdf
java basic .pdfjava basic .pdf
java basic .pdf
 
Beginning Java for .NET developers
Beginning Java for .NET developersBeginning Java for .NET developers
Beginning Java for .NET developers
 
Java programing considering performance
Java programing considering performanceJava programing considering performance
Java programing considering performance
 

Recently uploaded

Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 

Recently uploaded (20)

Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 

Playing with Java Classes and Bytecode: Understanding Classloading and AOP

  • 1. Playing with Java Classes and Bytecode What is a Class? How it is loaded and used? How to write a Java program that writes itself at runtime? Yoav Abrahami Wix.com
  • 2. Java Classloading • Why do we care? – Because if we’re gonna write code at runtime, we’d better know how to load and use it… – Because we don’t really understand classes • So… what identifies a class? – Its name – Its package – Its classloader • It means that – We can have multiple instances of a class loaded at the same time – Two instances of the same class from different classloaders are not compatible and not assignable – Static variables are static only in the context of a classloader, not globally as we’re always told
  • 3. Java Classloading • So what is this classloader? – A Java class (subclass of java.lang.ClassLoader), responsible for loading other classes used by the JVM – Classloaders are arranged as a tree • Bootstrap classloader – Loads the Java system • jre/lib/resources.jar – series of resource files • jre/lib/rt.jar – the java.*, javax.*, etc packages • jre/lib/sunrsasign.jar • jre/lib/jsse.jar – secure socket extension • jre/lib/jce.jar – Java cryptography extension • jre/lib/charsets.jar • jre/classes – The important stuff is in rt.jar – the base Java classes Bootstrap classloader Ext classloader Application / System classloader
  • 4. Java Classloading Commandline Java App Tomcat (6) Bootstrap classloader Ext classloader Application / System classloader Application / System classloader Common classloader WAR 1 classloader WAR 2 classloader
  • 5. Java Classloading Commandline Java App Tomcat (6) Bootstrap classloader Ext classloader Application / System classloader Application / System classloader Common classloader WAR 1 classloader WAR 2 classloader Loads the Application Jars from the classpath Loads only bootstrap.jar and tomcat-juli.jar Loads Tomcat commons library jars Loads jars in the webapp lib directory
  • 6. LETS TALK BUSINESS Ok, we understand classes. Where is the cool stuff?
  • 7. What we’re gonna talk about • Aspect Oriented Programming – Java Proxy – Spring Aspects – AspectJ Aspects • Doing the really cool stuff – The bootstrap classloader – The javaagent and class instrumentation – Writing bytecode at runtime • All in context of when I’ve had to use them
  • 8. The Java Proxy • What does it do? – Allows implementing one or more interfaces dynamically • When do we use it? – Generic implementation of an interface – such as in the case of a client calling a service. The client uses an interface with a generic implementation that marshals the method calls to whatever “on-the-wire” format. For instance, creating a SOAP client on the fly using an interface and WSDL – Simplistic AOP – to catch method calls, perform some pre/post/around logic and delegate the call to the real implementation. Can be used for transaction handling, logging, etc. • Limitations – Only supports Java interfaces – Intercepts only calls to the proxy instance. Direct calls to the delegate will not be intercepted (for instance, a call from one delegate method to another)
  • 9. The Java Proxy • Example code public interface SomeInterface { public void doSomething(); public void doAnotherThing(String name); } Object p = Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class<?>[]{SomeInterface.class}, new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("invoking method:" + method.getName()); if (args != null) for (Object arg: args) System.out.println(" arg: " + arg); return null; } }); SomeInterface s = (SomeInterface)p; s.doSomething(); s.doAnotherThing("hello");
  • 10. Spring AOP • What does it do? – Allows intercepting method calls to Spring beans, with or without an interface – Simpler code compared to the Java Proxy – Based on the proxy model – Spring BeanFactory returns a proxy to the real bean – Supports choosing the methods to intercept using AspectJ selectors – Aspects are written using the AspectJ Java syntax • When do we use it? – AOP on Spring beans – Transaction handling, logging, security handling – anything AOP is good for • Limitations – Only supports Spring beans – Intercepts only calls to the proxy instance. Direct calls to the delegate will not be intercepted (for instance, a call from one delegate method to another) – Supports only a subset of AspectJ selectors
  • 11. Spring AOP • Configuring Spring AOP • Example Aspect • Activating the Aspect – Using Spring component scan, by adding the @Component annotation on the aspect – Using Spring Beans XML @Aspect public class ExampleAspect { @Around("@annotation(com.experiments.RequireLogin)") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { ... } } <bean class="com.experiments.ExampleAspect"/> <aop:aspectj-autoproxy/>
  • 12. AspectJ • What does it do? – Allows intercepting any JoinPoint such as method calls, exceptions, etc. – Supports writing aspects using Java or AspectJ syntax – Modifies the actual class bytecode – Supports choosing the methods to intercept using AspectJ selectors – Modify existing classes, adding methods, members and super-interfaces to them – Weaves aspects on load time or compile time • When do we use it? – AOP on any Java class – Transaction handling, logging, security – anything AOP is good for – Introduce compiler-like coding rules • Limitations – For compile-time weaving – replaces the standard Java Compiler – For load-time weaving – requires elaborate JVM configuration
  • 13. AspectJ • Configuration options – Compile-time weaving – Load-time weaving – Load-time weaving with Spring • Dependencies – aspectjrt.jar must be in the classpath • Configuring AspectJ load-time weaving with Spring – Simple, isn’t it? • Well, not so simple… <aop:aspectj-autoproxy/> <context:load-time-weaver/>
  • 14. AspectJ • Need to include META-INF/aop.xml – declares the aspects for load-time weaving and the target packages to weave into <!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd"> <aspectj> <weaver> <!-- only any class from the com.experiments package --> <include within="com.experiments..*"/> </weaver> <aspects> <!-- weave in just this aspect --> <aspect name="com.experiments.ExampleAspect"/> </aspects> </aspectj>
  • 15. AspectJ • Per-platform configuration for class instrumentation – Command line & JUnit applications – using the -javaagent to load instrumentation jars • -javaagent:spring-instrument-<version>.jar -javaagent:aspectjweaver-<version>.jar – Maven running JUnit – using the maven-surefire-plugin, passing it the javaagent args – Note the two javaagent params must be at the same line – Tomcat 6 – • spring-instrument-tomcat-<version>.jar has to be copied to the Tomcat lib directory • The webapp must have a context.xml file in WEB-INFcontent.xml, with the minimum content – There are alternative locations for the context file. This is the location I find easiest to use. <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.6</version> <configuration> <forkMode>once</forkMode> <argLine> -javaagent:"${settings.localRepository}/org/springframework/spring- instrument/${org.springframework.version}/spring-instrument- ${org.springframework.version}.jar" -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/ ${org.aspectj.version}/aspectjweaver-${org.aspectj.version}.jar" </argLine> <useSystemClassLoader>true</useSystemClassLoader> </configuration> </plugin> <Context path="/"> <Loader loaderClass="org.springframework.instrument.classloading.tomcat. TomcatInstrumentableClassLoader"/> </Context>
  • 16. ASPECTJ 101 As long as we’re talking about aspects…
  • 17. AOP 101 – AspectJ Style • Aspect – a concern that cuts across multiple classes. Examples are logging, transaction handling, security, etc. • Join Point – a point during the execution of a program. Examples are when – A method is executed – A method is called – A constructor is executed – A constructor is called – An exception handler is executed – An advice is executed – Static initialization is executed – Initialization and pre-initialization of an object • Advice – an action taken by the aspect at a particular pointcut. Types of advice: – Before, after returning, after throwing, after finally, around • Pointcut – a selector of Join Points using predicates. An advice is associated with a pointcut expression and runs on any point matched by the pointcut
  • 18. AOP 101 – AspectJ Style • More on pointcuts – Pointcuts are query expressions on the code – May be joined using the and (‘&&’), or (‘||’) or not (‘!’) operators • Some pointcut predicates – execution(…) – when a particular method body executes – call(…) – when a method is called – handler(….) – when a particular exception handler executes – this(…) – when the currently executing object is of a certain type – target(…) – when the target object is of type – args(…) – when the method arguments match a certain type – within(…) – when the executing code belongs to a certain class – cflow(…) – when the program flow is in a certain method call (the method is a parent in the stack) – @annotation(…) – methods annotated with a certain annotation – @target(…) – when the target executing object has a certain annotation – @args(…) – when the runtime type of an argument has a certain annotation – @within(…) – limits to pointcuts within a class that has a certain annotation – bean(…) – a spring bean name
  • 19. AOP 101 – AspectJ Style • More on pointcuts – Pointcuts are query expressions on the code – May be joined using the and (‘&&’), or (‘||’) or not (‘!’) operators • Some pointcut predicates – execution(…) – when a particular method body executes – call(…) – when a method is called – handler(….) – when a particular exception handler executes – this(…) – when the currently executing object is of a certain type – target(…) – when the target object is of type – args(…) – when the method arguments match a certain type – within(…) – when the executing code belongs to a certain class – cflow(…) – when the program flow is in a certain method call (the method is a parent in the stack) – @annotation(…) – methods annotated with a certain annotation – @target(…) – when the target executing object has a certain annotation – @args(…) – when the runtime type of an argument has a certain annotation – @within(…) – limits to pointcuts within a class that has a certain annotation – bean(…) – a spring bean name Not Supported by Spring AOP Only Spring AOP
  • 20. AOP 101 – AspectJ Style • Some examples – execution (int *()) • JoinPoints that are integer-returning method executions that do not take parameters – @annotation(com.example.Log) && execution(* *(..)) • JoinPoints that are executions of methods annotated with the @Log annotation, regardless of the method return type, class, name or parameters – call(public * *(..)) • Call to any public method – !this(Point) && call(int *(..)) • Any call to a method returning an integer when the executing object is of any type other than Point – cflow(P) && cflow(Q) • All JoinPoint that are both in the control flow of P and in the control flow of Q
  • 21. AOP 101 – AspectJ Style • Coding Aspects using AspectJ Java Syntax • The AspectJ syntax @Aspect public class MyAspect { @Pointcut("within(com.springsource..*)") public void inSpring() {} @Pointcut("@Annotation(java.lang.Deprecated)") public void inDepracated() {} @Pointcut("inSpring() && inDepracated()") public void deprecatedInSpring() {} @Before("deprecatedInSpring()") public void pointcutRef() { ... } @Before("within(com.springsource..*) && @Annotation(java.lang.Deprecated)") public void pointcutInplace() { ... } } aspect A { pointcut fooPC(): execution(void Test.foo()); pointcut gooPC(): execution(void Test.goo()); pointcut printPC(): call(void java.io.PrintStream.println(String)); before(): cflow(fooPC()) && cflow(gooPC()) && printPC() && !within(A) { System.out.println("should occur"); } }
  • 22. AOP 101 – AspectJ Style • Adding code to existing classes using aspects (Inter-type declarations) – Adding implemented interfaces – Changing the superclass of a class – Adding methods to a class – Adding members to a class – Implement Mix-ins in Java • Using Join Points to raise custom compiler errors or warnings • Privileged aspects – Can access private, package and protected members of classes, bypassing the java member visibility constraints
  • 23. AOP 101 – AspectJ Style • Example of an aspect modifying a class aspect PointAssertions { private boolean Point.assertX(int x) { return (x <= 100 && x >= 0); } private boolean Point.assertY(int y) { return (y <= 100 && y >= 0); } before(Point p, int x): target(p) && args(x) && call(void setX(int)) { if (!p.assertX(x)) { System.out.println("Illegal value for x"); return; } } before(Point p, int y): target(p) && args(y) && call(void setY(int)) { if (!p.assertY(y)) { System.out.println("Illegal value for y"); return; } } } public class Point { int x, y; public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; } public static void main(String[] args) { Point p = new Point(); p.setX(3); p.setY(333); } }
  • 24. BACK TO THE COOL STUFF
  • 25. The bootstrap classloader • What does it do? – Allows replacing Java system classes – Bypasses all Java security policies set by SecurityManager • When do we use it? – Meddling with the core Java APIs – Terracotta uses it to replace the Java HashMap class with a distributed cache implementation • Limitations – Classes loaded by the bootstrap classloader can’t load classes that are not included in the bootstrap classpath • Usage – With the Java command line options • –bootclasspath: - list of jars to use instead of the standard list • –bootclasspath/a: - list of jars to append to the standard list • –bootclasspath/p: - list of jars to prepend to the standard list
  • 26. Javaagent and Instrument • What does it do? – Allows instrumenting / transforming / changing a class as it is loaded • When do we use it? – AspectJ uses it for load-time weaving – To modify classes as we load them • Limitations – Works on the class file bytes – requires intimate knowledge of the class file structure – Not very useful without a framework like AspectJ, BCEL, cglib, etc. • Usage – Using the –javaagent command line option to introduce an Agent jar – The Agent jar has to have a premain method • public static void premain(String agentArguments, Instrumentation instrumentation) – The Instrumentation class allows to redefine a class, add & remove transformers, and re-transform a class. – ClassFileTransformer has one method to transform a class file bytes (as byte[]).
  • 27. Writing Bytecode • What does it do? – Write new classes or modify existing classes at runtime – Load the new/modified classes – Instantiate them – Use them as any other Java class • When do we use it? – Implementing Proxies on any class – Spring AOP and Hibernate do just that – Hibernate uses bytecode manipulations of classes to introduce mechanisms for lazy- loading of members • My own experience – Performance – when a mapping library (in my case XML to objects) was too slow due to excessive use of reflection, coding simple mapping classes proved much faster – Adaptor for Beans – a reporting framework used reflection on beans to read the field definitions from a JavaObject datasource. When adapting a Java query interface that returns map-like objects, we had to generate wrapper classes adapting the map to the beans the framework expected.
  • 28. Writing Bytecode • Limitations – Hard to use – Generated bytecode cannot be debugged normally – there’s no source code  • BCEL – I’ve found using BCEL to be the easiest • BCEL is included with JRE 1.6 – In package com.sun.org.apache.bcel – However, the JRE version didn’t work for me – Eventually, I’ve used the Apache version – BCEL 5.2 • Guidelines – Keep the generated code small. Use helper methods / superclasses whenever you can. Remember, you can debug helper classes or superclasses, but you can’t debug generated bytecode – Classes can be generated at build-time or runtime. I’ve found runtime generation simpler to use – Use class generation-by-example
  • 29. Writing Bytecode • Code generation or bytecode generation? • Code generation – Performed at build-time - inputs to the generation process must be available at build time – Easier to debug – Tends to clutter the project source code – Code-generation code tends to be longer than bytecode-generation code – Hard to get the build right – separation of generated code from actual code • Bytecode generation – Performed at runtime – inputs to the generation process can be resolved at runtime – Requires a higher skill level – More complex to debug • At the philosophical level – If it can be generated, it’s not code! – We’re just configuring the JVM, not coding
  • 30. Writing Bytecode • Class generation-by-example – Write an example class of what you want to generate – Compile it – Run org.apache.bcel.util.BCELifier. It generates a factory class that generates your example class bytecode – Modify the generated factory class so that it generates the bytecode for the classes you want – Use a bytecode verifier to verify the generated classes – Decompile generated files and verify method logic. I recommend that you set the "annotate" option so you can see the bytecode instruction as comments. – BCEL also provides a tool to generate HTML documentation for your example class bytecode • Class loading – Code a new subclass of ClassLoader – Use the defineClass (protected) method to define the new generated class – Remember to link your classloader to a parent classloader
  • 31. Writing Bytecode • Example – mapping objects from type A to type B Using a superclass helper public abstract class BaseMapper { protected Object a; protected Object b; public BaseMapper(Object a, Object b) { this.a = a; this.b = b; } public abstract Object mapToB(Object a); public abstract Object mapToA(Object b); } public class ExampleMappedClass extends BaseMapper{ public ExampleMappedClass(Person person, PersonDTO personDTO) { super(person, personDTO); } @Override public PersonDTO mapToB(Object a) { Person person = (Person)a; PersonDTO personDTO = new PersonDTO(); personDTO.name = person.name; personDTO.lastName = person.lastName; personDTO.id = Integer.toString(person.id); return personDTO; } @Override public Person mapToA(Object b) { PersonDTO personDTO = (PersonDTO)b; Person person = new Person(); person.name = personDTO.name; person.lastName = personDTO.lastName; person.id = Integer.parseInt(personDTO.id); return person; } } The example class
  • 32. Writing Bytecode • Running BCELifier on the class – BCELifier has a main method, accepting one parameter – the class name • The created factory class – Defining the class and the class members public class ExampleMappedClassCreator implements Constants { private InstructionFactory _factory; private ConstantPoolGen _cp; private ClassGen _cg; public ExampleMappedClassCreator() { _cg = new ClassGen("com.experiments.ExampleMappedClass", "com.experiments.BaseMapper", "ExampleMappedClass.java", ACC_PUBLIC | ACC_SUPER, new String[] { }); _cp = _cg.getConstantPool(); _factory = new InstructionFactory(_cg, _cp); } public void create(OutputStream out) throws IOException { createMethod_0(); createMethod_1(); createMethod_2(); createMethod_3(); createMethod_4(); _cg.getJavaClass().dump(out); } ...
  • 33. Writing Bytecode • Creating the Factory class (continued) – Creating the constructor – Which generates bytecode for the constructor private void createMethod_0() { InstructionList il = new InstructionList(); MethodGen method = new MethodGen(ACC_PUBLIC, Type.VOID, new Type[] { new ObjectType("com.experiments.Person"), new ObjectType("com.experiments.PersonDTO") }, new String[] { "arg0", "arg1" }, "<init>", "com.experiments.ExampleMappedClass", il, _cp); InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 0)); il.append(_factory.createLoad(Type.OBJECT, 1)); il.append(_factory.createLoad(Type.OBJECT, 2)); il.append(_factory.createInvoke("com.experiments.BaseMapper", "<init>", Type.VOID, new Type[] { Type.OBJECT, Type.OBJECT }, Constants.INVOKESPECIAL)); InstructionHandle ih_6 = il.append(_factory.createReturn(Type.VOID)); method.setMaxStack(); method.setMaxLocals(); _cg.addMethod(method.getMethod()); il.dispose(); } public ExampleMappedClass(Person person, PersonDTO personDTO) { super(person, personDTO); }
  • 34. public PersonDTO mapToB(Object a) { Person person = (Person)a; PersonDTO personDTO = new PersonDTO(); personDTO.name = person.name; personDTO.lastName = person.lastName; personDTO.id = Integer.toString(person.id); return personDTO; }private void createMethod_1() { InstructionList il = new InstructionList(); MethodGen method = new MethodGen(ACC_1PUBLIC, new ObjectType("com.experiments.PersonDTO"), new Type[] { Type.OBJECT }, new String[] { "arg0" }, "mapToB", "com.experiments.ExampleMappedClass", il, _cp); InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 1)); il.append(_factory.createCheckCast(new ObjectType("com.experiments.Person"))); il.append(_factory.createStore(Type.OBJECT, 2)); InstructionHandle ih_5 = il.append(_factory.createNew("com.experiments.PersonDTO")); il.append(InstructionConstants.DUP); il.append(_factory.createInvoke("com.experiments.PersonDTO", "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); il.append(_factory.createStore(Type.OBJECT, 3)); InstructionHandle ih_13 = il.append(_factory.createLoad(Type.OBJECT, 3)); il.append(_factory.createLoad(Type.OBJECT, 2)); il.append(_factory.createFieldAccess("com.experiments.Person", "name", Type.STRING, Constants.GETFIELD)); il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "name", Type.STRING, Constants.PUTFIELD)); InstructionHandle ih_21 = il.append(_factory.createLoad(Type.OBJECT, 3)); il.append(_factory.createLoad(Type.OBJECT, 2)); il.append(_factory.createFieldAccess("com.experiments.Person", "lastName", Type.STRING, Constants.GETFIELD)); il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "lastName", Type.STRING, Constants.PUTFIELD)); InstructionHandle ih_29 = il.append(_factory.createLoad(Type.OBJECT, 3)); il.append(_factory.createLoad(Type.OBJECT, 2)); il.append(_factory.createFieldAccess("com.experiments.Person", "id", Type.INT, Constants.GETFIELD)); il.append(_factory.createInvoke("java.lang.Integer", "toString", Type.STRING, new Type[] { Type.INT }, Constants.INVOKESTATIC)); il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "id", Type.STRING, Constants.PUTFIELD)); InstructionHandle ih_40 = il.append(_factory.createLoad(Type.OBJECT, 3)); InstructionHandle ih_41 = il.append(_factory.createReturn(Type.OBJECT)); method.setMaxStack(); method.setMaxLocals(); _cg.addMethod(method.getMethod()); il.dispose(); } Writing Bytecode • Creating the Factory class (continued) – Creating the mapToB method
  • 35. public PersonDTO mapToB(Object a) { Person person = (Person)a; PersonDTO personDTO = new PersonDTO(); personDTO.name = person.name; personDTO.lastName = person.lastName; personDTO.id = Integer.toString(person.id); return personDTO; }private void createMethod_1() { InstructionList il = new InstructionList(); MethodGen method = new MethodGen(ACC_1PUBLIC, new ObjectType("com.experiments.PersonDTO"), new Type[] { Type.OBJECT }, new String[] { "arg0" }, "mapToB", "com.experiments.ExampleMappedClass", il, _cp); InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 1)); il.append(_factory.createCheckCast(new ObjectType("com.experiments.Person"))); il.append(_factory.createStore(Type.OBJECT, 2)); InstructionHandle ih_5 = il.append(_factory.createNew("com.experiments.PersonDTO")); il.append(InstructionConstants.DUP); il.append(_factory.createInvoke("com.experiments.PersonDTO", "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); il.append(_factory.createStore(Type.OBJECT, 3)); InstructionHandle ih_13 = il.append(_factory.createLoad(Type.OBJECT, 3)); il.append(_factory.createLoad(Type.OBJECT, 2)); il.append(_factory.createFieldAccess("com.experiments.Person", "name", Type.STRING, Constants.GETFIELD)); il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "name", Type.STRING, Constants.PUTFIELD)); InstructionHandle ih_21 = il.append(_factory.createLoad(Type.OBJECT, 3)); il.append(_factory.createLoad(Type.OBJECT, 2)); il.append(_factory.createFieldAccess("com.experiments.Person", "lastName", Type.STRING, Constants.GETFIELD)); il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "lastName", Type.STRING, Constants.PUTFIELD)); InstructionHandle ih_29 = il.append(_factory.createLoad(Type.OBJECT, 3)); il.append(_factory.createLoad(Type.OBJECT, 2)); il.append(_factory.createFieldAccess("com.experiments.Person", "id", Type.INT, Constants.GETFIELD)); il.append(_factory.createInvoke("java.lang.Integer", "toString", Type.STRING, new Type[] { Type.INT }, Constants.INVOKESTATIC)); il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "id", Type.STRING, Constants.PUTFIELD)); InstructionHandle ih_40 = il.append(_factory.createLoad(Type.OBJECT, 3)); InstructionHandle ih_41 = il.append(_factory.createReturn(Type.OBJECT)); method.setMaxStack(); method.setMaxLocals(); _cg.addMethod(method.getMethod()); il.dispose(); } Writing Bytecode • Creating the Factory class (continued) – Creating the mapToB method public Return type Input arguments Class name Method name Input argument names
  • 36. public PersonDTO mapToB(Object a) { Person person = (Person)a; PersonDTO personDTO = new PersonDTO(); personDTO.name = person.name; personDTO.lastName = person.lastName; personDTO.id = Integer.toString(person.id); return personDTO; }private void createMethod_1() { InstructionList il = new InstructionList(); MethodGen method = new MethodGen(ACC_1PUBLIC, new ObjectType("com.experiments.PersonDTO"), new Type[] { Type.OBJECT }, new String[] { "arg0" }, "mapToB", "com.experiments.ExampleMappedClass", il, _cp); InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 1)); il.append(_factory.createCheckCast(new ObjectType("com.experiments.Person"))); il.append(_factory.createStore(Type.OBJECT, 2)); InstructionHandle ih_5 = il.append(_factory.createNew("com.experiments.PersonDTO")); il.append(InstructionConstants.DUP); il.append(_factory.createInvoke("com.experiments.PersonDTO", "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); il.append(_factory.createStore(Type.OBJECT, 3)); InstructionHandle ih_13 = il.append(_factory.createLoad(Type.OBJECT, 3)); il.append(_factory.createLoad(Type.OBJECT, 2)); il.append(_factory.createFieldAccess("com.experiments.Person", "name", Type.STRING, Constants.GETFIELD)); il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "name", Type.STRING, Constants.PUTFIELD)); InstructionHandle ih_21 = il.append(_factory.createLoad(Type.OBJECT, 3)); il.append(_factory.createLoad(Type.OBJECT, 2)); il.append(_factory.createFieldAccess("com.experiments.Person", "lastName", Type.STRING, Constants.GETFIELD)); il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "lastName", Type.STRING, Constants.PUTFIELD)); InstructionHandle ih_29 = il.append(_factory.createLoad(Type.OBJECT, 3)); il.append(_factory.createLoad(Type.OBJECT, 2)); il.append(_factory.createFieldAccess("com.experiments.Person", "id", Type.INT, Constants.GETFIELD)); il.append(_factory.createInvoke("java.lang.Integer", "toString", Type.STRING, new Type[] { Type.INT }, Constants.INVOKESTATIC)); il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "id", Type.STRING, Constants.PUTFIELD)); InstructionHandle ih_40 = il.append(_factory.createLoad(Type.OBJECT, 3)); InstructionHandle ih_41 = il.append(_factory.createReturn(Type.OBJECT)); method.setMaxStack(); method.setMaxLocals(); _cg.addMethod(method.getMethod()); il.dispose(); } Writing Bytecode • Creating the Factory class (continued) – Creating the mapToB method Store the result as Object 2 Take Object 1 – the a parameter (Object 0 is this) Cast it to Person
  • 37. public PersonDTO mapToB(Object a) { Person person = (Person)a; PersonDTO personDTO = new PersonDTO(); personDTO.name = person.name; personDTO.lastName = person.lastName; personDTO.id = Integer.toString(person.id); return personDTO; }private void createMethod_1() { InstructionList il = new InstructionList(); MethodGen method = new MethodGen(ACC_1PUBLIC, new ObjectType("com.experiments.PersonDTO"), new Type[] { Type.OBJECT }, new String[] { "arg0" }, "mapToB", "com.experiments.ExampleMappedClass", il, _cp); InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 1)); il.append(_factory.createCheckCast(new ObjectType("com.experiments.Person"))); il.append(_factory.createStore(Type.OBJECT, 2)); InstructionHandle ih_5 = il.append(_factory.createNew("com.experiments.PersonDTO")); il.append(InstructionConstants.DUP); il.append(_factory.createInvoke("com.experiments.PersonDTO", "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); il.append(_factory.createStore(Type.OBJECT, 3)); InstructionHandle ih_13 = il.append(_factory.createLoad(Type.OBJECT, 3)); il.append(_factory.createLoad(Type.OBJECT, 2)); il.append(_factory.createFieldAccess("com.experiments.Person", "name", Type.STRING, Constants.GETFIELD)); il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "name", Type.STRING, Constants.PUTFIELD)); InstructionHandle ih_21 = il.append(_factory.createLoad(Type.OBJECT, 3)); il.append(_factory.createLoad(Type.OBJECT, 2)); il.append(_factory.createFieldAccess("com.experiments.Person", "lastName", Type.STRING, Constants.GETFIELD)); il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "lastName", Type.STRING, Constants.PUTFIELD)); InstructionHandle ih_29 = il.append(_factory.createLoad(Type.OBJECT, 3)); il.append(_factory.createLoad(Type.OBJECT, 2)); il.append(_factory.createFieldAccess("com.experiments.Person", "id", Type.INT, Constants.GETFIELD)); il.append(_factory.createInvoke("java.lang.Integer", "toString", Type.STRING, new Type[] { Type.INT }, Constants.INVOKESTATIC)); il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "id", Type.STRING, Constants.PUTFIELD)); InstructionHandle ih_40 = il.append(_factory.createLoad(Type.OBJECT, 3)); InstructionHandle ih_41 = il.append(_factory.createReturn(Type.OBJECT)); method.setMaxStack(); method.setMaxLocals(); _cg.addMethod(method.getMethod()); il.dispose(); } Writing Bytecode • Creating the Factory class (continued) – Creating the mapToB method Store the result as Object 3 Create new PersonDTO Invoke the personDTO constructor
  • 38. public PersonDTO mapToB(Object a) { Person person = (Person)a; PersonDTO personDTO = new PersonDTO(); personDTO.name = person.name; personDTO.lastName = person.lastName; personDTO.id = Integer.toString(person.id); return personDTO; }private void createMethod_1() { InstructionList il = new InstructionList(); MethodGen method = new MethodGen(ACC_1PUBLIC, new ObjectType("com.experiments.PersonDTO"), new Type[] { Type.OBJECT }, new String[] { "arg0" }, "mapToB", "com.experiments.ExampleMappedClass", il, _cp); InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 1)); il.append(_factory.createCheckCast(new ObjectType("com.experiments.Person"))); il.append(_factory.createStore(Type.OBJECT, 2)); InstructionHandle ih_5 = il.append(_factory.createNew("com.experiments.PersonDTO")); il.append(InstructionConstants.DUP); il.append(_factory.createInvoke("com.experiments.PersonDTO", "<init>", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); il.append(_factory.createStore(Type.OBJECT, 3)); InstructionHandle ih_13 = il.append(_factory.createLoad(Type.OBJECT, 3)); il.append(_factory.createLoad(Type.OBJECT, 2)); il.append(_factory.createFieldAccess("com.experiments.Person", "name", Type.STRING, Constants.GETFIELD)); il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "name", Type.STRING, Constants.PUTFIELD)); InstructionHandle ih_21 = il.append(_factory.createLoad(Type.OBJECT, 3)); il.append(_factory.createLoad(Type.OBJECT, 2)); il.append(_factory.createFieldAccess("com.experiments.Person", "lastName", Type.STRING, Constants.GETFIELD)); il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "lastName", Type.STRING, Constants.PUTFIELD)); InstructionHandle ih_29 = il.append(_factory.createLoad(Type.OBJECT, 3)); il.append(_factory.createLoad(Type.OBJECT, 2)); il.append(_factory.createFieldAccess("com.experiments.Person", "id", Type.INT, Constants.GETFIELD)); il.append(_factory.createInvoke("java.lang.Integer", "toString", Type.STRING, new Type[] { Type.INT }, Constants.INVOKESTATIC)); il.append(_factory.createFieldAccess("com.experiments.PersonDTO", "id", Type.STRING, Constants.PUTFIELD)); InstructionHandle ih_40 = il.append(_factory.createLoad(Type.OBJECT, 3)); InstructionHandle ih_41 = il.append(_factory.createReturn(Type.OBJECT)); method.setMaxStack(); method.setMaxLocals(); _cg.addMethod(method.getMethod()); il.dispose(); } Writing Bytecode • Creating the Factory class (continued) – Creating the mapToB method Pop the stack, writing the value to the name property of object 3 Load object 3 to the stack - Person Read the name field from object 2 to the stack Load object 2 to the stack - PersonDTO
  • 39. Writing Bytecode • Creating the Factory class (continued) – Creating the mapToB method – we got a second mapToB method – The first has signature PersonDTO mapToB(Object) – The second has signature Object mapToB(Object) – The second overrides the superclass mapToB method and calls the first – Narrowing the return type of mapToB was apparently not a good idea, given that generated classes loaded at runtime do not benefit from the narrowed type constraint private void createMethod_4() { InstructionList il = new InstructionList(); MethodGen method = new MethodGen(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC, Type.OBJECT, new Type[] { Type.OBJECT }, new String[] { "arg0" }, "mapToB", "com.experiments.ExampleMappedClass", il, _cp); InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 0)); il.append(_factory.createLoad(Type.OBJECT, 1)); il.append(_factory.createInvoke("com.experiments.ExampleMappedClass", "mapToB", new ObjectType("com.experiments.PersonDTO"), new Type[] { Type.OBJECT }, Constants.INVOKEVIRTUAL)); InstructionHandle ih_5 = il.append(_factory.createReturn(Type.OBJECT)); method.setMaxStack(); method.setMaxLocals(); _cg.addMethod(method.getMethod()); il.dispose(); }
  • 40. class MyClassLoader extends ClassLoader { MyClassLoader(ClassLoader parent) { super(parent); } public void defineClass(JavaClass javaClass) { byte[] classBytes = javaClass.getBytes(); defineClass(javaClass.getClassName(), classBytes, 0, classBytes.length); } } public JavaClass create() { createMethod_0(); createMethod_1(); createMethod_2(); createMethod_3(); createMethod_4(); return _cg.getJavaClass(); } MyClassLoader myClassLoader = new MyClassLoader(this.getClass().getClassLoader()); ExampleMappedClassCreator creator = new ExampleMappedClassCreator(); JavaClass javaClass = creator.create(); myClassLoader.defineClass(javaClass); Class<?> clazz = myClassLoader.loadClass(javaClass.getClassName()); Constructor<?> constructor = clazz.getConstructor(Person.class, PersonDTO.class); BaseMapper mapper = (BaseMapper)constructor.newInstance(new Person(), new PersonDTO()); Writing Bytecode• Using the generated class – The Class loader – Creating and loading the new class – Add a method returning JavaClass to the factory class – And use it
  • 41. class MyClassLoader extends ClassLoader { MyClassLoader(ClassLoader parent) { super(parent); } public void defineClass(JavaClass javaClass) { byte[] classBytes = javaClass.getBytes(); defineClass(javaClass.getClassName(), classBytes, 0, classBytes.length); } } public JavaClass create() { createMethod_0(); createMethod_1(); createMethod_2(); createMethod_3(); createMethod_4(); return _cg.getJavaClass(); } MyClassLoader myClassLoader = new MyClassLoader(this.getClass().getClassLoader()); ExampleMappedClassCreator creator = new ExampleMappedClassCreator(); JavaClass javaClass = creator.create(); myClassLoader.defineClass(javaClass); Class<?> clazz = myClassLoader.loadClass(javaClass.getClassName()); Constructor<?> constructor = clazz.getConstructor(Person.class, PersonDTO.class); BaseMapper mapper = (BaseMapper)constructor.newInstance(new Person(), new PersonDTO()); Writing Bytecode• Using the generated class – The Class loader – Creating and loading the new class – Add a method returning JavaClass to the factory class – And use it Create the classloader Create the class factory Create the class bytecode Define the new class Load the new class Get the new class constructor Call the constructor
  • 42. IT IS THAT SIMPLE 