hotspot & hotswap who and who are best friends
why we need hotswap ?• 主管 : 你在偷懒?• 汇编开发人员:我在编译。• C++ 开发人员 : 我在编译打包部署。• java 开发人员: 我在打包部署。• Jsp 开发人员:我在部署。• Python 开发人员 :………• Ruby 开发人员 :………
why we need hotswap?
• 线上紧急修改。 ( 方法体的修改、增加和减少方法 , 字段,类,接口,更改类继承拓扑结构 )
JVM 1.2 以后支持了 hotswap 功能
• JVMTM Tool Interfacetypedef struct { jclass klass; jint class_byte_count; const unsigned char* class_bytes;} jvmtiClassDefinition;jvmtiErrorRedefineClasses(jvmtiEnv* env, jint class_count, const jvmtiClassDefinition* class_definitions)
JVM 1.2 以后支持了 hotswap 功能
• JavaTM Virtual Machine Debug Interface Referencetypedef struct { jclass clazz; /* Class to be redefined */ jint class_byte_count; /* number of bytes defining class
(below) */ jbyte *class_bytes; /* bytes defining class */ /* (in Class File Format of JVM spec) */} JVMDI_class_definition; jvmdiErrorRedefineClasses(jint classCount, JVMDI_class_definition *classDefs)
Java dev 除打包部署外还干嘛?• 用 IDE(eclipse) 调试
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.
So, Here we go!
• Discarding classloaders
• java.lang.instrument
• Hacking changes into the JVM itself feels a fragile approach
Discarding classloaders
Discarding classloaders can help, but
• Not particularly granular• Instance state is lost• Can run into memory problems• Demo(discarding.classloaders.hotswap) by [email protected]
java.lang.instrument
1. a JRuby object is not much more than a Map from method names to their implementations and from field names to their values.
2. byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException
java.lang.instrument
java.lang.instrument.ClassFileTransformer. This class can do two things:1. replace method bodies of existing classes (but nothing else, it is
essentially the same as hotswap).2. modify classes before they get loaded into the java virtual machine
class Class1{
protected static int field;}
java.lang.instrument• class Class1
{ protected static int field; public static Object __REDEFINED_STATIC_METHOD_(int methodNo, 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; }}
java.lang.instrument
public class Proxy1{ public void setField(int param) { Object[] params = new Object[1]; params[0] = new Integer(param); Class1.__REDEFINED_STATIC_METHOD_(1,params); }}
Sounds well,but…
• Perfomance. subject to indirection & Pem memory
• Java SDK classes. The native code
• Compatibility. A.class.getMethods()
fakereplace
• Google Code project• Usual structure changes supported
1. Methods, fields, constructors2. Annotations
• Reflection instrumentation• Integrates support directly for some
frameworks
Fakereplace demo
Jrebel ( not free )one master class + several anonymous Solve problem1. direction and lightweight2. Avoids instrumenting the Java3. Tweaks the results of the Reflection API, so that we can
correctly include the added/removed members in these results
Jrebel Demo
Sounds perfect
国家队( nation team )• Hotswap.patch
hotspot and hotswap
1. Arbitrary changes possible (including changes to subtype relationships)
2. No performance penalty before or after the change3. No introduced indirections4. Continued execution of old active methods5. Only simple, comprehensible strategies for field
matching or method transitions6. Change possible at any point when the VM is suspended7. Graceful handling of accesses to deleted fields or calls of
deleted methods
Hotswap StatusType of Change Supported? Possible problems after
resumeSwap Method Body yes
Add Method yes
Remove Method yes NoSuchMethodError / none in advanced version
Add Field yes
Remove Field yes NoSuchFieldError / none for static fields in advanced version
Add Supertype yesRemove Supertype no / yes in advanced
versionnone, but not always guaranteed to be possible
Transformer Methods
class A
{
int x;
int doubleX;
static void $staticTransformer() //class transformer
{
System.out.println("Class A has a new version");
}
void $transformer() { doubleX = 2 * x; } //instance’s
}
Hotswap.patch demo
Hotswap.patch Algorithm
Loading the New Classes
Updating the Data Structures and Pointers
Loading the New Classes
step1:Find all affected classes. (VM_RedefineClasses::FindAffectedKlassesClosure)
Redefining D and B Find all affected classes
Loading the New Classes
step2:Sort the classes topologically. (VM_RedefineClasses::TopologicalClassSorting)
Topological order.
Updating the Data Structures and Pointers
• step1:Flush dependent code .Currently all compiled methods are deoptimized (Classes::flush_dependent_code)
Updating the Data Structures and Pointers
• step2:Update constant pool cache entries. (VM_RedefineClasses::adjust_cpool_cache)
Updating the Data Structures and Pointers
• step3: Swap pointers.利用 gc 的特性 ,gc 复制一个对象的后 会调整指向该
对象的 pointer (MarkSweep::adjust_pointer)
Updating the Data Structures and Pointers
• step4: Update instance fields.
I. all new fields are initialized to zero. (新建)
II. instanceKlass::do_fields_evolution( 标记 )III. MarkSweep::update_fields( 拷贝 )
Fantastic,but…
Question time
Party time