I need to capture a method call in Java and I do not want to use JPDA or JDI; I want it to happen in the original JVM.
For instance:
public class A {
public void m() {}
}
public class Main {
public static void main(String[] args) {
A a = new A();
a.m();
}
}
I do not want to actually let the method execute at the time, but need to capture it and schedule it in a queue. Thus, AOP will not help me in this regard. I thought about proxying the method. Something such as:
public class A {
public void m() {
methodQueue.add(new MethodInvocation() {
public void invoke() {m_orig();}
});
}
private void m_orig(){}
}
Any ideas? Thanks so much in advance.
You can use a technique called Dynamic Proxies in Java. They are described in detail in the following document: Dynamic Proxies
The solution for your problem would then be (with little changes necessary):
public interface A { void m(); }
public class AImpl implements A { public void m() {} }
public class EnqueueProxy implements java.lang.reflect.InvocationHandler {
private Object obj;
public static Object newInstance(Object obj) {
return java.lang.reflect.Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new EnqueueProxy(obj));
}
private EnqueueProxy(Object obj) {
this.obj = obj;
}
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
try {
MethodQueue mq = ... // get the queue from where you want
mq.add(new MethodInvocation(obj, m, args)
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
}
return null;
}
}
Then construct a EnqueueProxy for an implementation of the A interface and call the m method:
A a = (A) EnqueueProxy.newInstance(new AImpl());
a.m();
Looks like you would also be happy with a queue of Callables.