#fixed 4 - NSME with inheritance and static methods
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
package invokestatic.issue4;
|
||||
|
||||
public class A {
|
||||
|
||||
public static String getString() {
|
||||
return "String1";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package invokestatic.issue4;
|
||||
|
||||
public class AA {
|
||||
|
||||
public static String getString() {
|
||||
return "String1";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package invokestatic.issue4;
|
||||
|
||||
public class AAA {
|
||||
|
||||
public static String getString() {
|
||||
return "String1";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package invokestatic.issue4;
|
||||
|
||||
public class B extends A {
|
||||
|
||||
public static String getMessage() {
|
||||
return getString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package invokestatic.issue4;
|
||||
|
||||
public class BB extends AA {
|
||||
|
||||
public static String getMessage() {
|
||||
return BB.getString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package invokestatic.issue4;
|
||||
|
||||
public class BBB extends AAA {
|
||||
|
||||
public static String getMessage() {
|
||||
return AAA.getString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user