From 932ad16effbd35e7c6d1b273ed6ad8c70a080228 Mon Sep 17 00:00:00 2001 From: Andy Clement Date: Fri, 1 Mar 2013 15:08:05 -0800 Subject: [PATCH] when reloading is adding new fields and new ctors in one step, the ISMgr can fail to be initialized, this fixes that. --- .../src/ctors/JR.java | 23 ++++++++++++ .../src/ctors/JR2.java | 36 +++++++++++++++++++ .../loaded/FieldReaderWriter.java | 12 +++++-- .../loaded/test/FieldReloadingTests.java | 28 ++++++++++++++- 4 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 org.springsource.loaded.testdata/src/ctors/JR.java create mode 100644 org.springsource.loaded.testdata/src/ctors/JR2.java diff --git a/org.springsource.loaded.testdata/src/ctors/JR.java b/org.springsource.loaded.testdata/src/ctors/JR.java new file mode 100644 index 0000000..faed50d --- /dev/null +++ b/org.springsource.loaded.testdata/src/ctors/JR.java @@ -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 { + } +} diff --git a/org.springsource.loaded.testdata/src/ctors/JR2.java b/org.springsource.loaded.testdata/src/ctors/JR2.java new file mode 100644 index 0000000..2b08390 --- /dev/null +++ b/org.springsource.loaded.testdata/src/ctors/JR2.java @@ -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); + } + +} diff --git a/org.springsource.loaded/src/main/java/org/springsource/loaded/FieldReaderWriter.java b/org.springsource.loaded/src/main/java/org/springsource/loaded/FieldReaderWriter.java index 7156cb5..3f16454 100644 --- a/org.springsource.loaded/src/main/java/org/springsource/loaded/FieldReaderWriter.java +++ b/org.springsource.loaded/src/main/java/org/springsource/loaded/FieldReaderWriter.java @@ -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) { diff --git a/org.springsource.loaded/src/test/java/org/springsource/loaded/test/FieldReloadingTests.java b/org.springsource.loaded/src/test/java/org/springsource/loaded/test/FieldReloadingTests.java index 10d0f95..fc7b80e 100644 --- a/org.springsource.loaded/src/test/java/org/springsource/loaded/test/FieldReloadingTests.java +++ b/org.springsource.loaded/src/test/java/org/springsource/loaded/test/FieldReloadingTests.java @@ -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); + } } \ No newline at end of file