This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
package invokestatic.issue4;
|
||||
|
||||
public class AB extends codeforjar.A {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package invokestatic.issue4;
|
||||
|
||||
public class BBBB extends codeforjar.A {
|
||||
|
||||
public static String getMessage() {
|
||||
return getString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package invokestatic.issue4;
|
||||
|
||||
public class BBBBB extends AB {
|
||||
|
||||
public static String getMessage() {
|
||||
return getString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1118,33 +1118,47 @@ public class TypeRegistry {
|
||||
.getFromLatestByDescriptor(nameAndDescriptor);
|
||||
boolean dispatchThroughDescriptor = false;
|
||||
if (method == null) {
|
||||
// method has been deleted or is on a supertype
|
||||
// method has been deleted or is on a supertype. Look for it:
|
||||
|
||||
// TODO this block is based on something below in invokespecial handling but this has some
|
||||
// fixes in - should they be migrated down below or a common util method constructed?
|
||||
|
||||
// Search supertypes - block copied from invokespecialSearch below, TODO could refactor into common util
|
||||
Object dispatcherToUse = null;
|
||||
ReloadableType nextCandidate = reloadableType.getTypeRegistry().getReloadableType(reloadableType.getTypeDescriptor().getSupertypeName(),false);
|
||||
boolean found = false;
|
||||
while (nextCandidate != null) {
|
||||
MethodMember m = null;
|
||||
if (nextCandidate.hasBeenReloaded()) {
|
||||
m = nextCandidate.getLiveVersion().incrementalTypeDescriptor.getFromLatestByDescriptor(nameAndDescriptor);
|
||||
if (m != null && IncrementalTypeDescriptor.wasDeleted(m)) {
|
||||
m = null;
|
||||
String supertypename = reloadableType.getTypeDescriptor().getSupertypeName();
|
||||
TypeRegistry reg = reloadableType.getTypeRegistry();
|
||||
boolean found = false;
|
||||
while (supertypename != null) {
|
||||
ReloadableType nextInHierarchy = reg.getReloadableType(supertypename);
|
||||
if (nextInHierarchy == null) {
|
||||
TypeDescriptor td = reg.getDescriptorFor(supertypename);
|
||||
if (td != null) {
|
||||
method = td.getByNameAndDescriptor(nameAndDescriptor);
|
||||
supertypename = td.getSupertypeName();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else if (nextInHierarchy.hasBeenReloaded()) {
|
||||
method = nextInHierarchy.getLiveVersion().incrementalTypeDescriptor.getFromLatestByDescriptor(nameAndDescriptor);
|
||||
if (method != null && IncrementalTypeDescriptor.wasDeleted(method)) {
|
||||
method= null;
|
||||
}
|
||||
// ignore catchers because the dynamic __execute method wont have an implementation of them, we should
|
||||
// just keep looking for the real thing
|
||||
if (m != null && MethodMember.isCatcher(m)) {
|
||||
m = null;
|
||||
if (method != null && MethodMember.isCatcher(method)) {
|
||||
method = null;
|
||||
}
|
||||
} else {
|
||||
m = nextCandidate.getMethod(nameAndDescriptor);
|
||||
}
|
||||
if (m != null) {
|
||||
dispatcherToUse = reloadableType.getLatestDispatcherInstance();
|
||||
// it is reloadable but has not been reloaded
|
||||
method = nextInHierarchy.getMethod(nameAndDescriptor);
|
||||
}
|
||||
if (method != null) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
nextCandidate = reloadableType.getTypeRegistry().getReloadableType(reloadableType.getTypeDescriptor().getSupertypeName(),false);
|
||||
// the nextInHierarchy==null case will have already set the supertypename
|
||||
if (nextInHierarchy != null) {
|
||||
supertypename = nextInHierarchy.getSlashedSupertypeName();
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
return dispatcherToUse;
|
||||
|
||||
@@ -19,6 +19,7 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springsource.loaded.GlobalConfiguration;
|
||||
@@ -229,6 +230,48 @@ public class ReloadableTypeTests extends SpringLoadedTests {
|
||||
r = runUnguarded(B.getClazz(), "getMessage");
|
||||
assertEquals("String1",(String)r.returnValue);
|
||||
}
|
||||
|
||||
// The supertype is not reloadable,it is in a jar
|
||||
@Test
|
||||
public void invokeStaticReloading_gh4_5() throws Exception {
|
||||
TypeRegistry tr = getTypeRegistry("invokestatic.issue4..*");
|
||||
ReloadableType B = tr.addType("invokestatic.issue4.BBBB", loadBytesForClass("invokestatic.issue4.BBBB"));
|
||||
|
||||
Result r = runUnguarded(B.getClazz(), "getMessage");
|
||||
assertEquals("Hello",(String)r.returnValue);
|
||||
|
||||
ReloadableType thesuper = B.getSuperRtype();
|
||||
assertNull(thesuper);
|
||||
thesuper = tr.getReloadableType("invokestatic/issue4/subpkg/AAAA");
|
||||
assertNull(thesuper);
|
||||
|
||||
B.loadNewVersion(B.bytesInitial);
|
||||
|
||||
r = runUnguarded(B.getClazz(), "getMessage");
|
||||
assertEquals("Hello",(String)r.returnValue);
|
||||
}
|
||||
|
||||
// extra class in the middle: A in jar, subtype AB reloadable, subtype BBBBB reloadable
|
||||
@Test
|
||||
public void invokeStaticReloading_gh4_6() throws Exception {
|
||||
TypeRegistry tr = getTypeRegistry("invokestatic.issue4..*");
|
||||
ReloadableType AB = tr.addType("invokestatic.issue4.AB", loadBytesForClass("invokestatic.issue4.AB"));
|
||||
ReloadableType B = tr.addType("invokestatic.issue4.BBBBB", loadBytesForClass("invokestatic.issue4.BBBBB"));
|
||||
|
||||
Result r = runUnguarded(B.getClazz(), "getMessage");
|
||||
assertEquals("Hello",(String)r.returnValue);
|
||||
|
||||
ReloadableType thesuper = B.getSuperRtype();
|
||||
System.out.println(thesuper);
|
||||
assertNull(thesuper);
|
||||
thesuper = tr.getReloadableType("invokestatic/issue4/subpkg/AAAA");
|
||||
assertNull(thesuper);
|
||||
|
||||
B.loadNewVersion(B.bytesInitial);
|
||||
|
||||
r = runUnguarded(B.getClazz(), "getMessage");
|
||||
assertEquals("Hello",(String)r.returnValue);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
|
||||
@@ -89,6 +89,7 @@ public abstract class SpringLoadedTests implements Constants {
|
||||
protected String TestDataPath = "../org.springsource.loaded.testdata/bin";
|
||||
protected String GroovyTestDataPath = "../org.springsource.loaded.testdata.groovy/bin";
|
||||
protected String AspectjrtJar = "../org.springsource.loaded.testdata/aspectjrt.jar";
|
||||
protected String CodeJar = "../org.springsource.loaded.testdata/code.jar";
|
||||
protected String GroovyrtJar = "../org.springsource.loaded.testdata.groovy/groovy-1.8.2.jar";
|
||||
protected Result result;
|
||||
protected TypeRegistry registry;
|
||||
@@ -97,7 +98,7 @@ public abstract class SpringLoadedTests implements Constants {
|
||||
public void setup() throws Exception {
|
||||
SpringLoadedPreProcessor.disabled = true;
|
||||
NameRegistry.reset();
|
||||
binLoader = new TestClassLoader(toURLs(TestDataPath, AspectjrtJar), this.getClass().getClassLoader());
|
||||
binLoader = new TestClassLoader(toURLs(TestDataPath, AspectjrtJar,CodeJar), this.getClass().getClassLoader());
|
||||
}
|
||||
|
||||
@After
|
||||
|
||||
Reference in New Issue
Block a user