when reloading is adding new fields and new ctors in one step, the ISMgr can fail to be initialized, this fixes that.

This commit is contained in:
Andy Clement
2013-03-01 15:08:05 -08:00
parent 0c40cbfd66
commit 932ad16eff
4 changed files with 96 additions and 3 deletions

View File

@@ -0,0 +1,23 @@
package ctors;
public class JR {
public JR(int i) {
}
public static String printMessage() {
return "hello";
}
public static JR getInstance() {
return new JR(42);
}
public Object getFieldReflectively() throws Exception {
return null;
}
public void setFieldReflectively(int value) throws Exception {
}
}

View File

@@ -0,0 +1,36 @@
package ctors;
import java.lang.reflect.Field;
public class JR2 {
int field = 34;
public JR2(int i) {
}
public JR2() {
}
public static String printMessage() {
return "goodbye";
}
public static JR2 getInstance() {
return new JR2();
}
public Object getFieldReflectively() throws Exception {
Field f = this.getClass().getDeclaredField("field");
return f.get(this);
}
public void setFieldReflectively(int value) throws Exception {
Field f = this.getClass().getDeclaredField("field");
f.setAccessible(true);
f.set(this,value);
}
}

View File

@@ -363,8 +363,16 @@ public class FieldReaderWriter {
}
ISMgr stateManager = (ISMgr) fieldAccessorField.get(instance);
if (stateManager == null) {
throw new IllegalStateException("The class '" + clazz.getName()
+ "' has a null instance state manager object, instance is " + instance);
// Looks to not have been initialized yet, this can happen if a non standard ctor was used.
// We could push this step into the generated ctors...
ISMgr instanceStateManager = new ISMgr(instance, typeDescriptor.getReloadableType());
fieldAccessorField.set(instance,instanceStateManager);
stateManager = (ISMgr) fieldAccessorField.get(instance);
// For some reason it didn't stick!
if (stateManager == null) {
throw new IllegalStateException("The class '" + clazz.getName()
+ "' has a null instance state manager object, instance is " + instance);
}
}
return stateManager;
} catch (Exception e) {

View File

@@ -64,7 +64,7 @@ public class FieldReloadingTests extends SpringLoadedTests {
assertEquals(45, runOnInstance(addClazz, addInstance, "getValue").returnValue);
assertEquals(45, add.getField(addInstance, "i", false));
}
// Variant of the first test but uses a new instance after reloading
@Test
public void newFieldAddedInstance() throws Exception {
@@ -950,4 +950,30 @@ public class FieldReloadingTests extends SpringLoadedTests {
assertEquals((byte) 255, runOnInstance(clazz, rInstance, "getByte").returnValue);
assertEquals((byte) 255, type.getField(rInstance, "b", false));
}
@Test
public void ctorReloadWithNewField() throws Exception {
String y = "ctors.JR";
TypeRegistry tr = getTypeRegistry(y);
ReloadableType rtype = tr.addType(y, loadBytesForClass(y));
Class<?> clazz = rtype.getClazz();
Object instance = runStaticUnguarded(clazz, "getInstance").returnValue;
assertEquals("hello", runOnInstance(clazz, instance, "printMessage").returnValue);
rtype.loadNewVersion("2", retrieveRename(y, y + "2"));
assertEquals("goodbye", runOnInstance(clazz, instance, "printMessage").returnValue);
Object instance2 = runStaticUnguarded(clazz,"getInstance").returnValue;
Object ret = runOnInstance(clazz,instance2,"getFieldReflectively").returnValue;
assertEquals(34,ret);
ret = runOnInstance(clazz,instance2,"setFieldReflectively",99).returnValue;
ret = runOnInstance(clazz,instance2,"getFieldReflectively").returnValue;
assertEquals(99,ret);
}
}