Download - JavaOne 2015 - Having fun with Javassist
![Page 1: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/1.jpg)
Having fun with Javassist
![Page 2: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/2.jpg)
Me
Anton Arhipov @antonarhipov
We Javassist a lot!
![Page 3: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/3.jpg)
You?
Are you interested in Javassist?
Want to become a better programmer?
Bytecode instrumentation, anyone?
![Page 4: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/4.jpg)
![Page 5: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/5.jpg)
@Entity@Table(name = "owners")public class Owner extends Person { @Column(name = "address") @NotEmpty private String address; @Column(name = "city") @NotEmpty private String city; @Column(name = "telephone") @NotEmpty @Digits(fraction = 0, integer = 10) private String telephone; @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner") private Set<Pet> pets;
![Page 6: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/6.jpg)
public class JavassistLazyInitializer extends BasicLazyInitializer implements MethodHandler {
final JavassistLazyInitializer instance = new JavassistLazyInitializer(…); ProxyFactory factory = new ProxyFactory();factory.setSuperclass(interfaces.length == 1?persistentClass:null);factory.setInterfaces(interfaces);factory.setFilter(FINALIZE_FILTER); Class cl = factory.createClass();final HibernateProxy proxy = (HibernateProxy) cl.newInstance(); ((ProxyObject)proxy).setHandler(instance); instance.constructed = true;return proxy;
![Page 7: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/7.jpg)
public class JavassistLazyInitializer extends BasicLazyInitializer implements MethodHandler {
final JavassistLazyInitializer instance = new JavassistLazyInitializer(…); ProxyFactory factory = new ProxyFactory();factory.setSuperclass(interfaces.length == 1?persistentClass:null);factory.setInterfaces(interfaces);factory.setFilter(FINALIZE_FILTER); Class cl = factory.createClass();final HibernateProxy proxy = (HibernateProxy) cl.newInstance(); ((ProxyObject)proxy).setHandler(instance); instance.constructed = true;return proxy;
Generates proxy!
![Page 8: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/8.jpg)
The main use case for bytecode generation in Java framewoks
is to generate proxies
![Page 9: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/9.jpg)
![Page 10: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/10.jpg)
Agenda
Javassist basics -javaagent
HacksApplications
… and a little bit on the use of Javassist in JRebel
![Page 12: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/12.jpg)
ClassPool
CtClassCtClassCtClass
CtClass
CtFieldCtMethodCtConst
CtMethod
insertBeforeinsertAfterinstrument
It feels almost like Java Reflection API :)
![Page 13: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/13.jpg)
public static void main(String[] args) throws Exception {
ClassPool cp = ClassPool.getDefault();
CtClass ct = cp.makeClass("com.zt.A", cp.get("com.zt.Clazz"));
CtMethod[] methods = ct.getMethods(); for (CtMethod method : methods) { //… }
ct.writeFile("/output");
}
![Page 14: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/14.jpg)
public static void main(String[] args) throws Exception {
ClassPool cp = ClassPool.getDefault();
CtClass ct = cp.makeClass("com.zt.A", cp.get("com.zt.Clazz"));
CtMethod[] methods = ct.getMethods(); for (CtMethod method : methods) { //… }
ct.writeFile("/output");
}
ClassPool cp = new ClassPool(null); cp.appendSystemPath();
![Page 15: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/15.jpg)
public static void main(String[] args) throws Exception {
ClassPool cp = ClassPool.getDefault();
CtClass ct = cp.makeClass("com.zt.A", cp.get("com.zt.Clazz"));
CtMethod[] methods = ct.getMethods(); for (CtMethod method : methods) { //… }
ct.writeFile("/output");
}
public class A extends Clazz { public A() { } }
![Page 16: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/16.jpg)
public static void main(String[] args) throws Exception {
ClassPool cp = ClassPool.getDefault();
CtClass ct = cp.makeClass("com.zt.A", cp.get("com.zt.Clazz"));
CtMethod[] methods = ct.getMethods(); for (CtMethod method : methods) { //… }
ct.writeFile("/output");
}
![Page 17: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/17.jpg)
public static void main(String[] args) throws Exception {
ClassPool cp = ClassPool.getDefault();
CtClass ct = cp.makeClass("com.zt.A", cp.get("com.zt.Clazz"));
CtMethod[] methods = ct.getMethods(); for (CtMethod method : methods) { //… }
ct.writeFile("/output");
}
mars:output anton$ javap -‐c com/zt/A.class Compiled from "A.java" public class com.zt.A extends com.zt.Clazz { public com.zt.A(); Code: 0: aload_0 1: invokespecial #10 4: return
![Page 18: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/18.jpg)
public static void main(String[] args) throws Exception {
ClassPool cp = ClassPool.getDefault();
CtClass ct = cp.makeClass("com.zt.A", cp.get("com.zt.Clazz"));
CtMethod[] methods = ct.getMethods(); for (CtMethod method : methods) { //… }
ct.writeFile("/output");
}
Can generate classes from metadata at build time
![Page 19: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/19.jpg)
public static void main(String[] args) throws Exception {
ClassPool cp = ClassPool.getDefault(); cp.appendClassPath(new ClassPath(){ … });
CtClass ct = cp.get("com.zt.A");
CtMethod[] methods = ct.getMethods(); for (CtMethod method : methods) { //… }
ct.writeFile("/output");
}
… or you can post process the compiled classes
![Page 20: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/20.jpg)
public static void main(String[] args) throws Exception {
ClassPool cp = ClassPool.getDefault(); CtClass ctClass = cp.get("com.zt.A");
CtMethod foo = ctClass.getMethod("foo", "()V");
foo.insertBefore("System.out.println();");
Class c = ctClass.toClass(); A a = (A) c.newInstance(); a.foo("Hello");
}
![Page 21: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/21.jpg)
public static void main(String[] args) throws Exception {
ClassPool cp = ClassPool.getDefault(); CtClass ctClass = cp.get("com.zt.A");
CtMethod foo = ctClass.getMethod("foo", "()V");
foo.insertBefore("System.out.println();");
Class c = ctClass.toClass(); A a = (A) c.newInstance(); a.foo("Hello");
}
![Page 22: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/22.jpg)
public static void main(String[] args) throws Exception {
ClassPool cp = ClassPool.getDefault(); CtClass ctClass = cp.get("com.zt.A");
CtMethod foo = ctClass.getMethod("foo", "()V");
foo.insertBefore("System.out.println();");
Class c = ctClass.toClass(); A a = (A) c.newInstance(); a.foo("Hello");
}
public void foo() { }
![Page 23: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/23.jpg)
public static void main(String[] args) throws Exception {
ClassPool cp = ClassPool.getDefault(); CtClass ctClass = cp.get("com.zt.A");
CtMethod foo = ctClass.getMethod("foo", "(Ljava/lang/String;)V");
foo.insertBefore("System.out.println();");
Class c = ctClass.toClass(); A a = (A) c.newInstance(); a.foo("Hello");
}
public void foo(String s) { }
![Page 24: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/24.jpg)
public static void main(String[] args) throws Exception {
ClassPool cp = ClassPool.getDefault(); CtClass ctClass = cp.get("com.zt.A");
CtMethod foo = ctClass.getMethod("foo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
foo.insertBefore("System.out.println();");
Class c = ctClass.toClass(); A a = (A) c.newInstance(); a.foo("Hello");
}
Descriptors might get quite long ;)
![Page 25: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/25.jpg)
public static void main(String[] args) throws Exception {
ClassPool cp = ClassPool.getDefault(); CtClass ctClass = cp.get("com.zt.A");
CtMethod foo = ctClass.getMethod("foo", "(Ljava/lang/String;)V");
foo.insertBefore("System.out.println($1)");
Class c = ctClass.toClass(); A a = (A) c.newInstance(); a.foo("Hello");
}
$1, $2, $3 — local variables $0 — this for non-‐static methods
![Page 26: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/26.jpg)
public static void main(String[] args) throws Exception {
ClassPool cp = ClassPool.getDefault(); CtClass ctClass = cp.get("com.zt.A");
CtMethod foo = ctClass.getMethod("foo", "(Ljava/lang/String;)V");
foo.insertBefore("System.out.println($1)");
Class c = ctClass.toClass(); A a = (A) c.newInstance(); a.foo("Hello");
}
Exception in thread "main" javassist.CannotCompileException: [source error] ; is missing at javassist.CtBehavior.insertBefore(CtBehavior.java:774) at javassist.CtBehavior.insertBefore(CtBehavior.java:734) at com.zt.basics.Ex.main(Ex.java:35)
![Page 27: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/27.jpg)
public static void main(String[] args) throws Exception {
ClassPool cp = ClassPool.getDefault(); CtClass ctClass = cp.get("com.zt.A");
CtMethod foo = ctClass.getMethod("foo", "(Ljava/lang/String;)V");
foo.insertBefore("System.out.println($1);");
Class c = ctClass.toClass(); A a = (A) c.newInstance(); a.foo("Hello");
}
![Page 28: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/28.jpg)
CtMethod foo = …
foo.insertBefore(…);
foo.insertAfter(…);
Can implement tracing
![Page 29: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/29.jpg)
CtMethod foo = …
foo.insertBefore(…);
foo.insertAfter(…);
… or add logging
![Page 30: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/30.jpg)
CtMethod foo = …
foo.insertBefore(…);
foo.insertAfter(…);
… or implement AOP
![Page 31: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/31.jpg)
CtMethod foo = …
foo.instrument(new ExprEditor() { @Override public void edit(NewExpr e) throws CannotCompileException { e.replace("{" + "$_ = $proceed($$);" + "System.out.println($_);" + "}"); }
});
![Page 32: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/32.jpg)
CtMethod foo = …
foo.instrument(new ExprEditor() { @Override public void edit(NewExpr e) throws CannotCompileException { e.replace("{" + "$_ = $proceed($$);" + "System.out.println($_);" + "}"); }
});
![Page 33: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/33.jpg)
CtMethod foo = …
foo.instrument(new ExprEditor() { @Override public void edit(NewExpr e) throws CannotCompileException { e.replace("{" + "$_ = $proceed($$);" + "System.out.println($_);" + "}"); }
}); Intercept new instances
![Page 34: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/34.jpg)
CtMethod foo = …
foo.instrument(new ExprEditor() { @Override public void edit(NewExpr e) throws CannotCompileException { e.replace("{" + "$_ = $proceed($$);" + "System.out.println($_);" + "}"); }
}); Intercept new instances
![Page 35: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/35.jpg)
CtMethod foo = …
foo.instrument(new ExprEditor() { @Override public void edit(MethodCall m) throws CannotCompileException { if(m.getMethodName().contains("println")) { m.replace("{}"); } }
}); Remove unwanted invocations
![Page 36: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/36.jpg)
CtMethod foo = …
foo.instrument(new ExprEditor() { @Override public void edit(FieldAccess m) throws CannotCompileException { if (f.isWriter()) { CtField field = f.getField(); String setterName = findSetter(field); f.replace("{" + "$0." + setterName + "($$);" + "}"); } }
});
Replace direct field access with setter calls
![Page 37: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/37.jpg)
This slide is intentionally left blank
![Page 38: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/38.jpg)
Java Agent
![Page 39: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/39.jpg)
Java Agent
import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.Instrumentation;
public class Agent { public static void premain(String args, Instrumentation inst) throws Exception { inst.addTransformer(new ClassFileTransformer { // here be code }); } }
META-‐INF/MANIFEST.MF Premain-‐Class: Agent
$> java –javaagent:agent.jar application.Main
![Page 40: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/40.jpg)
ClassFileTransformernew ClassFileTransformer() { public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer){
ClassPool cp = ClassPool.getDefault(); CtClass ct = cp.makeClass(new ByteArrayInputStream(classfileBuffer)); // here we can do all the things to ‘ct’ return ct.toBytecode(); } }
![Page 41: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/41.jpg)
new ClassFileTransformer() { public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer){
ClassPool cp = ClassPool.getDefault(); CtClass ct = cp.makeClass(new ByteArrayInputStream(classfileBuffer)); // here we can do all the things to ‘ct’ return ct.toBytecode(); } }
ClassFileTransformer
![Page 42: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/42.jpg)
new ClassFileTransformer() { public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer){
ClassPool cp = ClassPool.getDefault(); CtClass ct = cp.makeClass(new ByteArrayInputStream(classfileBuffer)); // here we can do all the things to ‘ct’ return ct.toBytecode(); } }
ClassFileTransformer
![Page 43: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/43.jpg)
new ClassFileTransformer() { public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer){
ClassPool cp = ClassPool.getDefault(); CtClass ct = cp.makeClass(new ByteArrayInputStream(classfileBuffer)); // here we can do all the things to ‘ct’ return ct.toBytecode(); } }
ClassFileTransformer
![Page 44: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/44.jpg)
![Page 45: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/45.jpg)
![Page 46: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/46.jpg)
![Page 47: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/47.jpg)
![Page 48: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/48.jpg)
![Page 51: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/51.jpg)
JRebel core
Spring plugin
Hibernate plugin
EJB plugin
![Page 52: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/52.jpg)
JRebel core
Spring plugin
Hibernate plugin
EJB pluginjrebel.jar
![Page 53: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/53.jpg)
Spring plugin
Hibernate plugin
EJB pluginReloads
classes
JRebel core
![Page 54: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/54.jpg)
JRebel core
Spring plugin
Hibernate plugin
EJB pluginNotifies
plugins
![Page 55: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/55.jpg)
JRebel core
Spring plugin
Hibernate plugin
EJB plugin
Refresh configurations
![Page 56: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/56.jpg)
JRebel core
Javassist lives here
Spring plugin
Hibernate plugin
EJB plugin
![Page 57: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/57.jpg)
Spring
Hibernate
OpenEJB
JRebel core
Spring plugin
Hibernate plugin
EJB plugin
![Page 58: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/58.jpg)
class Framework { public void configure(){ } }
CtClass framework = cp.get("com.zt.Framework");
framework.addInterface( cp.get("com.zt.jrebel.Listener"));
class Framework implements Listener { public void configure(){ } } framework.addMethod(
CtNewMethod.make( "public void onEvent(){" + " configure();" + "}", framework ));
![Page 60: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/60.jpg)
![Page 61: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/61.jpg)
Your task
Javassist
![Page 62: JavaOne 2015 - Having fun with Javassist](https://reader031.vdocuments.site/reader031/viewer/2022030308/58f378611a28ab12688b4581/html5/thumbnails/62.jpg)
https://speakerdeck.com/antonarhipov
http://www.slideshare.net/arhan
@antonarhipov [email protected]
http://0t.ee/javaone-jr