When debugging the following code:
public class MyProxy {
public static void main(String[] args){
Consumer f = (Consumer) Proxy.newProxyInstance(
Consumer.class.getClassLoader(),
new Class[] { Consumer.class },
new Handler(new ConsumerImpl())
);
f.consume("Hello"); // set breakpoint here
System.out.println("done");
}
}
interface Consumer {
void consume(String s);
}
class ConsumerImpl implements Consumer {
public void consume(String s) {
System.out.println(s);
}
}
class Handler implements InvocationHandler {
private final Consumer original;
public Handler(Consumer original) {
this.original = original;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
System.out.println("BEFORE");
method.invoke(original, args);
System.out.println("AFTER");
return null;
}
}
The output is :
BEFORE
AFTER
BEFORE
AFTER
BEFORE
BEFORE
AFTER
Hello
BEFORE
AFTER
AFTER
BEFORE
AFTER
BEFORE
AFTER
BEFORE
AFTER
BEFORE
AFTER
done
BEFORE
AFTER
When the debugger pause at the breakpoint line, the output already have two lines, as I step into the invoke
method, the output is like shown. It's like the debugger is entering the invoke
method every step I make. Because if I don't step into the method, the output is :
BEFORE
AFTER
BEFORE
Hello
AFTER
BEFORE
AFTER
done
BEFORE
AFTER
If I run the code, output is as expected.
BEFORE
Hello
AFTER
done
Is it a bug of debugger or I do something wrong?
Env: Windows 64, Intellij IDEA, JDK8
It is not a bug in IDEA. if you try to debug this without any breakpoints you may get the same result as you expected. But if you put some breakpoint, IDEA will try to call the toString() method , then hashCode() method of the variables that it can evaluate.
ultimately for all methods , it will call your InvocationHandler implementation (not only for the "consume" method, you can print the method.getName() to make sure this in the invocation handler implementation).