Andy Clement
2013-04-30 13:55:03 -07:00
parent 875fe2fde1
commit 29b014175a
6 changed files with 99 additions and 18 deletions

View File

@@ -0,0 +1,5 @@
package invokestatic.issue4;
public class AB extends codeforjar.A {
}

View File

@@ -0,0 +1,9 @@
package invokestatic.issue4;
public class BBBB extends codeforjar.A {
public static String getMessage() {
return getString();
}
}

View File

@@ -0,0 +1,9 @@
package invokestatic.issue4;
public class BBBBB extends AB {
public static String getMessage() {
return getString();
}
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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