Upgrade to Pro — share decks privately, control downloads, hide ads and more …

GeeCON Prague 2014 - Having fun with Javassist

GeeCON Prague 2014 - Having fun with Javassist

Anton Arhipov

October 24, 2014
Tweet

More Decks by Anton Arhipov

Other Decks in Programming

Transcript

  1. !
    Having fun with
    Javassist
    Anton Arhipov
    @antonarhipov, 24th October 2014

    View Slide

  2. Hello! (Who’s that?)
    Anton Arhipov
    ZeroTurnaround
    XRebel
    JRebel
    @antonarhipov Prague, 24th October 2014
    @antonarhipov

    View Slide

  3. Why Javassist?
    @antonarhipov Prague, 24th October 2014
    It enables both tools I’m deeply involved with

    View Slide

  4. Why Javassist?
    @antonarhipov Prague, 24th October 2014
    Java bytecode manipulation made easy!

    View Slide

  5. Why Javassist?
    @antonarhipov Prague, 24th October 2014
    Java bytecode manipulation made easy!

    View Slide

  6. Why Javassist?
    @antonarhipov Prague, 24th October 2014
    It is fun!

    View Slide

  7. The Plan for This PrEseNtAtiOn
    @antonarhipov Prague, 24th October 2014
    Use cases for bytecode manipulation
    Code examples with Javassist
    How to brew a Java agent
    speakerdeck.com/antonarhipov github.com/zeroturnaround/callspy

    View Slide

  8. BYTECODE MANIPULATION
    @antonarhipov Prague, 24th October 2014

    View Slide

  9. Bytecode manipulation
    @antonarhipov Prague, 24th October 2014
    Code analysis:
    Find bugs in your application
    Examine code complexity
    Find classes by specific attributes / annotations

    View Slide

  10. Bytecode manipulation
    @antonarhipov Prague, 24th October 2014
    Code generation:
    Lazy load data from a database using proxies
    Add cross-cutting concerns to the code
    Generate classes from non-Java artefacts

    View Slide

  11. @antonarhipov Prague, 24th October 2014
    The main use case for Javassist: generate proxies
    Bytecode manipulation
    i.e. create a subclass at runtime that intercepts all method invocations
    java.lang.reflect.Proxy is not enough
    Hibernate proxies
    Spring AOP
    EJB proxies
    CDI proxies

    View Slide

  12. Bytecode manipulation
    @antonarhipov Prague, 24th October 2014
    Transforming classes without source code:
    Code profiling
    Code optimisation
    Some other crazy things…

    View Slide

  13. Bytecode manipulation
    @antonarhipov Prague, 24th October 2014
    … and of course, dynamically add logging to application
    Good news
    everyone! We’ll
    implement a logger
    today!

    View Slide

  14. Logging
    @antonarhipov Prague, 24th October 2014
    public void doSomething(){
    stmt;
    stmt;

    stmt;
    stmt;

    stmt;

    }


    View Slide

  15. Logging
    @antonarhipov Prague, 24th October 2014
    public void doSomething(){
    // no logging here
    stmt;

    stmt;
    stmt;

    stmt;

    }


    View Slide

  16. Logging
    @antonarhipov Prague, 24th October 2014
    public void doSomething(){
    // no logging here
    // argh!!!

    stmt;
    stmt;

    stmt;

    }

    If only I could add more
    logging here…

    View Slide

  17. Logging
    @antonarhipov Prague, 24th October 2014
    Instrument
    all the bytecode!

    View Slide

  18. Logging
    @antonarhipov Prague, 24th October 2014
    … with Javassist!

    View Slide

  19. JAVASSIST
    @antonarhipov Prague, 24th October 2014

    View Slide

  20. Javassist
    @antonarhipov Prague, 24th October 2014
    Bytecode manipulation made easy
    Source-level and bytecode-level API
    Uses vocabulary for a Java language
    On-the-fly compilation of the injected code
    www.javassist.org

    View Slide

  21. @antonarhipov Prague, 24th October 2014

    View Slide

  22. @antonarhipov Prague, 24th October 2014

    View Slide

  23. Javassist
    @antonarhipov Prague, 24th October 2014
    ClassPool CtClass CtMethod
    CtClass
    CtClass
    CtClass
    CtField
    CtConst
    CtMethod
    insertBefore
    instrument
    insertAfter

    View Slide

  24. JAVA AGENTS
    @antonarhipov Prague, 24th October 2014

    View Slide

  25. How would you make a tool?
    A tool should not force the user
    into a special programming model!
    @antonarhipov Prague, 24th October 2014

    View Slide

  26. -javaagent:logger.jar
    @antonarhipov Prague, 24th October 2014
    Java agent to the rescue!

    View Slide

  27. @antonarhipov Prague, 24th October 2014

    View Slide

  28. @antonarhipov Prague, 24th October 2014
    import java.lang.instrument.ClassFileTransformer;!
    import java.lang.instrument.Instrumentation;!
    !
    public class Agent {!
    !
    public static void premain(String args, Instrumentation inst) {!
    inst.addTransformer(new ClassFileTransformer { … });!
    }!
    !
    public static void agentmain(String args, Instrumentation inst) {!
    premain(args, inst);!
    }!
    }

    View Slide

  29. @antonarhipov Prague, 24th October 2014
    public static void premain(String args, Instrumentation inst)
    • java -javaagent:[=options]

    • META-INF/MANIFEST.MF is required

    View Slide

  30. @antonarhipov Prague, 24th October 2014
    public static void agentmain(String args, Instrumentation inst)
    • Executed when the agent attaches to the running JVM

    • META-INF/MANIFEST.MF is required

    • Requires support for loading agents in JVM

    • Allows adding the code to JVM post-factum

    View Slide

  31. Manifest-Version: 1.0

    Ant-Version: Apache Ant 1.8.1

    Created-By: 1.7.0_15-b03 (Oracle Corporation)

    Premain-Class: com.zeroturnaround.javarebel.java5.AgentInstall

    Can-Redefine-Classes: true

    Boot-Class-Path: jrebel.jar

    Main-Class: com.zeroturnaround.javarebel.java4.Install

    Implementation-Title: JRebel

    Specification-Title: jrebel

    Specification-Version: 5.4.0

    Implementation-Version: 201309021535
    MANIFEST.MF
    @antonarhipov Prague, 24th October 2014

    View Slide

  32. import com.sun.tools.attach.VirtualMachine;!
    !
    //attach to target VM!
    VirtualMachine vm = VirtualMachine.attach("2177");!
    !
    //get system properties in the target VM!
    Properties props = vm.getSystemProperties();!
    !
    //load agent into the VM!
    vm.loadAgent("agent.jar", "arg1=x,arg2=y");!
    !
    //detach from VM!
    vm.detach();!
    http://docs.oracle.com/javase/7/docs/jdk/api/attach/spec/com/sun/tools/attach/VirtualMachine.html
    @antonarhipov Prague, 24th October 2014

    View Slide

  33. JVM JVM
    Process 1 Process 2
    Agent
    -cp tools.jar
    @antonarhipov Prague, 24th October 2014

    View Slide

  34. Instrumentation API
    @antonarhipov Prague, 24th October 2014

    View Slide

  35. java.lang.instrument.Instrumentation
    void addTransformer(ClassFileTransformer transformer,!
    boolean canRetransform);!
    !
    void appendToBootstrapClassLoaderSearch(JarFile jarfile);!
    void appendToSystemClassLoaderSearch(JarFile jarfile);!
    !
    Class[] getAllLoadedClasses();!
    Class[] getInitiatedClasses(ClassLoader loader);!
    !
    void redefineClasses(ClassDefinition... classes);!
    void retransformClasses(Class>... classes);!
    @antonarhipov Prague, 24th October 2014

    View Slide

  36. java.lang.instrument.ClassFileTransformer
    byte[] transform(ClassLoader loader, !
    String className,!
    Class> classBeingRedefined,!
    ProtectionDomain pd,!
    byte[] classfileBuffer);!
    @antonarhipov Prague, 24th October 2014

    View Slide

  37. public class MyTransformer implements ClassFileTransformer {!
    public void byte[] transform(ClassLoader loader, !
    String className,!
    Class> classBeingRedefined,!
    ProtectionDomain pd,!
    byte[] classfileBuffer){!
    !
    ClassPool cp = ClassPool.getDefault();!
    CtClass ct = cp.makeClass(new!
    ByteArrayInputStream(classfileBuffer));!
    !
    // transform the bytes as required, !
    // for instance - with Javassist!
    !
    return ct.toBytecode();!
    }!
    }!

    View Slide

  38. !
    Class loading
    Instrumentation

    View Slide

  39. !
    Class loading
    Instrumentation ClassFileTransformer
    ClassFileTransformer
    ClassFileTransformer

    View Slide

  40. !
    Class loading
    Javassist
    Instrumentation ClassFileTransformer
    ClassFileTransformer
    ClassFileTransformer
    ASM

    View Slide

  41. View Slide

  42. JAVASSIST APPLICATIONS
    Anton Arhipov Prague, 24th October 2014

    View Slide

  43. JRebel
    Anton Arhipov Prague, 24th October 2014
    JRebel
    core
    Spring
    plugin
    Hibernate
    plugin
    EJB
    plugin

    View Slide

  44. JRebel
    Anton Arhipov Prague, 24th October 2014
    JRebel
    core
    Spring
    plugin
    Hibernate
    plugin
    EJB
    plugin
    Reloads
    classes

    View Slide

  45. JRebel
    Anton Arhipov Prague, 24th October 2014
    JRebel
    core
    Spring
    plugin
    Hibernate
    plugin
    EJB
    plugin
    Notifies
    plugins

    View Slide

  46. JRebel
    Anton Arhipov Prague, 24th October 2014
    JRebel
    core
    Spring
    plugin
    Hibernate
    plugin
    EJB
    plugin
    Reload
    configurations

    View Slide

  47. JRebel
    Anton Arhipov Prague, 24th October 2014
    JRebel
    core
    Spring
    plugin
    Hibernate
    plugin
    EJB
    plugin
    Implemented with Javassist

    View Slide

  48. Anton Arhipov Prague, 24th October 2014

    View Slide

  49. XRebel
    Anton Arhipov Prague, 24th October 2014

    View Slide

  50. XRebel
    Anton Arhipov Prague, 24th October 2014

    View Slide

  51. XRebel
    Anton Arhipov Prague, 24th October 2014
    Injected via the application server with Javassist

    View Slide

  52. XRebel
    Anton Arhipov Prague, 24th October 2014

    View Slide

  53. THANK YOU!
    Anton Arhipov Prague, 24th October 2014
    [email protected]
    @antonarhipov

    View Slide