5. JVM 1.2 以后支持了hotswap功能 JavaTM Virtual Machine Debug Interface Reference typedefstruct { jclassclazz; /* Class to be redefined */ jintclass_byte_count; /* number of bytes defining class (below) */ jbyte *class_bytes; /* bytes defining class */ /* (in Class File Format of JVM spec) */ } JVMDI_class_definition; jvmdiError RedefineClasses(jintclassCount, JVMDI_class_definition *classDefs)
7. Sounds good,what's the problem? Unfortunately, this redefinition is limited only to changing method bodies — it cannot either add methods or fields or otherwise change anything else, except for the method bodies.
8. So, Here we go! Discarding classloaders java.lang.instrument Hacking changes into the JVM itself feels a fragile approach
10. Discarding classloaders can help, but Not particularly granular Instance state is lost Can run into memory problems Demo(discarding.classloaders.hotswap) by ken.wug@gmail.com
11. java.lang.instrument a JRuby object is not much more than a Map from method names to their implementations and from field names to their values. byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomainprotectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException
12. java.lang.instrument java.lang.instrument.ClassFileTransformer. This class can do two things: replace method bodies of existing classes (but nothing else, it is essentially the same as hotswap). modify classes before they get loaded into the java virtual machine class Class1 { protected static int field; }
13. java.lang.instrument class Class1{ protected static int field; public static Object __REDEFINED_STATIC_METHOD_(intmethodNo, Object[] parameters) { if(methodNo == 0) { return field; } if(methodNo == 1) { Integer p0 = (Integer)parameters[0]; int unboxedP0 = p0.intValue(); field = unboxedP0; return null; } return null; }}
14. java.lang.instrument public class Proxy1{ public void setField(intparam) { Object[] params = new Object[1]; params[0] = new Integer(param); Class1.__REDEFINED_STATIC_METHOD_(1,params); }}
15. Sounds well,but… Perfomance. subject to indirection & Pem memory Java SDK classes. The native code Compatibility. A.class.getMethods()
16. fakereplace Google Code project Usual structure changes supported Methods, fields, constructors Annotations Reflection instrumentation Integrates support directly for some frameworks
18. Jrebel(not free) one master class + several anonymous Solve problem direction and lightweight Avoids instrumenting the Java Tweaks the results of the Reflection API, so that we can correctly include the added/removed members in these results
22. hotspot and hotswap Arbitrary changes possible (including changes to subtype relationships) No performance penalty before or after the change No introduced indirections Continued execution of old active methods Only simple, comprehensible strategies for field matching or method transitions Change possible at any point when the VM is suspended Graceful handling of accesses to deleted fields or calls of deleted methods
24. Transformer Methods class A { int x; intdoubleX; static void $staticTransformer() //class transformer { System.out.println("Class A has a new version"); } void $transformer() { doubleX = 2 * x; } //instance’s }
28. Loading the New Classes step2:Sort the classes topologically. (VM_RedefineClasses::TopologicalClassSorting) Topological order.
29. Updating the Data Structures and Pointers step1:Flush dependent code . Currently all compiled methods are deoptimized (Classes::flush_dependent_code)
30. Updating the Data Structures and Pointers step2:Update constant pool cache entries. (VM_RedefineClasses::adjust_cpool_cache)
31. Updating the Data Structures and Pointers step3: Swap pointers. 利用gc的特性 ,gc 复制一个对象的后 会调整指向该对象的pointer (MarkSweep::adjust_pointer)
32. Updating the Data Structures and Pointers step4: Update instance fields. all new fields are initialized to zero.(新建) instanceKlass::do_fields_evolution(标记) MarkSweep::update_fields(拷贝)