SlideShare ist ein Scribd-Unternehmen logo
1 von 134
Downloaden Sie, um offline zu lesen
QCon NY 2014
Living in the Matrix with
Bytecode Manipulation
Tuesday, June 10, 14
Ashley Puls
Senior Software Engineer
New Relic, Inc.
Tuesday, June 10, 14
Outline
• What is bytecode?
• Why manipulate bytecode?
• What frameworks can be used to
manipulate bytecode?
• Examine two frameworks in depth
Tuesday, June 10, 14
What is Java bytecode?
.java file .class file
Java compiler
(javac)
Class Loader
Bytecode
Verifier
Java Runtime
System
Native OS
Java Virtual Machine
Source: http://www.techlila.com/write-programs-linux/
Tuesday, June 10, 14
What is Java bytecode?
.java file .class file
Java compiler
(javac)
Class Loader
Bytecode
Verifier
Java Runtime
System
Native OS
Java Virtual Machine
Source: http://www.techlila.com/write-programs-linux/
Tuesday, June 10, 14
What is Java bytecode?
.java file .class file
Java compiler
(javac)
Class Loader
Bytecode
Verifier
Java Runtime
System
Native OS
Java Virtual Machine
Source: http://www.techlila.com/write-programs-linux/
Instruction set of the Java Virtual Machine
Tuesday, June 10, 14
Why learn about Java bytecode
manipulation frameworks ?
Tuesday, June 10, 14
Why learn about Java bytecode
manipulation frameworks ?
• A bytecode manipulation framework is likely already
on your stack
• Spring
• Hibernate
• Groovy
• Clojure
• Eclipse
• JRuby
Tuesday, June 10, 14
• A bytecode manipulation framework is likely already
on your stack
• Spring
• Hibernate
• Groovy
• Clojure
• Eclipse
• JRuby
• Its really fun!!!
Why learn about Java bytecode
manipulation frameworks ?
Tuesday, June 10, 14
Why learn about Java bytecode
manipulation frameworks ?
• program analysis
• find bugs in code
• examine code complexity
• generate classes
• proxies
• remove access to certain APIs
• compiler for another language like Scala
• transform classes without Java source code
• profilers
• optimization and obfuscation
• additional logging
Tuesday, June 10, 14
Why learn about Java bytecode
manipulation frameworks ?
• program analysis
• find bugs in code
• examine code complexity
• generate classes
• proxies
• remove access to certain APIs
• compiler for another language like Scala
• transform classes without Java source code
• profilers
• optimization and obfuscation
• additional logging
Tuesday, June 10, 14
Logging
Source: http://www.vforteachers.com/About_NetSupport.htm
Tuesday, June 10, 14
Logging
Source: http://www.vforteachers.com/About_NetSupport.htm, http://inzolo.com/blog/tutorials/bank-accounts
Tuesday, June 10, 14
Logging
Source: http://www.vforteachers.com/About_NetSupport.htm, http://upload.wikimedia.org/wikipedia/commons/d/d3/49024-SOS-ATM.JPG
Tuesday, June 10, 14
Logging
Audit Log: a message should be
logged every time an important
method is called
Source: http://www.vforteachers.com/About_NetSupport.htm
Tuesday, June 10, 14
Logging
Source: http://www.vforteachers.com/About_NetSupport.htm
log important input parameters
to the method
Audit Log: a message should be
logged every time an important
method is called
Tuesday, June 10, 14
Logging
public class BankTransactions {
	 public static void main(String[] args) {
	 	 BankTransactions bank = new BankTransactions();
	 	 // login and add i dollars to account
	 	 for (int i = 0; i < 100; i++) {
	 	 	 String accountId = "account" + i;
	 	 	 bank.login("password", accountId, "Ashley");
bank.unimportantProcessing(accountId);
	 	 	 bank.finalizeTransaction(accountId, Double.valueOf(i));
	 	 }
System.out.println(“Transactions completed”);
	 }
}
Tuesday, June 10, 14
Logging
public class BankTransactions {
	 public static void main(String[] args) {
	 	 BankTransactions bank = new BankTransactions();
	 	 // login and add i dollars to each account
	 	 for (int i = 0; i < 100; i++) {
	 	 	 String accountId = "account" + i;
	 	 	 bank.login("password", accountId, "Ashley");
bank.unimportantProcessing(accountId);
	 	 	 bank.finalizeTransaction(accountId, Double.valueOf(i));
	 	 }
System.out.println(“Transactions completed”);
	 }
}
Tuesday, June 10, 14
Logging
/**
* A method annotation which should be used to indicate important methods whose
* invocations should be logged.
*
*/
public @interface ImportantLog {
	 /**
	 * The method parameter indexes whose values should be logged. For example,
	 * if we have the method hello(int paramA, int paramB, int paramC), and we
	 * wanted to log the values of paramA and paramC, then fields would be ["0",
	 * "2"]. If we only want to log the value of paramB, then fields would be
	 * ["1"].
	 */
	 String[] fields();
}
Tuesday, June 10, 14
Logging
	 public void login(String password, String accountId, String userName) {
	 	 // login logic
	 }
	 public void finalizeTransaction(String accountId, Double moneyToAdd) {
	 	 // transaction logic
	 }
Tuesday, June 10, 14
Logging
	 @ImportantLog(fields = { "1", "2" })
	 public void login(String password, String accountId, String userName) {
	 	 // login logic
	 }
	 @ImportantLog(fields = { "0", "1" })
	 public void finalizeTransaction(String accountId, Double moneyToAdd) {
	 	 // transaction logic
	 }
Tuesday, June 10, 14
Logging
	 @ImportantLog(fields = { "1", "2" })
	 public void login(String password, String accountId, String userName) {
	 	 // login logic
	 }
	 @ImportantLog(fields = { "0", "1" })
	 public void finalizeTransaction(String accountId, Double moneyToAdd) {
	 	 // transaction logic
	 }
A call was made to method "login" on class "com/example/qcon/mains/BankTransactions".
Important params:
Index 1 value: ${accountId}
Index 2 value: ${userName}
Tuesday, June 10, 14
Logging
	 @ImportantLog(fields = { "1", "2" })
	 public void login(String password, String accountId, String userName) {
	 	 // login logic
	 }
	 @ImportantLog(fields = { "0", "1" })
	 public void finalizeTransaction(String accountId, Double moneyToAdd) {
	 	 // transaction logic
	 }
