#fixed 4 - NSME with inheritance and static methods

This commit is contained in:
Andy Clement
2013-04-25 15:21:28 -07:00
parent aa8ee46b86
commit 52b5278a60
8 changed files with 146 additions and 1 deletions

View File

@@ -0,0 +1,8 @@
package invokestatic.issue4;
public class A {
public static String getString() {
return "String1";
}
}

View File

@@ -0,0 +1,8 @@
package invokestatic.issue4;
public class AA {
public static String getString() {
return "String1";
}
}

View File

@@ -0,0 +1,8 @@
package invokestatic.issue4;
public class AAA {
public static String getString() {
return "String1";
}
}

View File

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

View File

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

View File

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

View File

@@ -1115,7 +1115,37 @@ public class TypeRegistry {
.getFromLatestByDescriptor(nameAndDescriptor);
boolean dispatchThroughDescriptor = false;
if (method == null) {
// method has been deleted
// method has been deleted or is on a supertype
// 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;
}
// 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;
}
} else {
m = nextCandidate.getMethod(nameAndDescriptor);
}
if (m != null) {
dispatcherToUse = reloadableType.getLatestDispatcherInstance();
found = true;
break;
}
nextCandidate = reloadableType.getTypeRegistry().getReloadableType(reloadableType.getTypeDescriptor().getSupertypeName(),false);
}
if (found) {
return dispatcherToUse;
}
throw new NoSuchMethodError(reloadableType.getBaseName() + "." + nameAndDescriptor);
} else if (IncrementalTypeDescriptor.isBrandNewMethod(method)) {
// definetly need to use the dispatcher

View File

@@ -166,6 +166,70 @@ public class ReloadableTypeTests extends SpringLoadedTests {
assertEquals(3, runOnInstance(rtype.getClazz(), instance, "getProtectedStaticField").returnValue);
}
// github issue 4
@Test
public void invokeStaticReloading_gh4_1() throws Exception {
TypeRegistry tr = getTypeRegistry("invokestatic..*");
ReloadableType A = tr.addType("invokestatic.issue4.A", loadBytesForClass("invokestatic.issue4.A"));
ReloadableType B = tr.addType("invokestatic.issue4.B", loadBytesForClass("invokestatic.issue4.B"));
Result r = runUnguarded(B.getClazz(), "getMessage");
assertEquals("String1",(String)r.returnValue);
B.loadNewVersion(B.bytesInitial);
r = runUnguarded(B.getClazz(), "getMessage");
assertEquals("String1",(String)r.returnValue);
}
@Test
public void invokeStaticReloading_gh4_2() throws Exception {
TypeRegistry tr = getTypeRegistry("invokestatic..*");
ReloadableType AA = tr.addType("invokestatic.issue4.AA", loadBytesForClass("invokestatic.issue4.AA"));
ReloadableType BB = tr.addType("invokestatic.issue4.BB", loadBytesForClass("invokestatic.issue4.BB"));
Result r = runUnguarded(BB.getClazz(), "getMessage");
assertEquals("String1",(String)r.returnValue);
BB.loadNewVersion(BB.bytesInitial);
r = runUnguarded(BB.getClazz(), "getMessage");
assertEquals("String1",(String)r.returnValue);
}
@Test
public void invokeStaticReloading_gh4_3() throws Exception {
TypeRegistry tr = getTypeRegistry("invokestatic..*");
ReloadableType AAA = tr.addType("invokestatic.issue4.AAA", loadBytesForClass("invokestatic.issue4.AAA"));
ReloadableType BBB = tr.addType("invokestatic.issue4.BBB", loadBytesForClass("invokestatic.issue4.BBB"));
Result r = runUnguarded(BBB.getClazz(), "getMessage");
assertEquals("String1",(String)r.returnValue);
AAA.loadNewVersion(AAA.bytesInitial);
r = runUnguarded(BBB.getClazz(), "getMessage");
assertEquals("String1",(String)r.returnValue);
}
@Test
public void invokeStaticReloading_gh4_4() throws Exception {
TypeRegistry tr = getTypeRegistry("invokestatic..*");
ReloadableType A = tr.addType("invokestatic.issue4.A", loadBytesForClass("invokestatic.issue4.A"));
ReloadableType B = tr.addType("invokestatic.issue4.B", loadBytesForClass("invokestatic.issue4.B"));
Result r = runUnguarded(B.getClazz(), "getMessage");
assertEquals("String1",(String)r.returnValue);
A.loadNewVersion(A.bytesInitial);
B.loadNewVersion(B.bytesInitial);
r = runUnguarded(B.getClazz(), "getMessage");
assertEquals("String1",(String)r.returnValue);
}
@Test
public void protectedFieldAccessors2() throws Exception {