Взгляните на эту странную проблему:
- У меня есть точка останова при любом доступе к полю
res1
- Res1 isприсвоено значение f, которое равно "bar"
- Res1 теперь равно "bar"
- На следующем перерыве res1 внезапно
null
Почемуэто невозможно?
- Из-за точки останова на res1 я вижу, что она вообще не должна была измениться
- И не могла, потому что я явно неизмените его между присваиванием и
assertEquals
, и этот код выполняется в одном потоке JUnit. - Нет других полей или переменных с именем
res1
.
Что можетбыть на ногах?Я предполагаю, что это не ошибка в JVM, но кто знает.
Как сказал Джон Скит, проблема в том, что экземпляры разные.Это вызвано странной проблемой отражения:
public class ServiceObject {
private static final Map<Class<?>, Map<String, Operation>> opsByClass =
new ConcurrentHashMap<Class<?>, Map<String,Operation>>();
private final Object target;
private final Map<String, Operation> myClassOps;
private class Operation {
private final Method method;
public Operation(Method met) {
this.method = met;
method.setAccessible(true);
}
public void execute(Map<String,?> args, Responder responder, Object context, boolean coerce) {
...
method.invoke(target, mArgs);
}
}
public ServiceObject(Object target) {
Class<?> myClass = target.getClass();
Map<String, Operation> op = opsByClass.get(myClass);
if (op == null) {
op = new HashMap<String, Operation>();
for (Method meth : myClass.getMethods()) {
...
op.put(opName, new Operation(meth));
}
opsByClass.put(myClass, op);
}
this.target = target;
this.myClassOps = op;
}
public void execute(String opName) {
Operation op = myClassOps.get(opName);
...
op.execute(args, responder, context, coerce);
}
}
// Foo is equivalent to the class that contains <res1> above
class Foo {
@ServiceOperation
public void bar() {
// breakpoint here
}
}
Что происходит при выполнении тестов:
a = new Foo();
b = new Foo();
svc = new ServiceObject(a);
svc.execute("bar", ...); // inside Foo.bar() <this> will be <a>
svc = new ServiceObject(b);
svc.execute("bar", ...); // inside Foo.bar() <this> will still be <a>, but should be <b>