Reputation: 13866
I would like to create an application which for example measures the execution time of a certain block of code. In this case it should have a structure like this:
public static long measureExecution(String code){
long start = System.nanoTime();
executeCode(code); // <----
long time = System.nanoTime() - start;
return time;
}
I'm curious about the method designated by the arrow, I need some sort of a placeholder. How should be this method implemented? Is it even possible to execute a custom Java code inside running Java application?
I was thinking that it can be done with some sort of overriding of another methods body, but I can't quite figure out how.
Thanks for your opinions!
Upvotes: 6
Views: 2577
Reputation: 1494
You can use OpenHFT/Java-Runtime-Compiler:
https://github.com/OpenHFT/Java-Runtime-Compiler
Also, you can use ToolProvider class (Compiler API), since java 1.6:
private Path compileJavaFile(Path javaFile, String className) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
compiler.run(null, null, null, javaFile.toFile().getAbsolutePath());
return javaFile.getParent().resolve(className);
}
Upvotes: 2
Reputation: 8657
You could use a Dynamic Proxy
to wrap your methods invocation, here an example:
First you need to create InvocationHandler
class:
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("About to invoke " + method + "\n with argument " + args);
Object rv = method.invoke(target, args);
System.out.println(" Call returned " + rv);// here you could print the time instead
return rv;
}
}
Then Create a factory to get you object and Wrap it with the previous created proxy.
public class MyFactory {
public static MyInterface getMyInterface() {
MyInterface mc = new MyClass();
InvocationHandler h = new MyInvocationHandler(mc);
MyInterface mi = (MyInterface) Proxy.newProxyInstance(MyInterface.class.getClassLoader(),
new Class[] { MyInterface.class }, h);
return mi;
}
}
Hope that help you.
Upvotes: 0
Reputation: 207006
You could pass a Runnable
:
public static long measureExecution(Runnable code) {
long start = System.nanoTime();
code.run();
long time = System.nanoTime() - start;
return time;
}
At the place where you call the method, use an anonymous inner class to wrap the code you want to measure:
long time = measureExecution(new Runnable() {
@Override
public void run() {
System.out.println("Do something");
}
});
(If you were using Java 8, you could use a lambda expression instead of an anonymous inner class, which would make the code shorter and easier to read).
Upvotes: 4