A call was made to method "finalizeTransaction" on class "com/example/qcon/
mains/BankTransactions".
Important params:
Index 0 value: ${accountId}
Index 1 value: ${moneyToAdd}
A call was made to method "login" on class "com/example/qcon/mains/BankTransactions".
Important params:
Index 1 value: ${accountId}
Index 2 value: ${userName}
Tuesday, June 10, 14
Java Agent
• Ability to modify the bytecode without modifying the
application source code
• Added in Java 1.5
• Docs: http://docs.oracle.com/javase/8/docs/api/
java/lang/instrument/package-summary.html
Tuesday, June 10, 14
Typical Java Process
JVM
public static void main(String[] args)
BankTransactions.class
Classloader
java com/example/qcon/mains/BankTransactions
Transactions completed
Tuesday, June 10, 14
Java Agent
JVMAgent
java -javaagent:/path/to/agent.jar com/example/qcon/mains/
BankTransactions
Tuesday, June 10, 14
Java Agent
JVM
java -javaagent:/path/to/agent.jar com/example/qcon/mains/
BankTransactions
Tuesday, June 10, 14
Java Agent
JVMAgent
java -javaagent:/path/to/agent.jar com/example/qcon/mains/
BankTransactions
Tuesday, June 10, 14
Java Agent
JVM
void premain(String agentArgs, Instrumentation inst)
Agent.class
MyTransformer.class
byte[] transform( . . . , byte[] bankTransBytes)
Agent
1. call Agent premain in manifest
2. JVM registers my transformer
java -javaagent:/path/to/agent.jar com/example/qcon/mains/
BankTransactions
Tuesday, June 10, 14
Java Agent
JVM
void premain(String agentArgs, Instrumentation inst)
Agent.class
MyTransformer.class
byte[] transform( . . . , byte[] bankTransBytes)
Agent
1. call Agent premain in manifest
2. JVM registers my transformer
3. Give BankTransactions bytes to
MyTransformer
4. MyTransformer provides
bytes to load
java -javaagent:/path/to/agent.jar com/example/qcon/mains/
BankTransactions
Tuesday, June 10, 14
Java Agent
JVM
void main(String[] args)
BankTransactions.class
void premain(String agentArgs, Instrumentation inst)
Agent.class
MyTransformer.class
byte[] transform( . . . , byte[] bankTransBytes)
Agent
1. call Agent premain in manifest
2. JVM registers my transformer
3. Give BankTransactions bytes to
MyTransformer
4. MyTransformer provides
bytes to load
5. BankTransactions loaded and main
runs
java -javaagent:/path/to/agent.jar com/example/qcon/mains/
BankTransactions
Transactions completed
Tuesday, June 10, 14
lets code
Manifest:
Premain-Class: com.example.qcon.agent.Agent
Tuesday, June 10, 14
lets code
package com.example.qcon.agent;
public class Agent {
	 public static void premain(String agentArgs, Instrumentation inst) {
	 	 System.out.println("Starting the agent");
	 	 inst.addTransformer(new ImportantLogClassTransformer());
	 }
}
Manifest:
Premain-Class: com.example.qcon.agent.Agent
Tuesday, June 10, 14
lets code
package com.example.qcon.agent;
public class Agent {
	 public static void premain(String agentArgs, Instrumentation inst) {
	 	 System.out.println("Starting the agent");
	 	 inst.addTransformer(new ImportantLogClassTransformer());
	 }
}
Manifest:
Premain-Class: com.example.qcon.agent.Agent
Tuesday, June 10, 14
lets code
package com.example.qcon.agent;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
public class ImportantLogClassTransformer implements
ClassFileTransformer {
	 public byte[] transform(ClassLoader loader, String className,
	 	 	 Class classBeingRedefined, ProtectionDomain protectionDomain,
	 	 	 byte[] classfileBuffer) throws IllegalClassFormatException {
//TODO
	 	 return null;
	 }
}
Tuesday, June 10, 14
lets code
package com.example.qcon.agent;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
public class ImportantLogClassTransformer implements
ClassFileTransformer {
	 public byte[] transform(ClassLoader loader, String className,
	 	 	 Class classBeingRedefined, ProtectionDomain protectionDomain,
	 	 	 byte[] classfileBuffer) throws IllegalClassFormatException {
//TODO
	 	 return null;
	 }
}
Tuesday, June 10, 14
lets code
package com.example.qcon.agent;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
public class ImportantLogClassTransformer implements
ClassFileTransformer {
	 public byte[] transform(ClassLoader loader, String className,
	 	 	 Class classBeingRedefined, ProtectionDomain protectionDomain,
	 	 	 byte[] classfileBuffer) throws IllegalClassFormatException {
System.out.println(" Loading class: " + className);
	 	 return null;
	 }
}
Tuesday, June 10, 14
lets code
Starting the agent
Loading class: java/lang/invoke/MethodHandleImpl
Loading class: java/lang/invoke/MemberName$Factory
Loading class: java/lang/invoke/LambdaForm$NamedFunction
Loading class: java/lang/invoke/MethodType$ConcurrentWeakInternSet
Loading class: java/lang/invoke/MethodHandleStatics
Loading class: java/lang/invoke/MethodHandleStatics$1
Loading class: java/lang/invoke/MethodTypeForm
Loading class: java/lang/invoke/Invokers
Loading class: java/lang/invoke/MethodType$ConcurrentWeakInternSet$WeakEntry
Loading class: java/lang/Void
Loading class: java/lang/IllegalAccessException
Loading class: sun/misc/PostVMInitHook
Loading class: sun/launcher/LauncherHelper
Loading class: java/util/concurrent/ConcurrentHashMap$ForwardingNode
Loading class: sun/misc/URLClassPath$FileLoader$1
Loading class: com/example/qcon/mains/BankTransactions
Loading class: sun/launcher/LauncherHelper$FXHelper
Tuesday, June 10, 14
lets code
package com.example.qcon.agent;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
public class ImportantLogClassTransformer implements
ClassFileTransformer {
	 public byte[] transform(ClassLoader loader, String className,
	 	 	 Class classBeingRedefined, ProtectionDomain protectionDomain,
	 	 	 byte[] classfileBuffer) throws IllegalClassFormatException {
System.out.println(" Loading class: " + className);
	 	 return null;
	 }
}
Tuesday, June 10, 14
lets code
package com.example.qcon.agent;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
public class ImportantLogClassTransformer implements
ClassFileTransformer {
	 public byte[] transform(ClassLoader loader, String className,
	 	 	 Class classBeingRedefined, ProtectionDomain protectionDomain,
	 	 	 byte[] classfileBuffer) throws IllegalClassFormatException {
// manipulate the bytes here and then return them
	 	 return null;
	 }
}
Tuesday, June 10, 14
Bytecode Manipulation Frameworks
• ASM: http://asm.ow2.org/
• BCEL: http://commons.apache.org/proper/commons-bcel/
• CGLib: https://github.com/cglib/cglib
• Javassist: http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/
• Serp: http://serp.sourceforge.net/
• Cojen: https://github.com/cojen/Cojen/wiki
• Soot: http://www.sable.mcgill.ca/soot/
Tuesday, June 10, 14
Bytecode Manipulation Frameworks
• ASM: http://asm.ow2.org/
• BCEL: http://commons.apache.org/proper/commons-bcel/
• CGLib: https://github.com/cglib/cglib
• Javassist: http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/
• Serp: http://serp.sourceforge.net/
• Cojen: https://github.com/cojen/Cojen/wiki
• Soot: http://www.sable.mcgill.ca/soot/
Tuesday, June 10, 14
Javassist
• Java Programming Assistant
• Subproject of JBoss
• Actively updated
• Version 3.18.2 released May 2014
• Source code: https://github.com/jboss-javassist/
javassist
• Documentation: http://www.csg.ci.i.u-tokyo.ac.jp/
~chiba/javassist/tutorial/tutorial.html
Tuesday, June 10, 14
Javassist
ArrayList
HashMap
CtClass: represents a compile time class
Tuesday, June 10, 14
Javassist
ClassPool: container of CtClass objects
ArrayList
HashMap
CtClass: represents a compile time class
Tuesday, June 10, 14
Javassist
ClassPool: container of CtClass objects
ArrayList
HashMap
ArrayList
HashMap
CtClass: represents a compile time class
Tuesday, June 10, 14
Javassist
ClassPool: container of CtClass objects
ArrayList
HashMap
BankTrans
ArrayList
HashMap
CtClass: represents a compile time class
Tuesday, June 10, 14
Javassist
CtClass: represents a compile time class
ClassPool: container of CtClass objects
ArrayList
HashMap
BankTrans
ArrayList
HashMap
ByteArrayClassPath: converts a byte[] to a CtClass
Tuesday, June 10, 14
Javassist
ClassPool: container of CtClass objects
ArrayList
HashMap
BankTrans
ArrayList
HashMap
Classpool.getDefault().insertClassPath(new ByteArrayClassPath(“BankTrans”, classBytes);
ByteArrayClassPath: converts a byte[] to a CtClass
CtClass: represents a compile time class
Tuesday, June 10, 14
Javassist
ClassPool: container of CtClass objects
ArrayList
HashMap
BankTrans
ArrayList
HashMap
BankTrans
Classpool.getDefault().insertClassPath(new ByteArrayClassPath(“BankTrans”, classBytes);
ByteArrayClassPath: converts a byte[] to a CtClass
CtClass: represents a compile time class
Tuesday, June 10, 14
Javassist
ClassPool: container of CtClass objects
ArrayList
HashMap
BankTrans
ArrayList
HashMap
BankTrans
Classpool.getDefault().insertClassPath(new ByteArrayClassPath(“BankTrans”, classBytes);
ByteArrayClassPath: converts a byte[] to a CtClass
CtClass: represents a compile time class
CtClass bank = Classpool.getDefault().get(“BankTrans”);
Tuesday, June 10, 14
Javassist
ClassPool: container of CtClass objects
ArrayList
HashMap
BankTrans
ArrayList
HashMap
BankTrans
ByteArrayClassPath: converts a byte[] to a CtClass
CtClass: represents a compile time class
BankTrans
Classpool.getDefault().insertClassPath(new ByteArrayClassPath(“BankTrans”, classBytes);
CtClass bank = Classpool.getDefault().get(“BankTrans”);
Tuesday, June 10, 14
Javassist
BankTrans
CtClass: represents a compile time class
Tuesday, June 10, 14
Javassist
CtConstructor: represents a compile time constructor
init
BankTrans
CtClass: represents a compile time class
Tuesday, June 10, 14
Javassist
CtConstructor: represents a compile time constructor
init
BankTrans
CtClass: represents a compile time class
CtMethod: represents a compile time class
login
process
Tuesday, June 10, 14
Javassist
CtConstructor: represents a compile time constructor
init
CtClass: represents a compile time class
CtMethod: represents a compile time method
CtMethod loginMethod = hasmapCtClass.getDeclaredMethod(“login”);
BankTrans
login
process
Tuesday, June 10, 14
Javassist
CtConstructor: represents a compile time constructor
init
CtClass: represents a compile time class
CtMethod: represents a compile time method
CtMethod loginMethod = hasmapCtClass.getDeclaredMethod(“login”);
login
BankTrans
login
process
Tuesday, June 10, 14
Javassist
login
CtMethod: represents a compile time method
Tuesday, June 10, 14
Javassist
Modifications:
login
CtMethod: represents a compile time method
Tuesday, June 10, 14
Javassist
Modifications:
login
CtMethod: represents a compile time method
putMethod.insertAfter(“System.out.println(”after method”);”);
putMethod.insertBefore(“System.out.println(“before method”);”);
Tuesday, June 10, 14
Javassist
Modifications:
System.out.println(“before method”);
CtMethod: represents a compile time method
putMethod.insertAfter(“System.out.println(”after method”);”);
putMethod.insertBefore(“System.out.println(“before method”);”);
System.out.println(“after method”);
login
Tuesday, June 10, 14
Javassist
Modifications:
CtMethod: represents a compile time method
CtClass exceptionType = classpool.get(“java.io.IOException”);
putMethod.addCatch(“{System.out.println($e); throw $e}”, exceptionType);
login
Tuesday, June 10, 14
Javassist
Modifications:
CtMethod: represents a compile time method
CtClass exceptionType = classpool.get(“java.io.IOException”);
System.out.println(“exception”);
throw exception;
putMethod.addCatch(“{System.out.println($e); throw $e}”, exceptionType);
login
Tuesday, June 10, 14
Javassist
Modifications:
CtMethod: represents a compile time method
putMethod.insertAt(5, true, “System.out.println(“hello”);”);
login
Tuesday, June 10, 14
Javassist
Modifications:
CtMethod: represents a compile time method
putMethod.insertAt(5, true, “System.out.println(“hello”);”);
System.out.println(“hello”);
login
Tuesday, June 10, 14
Javassist
Modifications:
CtMethod: represents a compile time method
insertBefore insertAfter insertAt addCatch
System.out.println(“before method”);
System.out.println(“after method”);
System.out.println(“hello”);
System.out.println(“exception”);
throw exception;
login
Tuesday, June 10, 14
Javassist
Modifications:
CtMethod: represents a compile time method
insertBefore insertAfter insertAt addCatch
Freeze Class:
System.out.println(“before method”);
System.out.println(“after method”);
System.out.println(“hello”);
System.out.println(“exception”);
throw exception;
login
Tuesday, June 10, 14
Javassist
Modifications:
CtMethod: represents a compile time method
insertBefore insertAfter insertAt addCatch
Freeze Class:
System.out.println(“before method”);
System.out.println(“after method”);
System.out.println(“hello”);
System.out.println(“exception”);
throw exception;
writeFile() toClass() toBytecode()
login
Tuesday, June 10, 14
lets code
Tuesday, June 10, 14
lets code
package com.example.qcon.agent;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
public class ImportantLogClassTransformer implements ClassFileTransformer {
	 public byte[] transform(ClassLoader loader, String className,
	 	 	 Class classBeingRedefined, ProtectionDomain protectionDomain,
	 	 	 byte[] classfileBuffer) throws IllegalClassFormatException {
//TODO
	 	 return null;
	 }
}
Tuesday, June 10, 14
lets code
package com.example.qcon.agent;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
public class ImportantLogClassTransformer implements ClassFileTransformer {
	 public byte[] transform(ClassLoader loader, String className,
	 	 	 Class classBeingRedefined, ProtectionDomain protectionDomain,
	 	 	 byte[] classfileBuffer) throws IllegalClassFormatException {
//TODO
	 	 return null;
	 }
}
Tuesday, June 10, 14
lets code
public byte[] transform(ClassLoader loader, String className,
	 	 Class classBeingRedefined, ProtectionDomain protectionDomain,
	 	 byte[] cfbuffer) throws IllegalClassFormatException {
1. convert byte array to a ct class object
2. check each method of ct class for annotation @ImportantLog
3. if @ImportantLog annotation present on method, then
a. get important method parameter indexes
b. add logging statement to beginning of the method
	 return null;
}
Tuesday, June 10, 14
lets code
public byte[] transform(ClassLoader loader, String className,
	 	 Class classBeingRedefined, ProtectionDomain protectionDomain,
	 	 byte[] cfbuffer) throws IllegalClassFormatException {
	 	 pool.insertClassPath(new ByteArrayClassPath(className,
	 	 	 	 classfileBuffer));
	 	 CtClass cclass = pool.get(className.replaceAll("/", "."));
2. check each method of ct class for annotation @ImportantLog
3. if @ImportantLog annotation present on method, then
a. get important method parameter indexes
b. add logging statement to beginning of the method
	 	
	 return null;
}
Tuesday, June 10, 14
lets code
public byte[] transform(ClassLoader loader, String className,
	 	 Class classBeingRedefined, ProtectionDomain protectionDomain,
	 	 byte[] cfbuffer) throws IllegalClassFormatException {
	 	 pool.insertClassPath(new ByteArrayClassPath(className,
	 	 	 	 classfileBuffer));
	 	 CtClass cclass = pool.get(className.replaceAll("/", "."));
if (!cclass.isFrozen()) {
	 for (CtMethod currentMethod : cclass.getDeclaredMethods()) {
Annotation annotation = getAnnotation(currentMethod);
3. if @ImportantLog annotation present on method, then
a. get important method parameter indexes
b. add logging statement to beginning of the method
	 	 }
}
	 return null;
}
Tuesday, June 10, 14
lets code
public byte[] transform(ClassLoader loader, String className,
	 	 Class classBeingRedefined, ProtectionDomain protectionDomain,
	 	 byte[] cfbuffer) throws IllegalClassFormatException {
	 	 pool.insertClassPath(new ByteArrayClassPath(className,
	 	 	 	 classfileBuffer));
	 	 CtClass cclass = pool.get(className.replaceAll("/", "."));
if (!cclass.isFrozen()) {
	 for (CtMethod currentMethod : cclass.getDeclaredMethods()) {
Annotation annotation = getAnnotation(currentMethod);
	 	 	 	 if (annotation != null) {
	 	 	 	 	 List<String> parameterIndexes = getParamIndexes(annotation);
b. add logging statement to beginning of the method
	 	 	 	 }
	 	 }
}
	 return null;
}
Tuesday, June 10, 14
lets code
public byte[] transform(ClassLoader loader, String className,
	 	 Class classBeingRedefined, ProtectionDomain protectionDomain,
	 	 byte[] cfbuffer) throws IllegalClassFormatException {
	 	 pool.insertClassPath(new ByteArrayClassPath(className,
	 	 	 	 classfileBuffer));
	 	 CtClass cclass = pool.get(className.replaceAll("/", "."));
if (!cclass.isFrozen()) {
	 for (CtMethod currentMethod : cclass.getDeclaredMethods()) {
Annotation annotation = getAnnotation(currentMethod);
	 	 	 	 if (annotation != null) {
	 	 	 	 	 List<String> parameterIndexes = getParamIndexes(annotation);
currentMethod.insertBefore(createJavaString(
	 	 	 	 	 currentMethod, className, parameterIndexes));
	 	 	 	 }
	 	 }
return cclass.toBytecode();
}
	 return null;
}
Tuesday, June 10, 14
lets code
public byte[] transform(ClassLoader loader, String className,
	 	 Class classBeingRedefined, ProtectionDomain protectionDomain,
	 	 byte[] cfbuffer) throws IllegalClassFormatException {
	 	 pool.insertClassPath(new ByteArrayClassPath(className,
	 	 	 	 classfileBuffer));
	 	 CtClass cclass = pool.get(className.replaceAll("/", "."));
if (!cclass.isFrozen()) {
	 for (CtMethod currentMethod : cclass.getDeclaredMethods()) {
Annotation annotation = getAnnotation(currentMethod);
	 	 	 	 if (annotation != null) {
	 	 	 	 	 List<String> parameterIndexes = getParamIndexes(annotation);
currentMethod.insertBefore(createJavaString(
	 	 	 	 	 currentMethod, className, parameterIndexes));
	 	 	 	 }
	 	 }
return cclass.toBytecode();
}
	 return null;
}
Tuesday, June 10, 14
lets code
	 	 private Annotation getAnnotation(CtMethod method) {
	 	 MethodInfo mInfo = method.getMethodInfo();
	 	 // the attribute we are looking for is a runtime invisible attribute
	 	 // use Retention(RetentionPolicy.RUNTIME) on the annotation to make it
	 	 // visible at runtime
	 	 AnnotationsAttribute attInfo = (AnnotationsAttribute) mInfo
	 	 	 	 .getAttribute(AnnotationsAttribute.invisibleTag);
	 	 if (attInfo != null) {
	 	 	 // this is the type name meaning use dots instead of slashes
	 	 	 return attInfo.getAnnotation("com.example.qcon.mains.ImportantLog");
	 	 }
	 	 return null;
	 }
Tuesday, June 10, 14
lets code
public byte[] transform(ClassLoader loader, String className,
	 	 Class classBeingRedefined, ProtectionDomain protectionDomain,
	 	 byte[] cfbuffer) throws IllegalClassFormatException {
	 	 pool.insertClassPath(new ByteArrayClassPath(className,
	 	 	 	 classfileBuffer));
	 	 CtClass cclass = pool.get(className.replaceAll("/", "."));
if (!cclass.isFrozen()) {
	 for (CtMethod currentMethod : cclass.getDeclaredMethods()) {
Annotation annotation = getAnnotation(currentMethod);
	 	 	 	 if (annotation != null) {
	 	 	 	 	 List<String> parameterIndexes = getParamIndexes(annotation);
currentMethod.insertBefore(createJavaString(
	 	 	 	 	 currentMethod, className, parameterIndexes));
	 	 	 	 }
	 	 }
return cclass.toBytecode();
}
	 return null;
}
Tuesday, June 10, 14
lets code
	 private List<String> getParamIndexes(Annotation annotation) {
	 	 ArrayMemberValue fields = (ArrayMemberValue) annotation
	 	 	 	 .getMemberValue(“fields”);
	 	 if (fields != null) {
	 	 	 MemberValue[] values = (MemberValue[]) fields.getValue();
	 	 	 List<String> parameterIndexes = new ArrayList<String>();
	 	 	 for (MemberValue val : values) {
	 	 	 	 parameterIndexes.add(((StringMemberValue) val).getValue());
	 	 	 }
	 	 	 return parameterIndexes;
	 	 }
	 	 return Collections.emptyList();
	 }
Tuesday, June 10, 14
lets code
public byte[] transform(ClassLoader loader, String className,
	 	 Class classBeingRedefined, ProtectionDomain protectionDomain,
	 	 byte[] cfbuffer) throws IllegalClassFormatException {
	 	 pool.insertClassPath(new ByteArrayClassPath(className,
	 	 	 	 classfileBuffer));
	 	 CtClass cclass = pool.get(className.replaceAll("/", "."));
if (!cclass.isFrozen()) {
	 for (CtMethod currentMethod : cclass.getDeclaredMethods()) {
Annotation annotation = getAnnotation(currentMethod);
	 	 	 	 if (annotation != null) {
	 	 	 	 	 List<String> parameterIndexes = getParamIndexes(annotation);
currentMethod.insertBefore(createJavaString(
	 	 	 	 	 currentMethod, className, parameterIndexes));
	 	 	 	 }
	 	 }
return cclass.toBytecode();
}
	 return null;
}
Tuesday, June 10, 14
lets code
	 private String createJavaString(CtMethod currentMethod, String className,
	 	 	 List<String> indexParameters) {
	 	 StringBuilder sb = new StringBuilder();
	 	 sb.append("{StringBuilder sb = new StringBuilder");
	 	 sb.append("("A call was made to method '");");
	 	 sb.append("sb.append("");
	 	 sb.append(currentMethod.getName());
	 	 sb.append("");sb.append("' on class '");");
	 	 sb.append("sb.append("");
	 	 sb.append(className);
	 	 sb.append("");sb.append("'.");");
	 	 sb.append("sb.append("n Important params:");");
. . .
Tuesday, June 10, 14
lets code
	 private String createJavaString(CtMethod currentMethod, String className,
	 	 	 List<String> indexParameters) {
	 	 StringBuilder sb = new StringBuilder();
	 	 sb.append("{StringBuilder sb = new StringBuilder");
	 	 sb.append("("A call was made to method '");");
	 	 sb.append("sb.append("");
	 	 sb.append(currentMethod.getName());
	 	 sb.append("");sb.append("' on class '");");
	 	 sb.append("sb.append("");
	 	 sb.append(className);
	 	 sb.append("");sb.append("'.");");
	 	 sb.append("sb.append("n Important params:");");
. . .
Put multiple statements inside brackets {}
Tuesday, June 10, 14
lets code
	 private String createJavaString(CtMethod currentMethod, String className,
	 	 	 List<String> indexParameters) {
. . .
	 	 for (String index : indexParameters) {
	 	 	 try {
	 	 	 	 int localVar = Integer.parseInt(index) + 1;
	 	 	 	 sb.append("sb.append("n Index: ");");
	 	 	 	 sb.append("sb.append("");
	 	 	 	 sb.append(index);
	 	 	 	 sb.append("");sb.append(" value: ");");
	 	 	 	 sb.append("sb.append($" + localVar + ");");
	 	 	 } catch (NumberFormatException e) {
	 	 	 	 e.printStackTrace();
	 	 	 }
	 	 }
	 	 sb.append("System.out.println(sb.toString());}");
	 	 return sb.toString();
	 }
Tuesday, June 10, 14
lets code
	 private String createJavaString(CtMethod currentMethod, String className,
	 	 	 List<String> indexParameters) {
. . .
	 	 for (String index : indexParameters) {
	 	 	 try {
	 	 	 	 int localVar = Integer.parseInt(index) + 1;
	 	 	 	 sb.append("sb.append("n Index: ");");
	 	 	 	 sb.append("sb.append("");
	 	 	 	 sb.append(index);
	 	 	 	 sb.append("");sb.append(" value: ");");
	 	 	 	 sb.append("sb.append($" + localVar + ");");
	 	 	 } catch (NumberFormatException e) {
	 	 	 	 e.printStackTrace();
	 	 	 }
	 	 }
	 	 sb.append("System.out.println(sb.toString());}");
	 	 return sb.toString();
	 }
$0, $1, $2, ... can be used to access
“this” and the actual method parameters
Tuesday, June 10, 14
lets code
public byte[] transform(ClassLoader loader, String className,
	 	 Class classBeingRedefined, ProtectionDomain protectionDomain,
	 	 byte[] cfbuffer) throws IllegalClassFormatException {
	 	 pool.insertClassPath(new ByteArrayClassPath(className,
	 	 	 	 classfileBuffer));
	 	 CtClass cclass = pool.get(className.replaceAll("/", "."));
if (!cclass.isFrozen()) {
	 for (CtMethod currentMethod : cclass.getDeclaredMethods()) {
Annotation annotation = getAnnotation(currentMethod);
	 	 	 	 if (annotation != null) {
	 	 	 	 	 List<String> parameterIndexes = getParamIndexes(annotation);
currentMethod.insertBefore(createJavaString(
	 	 	 	 	 currentMethod, className, parameterIndexes));
	 	 	 	 }
	 	 }
return cclass.toBytecode();
}
	 return null;
}
Tuesday, June 10, 14
Javassist
• Positives
• Simplicity
• Do not have to write actual bytecode
• Decent documentation
• Negatives
• Generally slower than ASM
• Less functionality
Tuesday, June 10, 14
ASM
• Released in Open Source in 2002
• Actively updated
• Version 5.0.3 released May 2014
• Two ASM libraries
• event based (SAX like)
• visitor design pattern
• object based (DOM like)
• Documentation: http://download.forge.objectweb.org/
asm/asm4-guide.pdf
Tuesday, June 10, 14
ASM
Source: http://download.forge.objectweb.org/asm/asm4-guide.pdf
Tuesday, June 10, 14
ASM
Source: http://download.forge.objectweb.org/asm/asm4-guide.pdf
Tuesday, June 10, 14
ASM
Source: http://download.forge.objectweb.org/asm/asm4-guide.pdf
Tuesday, June 10, 14
ASM
ClassReader: given a byte[], parses a compiled class
ClassReader:
event producer
BankTrans
ClassWriter:
event consumer
ClassVisitor:
event filter
Tuesday, June 10, 14
ASM
ClassReader: given a byte[], parses a compiled class
ClassReader:
event producer
BankTrans
ClassWriter:
event consumer
visitField
visitMethod
ClassVisitor:
event filter
Tuesday, June 10, 14
ASM
ClassVisitor: delegates class events, event filter
visitAttribute visitField visitMethod visitInnerClass visitEnd
ClassReader: given a byte[], parses a compiled class
ClassReader:
event producer
BankTrans
ClassWriter:
event consumer
visitField
visitMethod
ClassVisitor:
event filter
Tuesday, June 10, 14
ASM
ClassVisitor: delegates class events, event filter
visitAttribute visitField visitMethod visitInnerClass visitEnd
ClassWriter: produces output byte[]
ClassReader: given a byte[], parses a compiled class
ClassReader:
event producer
BankTrans
ClassWriter:
event consumer
visitField
visitMethod
BankTrans
ClassVisitor:
event filter
Tuesday, June 10, 14
lets code
package com.example.qcon.agent;
import java.lang.instrument.Instrumentation;
public class Agent {
	 public static void premain(String agentArgs, Instrumentation inst) {
	 	 System.out.println("Starting the agent");
	 	 inst.addTransformer(new ImportantLogClassTransformer());
	 }
}
Tuesday, June 10, 14
lets code
package com.example.qcon.agent;
import java.lang.instrument.Instrumentation;
public class Agent {
	 public static void premain(String agentArgs, Instrumentation inst) {
	 	 System.out.println("Starting the agent");
	 	 inst.addTransformer(new ImportantLogClassTransformer());
	 }
}
Tuesday, June 10, 14
lets code
package com.example.qcon.agent;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
public class ImportantLogClassTransformer implements ClassFileTransformer {
	 public byte[] transform(ClassLoader loader, String className,
	 	 	 Class classBeingRedefined, ProtectionDomain protectionDomain,
	 	 	 byte[] classfileBuffer) throws IllegalClassFormatException {
//TODO
	 	 return null;
	 }
}
Tuesday, June 10, 14
lets code
package com.example.qcon.agent;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
public class ImportantLogClassTransformer implements ClassFileTransformer {
	 public byte[] transform(ClassLoader loader, String className,
	 	 	 Class classBeingRedefined, ProtectionDomain protectionDomain,
	 	 	 byte[] classfileBuffer) throws IllegalClassFormatException {
//TODO
	 	 return null;
	 }
}
Tuesday, June 10, 14
lets code
	 public byte[] transform(ClassLoader loader, String className,
	 	 	 Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
	 	 	 byte[] classfileBuffer) throws IllegalClassFormatException {
	 	 	 ClassReader cr = new ClassReader(classfileBuffer);
	 	 	 ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
	 	 	 cr.accept(cw, 0);
	 	 	 return cw.toByteArray();
	 }
Tuesday, June 10, 14
lets code
	 public byte[] transform(ClassLoader loader, String className,
	 	 	 Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
	 	 	 byte[] classfileBuffer) throws IllegalClassFormatException {
	 	 	 ClassReader cr = new ClassReader(classfileBuffer);
	 	 	 ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
ClassVisitor cv = new LogMethodClassVisitor(cw, className);
	 	 	 cr.accept(cv, 0);
	 	 	 return cw.toByteArray();
	 }
Tuesday, June 10, 14
ASM
ClassVisitor: delegates class events, event filter
visitAttribute visitField visitMethod visitInnerClass visitEnd
ClassWriter: produces output byte[]
ClassReader: given a byte[], parses a compiled class
ClassReader:
event producer
BankTrans
ClassWriter:
event consumer
visitMethod
BankTrans
LogMethod
ClassVisitor:
event filter
Tuesday, June 10, 14
ASM
Source: http://download.forge.objectweb.org/asm/asm4-guide.pdf
Tuesday, June 10, 14
lets code
public class LogMethodClassVisitor extends ClassVisitor {
	 private String className;
	 public LogMethodIfAnnotationVisitor(ClassVisitor cv, String pClassName) {
	 	 super(Opcodes.ASM5, cv);
	 	 className = pClassName;
	 }
	 @Override
	 public MethodVisitor visitMethod(int access, String name, String desc,
	 	 	 String signature, String[] exceptions) {
// put our logic in here
	 }
}
Tuesday, June 10, 14
lets code
public class LogMethodClassVisitor extends ClassVisitor {
	 private String className;
	 public LogMethodIfAnnotationVisitor(ClassVisitor cv, String pClassName) {
	 	 super(Opcodes.ASM5, cv);
	 	 className = pClassName;
	 }
	 @Override
	 public MethodVisitor visitMethod(int access, String name, String desc,
	 	 	 String signature, String[] exceptions) {
// put our logic in here
	 }
}
Tuesday, June 10, 14
ASM
Source: http://download.forge.objectweb.org/asm/asm4-guide.pdf
Tuesday, June 10, 14
ASM
Source: http://download.forge.objectweb.org/asm/asm4-guide.pdf
Tuesday, June 10, 14
ASM
Source: http://download.forge.objectweb.org/asm/asm4-guide.pdf
Tuesday, June 10, 14
ASM
MethodVisitor: method event filter
MethodVisitor MethodVisitor
visitCode
login method
visitor
login method
visitor
visitAnnotation visitEnd visitCode visitTryCatchBlock
visitEnd
visitAttribute
Tuesday, June 10, 14
ASM
Source: http://download.forge.objectweb.org/asm/asm4-guide.pdf
Tuesday, June 10, 14
lets code
public class LogMethodClassVisitor extends ClassVisitor {
	 private String className;
	 public LogMethodIfAnnotationVisitor(ClassVisitor cv, String pClassName) {
	 	 super(Opcodes.ASM5, cv);
	 	 className = pClassName;
	 }
	 @Override
	 public MethodVisitor visitMethod(int access, String name, String desc,
	 	 	 String signature, String[] exceptions) {
		 MethodVisitor mv = super.visitMethod(access, name, desc, signature,
exceptions);
	 	 return new PrintMessageMethodVisitor(mv, name, className);
	 }
}
Tuesday, June 10, 14
lets code
public class PrintMessageMethodVisitor extends MethodVisitor {
	 	 private String methodName;
	 	 private String className;
private boolean isAnnotationPresent;
	 	 private List<String> parameterIndexes;
	 	 public PrintMessageMethodVisitor(MethodVisitor mv, String methodName,
	 	 	 	 String className) {
	 	 }
	 	 @Override
	 	 public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
	
	 	 }
	 	 @Override
	 	 public void visitCode() {
}
}
Tuesday, June 10, 14
lets code
public class PrintMessageMethodVisitor extends MethodVisitor {
	 	 private String methodName;
	 	 private String className;
private boolean isAnnotationPresent;
	 	 private List<String> parameterIndexes;
	 	 public PrintMessageMethodVisitor(MethodVisitor mv, String methodName,
	 	 	 	 String className) {
// initialize instance variables
	 	 }
	 	 @Override
	 	 public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
	 	 1. check method for annotation @ImportantLog
2. if annotation present, then get important method param indexes
	 	 }
	 	 @Override
	 	 public void visitCode() {
	 	 	 3. if annotation present, add logging to beginning of the method
}
}
Tuesday, June 10, 14
lets code
	
	 public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
	 	 if ("Lcom/example/qcon/mains/ImportantLog;".equals(desc)) {
isAnnotationPresent = true;
	 	 	 return new AnnotationVisitor(Opcodes.ASM5,
	 	 	 	 	 super.visitAnnotation(desc, visible)) {
	 	 	 	 public AnnotationVisitor visitArray(String name) {
	 	 	 	 	 if (“fields”.equals(name)) {
	 	 	 	 	 	 return new AnnotationVisitor(Opcodes.ASM5,
	 	 	 	 	 	 	 	 super.visitArray(name)) {
	 	 	 	 	 	 	 public void visit(String name, Object value) {
	 	 	 	 	 	 	 	 parameterIndexes.add((String) value);
	 	 	 	 	 	 	 	 super.visit(name, value);
	 	 	 	 	 	 	 }
	 	 	 	 	 	 };
	 	 	 	 	 } else {
	 	 	 	 	 	 return super.visitArray(name);
	 	 	 	 	 }
	 	 	 	 }
	 	 	 };
	 	 }
	 	 return super.visitAnnotation(desc, visible);
	 }
Tuesday, June 10, 14
lets code
public class PrintMessageMethodVisitor extends MethodVisitor {
	 	 private String methodName;
	 	 private String className;
private boolean isAnnotationPresent;
	 	 private List<String> parameterIndexes;
	 	 public PrintMessageMethodVisitor(MethodVisitor mv, String methodName,
	 	 	 	 String className) {
// initialize instance variables
	 	 }
	 	 @Override
	 	 public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
	 	 1. check method for annotation @ImportantLog
2. if annotation present, then get important method param indexes
	 	 }
	 	 @Override
	 	 public void visitCode() {
	 	 	 3. if annotation present, add logging statement to beginning of the method
}
}
Tuesday, June 10, 14
lets code
public void visitCode() {		
if (isAnnotationPresent) {
	 	 	 // create string builder
	 	 	 	 mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out",
	 	 	 	 	 	 "Ljava/io/PrintStream;");
	 	 	 	 mv.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder");
	 	 	 	 mv.visitInsn(Opcodes.DUP);
	 	 	 	 // add everything to the string builder
	 	 	 	 mv.visitLdcInsn("A call was made to method "");
	 	 	 	 mv.visitMethodInsn(Opcodes.INVOKESPECIAL,
	 	 	 	 	 	 "java/lang/StringBuilder", "<init>",
	 	 	 	 	 	 "(Ljava/lang/String;)V", false);
	 	 	 	 mv.visitLdcInsn(methodName);
	 	 	 	 mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
	 	 	 	 	 	 "java/lang/StringBuilder", "append",
	 	 	 	 	 	 "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
. . .
Tuesday, June 10, 14
What is Java bytecode?
use javap to examine the bytecode
Tuesday, June 10, 14
What is Java bytecode?
public class PrintMessage {
	 private String methodName;
	 private String className;
	 public PrintMessage(String mName, String cName) {
	 	 methodName = mName;
	 	 className = cName;
	 }
	 public void print() {
	 	 StringBuilder sb = new StringBuilder();
	 	 sb.append("A call was made to method "");
	 	 sb.append(methodName);
	 	 sb.append("" on class "");
	 	 sb.append(className);
	 	 sb.append("".");
	 	 System.out.println(sb.toString());
	 }
Tuesday, June 10, 14
What is Java bytecode?
javap -c bin/com/example/qcon/mains/PrintMessage
Tuesday, June 10, 14
What is Java bytecode?
javap -c bin/com/example/qcon/mains/PrintMessage
public void print();
Code:
0: new #38 // class java/lang/StringBuilder
3: dup
4: invokespecial #40 // Method java/lang/
StringBuilder."<init>":()V
7: astore_1
8: aload_1
9: ldc #41 // String A call was made to method "
11: invokevirtual #43 // Method java/lang/
StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
14: pop
15: aload_1
16: aload_0
17: getfield #14 // Field methodName:Ljava/lang/String;
20: invokevirtual #43 // Method java/lang/
StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
. . .
Tuesday, June 10, 14
What is Java bytecode?
each line represents one JVM instruction
public void print();
Code:
0: new #38 // class java/lang/StringBuilder
3: dup
4: invokespecial #40 // Method java/lang/
StringBuilder."<init>":()V
7: astore_1
8: aload_1
9: ldc #41 // String A call was made to method "
11: invokevirtual #43 // Method java/lang/
StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
14: pop
15: aload_1
16: aload_0
17: getfield #14 // Field methodName:Ljava/lang/String;
20: invokevirtual #43 // Method java/lang/
StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
. . .
Tuesday, June 10, 14
What is Java bytecode?
JVM instruction = 1 opcode with 0 or more operands
public void print();
Code:
0: new #38 // class java/lang/StringBuilder
3: dup
4: invokespecial #40 // Method java/lang/
StringBuilder."<init>":()V
7: astore_1
8: aload_1
9: ldc #41 // String A call was made to method "
11: invokevirtual #43 // Method java/lang/
StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
14: pop
15: aload_1
16: aload_0
17: getfield #14 // Field methodName:Ljava/lang/String;
20: invokevirtual #43 // Method java/lang/
StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
. . .
Tuesday, June 10, 14
What is Java bytecode?
Opcode Description
load
load a reference onto the stack from a local variable
iload, lload, fload, dload, aload
store
stores a value from the stack into a local variable
istore, lstore, fstore, dstore, astore
lcd push a constant from a constant pool onto the stack
return
method return instruction
ireturn, lreturn, freturn, dreturn, areturn, return
invokevirtual invoke an instance method on an object
invokespecial
invokes an instance method requiring special handling
such as an initialization method
See the spec for more info: http://docs.oracle.com/javase/specs/jvms/se8/jvms8.pdf
Tuesday, June 10, 14
What is Java bytecode?
Opcode Description
invokestatic invoke a class (static) method on a named class
athrow throws an exception
new create a new class
newarray create a new array
if<cond>
branch if int comparison with 0 succeeds
ifeq, ifne, iflt, ifge, ifgt, ifle
dup duplicate the top operand stack value
See the spec for more info: http://docs.oracle.com/javase/specs/jvms/se8/jvms8.pdf
Tuesday, June 10, 14
What is Java bytecode?
Tuesday, June 10, 14
What is Java bytecode?
Tuesday, June 10, 14
What is Java bytecode?
Tuesday, June 10, 14
lets code
public void visitCode() {		
if (isAnnotationPresent) {
	 	 	 // create string builder
	 	 	 	 mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out",
	 	 	 	 	 	 "Ljava/io/PrintStream;");
	 	 	 	 mv.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder");
	 	 	 	 mv.visitInsn(Opcodes.DUP);
	 	 	 	 // add everything to the string builder
	 	 	 	 mv.visitLdcInsn("A call was made to method "");
	 	 	 	 mv.visitMethodInsn(Opcodes.INVOKESPECIAL,
	 	 	 	 	 	 "java/lang/StringBuilder", "<init>",
	 	 	 	 	 	 "(Ljava/lang/String;)V", false);
	 	 	 	 mv.visitLdcInsn(methodName);
	 	 	 	 mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
	 	 	 	 	 	 "java/lang/StringBuilder", "append",
	 	 	 	 	 	 "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
. . .
Tuesday, June 10, 14
ASM
• Positives
• Speed and Size
• Decent documentation
• Depth of Functionality
• Number of people using framework
• Negatives
• Need to write actual byte code
• longer developer ramp-up
Tuesday, June 10, 14
Why learn about Java bytecode
manipulation frameworks ?
• program analysis
• find bugs in code
• examine code complexity
• generate classes
• proxies
• remove access to certain APIs
• compiler for another language like Scala
• transform classes without Java source code
• profilers
• optimization and obfuscation
• additional logging
Tuesday, June 10, 14
Bytecode Manipulation Frameworks
• ASM: http://asm.ow2.org/
• BCEL: http://commons.apache.org/proper/commons-bcel/
• CGLib: https://github.com/cglib/cglib
• Javassist: http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/
• Serp: http://serp.sourceforge.net/
• Cojen: https://github.com/cojen/Cojen/wiki
• Soot: http://www.sable.mcgill.ca/soot/
Tuesday, June 10, 14
Source: http://www.kulfoto.com/dog-pictures/15799/mans-best-friend
Make bytecode manipulation frameworks your friend.
They might save your job one day.
Tuesday, June 10, 14
Tuesday, June 10, 14
Source: http://alangregerman.typepad.com/.a/6a00d83516c0ad53ef017c3329aba8970b-800wi
Questions?
Tuesday, June 10, 14

Weitere ähnliche Inhalte

Was ist angesagt?

Workshop spring session 2 - La persistance au sein des applications Java
Workshop spring   session 2 - La persistance au sein des applications JavaWorkshop spring   session 2 - La persistance au sein des applications Java
Workshop spring session 2 - La persistance au sein des applications JavaAntoine Rey
 
Testing Spring Boot Applications
Testing Spring Boot ApplicationsTesting Spring Boot Applications
Testing Spring Boot ApplicationsVMware Tanzu
 
Introduction to JPA and Hibernate including examples
Introduction to JPA and Hibernate including examplesIntroduction to JPA and Hibernate including examples
Introduction to JPA and Hibernate including examplesecosio GmbH
 
Java entreprise edition et industrialisation du génie logiciel par m.youssfi
Java entreprise edition et industrialisation du génie logiciel par m.youssfiJava entreprise edition et industrialisation du génie logiciel par m.youssfi
Java entreprise edition et industrialisation du génie logiciel par m.youssfiENSET, Université Hassan II Casablanca
 
Les Streams de Java 8
Les Streams de Java 8Les Streams de Java 8
Les Streams de Java 8Antoine Rey
 
WAF Bypass Techniques - Using HTTP Standard and Web Servers’ Behaviour
WAF Bypass Techniques - Using HTTP Standard and Web Servers’ BehaviourWAF Bypass Techniques - Using HTTP Standard and Web Servers’ Behaviour
WAF Bypass Techniques - Using HTTP Standard and Web Servers’ BehaviourSoroush Dalili
 
Introduction à spring boot
Introduction à spring bootIntroduction à spring boot
Introduction à spring bootAntoine Rey
 
Workshop Spring - Session 4 - Spring Batch
Workshop Spring -  Session 4 - Spring BatchWorkshop Spring -  Session 4 - Spring Batch
Workshop Spring - Session 4 - Spring BatchAntoine Rey
 
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration수홍 이
 
우아한테크세미나-우아한멀티모듈
우아한테크세미나-우아한멀티모듈우아한테크세미나-우아한멀티모듈
우아한테크세미나-우아한멀티모듈용근 권
 
Testing with Spring: An Introduction
Testing with Spring: An IntroductionTesting with Spring: An Introduction
Testing with Spring: An IntroductionSam Brannen
 
Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Roman Elizarov
 
Advanced Sql Injection ENG
Advanced Sql Injection ENGAdvanced Sql Injection ENG
Advanced Sql Injection ENGDmitry Evteev
 
Hunting for security bugs in AEM webapps
Hunting for security bugs in AEM webappsHunting for security bugs in AEM webapps
Hunting for security bugs in AEM webappsMikhail Egorov
 

Was ist angesagt? (20)

Les Servlets et JSP
Les Servlets et JSPLes Servlets et JSP
Les Servlets et JSP
 
Workshop spring session 2 - La persistance au sein des applications Java
Workshop spring   session 2 - La persistance au sein des applications JavaWorkshop spring   session 2 - La persistance au sein des applications Java
Workshop spring session 2 - La persistance au sein des applications Java
 
Building Advanced XSS Vectors
Building Advanced XSS VectorsBuilding Advanced XSS Vectors
Building Advanced XSS Vectors
 
Testing Spring Boot Applications
Testing Spring Boot ApplicationsTesting Spring Boot Applications
Testing Spring Boot Applications
 
Introduction to JPA and Hibernate including examples
Introduction to JPA and Hibernate including examplesIntroduction to JPA and Hibernate including examples
Introduction to JPA and Hibernate including examples
 
Cours design pattern m youssfi partie 6 proxy
Cours design pattern m youssfi partie 6 proxyCours design pattern m youssfi partie 6 proxy
Cours design pattern m youssfi partie 6 proxy
 
Java entreprise edition et industrialisation du génie logiciel par m.youssfi
Java entreprise edition et industrialisation du génie logiciel par m.youssfiJava entreprise edition et industrialisation du génie logiciel par m.youssfi
Java entreprise edition et industrialisation du génie logiciel par m.youssfi
 
Les Streams de Java 8
Les Streams de Java 8Les Streams de Java 8
Les Streams de Java 8
 
WAF Bypass Techniques - Using HTTP Standard and Web Servers’ Behaviour
WAF Bypass Techniques - Using HTTP Standard and Web Servers’ BehaviourWAF Bypass Techniques - Using HTTP Standard and Web Servers’ Behaviour
WAF Bypass Techniques - Using HTTP Standard and Web Servers’ Behaviour
 
Gestion comptes bancaires Spring boot
Gestion comptes bancaires Spring bootGestion comptes bancaires Spring boot
Gestion comptes bancaires Spring boot
 
Introduction à spring boot
Introduction à spring bootIntroduction à spring boot
Introduction à spring boot
 
Workshop Spring - Session 4 - Spring Batch
Workshop Spring -  Session 4 - Spring BatchWorkshop Spring -  Session 4 - Spring Batch
Workshop Spring - Session 4 - Spring Batch
 
Spring jdbc
Spring jdbcSpring jdbc
Spring jdbc
 
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
 
우아한테크세미나-우아한멀티모듈
우아한테크세미나-우아한멀티모듈우아한테크세미나-우아한멀티모듈
우아한테크세미나-우아한멀티모듈
 
Testing with Spring: An Introduction
Testing with Spring: An IntroductionTesting with Spring: An Introduction
Testing with Spring: An Introduction
 
Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017
 
Advanced Sql Injection ENG
Advanced Sql Injection ENGAdvanced Sql Injection ENG
Advanced Sql Injection ENG
 
Hunting for security bugs in AEM webapps
Hunting for security bugs in AEM webappsHunting for security bugs in AEM webapps
Hunting for security bugs in AEM webapps
 
Java 8 streams
Java 8 streamsJava 8 streams
Java 8 streams
 

Andere mochten auch

Mastering Java Bytecode - JAX.de 2012
Mastering Java Bytecode - JAX.de 2012Mastering Java Bytecode - JAX.de 2012
Mastering Java Bytecode - JAX.de 2012Anton Arhipov
 
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
 
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
 
Escalating complexity: DevOps learnings from Air France 447
Escalating complexity: DevOps learnings from Air France 447Escalating complexity: DevOps learnings from Air France 447
Escalating complexity: DevOps learnings from Air France 447Lindsay Holmwood
 
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
 
Java bytecode and classes
Java bytecode and classesJava bytecode and classes
Java bytecode and classesyoavwix
 
Java byte code & virtual machine
Java byte code & virtual machineJava byte code & virtual machine
Java byte code & virtual machineLaxman Puri
 
Debugging Native heap OOM - JavaOne 2013
Debugging Native heap OOM - JavaOne 2013Debugging Native heap OOM - JavaOne 2013
Debugging Native heap OOM - JavaOne 2013MattKilner
 
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
 

Andere mochten auch (12)

Mastering Java Bytecode - JAX.de 2012
Mastering Java Bytecode - JAX.de 2012Mastering Java Bytecode - JAX.de 2012
Mastering Java Bytecode - JAX.de 2012
 
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...
 
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...
 
Escalating complexity: DevOps learnings from Air France 447
Escalating complexity: DevOps learnings from Air France 447Escalating complexity: DevOps learnings from Air France 447
Escalating complexity: DevOps learnings from Air France 447
 
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
 
Java bytecode and classes
Java bytecode and classesJava bytecode and classes
Java bytecode and classes
 
Java byte code & virtual machine
Java byte code & virtual machineJava byte code & virtual machine
Java byte code & virtual machine
 
Debugging Native heap OOM - JavaOne 2013
Debugging Native heap OOM - JavaOne 2013Debugging Native heap OOM - JavaOne 2013
Debugging Native heap OOM - JavaOne 2013
 
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 byte code in practice
Java byte code in practiceJava byte code in practice
Java byte code in practice
 

Ähnlich wie Bytecode manipulation with Javassist and ASM

Living in the Matrix with Bytecode Manipulation
Living in the Matrix with Bytecode ManipulationLiving in the Matrix with Bytecode Manipulation
Living in the Matrix with Bytecode ManipulationC4Media
 
JavaZone 2017 - The Hitchhiker’s guide to Java class reloading
JavaZone 2017 - The Hitchhiker’s guide to Java class reloadingJavaZone 2017 - The Hitchhiker’s guide to Java class reloading
JavaZone 2017 - The Hitchhiker’s guide to Java class reloadingAnton Arhipov
 
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
JavaOne 2017 - The hitchhiker’s guide to Java class reloadingJavaOne 2017 - The hitchhiker’s guide to Java class reloading
JavaOne 2017 - The hitchhiker’s guide to Java class reloadingAnton Arhipov
 
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
JavaOne 2017 - The hitchhiker’s guide to Java class reloadingJavaOne 2017 - The hitchhiker’s guide to Java class reloading
JavaOne 2017 - The hitchhiker’s guide to Java class reloadingAnton Arhipov
 
Job Managment Portlet
Job Managment PortletJob Managment Portlet
Job Managment Portletriround
 
Functional Reactive Programming in the Netflix API
Functional Reactive Programming in the Netflix APIFunctional Reactive Programming in the Netflix API
Functional Reactive Programming in the Netflix APIC4Media
 
That’s a nice UI, but have you internationalized your Javascript?
That’s a nice UI, but have you internationalized your Javascript?That’s a nice UI, but have you internationalized your Javascript?
That’s a nice UI, but have you internationalized your Javascript?Lovemore
 
Java Advance 4deleteQuery.PNGJava Advance 4deleteQuerySucc.docx
Java Advance 4deleteQuery.PNGJava Advance 4deleteQuerySucc.docxJava Advance 4deleteQuery.PNGJava Advance 4deleteQuerySucc.docx
Java Advance 4deleteQuery.PNGJava Advance 4deleteQuerySucc.docxpriestmanmable
 
20150516 modern web_conf_tw
20150516 modern web_conf_tw20150516 modern web_conf_tw
20150516 modern web_conf_twTse-Ching Ho
 
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHPIPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHPGuilherme Blanco
 
Web UI performance tuning
Web UI performance tuningWeb UI performance tuning
Web UI performance tuningAndy Pemberton
 
softshake 2014 - Java EE
softshake 2014 - Java EEsoftshake 2014 - Java EE
softshake 2014 - Java EEAlexis Hassler
 
Migrating from Struts 1 to Struts 2
Migrating from Struts 1 to Struts 2Migrating from Struts 1 to Struts 2
Migrating from Struts 1 to Struts 2Matt Raible
 
Rapid java backend and api development for mobile devices
Rapid java backend and api development for mobile devicesRapid java backend and api development for mobile devices
Rapid java backend and api development for mobile devicesciklum_ods
 
比XML更好用的Java Annotation
比XML更好用的Java Annotation比XML更好用的Java Annotation
比XML更好用的Java Annotationjavatwo2011
 
What is this DI and AOP stuff anyway...
What is this DI and AOP stuff anyway...What is this DI and AOP stuff anyway...
What is this DI and AOP stuff anyway...Richard McIntyre
 
Rapid Network Application Development with Apache MINA
Rapid Network Application Development with Apache MINARapid Network Application Development with Apache MINA
Rapid Network Application Development with Apache MINAtrustinlee
 

Ähnlich wie Bytecode manipulation with Javassist and ASM (20)

Living in the Matrix with Bytecode Manipulation
Living in the Matrix with Bytecode ManipulationLiving in the Matrix with Bytecode Manipulation
Living in the Matrix with Bytecode Manipulation
 
JavaZone 2017 - The Hitchhiker’s guide to Java class reloading
JavaZone 2017 - The Hitchhiker’s guide to Java class reloadingJavaZone 2017 - The Hitchhiker’s guide to Java class reloading
JavaZone 2017 - The Hitchhiker’s guide to Java class reloading
 
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
JavaOne 2017 - The hitchhiker’s guide to Java class reloadingJavaOne 2017 - The hitchhiker’s guide to Java class reloading
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
 
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
JavaOne 2017 - The hitchhiker’s guide to Java class reloadingJavaOne 2017 - The hitchhiker’s guide to Java class reloading
JavaOne 2017 - The hitchhiker’s guide to Java class reloading
 
Job Managment Portlet
Job Managment PortletJob Managment Portlet
Job Managment Portlet
 
Functional Reactive Programming in the Netflix API
Functional Reactive Programming in the Netflix APIFunctional Reactive Programming in the Netflix API
Functional Reactive Programming in the Netflix API
 
That’s a nice UI, but have you internationalized your Javascript?
That’s a nice UI, but have you internationalized your Javascript?That’s a nice UI, but have you internationalized your Javascript?
That’s a nice UI, but have you internationalized your Javascript?
 
Adopt JSR 354
Adopt JSR 354Adopt JSR 354
Adopt JSR 354
 
Java Advance 4deleteQuery.PNGJava Advance 4deleteQuerySucc.docx
Java Advance 4deleteQuery.PNGJava Advance 4deleteQuerySucc.docxJava Advance 4deleteQuery.PNGJava Advance 4deleteQuerySucc.docx
Java Advance 4deleteQuery.PNGJava Advance 4deleteQuerySucc.docx
 
20150516 modern web_conf_tw
20150516 modern web_conf_tw20150516 modern web_conf_tw
20150516 modern web_conf_tw
 
JSR 354 LJC-Hackday
JSR 354 LJC-HackdayJSR 354 LJC-Hackday
JSR 354 LJC-Hackday
 
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHPIPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
 
Web UI performance tuning
Web UI performance tuningWeb UI performance tuning
Web UI performance tuning
 
Exploring Kotlin
Exploring KotlinExploring Kotlin
Exploring Kotlin
 
softshake 2014 - Java EE
softshake 2014 - Java EEsoftshake 2014 - Java EE
softshake 2014 - Java EE
 
Migrating from Struts 1 to Struts 2
Migrating from Struts 1 to Struts 2Migrating from Struts 1 to Struts 2
Migrating from Struts 1 to Struts 2
 
Rapid java backend and api development for mobile devices
Rapid java backend and api development for mobile devicesRapid java backend and api development for mobile devices
Rapid java backend and api development for mobile devices
 
比XML更好用的Java Annotation
比XML更好用的Java Annotation比XML更好用的Java Annotation
比XML更好用的Java Annotation
 
What is this DI and AOP stuff anyway...
What is this DI and AOP stuff anyway...What is this DI and AOP stuff anyway...
What is this DI and AOP stuff anyway...
 
Rapid Network Application Development with Apache MINA
Rapid Network Application Development with Apache MINARapid Network Application Development with Apache MINA
Rapid Network Application Development with Apache MINA
 

Kürzlich hochgeladen

%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durban%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durbanmasabamasaba
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrainmasabamasaba
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfVishalKumarJha10
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionOnePlan Solutions
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension AidPhilip Schwarz
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...masabamasaba
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...SelfMade bd
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyviewmasabamasaba
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfkalichargn70th171
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburgmasabamasaba
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024Mind IT Systems
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech studentsHimanshiGarg82
 

Kürzlich hochgeladen (20)

%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durban%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durban
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
%in Lydenburg+277-882-255-28 abortion pills for sale in Lydenburg
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 

Bytecode manipulation with Javassist and ASM

  • 1. QCon NY 2014 Living in the Matrix with Bytecode Manipulation Tuesday, June 10, 14
  • 2. Ashley Puls Senior Software Engineer New Relic, Inc. Tuesday, June 10, 14
  • 3. Outline • What is bytecode? • Why manipulate bytecode? • What frameworks can be used to manipulate bytecode? • Examine two frameworks in depth Tuesday, June 10, 14
  • 4. What is Java bytecode? .java file .class file Java compiler (javac) Class Loader Bytecode Verifier Java Runtime System Native OS Java Virtual Machine Source: http://www.techlila.com/write-programs-linux/ Tuesday, June 10, 14
  • 5. What is Java bytecode? .java file .class file Java compiler (javac) Class Loader Bytecode Verifier Java Runtime System Native OS Java Virtual Machine Source: http://www.techlila.com/write-programs-linux/ Tuesday, June 10, 14
  • 6. What is Java bytecode? .java file .class file Java compiler (javac) Class Loader Bytecode Verifier Java Runtime System Native OS Java Virtual Machine Source: http://www.techlila.com/write-programs-linux/ Instruction set of the Java Virtual Machine Tuesday, June 10, 14
  • 7. Why learn about Java bytecode manipulation frameworks ? Tuesday, June 10, 14
  • 8. Why learn about Java bytecode manipulation frameworks ? • A bytecode manipulation framework is likely already on your stack • Spring • Hibernate • Groovy • Clojure • Eclipse • JRuby Tuesday, June 10, 14
  • 9. • A bytecode manipulation framework is likely already on your stack • Spring • Hibernate • Groovy • Clojure • Eclipse • JRuby • Its really fun!!! Why learn about Java bytecode manipulation frameworks ? Tuesday, June 10, 14
  • 10. Why learn about Java bytecode manipulation frameworks ? • program analysis • find bugs in code • examine code complexity • generate classes • proxies • remove access to certain APIs • compiler for another language like Scala • transform classes without Java source code • profilers • optimization and obfuscation • additional logging Tuesday, June 10, 14
  • 11. Why learn about Java bytecode manipulation frameworks ? • program analysis • find bugs in code • examine code complexity • generate classes • proxies • remove access to certain APIs • compiler for another language like Scala • transform classes without Java source code • profilers • optimization and obfuscation • additional logging Tuesday, June 10, 14
  • 15. Logging Audit Log: a message should be logged every time an important method is called Source: http://www.vforteachers.com/About_NetSupport.htm Tuesday, June 10, 14
  • 16. Logging Source: http://www.vforteachers.com/About_NetSupport.htm log important input parameters to the method Audit Log: a message should be logged every time an important method is called Tuesday, June 10, 14
  • 17. Logging public class BankTransactions { public static void main(String[] args) { BankTransactions bank = new BankTransactions(); // login and add i dollars to account for (int i = 0; i < 100; i++) { String accountId = "account" + i; bank.login("password", accountId, "Ashley"); bank.unimportantProcessing(accountId); bank.finalizeTransaction(accountId, Double.valueOf(i)); } System.out.println(“Transactions completed”); } } Tuesday, June 10, 14
  • 18. Logging public class BankTransactions { public static void main(String[] args) { BankTransactions bank = new BankTransactions(); // login and add i dollars to each account for (int i = 0; i < 100; i++) { String accountId = "account" + i; bank.login("password", accountId, "Ashley"); bank.unimportantProcessing(accountId); bank.finalizeTransaction(accountId, Double.valueOf(i)); } System.out.println(“Transactions completed”); } } Tuesday, June 10, 14
  • 19. Logging /** * A method annotation which should be used to indicate important methods whose * invocations should be logged. * */ public @interface ImportantLog { /** * The method parameter indexes whose values should be logged. For example, * if we have the method hello(int paramA, int paramB, int paramC), and we * wanted to log the values of paramA and paramC, then fields would be ["0", * "2"]. If we only want to log the value of paramB, then fields would be * ["1"]. */ String[] fields(); } Tuesday, June 10, 14
  • 20. Logging public void login(String password, String accountId, String userName) { // login logic } public void finalizeTransaction(String accountId, Double moneyToAdd) { // transaction logic } Tuesday, June 10, 14
  • 21. Logging @ImportantLog(fields = { "1", "2" }) public void login(String password, String accountId, String userName) { // login logic } @ImportantLog(fields = { "0", "1" }) public void finalizeTransaction(String accountId, Double moneyToAdd) { // transaction logic } Tuesday, June 10, 14
  • 22. Logging @ImportantLog(fields = { "1", "2" }) public void login(String password, String accountId, String userName) { // login logic } @ImportantLog(fields = { "0", "1" }) public void finalizeTransaction(String accountId, Double moneyToAdd) { // transaction logic } A call was made to method "login" on class "com/example/qcon/mains/BankTransactions". Important params: Index 1 value: ${accountId} Index 2 value: ${userName} Tuesday, June 10, 14
  • 23. Logging @ImportantLog(fields = { "1", "2" }) public void login(String password, String accountId, String userName) { // login logic } @ImportantLog(fields = { "0", "1" }) public void finalizeTransaction(String accountId, Double moneyToAdd) { // transaction logic } A call was made to method "finalizeTransaction" on class "com/example/qcon/ mains/BankTransactions". Important params: Index 0 value: ${accountId} Index 1 value: ${moneyToAdd} A call was made to method "login" on class "com/example/qcon/mains/BankTransactions". Important params: Index 1 value: ${accountId} Index 2 value: ${userName} Tuesday, June 10, 14
  • 24. Java Agent • Ability to modify the bytecode without modifying the application source code • Added in Java 1.5 • Docs: http://docs.oracle.com/javase/8/docs/api/ java/lang/instrument/package-summary.html Tuesday, June 10, 14
  • 25. Typical Java Process JVM public static void main(String[] args) BankTransactions.class Classloader java com/example/qcon/mains/BankTransactions Transactions completed Tuesday, June 10, 14
  • 26. Java Agent JVMAgent java -javaagent:/path/to/agent.jar com/example/qcon/mains/ BankTransactions Tuesday, June 10, 14
  • 27. Java Agent JVM java -javaagent:/path/to/agent.jar com/example/qcon/mains/ BankTransactions Tuesday, June 10, 14
  • 28. Java Agent JVMAgent java -javaagent:/path/to/agent.jar com/example/qcon/mains/ BankTransactions Tuesday, June 10, 14
  • 29. Java Agent JVM void premain(String agentArgs, Instrumentation inst) Agent.class MyTransformer.class byte[] transform( . . . , byte[] bankTransBytes) Agent 1. call Agent premain in manifest 2. JVM registers my transformer java -javaagent:/path/to/agent.jar com/example/qcon/mains/ BankTransactions Tuesday, June 10, 14
  • 30. Java Agent JVM void premain(String agentArgs, Instrumentation inst) Agent.class MyTransformer.class byte[] transform( . . . , byte[] bankTransBytes) Agent 1. call Agent premain in manifest 2. JVM registers my transformer 3. Give BankTransactions bytes to MyTransformer 4. MyTransformer provides bytes to load java -javaagent:/path/to/agent.jar com/example/qcon/mains/ BankTransactions Tuesday, June 10, 14
  • 31. Java Agent JVM void main(String[] args) BankTransactions.class void premain(String agentArgs, Instrumentation inst) Agent.class MyTransformer.class byte[] transform( . . . , byte[] bankTransBytes) Agent 1. call Agent premain in manifest 2. JVM registers my transformer 3. Give BankTransactions bytes to MyTransformer 4. MyTransformer provides bytes to load 5. BankTransactions loaded and main runs java -javaagent:/path/to/agent.jar com/example/qcon/mains/ BankTransactions Transactions completed Tuesday, June 10, 14
  • 33. lets code package com.example.qcon.agent; public class Agent { public static void premain(String agentArgs, Instrumentation inst) { System.out.println("Starting the agent"); inst.addTransformer(new ImportantLogClassTransformer()); } } Manifest: Premain-Class: com.example.qcon.agent.Agent Tuesday, June 10, 14
  • 34. lets code package com.example.qcon.agent; public class Agent { public static void premain(String agentArgs, Instrumentation inst) { System.out.println("Starting the agent"); inst.addTransformer(new ImportantLogClassTransformer()); } } Manifest: Premain-Class: com.example.qcon.agent.Agent Tuesday, June 10, 14
  • 35. lets code package com.example.qcon.agent; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; public class ImportantLogClassTransformer implements ClassFileTransformer { public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { //TODO return null; } } Tuesday, June 10, 14
  • 36. lets code package com.example.qcon.agent; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; public class ImportantLogClassTransformer implements ClassFileTransformer { public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { //TODO return null; } } Tuesday, June 10, 14
  • 37. lets code package com.example.qcon.agent; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; public class ImportantLogClassTransformer implements ClassFileTransformer { public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { System.out.println(" Loading class: " + className); return null; } } Tuesday, June 10, 14
  • 38. lets code Starting the agent Loading class: java/lang/invoke/MethodHandleImpl Loading class: java/lang/invoke/MemberName$Factory Loading class: java/lang/invoke/LambdaForm$NamedFunction Loading class: java/lang/invoke/MethodType$ConcurrentWeakInternSet Loading class: java/lang/invoke/MethodHandleStatics Loading class: java/lang/invoke/MethodHandleStatics$1 Loading class: java/lang/invoke/MethodTypeForm Loading class: java/lang/invoke/Invokers Loading class: java/lang/invoke/MethodType$ConcurrentWeakInternSet$WeakEntry Loading class: java/lang/Void Loading class: java/lang/IllegalAccessException Loading class: sun/misc/PostVMInitHook Loading class: sun/launcher/LauncherHelper Loading class: java/util/concurrent/ConcurrentHashMap$ForwardingNode Loading class: sun/misc/URLClassPath$FileLoader$1 Loading class: com/example/qcon/mains/BankTransactions Loading class: sun/launcher/LauncherHelper$FXHelper Tuesday, June 10, 14
  • 39. lets code package com.example.qcon.agent; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; public class ImportantLogClassTransformer implements ClassFileTransformer { public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { System.out.println(" Loading class: " + className); return null; } } Tuesday, June 10, 14
  • 40. lets code package com.example.qcon.agent; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; public class ImportantLogClassTransformer implements ClassFileTransformer { public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { // manipulate the bytes here and then return them return null; } } Tuesday, June 10, 14
  • 41. Bytecode Manipulation Frameworks • ASM: http://asm.ow2.org/ • BCEL: http://commons.apache.org/proper/commons-bcel/ • CGLib: https://github.com/cglib/cglib • Javassist: http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/ • Serp: http://serp.sourceforge.net/ • Cojen: https://github.com/cojen/Cojen/wiki • Soot: http://www.sable.mcgill.ca/soot/ Tuesday, June 10, 14
  • 42. Bytecode Manipulation Frameworks • ASM: http://asm.ow2.org/ • BCEL: http://commons.apache.org/proper/commons-bcel/ • CGLib: https://github.com/cglib/cglib • Javassist: http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/ • Serp: http://serp.sourceforge.net/ • Cojen: https://github.com/cojen/Cojen/wiki • Soot: http://www.sable.mcgill.ca/soot/ Tuesday, June 10, 14
  • 43. Javassist • Java Programming Assistant • Subproject of JBoss • Actively updated • Version 3.18.2 released May 2014 • Source code: https://github.com/jboss-javassist/ javassist • Documentation: http://www.csg.ci.i.u-tokyo.ac.jp/ ~chiba/javassist/tutorial/tutorial.html Tuesday, June 10, 14
  • 44. Javassist ArrayList HashMap CtClass: represents a compile time class Tuesday, June 10, 14
  • 45. Javassist ClassPool: container of CtClass objects ArrayList HashMap CtClass: represents a compile time class Tuesday, June 10, 14
  • 46. Javassist ClassPool: container of CtClass objects ArrayList HashMap ArrayList HashMap CtClass: represents a compile time class Tuesday, June 10, 14
  • 47. Javassist ClassPool: container of CtClass objects ArrayList HashMap BankTrans ArrayList HashMap CtClass: represents a compile time class Tuesday, June 10, 14
  • 48. Javassist CtClass: represents a compile time class ClassPool: container of CtClass objects ArrayList HashMap BankTrans ArrayList HashMap ByteArrayClassPath: converts a byte[] to a CtClass Tuesday, June 10, 14
  • 49. Javassist ClassPool: container of CtClass objects ArrayList HashMap BankTrans ArrayList HashMap Classpool.getDefault().insertClassPath(new ByteArrayClassPath(“BankTrans”, classBytes); ByteArrayClassPath: converts a byte[] to a CtClass CtClass: represents a compile time class Tuesday, June 10, 14
  • 50. Javassist ClassPool: container of CtClass objects ArrayList HashMap BankTrans ArrayList HashMap BankTrans Classpool.getDefault().insertClassPath(new ByteArrayClassPath(“BankTrans”, classBytes); ByteArrayClassPath: converts a byte[] to a CtClass CtClass: represents a compile time class Tuesday, June 10, 14
  • 51. Javassist ClassPool: container of CtClass objects ArrayList HashMap BankTrans ArrayList HashMap BankTrans Classpool.getDefault().insertClassPath(new ByteArrayClassPath(“BankTrans”, classBytes); ByteArrayClassPath: converts a byte[] to a CtClass CtClass: represents a compile time class CtClass bank = Classpool.getDefault().get(“BankTrans”); Tuesday, June 10, 14
  • 52. Javassist ClassPool: container of CtClass objects ArrayList HashMap BankTrans ArrayList HashMap BankTrans ByteArrayClassPath: converts a byte[] to a CtClass CtClass: represents a compile time class BankTrans Classpool.getDefault().insertClassPath(new ByteArrayClassPath(“BankTrans”, classBytes); CtClass bank = Classpool.getDefault().get(“BankTrans”); Tuesday, June 10, 14
  • 53. Javassist BankTrans CtClass: represents a compile time class Tuesday, June 10, 14
  • 54. Javassist CtConstructor: represents a compile time constructor init BankTrans CtClass: represents a compile time class Tuesday, June 10, 14
  • 55. Javassist CtConstructor: represents a compile time constructor init BankTrans CtClass: represents a compile time class CtMethod: represents a compile time class login process Tuesday, June 10, 14
  • 56. Javassist CtConstructor: represents a compile time constructor init CtClass: represents a compile time class CtMethod: represents a compile time method CtMethod loginMethod = hasmapCtClass.getDeclaredMethod(“login”); BankTrans login process Tuesday, June 10, 14
  • 57. Javassist CtConstructor: represents a compile time constructor init CtClass: represents a compile time class CtMethod: represents a compile time method CtMethod loginMethod = hasmapCtClass.getDeclaredMethod(“login”); login BankTrans login process Tuesday, June 10, 14
  • 58. Javassist login CtMethod: represents a compile time method Tuesday, June 10, 14
  • 59. Javassist Modifications: login CtMethod: represents a compile time method Tuesday, June 10, 14
  • 60. Javassist Modifications: login CtMethod: represents a compile time method putMethod.insertAfter(“System.out.println(”after method”);”); putMethod.insertBefore(“System.out.println(“before method”);”); Tuesday, June 10, 14
  • 61. Javassist Modifications: System.out.println(“before method”); CtMethod: represents a compile time method putMethod.insertAfter(“System.out.println(”after method”);”); putMethod.insertBefore(“System.out.println(“before method”);”); System.out.println(“after method”); login Tuesday, June 10, 14
  • 62. Javassist Modifications: CtMethod: represents a compile time method CtClass exceptionType = classpool.get(“java.io.IOException”); putMethod.addCatch(“{System.out.println($e); throw $e}”, exceptionType); login Tuesday, June 10, 14
  • 63. Javassist Modifications: CtMethod: represents a compile time method CtClass exceptionType = classpool.get(“java.io.IOException”); System.out.println(“exception”); throw exception; putMethod.addCatch(“{System.out.println($e); throw $e}”, exceptionType); login Tuesday, June 10, 14
  • 64. Javassist Modifications: CtMethod: represents a compile time method putMethod.insertAt(5, true, “System.out.println(“hello”);”); login Tuesday, June 10, 14
  • 65. Javassist Modifications: CtMethod: represents a compile time method putMethod.insertAt(5, true, “System.out.println(“hello”);”); System.out.println(“hello”); login Tuesday, June 10, 14
  • 66. Javassist Modifications: CtMethod: represents a compile time method insertBefore insertAfter insertAt addCatch System.out.println(“before method”); System.out.println(“after method”); System.out.println(“hello”); System.out.println(“exception”); throw exception; login Tuesday, June 10, 14
  • 67. Javassist Modifications: CtMethod: represents a compile time method insertBefore insertAfter insertAt addCatch Freeze Class: System.out.println(“before method”); System.out.println(“after method”); System.out.println(“hello”); System.out.println(“exception”); throw exception; login Tuesday, June 10, 14
  • 68. Javassist Modifications: CtMethod: represents a compile time method insertBefore insertAfter insertAt addCatch Freeze Class: System.out.println(“before method”); System.out.println(“after method”); System.out.println(“hello”); System.out.println(“exception”); throw exception; writeFile() toClass() toBytecode() login Tuesday, June 10, 14
  • 70. lets code package com.example.qcon.agent; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; public class ImportantLogClassTransformer implements ClassFileTransformer { public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { //TODO return null; } } Tuesday, June 10, 14
  • 71. lets code package com.example.qcon.agent; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; public class ImportantLogClassTransformer implements ClassFileTransformer { public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { //TODO return null; } } Tuesday, June 10, 14
  • 72. lets code public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] cfbuffer) throws IllegalClassFormatException { 1. convert byte array to a ct class object 2. check each method of ct class for annotation @ImportantLog 3. if @ImportantLog annotation present on method, then a. get important method parameter indexes b. add logging statement to beginning of the method return null; } Tuesday, June 10, 14
  • 73. lets code public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] cfbuffer) throws IllegalClassFormatException { pool.insertClassPath(new ByteArrayClassPath(className, classfileBuffer)); CtClass cclass = pool.get(className.replaceAll("/", ".")); 2. check each method of ct class for annotation @ImportantLog 3. if @ImportantLog annotation present on method, then a. get important method parameter indexes b. add logging statement to beginning of the method return null; } Tuesday, June 10, 14
  • 74. lets code public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] cfbuffer) throws IllegalClassFormatException { pool.insertClassPath(new ByteArrayClassPath(className, classfileBuffer)); CtClass cclass = pool.get(className.replaceAll("/", ".")); if (!cclass.isFrozen()) { for (CtMethod currentMethod : cclass.getDeclaredMethods()) { Annotation annotation = getAnnotation(currentMethod); 3. if @ImportantLog annotation present on method, then a. get important method parameter indexes b. add logging statement to beginning of the method } } return null; } Tuesday, June 10, 14
  • 75. lets code public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] cfbuffer) throws IllegalClassFormatException { pool.insertClassPath(new ByteArrayClassPath(className, classfileBuffer)); CtClass cclass = pool.get(className.replaceAll("/", ".")); if (!cclass.isFrozen()) { for (CtMethod currentMethod : cclass.getDeclaredMethods()) { Annotation annotation = getAnnotation(currentMethod); if (annotation != null) { List<String> parameterIndexes = getParamIndexes(annotation); b. add logging statement to beginning of the method } } } return null; } Tuesday, June 10, 14
  • 76. lets code public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] cfbuffer) throws IllegalClassFormatException { pool.insertClassPath(new ByteArrayClassPath(className, classfileBuffer)); CtClass cclass = pool.get(className.replaceAll("/", ".")); if (!cclass.isFrozen()) { for (CtMethod currentMethod : cclass.getDeclaredMethods()) { Annotation annotation = getAnnotation(currentMethod); if (annotation != null) { List<String> parameterIndexes = getParamIndexes(annotation); currentMethod.insertBefore(createJavaString( currentMethod, className, parameterIndexes)); } } return cclass.toBytecode(); } return null; } Tuesday, June 10, 14
  • 77. lets code public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] cfbuffer) throws IllegalClassFormatException { pool.insertClassPath(new ByteArrayClassPath(className, classfileBuffer)); CtClass cclass = pool.get(className.replaceAll("/", ".")); if (!cclass.isFrozen()) { for (CtMethod currentMethod : cclass.getDeclaredMethods()) { Annotation annotation = getAnnotation(currentMethod); if (annotation != null) { List<String> parameterIndexes = getParamIndexes(annotation); currentMethod.insertBefore(createJavaString( currentMethod, className, parameterIndexes)); } } return cclass.toBytecode(); } return null; } Tuesday, June 10, 14
  • 78. lets code private Annotation getAnnotation(CtMethod method) { MethodInfo mInfo = method.getMethodInfo(); // the attribute we are looking for is a runtime invisible attribute // use Retention(RetentionPolicy.RUNTIME) on the annotation to make it // visible at runtime AnnotationsAttribute attInfo = (AnnotationsAttribute) mInfo .getAttribute(AnnotationsAttribute.invisibleTag); if (attInfo != null) { // this is the type name meaning use dots instead of slashes return attInfo.getAnnotation("com.example.qcon.mains.ImportantLog"); } return null; } Tuesday, June 10, 14
  • 79. lets code public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] cfbuffer) throws IllegalClassFormatException { pool.insertClassPath(new ByteArrayClassPath(className, classfileBuffer)); CtClass cclass = pool.get(className.replaceAll("/", ".")); if (!cclass.isFrozen()) { for (CtMethod currentMethod : cclass.getDeclaredMethods()) { Annotation annotation = getAnnotation(currentMethod); if (annotation != null) { List<String> parameterIndexes = getParamIndexes(annotation); currentMethod.insertBefore(createJavaString( currentMethod, className, parameterIndexes)); } } return cclass.toBytecode(); } return null; } Tuesday, June 10, 14
  • 80. lets code private List<String> getParamIndexes(Annotation annotation) { ArrayMemberValue fields = (ArrayMemberValue) annotation .getMemberValue(“fields”); if (fields != null) { MemberValue[] values = (MemberValue[]) fields.getValue(); List<String> parameterIndexes = new ArrayList<String>(); for (MemberValue val : values) { parameterIndexes.add(((StringMemberValue) val).getValue()); } return parameterIndexes; } return Collections.emptyList(); } Tuesday, June 10, 14
  • 81. lets code public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] cfbuffer) throws IllegalClassFormatException { pool.insertClassPath(new ByteArrayClassPath(className, classfileBuffer)); CtClass cclass = pool.get(className.replaceAll("/", ".")); if (!cclass.isFrozen()) { for (CtMethod currentMethod : cclass.getDeclaredMethods()) { Annotation annotation = getAnnotation(currentMethod); if (annotation != null) { List<String> parameterIndexes = getParamIndexes(annotation); currentMethod.insertBefore(createJavaString( currentMethod, className, parameterIndexes)); } } return cclass.toBytecode(); } return null; } Tuesday, June 10, 14
  • 82. lets code private String createJavaString(CtMethod currentMethod, String className, List<String> indexParameters) { StringBuilder sb = new StringBuilder(); sb.append("{StringBuilder sb = new StringBuilder"); sb.append("("A call was made to method '");"); sb.append("sb.append(""); sb.append(currentMethod.getName()); sb.append("");sb.append("' on class '");"); sb.append("sb.append(""); sb.append(className); sb.append("");sb.append("'.");"); sb.append("sb.append("n Important params:");"); . . . Tuesday, June 10, 14
  • 83. lets code private String createJavaString(CtMethod currentMethod, String className, List<String> indexParameters) { StringBuilder sb = new StringBuilder(); sb.append("{StringBuilder sb = new StringBuilder"); sb.append("("A call was made to method '");"); sb.append("sb.append(""); sb.append(currentMethod.getName()); sb.append("");sb.append("' on class '");"); sb.append("sb.append(""); sb.append(className); sb.append("");sb.append("'.");"); sb.append("sb.append("n Important params:");"); . . . Put multiple statements inside brackets {} Tuesday, June 10, 14
  • 84. lets code private String createJavaString(CtMethod currentMethod, String className, List<String> indexParameters) { . . . for (String index : indexParameters) { try { int localVar = Integer.parseInt(index) + 1; sb.append("sb.append("n Index: ");"); sb.append("sb.append(""); sb.append(index); sb.append("");sb.append(" value: ");"); sb.append("sb.append($" + localVar + ");"); } catch (NumberFormatException e) { e.printStackTrace(); } } sb.append("System.out.println(sb.toString());}"); return sb.toString(); } Tuesday, June 10, 14
  • 85. lets code private String createJavaString(CtMethod currentMethod, String className, List<String> indexParameters) { . . . for (String index : indexParameters) { try { int localVar = Integer.parseInt(index) + 1; sb.append("sb.append("n Index: ");"); sb.append("sb.append(""); sb.append(index); sb.append("");sb.append(" value: ");"); sb.append("sb.append($" + localVar + ");"); } catch (NumberFormatException e) { e.printStackTrace(); } } sb.append("System.out.println(sb.toString());}"); return sb.toString(); } $0, $1, $2, ... can be used to access “this” and the actual method parameters Tuesday, June 10, 14
  • 86. lets code public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] cfbuffer) throws IllegalClassFormatException { pool.insertClassPath(new ByteArrayClassPath(className, classfileBuffer)); CtClass cclass = pool.get(className.replaceAll("/", ".")); if (!cclass.isFrozen()) { for (CtMethod currentMethod : cclass.getDeclaredMethods()) { Annotation annotation = getAnnotation(currentMethod); if (annotation != null) { List<String> parameterIndexes = getParamIndexes(annotation); currentMethod.insertBefore(createJavaString( currentMethod, className, parameterIndexes)); } } return cclass.toBytecode(); } return null; } Tuesday, June 10, 14
  • 87. Javassist • Positives • Simplicity • Do not have to write actual bytecode • Decent documentation • Negatives • Generally slower than ASM • Less functionality Tuesday, June 10, 14
  • 88. ASM • Released in Open Source in 2002 • Actively updated • Version 5.0.3 released May 2014 • Two ASM libraries • event based (SAX like) • visitor design pattern • object based (DOM like) • Documentation: http://download.forge.objectweb.org/ asm/asm4-guide.pdf Tuesday, June 10, 14
  • 92. ASM ClassReader: given a byte[], parses a compiled class ClassReader: event producer BankTrans ClassWriter: event consumer ClassVisitor: event filter Tuesday, June 10, 14
  • 93. ASM ClassReader: given a byte[], parses a compiled class ClassReader: event producer BankTrans ClassWriter: event consumer visitField visitMethod ClassVisitor: event filter Tuesday, June 10, 14
  • 94. ASM ClassVisitor: delegates class events, event filter visitAttribute visitField visitMethod visitInnerClass visitEnd ClassReader: given a byte[], parses a compiled class ClassReader: event producer BankTrans ClassWriter: event consumer visitField visitMethod ClassVisitor: event filter Tuesday, June 10, 14
  • 95. ASM ClassVisitor: delegates class events, event filter visitAttribute visitField visitMethod visitInnerClass visitEnd ClassWriter: produces output byte[] ClassReader: given a byte[], parses a compiled class ClassReader: event producer BankTrans ClassWriter: event consumer visitField visitMethod BankTrans ClassVisitor: event filter Tuesday, June 10, 14
  • 96. lets code package com.example.qcon.agent; import java.lang.instrument.Instrumentation; public class Agent { public static void premain(String agentArgs, Instrumentation inst) { System.out.println("Starting the agent"); inst.addTransformer(new ImportantLogClassTransformer()); } } Tuesday, June 10, 14
  • 97. lets code package com.example.qcon.agent; import java.lang.instrument.Instrumentation; public class Agent { public static void premain(String agentArgs, Instrumentation inst) { System.out.println("Starting the agent"); inst.addTransformer(new ImportantLogClassTransformer()); } } Tuesday, June 10, 14
  • 98. lets code package com.example.qcon.agent; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; public class ImportantLogClassTransformer implements ClassFileTransformer { public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { //TODO return null; } } Tuesday, June 10, 14
  • 99. lets code package com.example.qcon.agent; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; public class ImportantLogClassTransformer implements ClassFileTransformer { public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { //TODO return null; } } Tuesday, June 10, 14
  • 100. lets code public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { ClassReader cr = new ClassReader(classfileBuffer); ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES); cr.accept(cw, 0); return cw.toByteArray(); } Tuesday, June 10, 14
  • 101. lets code public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { ClassReader cr = new ClassReader(classfileBuffer); ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES); ClassVisitor cv = new LogMethodClassVisitor(cw, className); cr.accept(cv, 0); return cw.toByteArray(); } Tuesday, June 10, 14
  • 102. ASM ClassVisitor: delegates class events, event filter visitAttribute visitField visitMethod visitInnerClass visitEnd ClassWriter: produces output byte[] ClassReader: given a byte[], parses a compiled class ClassReader: event producer BankTrans ClassWriter: event consumer visitMethod BankTrans LogMethod ClassVisitor: event filter Tuesday, June 10, 14
  • 104. lets code public class LogMethodClassVisitor extends ClassVisitor { private String className; public LogMethodIfAnnotationVisitor(ClassVisitor cv, String pClassName) { super(Opcodes.ASM5, cv); className = pClassName; } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { // put our logic in here } } Tuesday, June 10, 14
  • 105. lets code public class LogMethodClassVisitor extends ClassVisitor { private String className; public LogMethodIfAnnotationVisitor(ClassVisitor cv, String pClassName) { super(Opcodes.ASM5, cv); className = pClassName; } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { // put our logic in here } } Tuesday, June 10, 14
  • 109. ASM MethodVisitor: method event filter MethodVisitor MethodVisitor visitCode login method visitor login method visitor visitAnnotation visitEnd visitCode visitTryCatchBlock visitEnd visitAttribute Tuesday, June 10, 14
  • 111. lets code public class LogMethodClassVisitor extends ClassVisitor { private String className; public LogMethodIfAnnotationVisitor(ClassVisitor cv, String pClassName) { super(Opcodes.ASM5, cv); className = pClassName; } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); return new PrintMessageMethodVisitor(mv, name, className); } } Tuesday, June 10, 14
  • 112. lets code public class PrintMessageMethodVisitor extends MethodVisitor { private String methodName; private String className; private boolean isAnnotationPresent; private List<String> parameterIndexes; public PrintMessageMethodVisitor(MethodVisitor mv, String methodName, String className) { } @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { } @Override public void visitCode() { } } Tuesday, June 10, 14
  • 113. lets code public class PrintMessageMethodVisitor extends MethodVisitor { private String methodName; private String className; private boolean isAnnotationPresent; private List<String> parameterIndexes; public PrintMessageMethodVisitor(MethodVisitor mv, String methodName, String className) { // initialize instance variables } @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { 1. check method for annotation @ImportantLog 2. if annotation present, then get important method param indexes } @Override public void visitCode() { 3. if annotation present, add logging to beginning of the method } } Tuesday, June 10, 14
  • 114. lets code public AnnotationVisitor visitAnnotation(String desc, boolean visible) { if ("Lcom/example/qcon/mains/ImportantLog;".equals(desc)) { isAnnotationPresent = true; return new AnnotationVisitor(Opcodes.ASM5, super.visitAnnotation(desc, visible)) { public AnnotationVisitor visitArray(String name) { if (“fields”.equals(name)) { return new AnnotationVisitor(Opcodes.ASM5, super.visitArray(name)) { public void visit(String name, Object value) { parameterIndexes.add((String) value); super.visit(name, value); } }; } else { return super.visitArray(name); } } }; } return super.visitAnnotation(desc, visible); } Tuesday, June 10, 14
  • 115. lets code public class PrintMessageMethodVisitor extends MethodVisitor { private String methodName; private String className; private boolean isAnnotationPresent; private List<String> parameterIndexes; public PrintMessageMethodVisitor(MethodVisitor mv, String methodName, String className) { // initialize instance variables } @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { 1. check method for annotation @ImportantLog 2. if annotation present, then get important method param indexes } @Override public void visitCode() { 3. if annotation present, add logging statement to beginning of the method } } Tuesday, June 10, 14
  • 116. lets code public void visitCode() { if (isAnnotationPresent) { // create string builder mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder"); mv.visitInsn(Opcodes.DUP); // add everything to the string builder mv.visitLdcInsn("A call was made to method ""); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false); mv.visitLdcInsn(methodName); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); . . . Tuesday, June 10, 14
  • 117. What is Java bytecode? use javap to examine the bytecode Tuesday, June 10, 14
  • 118. What is Java bytecode? public class PrintMessage { private String methodName; private String className; public PrintMessage(String mName, String cName) { methodName = mName; className = cName; } public void print() { StringBuilder sb = new StringBuilder(); sb.append("A call was made to method ""); sb.append(methodName); sb.append("" on class ""); sb.append(className); sb.append(""."); System.out.println(sb.toString()); } Tuesday, June 10, 14
  • 119. What is Java bytecode? javap -c bin/com/example/qcon/mains/PrintMessage Tuesday, June 10, 14
  • 120. What is Java bytecode? javap -c bin/com/example/qcon/mains/PrintMessage public void print(); Code: 0: new #38 // class java/lang/StringBuilder 3: dup 4: invokespecial #40 // Method java/lang/ StringBuilder."<init>":()V 7: astore_1 8: aload_1 9: ldc #41 // String A call was made to method " 11: invokevirtual #43 // Method java/lang/ StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 14: pop 15: aload_1 16: aload_0 17: getfield #14 // Field methodName:Ljava/lang/String; 20: invokevirtual #43 // Method java/lang/ StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; . . . Tuesday, June 10, 14
  • 121. What is Java bytecode? each line represents one JVM instruction public void print(); Code: 0: new #38 // class java/lang/StringBuilder 3: dup 4: invokespecial #40 // Method java/lang/ StringBuilder."<init>":()V 7: astore_1 8: aload_1 9: ldc #41 // String A call was made to method " 11: invokevirtual #43 // Method java/lang/ StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 14: pop 15: aload_1 16: aload_0 17: getfield #14 // Field methodName:Ljava/lang/String; 20: invokevirtual #43 // Method java/lang/ StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; . . . Tuesday, June 10, 14
  • 122. What is Java bytecode? JVM instruction = 1 opcode with 0 or more operands public void print(); Code: 0: new #38 // class java/lang/StringBuilder 3: dup 4: invokespecial #40 // Method java/lang/ StringBuilder."<init>":()V 7: astore_1 8: aload_1 9: ldc #41 // String A call was made to method " 11: invokevirtual #43 // Method java/lang/ StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 14: pop 15: aload_1 16: aload_0 17: getfield #14 // Field methodName:Ljava/lang/String; 20: invokevirtual #43 // Method java/lang/ StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; . . . Tuesday, June 10, 14
  • 123. What is Java bytecode? Opcode Description load load a reference onto the stack from a local variable iload, lload, fload, dload, aload store stores a value from the stack into a local variable istore, lstore, fstore, dstore, astore lcd push a constant from a constant pool onto the stack return method return instruction ireturn, lreturn, freturn, dreturn, areturn, return invokevirtual invoke an instance method on an object invokespecial invokes an instance method requiring special handling such as an initialization method See the spec for more info: http://docs.oracle.com/javase/specs/jvms/se8/jvms8.pdf Tuesday, June 10, 14
  • 124. What is Java bytecode? Opcode Description invokestatic invoke a class (static) method on a named class athrow throws an exception new create a new class newarray create a new array if<cond> branch if int comparison with 0 succeeds ifeq, ifne, iflt, ifge, ifgt, ifle dup duplicate the top operand stack value See the spec for more info: http://docs.oracle.com/javase/specs/jvms/se8/jvms8.pdf Tuesday, June 10, 14
  • 125. What is Java bytecode? Tuesday, June 10, 14
  • 126. What is Java bytecode? Tuesday, June 10, 14
  • 127. What is Java bytecode? Tuesday, June 10, 14
  • 128. lets code public void visitCode() { if (isAnnotationPresent) { // create string builder mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder"); mv.visitInsn(Opcodes.DUP); // add everything to the string builder mv.visitLdcInsn("A call was made to method ""); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false); mv.visitLdcInsn(methodName); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); . . . Tuesday, June 10, 14
  • 129. ASM • Positives • Speed and Size • Decent documentation • Depth of Functionality • Number of people using framework • Negatives • Need to write actual byte code • longer developer ramp-up Tuesday, June 10, 14
  • 130. Why learn about Java bytecode manipulation frameworks ? • program analysis • find bugs in code • examine code complexity • generate classes • proxies • remove access to certain APIs • compiler for another language like Scala • transform classes without Java source code • profilers • optimization and obfuscation • additional logging Tuesday, June 10, 14
  • 131. Bytecode Manipulation Frameworks • ASM: http://asm.ow2.org/ • BCEL: http://commons.apache.org/proper/commons-bcel/ • CGLib: https://github.com/cglib/cglib • Javassist: http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/ • Serp: http://serp.sourceforge.net/ • Cojen: https://github.com/cojen/Cojen/wiki • Soot: http://www.sable.mcgill.ca/soot/ Tuesday, June 10, 14
  • 132. Source: http://www.kulfoto.com/dog-pictures/15799/mans-best-friend Make bytecode manipulation frameworks your friend. They might save your job one day. Tuesday, June 10, 14