1. Playing with Java Classes
and Bytecode
What is a Class?
How it is loaded and used?
How can I write a code at runtime, using that code?
2. Java Classloading
• Why do we care?
– Because if we gonna write code at runtime, we better know how
to load it and use it…
– Because we do not really understand classes
• So… what identifies a class?
– It’s name
– It’s package
– It’s classloader
• It means that
– We can have multiple instances of a class loaded.
– 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 are
always told.
3. Java Classloading
• So what is this classloader?
– It is a class written in Java (subclass of java.lang.ClassLoader), responsible to load other
classes for use by the JVM
– Arranged as a tree of classloaders
• 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
Loads the Application Jars
from the classpath
Loads just the
bootstrap.jar and
tomcat-juli.jar
Loads the tomcat
commons library jars
Loads the jars in the
webapp lib directory
6. What we gonna talk about
• Aspect Oriented Programming
– Java Proxy
– Spring Aspects
– AspectJ Aspects
• Doing the real cool stuff
– The bootstrap classloader
– The javaagent and class instrumentation
– Writing bytecode at runtime
7. The Java Proxy
• What it does
– It allows to implement one or more interfaces dynamically
• When to use it
– Generic implementation of an interface – such as in the case of client code calling a
service. The generic implementation can marshal the client method call to whatever
“on-the-wire” format, saving the developer from coding stubs.
– Simplistic aspect oriented programming – 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
– Can only function on Java interfaces
– Intercepts only calls done on the proxy instance. When used on
the delegate model, calls directly on the delegate will not be
intercepted.
9. Spring AOP
• What it does
– Allows to intercept method calls to Spring beans, without the requirement for an
interface
– Simplifies the code compared to the Java Proxy
– Works in the proxy model – spring beans factory returns a proxy to the bean we
intercept methods of
– Allows using AspectJ selectors to select the methods to intercept
– Aspects are written using the AspectJ Java syntax
• When to use it
– Aspect programming on Spring beans.
– Transaction handling, logging, security handling – anything AOP is good for
• Limitations
– Can only function on Spring Beans
– Intercepts only calls done on the proxy instance. Inner bean calls will
not be intercepted
– Supports only a small subset of AspectJ selectors – only the method
execution join points are supported.
10. 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
11. AspectJ
• What it does
– Allows to intercept any Join Point such as method calls, exceptions, etc
– Allows writing aspects using Java or AspectJ syntax
– Changes the actual class bytecode
– Allows using AspectJ selectors to select the methods to intercept
– Change existing classes, adding methods, members and super-interfaces to them
– Weaves aspects on load time or compile time
• When to use it
– Aspect programming on any Java object
– Transaction handling, logging, security handling – anything AOP is good for
– Introduce compiler like coding rules
• Limitations
– Requires custom Java Compiler (AspectJ compiler)
– Or requires custom definitions for load time weaving
(depending on run environment)
12. AspectJ
• Configuration options
– Compile time weaving
– Load time weaving
– Load time weaving with Spring
• Configuring AspectJ Load time weaving with Spring
– Simple, isn’t it?
• Well, there are additional requirements
• Dependencies
– aspectjrt.jar must be in the classpath
• (continues on next slide)
13. AspectJ
• META-INF/aop.xml
– declares the aspects for load time weaving and the target packages to weave into
• Class instrumentation
– Commandline & 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 –
• The jar spring-instrument-tomcat-<version>.jar has to be copied to tomcats lib directory
• The webapp has to have a context.xml file in WEB-INFcontent.xml, with the minimum content
– Note there are alternative locations for the context file. This is the location I find easiest to use.
15. Intro to AOP (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 – action taken by the aspect at a particular pointcut. Types of advice
– Before, after returning, after throwing, after finally, around
• Pointcut – a selector of pointcuts using predicates. An advice is associated with a
pointcut expression and runs on any point matched by the pointcut
16. Intro to AOP (AspectJ Style)
• More on pointcuts
– Pointcuts are query expressions on the code.
– Can 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(…) – then 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
17. Intro to AOP (AspectJ Style)
• Some examples
– execution (int *())
• joinpoints who are method executions for methods who return an int and do not take
parameters
– @annotation(com.example.Log) && execution(* *(..))
• joinpoints who are method executions for 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 method call to an int method when the executing object is any type except Point.
– cflow(P) && cflow(Q)
• each join point that is in both the control flow of P and in the control flow of Q
18. Intro to AOP (AspectJ Style)
• Coding Aspects using AspectJ Java Syntax
• AspectJ AspectJ syntax
19. Intro to AOP (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 variable to a class
– Turning java into multiple inheritance system – change interfaces to include method
implementation and variables
• Using join points as compiler errors or warnings
• SoftExceptions
– catching an exception at a join point and replacing it with SoftException (subclass of
RuntimeException)
• Privileged aspects
– Can access private, package and protected members of classes, bypassing the java
member visibility constraints
20. Intro to AOP (AspectJ Style)
• Example of an aspect modifying a class
22. Bootstrap classloader
• What it does
– Allows to replace java system classes
– Bypasses all java security policy set by SecurityManager
• When to use it
– Snuff inside the core Java APIs
– Change core Java API functionality
– Terracotta uses it to replace the Java HashMap class with a distributed cache
implementation
• Limitations
– Classes loaded by the bootstrap classloader are not able to load classes not included in
the bootstrap classloader jar list
• Usage
– With the java commandline 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
23. Javaagent and Instrument
• What it does
– Allows to instrument / transform / change a class definition
as it is loaded
• When to use it
– AspectJ uses it for load time weaving
– To modify classes as we load them
• Limitations
– It 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 java commandline parameter 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 retransform a class.
– ClassFileTransformer has one method to transform a class
file bytes (as a byte[]).
24. Writing Bytecode
• What it does
– Allows to write new classes or modify existing classes at runtime
– Load the new/modified classes
– Instantiate them
– Use them as any other Java class
• When to use it
– Performance – when a mapping library (in my case XML to objects) was too slow
because of excessive use of reflections, coding simple mapping classes proved match
faster
– Implementing Proxies on any class – Spring AOP and Hibernate do just that
– Hibernate uses bytecode modification of classes to introduce mechanisms for lazy
loading of members
– Adaptor for Beans – a reporting framework used reflection on beans to read the field
definitions from in it’s Java Object 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.
25. Writing Bytecode
• Limitations
– Hard to use
– Generated bytecode cannot be debugged normally - we do
not have the source code
• BCEL – I have found using BCEL to be easiest for me
• BCEL is included with JRE 1.6 under the package
com.sun.org.apache.bcel
– However, the JRE version did not work for me.
– I have used the apache version – 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 cannot debug
generated bytecode.
– Classes can be generated at build time or runtime.
I have found runtime generation simpler to use
– Use class generation by example
• Good resource
– http://java.sys-con.com/node/49088
26. 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 will create java code, that when running it, will
create a factory class that generates your example class.
– You can also use org.apache.bcel.util.Class2-HTML to get HTML documentation of your
example class bytecode.
– Modify the generated factory class to generate the bytecode for the classes you want
– Use org.apache.bcel.verifier.Verifier or
com.pavelvlasov.codegen.ClassGeneratorBase.verify() to verify that the generated
classes are valid
– Use Jad, Jadclipse or DJ Java Decompiler to decompile generated files and verify method
logic. I recommend that you set the "annotate" option so you can see the bytecode
instruction as comments.
• Class loading
– Code a new subclass of ClassLoader
– Use the defineClass (protected) method to define the new
generated class
– Remember to link your class loader to a parent class loader
27. Writing Bytecode
• Example – mapping objects from type A to type B
Using a superclass helper
–
– The example class
28. Writing Bytecode
• Running BCELifier on the class
– BCELifier has a main method, getting one parameter – the class name
• The created factory class
– Defining the class and the class members
29. Writing Bytecode
• Creating the Factory class (continued)
– Creating the constructor
– Which creates the constructor
30. Writing Bytecode
• Creating the Factory class (continued)
– Creating the mapToB method
public
Return type
Input arguments
Input argument names
Method name
Class name
31. 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
32. Writing Bytecode
• Creating the Factory class (continued)
– Creating the mapToB method
Store the result as Object 3
Create new PersonDTO
Invoke the personDTO constructor
33. 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
34. Writing Bytecode
• Creating the Factory class (continued)
– Creating the mapToB method – we got another 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.
– Guess narrowing the return type of mapToB was not a really good idea, given generated
class loaded at runtime does not really benefit from the narrowed type constraint
–
35. 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