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

JRebel Under the Covers

Simon Maple
September 16, 2015

JRebel Under the Covers

This talk presents a number of conceptual and technical challenges that we discovered while building JRebel. JRebel performs class reloading and framework integrations which the JVM doesn't provide out the box. This session demystifies the magic.
This talk presents a number of conceptual and technical challenges that we discovered while building JRebel. At first, the JVM wasn't designed for live updates, so we will talk about the engine that mitigates the problem. Secondly, the diversity of Java ecosystem, created by the variety of application servers, the frameworks and tools, makes it challenging in creating a generic solution that would fit the majority of developers. We will see, how Java platform itself allows us to develop a solution by applying bytecode instrumentation mechanism.
JRebel does live code reloading to ensure that the developer can keep instantly alternating between the developing environment and the web browser, to save wasted time and increase the productivity flow.

Simon Maple

September 16, 2015
Tweet

More Decks by Simon Maple

Other Decks in Education

Transcript

  1. JRebel  Under  the  Covers  
    How  is  it  even  possible?  

    View Slide

  2. Simon  Maple  -­‐  @sjmaple  
    @sjmaple
    Simon Maple

    View Slide

  3. View Slide

  4. View Slide

  5. Make a change
    Compile
    Build
    Deploy
    Observe the result
    Take some
    coffee
    Avg: 3 min

    View Slide

  6. View Slide

  7. state
    external
    serializable
    temporary
    derivative

    View Slide

  8. How can I reload a single
    class preserving the state?

    View Slide

  9. ClassLoader API

    View Slide

  10. View Slide

  11. How to reload web application?
    (and preserve state)

    View Slide

  12. Classes
    Libraries
    OldClassLoader NewClassLoader
    Sevlet New
    Classes
    New
    Libraries
    Sevlet
    Session Session
    init()
    App
    State
    App
    State
    Serialize/deserialize

    View Slide

  13. OldClassLoader NewClassLoader
    Sevlet New
    Classes
    New
    Libraries
    Sevlet
    Session Session
    App
    State
    App
    State

    View Slide

  14. Class loaders are good for
    isolation, but suck at
    reloading the code …
    (and perfect for memory leaks)

    View Slide

  15. View Slide

  16. Leaking ClassLoaders

    View Slide

  17. Hello, HotSwap!
    Hotswapping methods since 2002

    View Slide

  18. M. Dmitriev. Safe class and data evolution in large and long-lived java[tm] applications. Technical report, Mountain View, CA, 2001.

    View Slide

  19. The  Heap  &  Garbage  CollecBon  

    View Slide

  20. Hello, JRebel!
    Improving HotSwap since 2007

    View Slide

  21. Demo Time!

    View Slide

  22. HotSwap   JRebel  
    Changing  method  bodies  
    Adding/removing  methods  
    Adding/removing  constructors  
    Adding/removing  fields  
    Adding/removing  annotaBons  
    Changing  superclass  
    Adding/removing  interfaces  

    View Slide

  23. How does it work???

    View Slide

  24. The
    engine

    View Slide

  25. ClassA
    +field1
    +field2
    +field3
    +method1(n:int)
    +method2(s:String)
    +method3(z:double)
    ClassA
    +field1
    +field2
    +field3
    +proxy methods
    ClassA0
    +method1(n:int)
    +method2(s:String)
    +method3(z:double)
    Transformer

    View Slide

  26. public class C extends X {
    int y = 5;
    int method1(int x) {
    return x + y;
    }
    void method2(String s) {
    System.out.println(s);
    }
    }

    View Slide

  27. public class C extends X {
    int y = 5;
    int method1(int x) {
    Object[] o = new Object[1];
    o[0] = x;
    return Runtime.redirect(this, o, "C", "method1", "(I)I");
    }
    void method2(String s) {
    Object[] o = new Object[1];
    o[0] = s;
    return Runtime.redirect(
    this, o, "C", "method2", "(Ljava/lang/String;)V");
    }
    }

    View Slide

  28. public abstract class C0 {
    public static int method1(C c, int x) {
    int tmp1 = Runtime.getFieldValue(c, "C", "y", "I");
    return x + tmp1;
    }
    public static void method2(C c, String s) {
    PrintStream tmp1 = Runtime.getFieldValue(
    null, "java/lang/System", "out", "Ljava/io/PrintStream;");
    Object[] o = new Object[1];
    o[0] = s;
    Runtime.redirect(
    tmp1, o, "java/io/PrintStream;", "println",
    "(Ljava/lang/String;)V");
    }
    }

    View Slide

  29. public class C extends X {
    int y = 5;
    int method1(int x) {
    return x + y;
    }
    //...
    }
    public class C extends X {
    int y = 5;
    int z() {
    return 10;
    }
    int method1(int x) {
    return x + y + z();
    }
    //...
    }

    View Slide

  30. public class C1 {
    public static int z(C c) {
    return 10;
    }
    public static int method1(C c, int x) {
    int tmp1 = Runtime.getFieldValue(c, "C", "y", "I");
    int tmp2 = Runtime.redirect(c, null, "C", "z", "(V)I");
    return x + tmp1 + tmp2;
    }
    //...
    }

    View Slide

  31. JRebel Reloading

    View Slide

  32. View Slide

  33. View Slide

  34. static { }
    Adding new static fields
    Removing static fields
    Changing values of static fields
    Factories
    etc

    View Slide

  35. package a;
    public class A {
    int say() {return 1;}
    }
    package a;
    class Test {
    public static void main(String args[]) {
    a.A a = new b.B();
    System.out.println(a.say());
    }
    }
    package b;
    public class B extends a.A {
    int say() {return 2;}
    }
    An Exercise

    View Slide

  36. “package” visibility
    package -> public -> package

    View Slide

  37. concurrency
    synchronized volatile
    Object.wait() Object.notify()

    View Slide

  38. serialization
    Serializable Externalizable
    transient

    View Slide

  39. reflection
    Class, Method, Field,
    Constructor, Proxy

    View Slide

  40. View Slide

  41. The
    Ecosystem

    View Slide

  42. Javassist: binary patching
    for fun and profit

    View Slide

  43. 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 { });
    }
    }
    java  –javaagent:agent.jar  …  
    META-INF/MANIFEST.MF
    Premain-Class: Agent

    View Slide

  44. 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));
    transformClass(ct, cp);
    return ct.toBytecode();
    }
    }

    View Slide

  45. 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));
    transformClass(ct, cp);
    return ct.toBytecode();
    }
    }

    View Slide

  46. JRebel Plugins

    View Slide

  47. @Path(“/”)
    public String foo() {
    return “Foo”;
    }
    @Path(“/foobar”)
    public String foo() {
    return “FooBar”;
    }
    JRebel
     
    core
     
    JRebel
     
    Spring
     
    plugin
     

    View Slide

  48. Remote?

    View Slide

  49. THE IMPACT

    View Slide

  50. http://zeroturnaround.com/company/case-studies/
    “Team velocity was increased by
    40.6%, and according to t-test it
    was a statistically significant
    difference.”
    “Netty and Spring together with
    JRebel is real pleasure to work
    with. The value of time saved is
    over 50% of my development
    time.”

    View Slide

  51. Questions?
    @sjmaple

    View Slide

  52. View Slide

  53. View Slide

  54. Credits
    https://www.flickr.com/photos/smemon/4556099850/
    https://www.flickr.com/photos/gforsythe/10173857405
    https://www.flickr.com/photos/dkshots/6967173295
    https://www.flickr.com/photos/reckless_sniper/4545673070
    https://www.flickr.com/photos/omcoc/8350510425
    https://www.flickr.com/photos/bufivla/3619927485
    https://www.flickr.com/photos/39747297@N05/5229733647
    http://leadershipelements.files.wordpress.com/2014/01/square-peg-round-hole.jpg

    View Slide