In my spare time I have been working on fakereplace, a project that aims to provide more fine grained hot deployment in java that what is currently availible.
Currently hot deployment of code changes is done one of two ways, either by discarding the applications ClassLoader(s) and reloading the application, or by using JVM HotSwap.
Discarding the ClassLoader and then re-loading all application classes works quite well for small projects, however for large applications it is often not as effective. For bigger projects the time spent initialising the application is often much greater than the amount of time the application server takes to load, so the time saving is quite small. Discarding the old application can also result in significant garbage collection overhead, so in some cases a hot deployment can actually be slower than an application server restart.
HotSwap on the other hand works pretty much instantly, however it is quite limited in the changes it can make. It does not allow changes to the schema of the class, only the bytecode in method bodies. This can be quite a time saver in some situations, however it is certainly not a complete solution.
Fakereplace utilises a different approach, it works by transforming the bytecode of classes as they are loaded into the JVM in order to make them hot reloadable, and then it uses the java.lang.instrument api to hot swap the classes (this API allows you to redefine classes at runtime, with the same limitations at HotSwap). The modified classes are recompiled to that they appear to have been hot redeployed, even though the class schema has not changed.
Currently Fakereplace works with Jboss Seam 2.x, and is under heavy development. If you want to try it out it can be found here. If you would like to learn more about how it works, read on.
class Class1 { protected static int field; }
class Class1 { protected static int field; public static int getField() { return field; } public static void setField(int val) { field = val; } }
class Class1 { protected static int field; public static Object __REDEFINED_STATIC_METHOD_(int methodNo, Object[] parameters) { return null; } }
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; } }
public class FakeObject1 { public void setField(int param) { Object[] params = new Object[1]; params[0] = new Integer(param); Class1.__REDEFINED_STATIC_METHOD_(1,params); } }
Class.getMethods()
ReflectionDelegate.getMethods(Class clazz);
Comments