6

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!

Dropout
  • 13,107
  • 9
  • 51
  • 105
  • inb4 javaception; Please don't beat me if the question has been asked, I was looking - couldn't find it. – Dropout Feb 18 '14 at 09:19
  • 1
    Have a look at [AOP](http://en.wikipedia.org/wiki/Aspect-oriented_programming) – Nandkumar Tekale Feb 18 '14 at 09:19
  • Thanks @NandkumarTekale, I'm just reading through it. – Dropout Feb 18 '14 at 09:22
  • Have a look [here](https://github.com/fge/json-schema-processor-examples/tree/master/src/main/java/com/github/fge/compiler) – fge Feb 18 '14 at 09:22
  • 1
    What is the content of `code`? Is it the name of a method or is it actual java source code in the form of a string? – Jeroen Vannevel Feb 18 '14 at 09:23
  • @JeroenVannevel it should be an input from the user. Imagine it as a *textarea* on a page where user can insert his code and the press *execute* :) – Dropout Feb 18 '14 at 09:25
  • 1
    maybe this help you http://www.accordess.com/wpblog/an-overview-of-java-compilation-api-jsr-199/ – karci10 Feb 18 '14 at 09:58
  • 1
    accurate benchmarking is a complex task. Start with an existing library like http://openjdk.java.net/projects/code-tools/jmh/ – Alexei Kaigorodov Feb 18 '14 at 10:07
  • @AlexeiKaigorodov the question is not about benchmarking or execution time, that was just an example. Thanks for the info though! – Dropout Feb 18 '14 at 10:20
  • Likely duplicate of http://stackoverflow.com/questions/588242/how-could-i-call-java-code-dynamically – Barett Mar 28 '14 at 21:23

3 Answers3

4

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).

Jesper
  • 195,030
  • 44
  • 313
  • 345
  • Thanks! Is it possible to do this at runtime? To input the code, compile it and pass it as runnable? – Dropout Feb 18 '14 at 09:24
  • 2
    You mean, someone gives your program some source code, and you want your program to compile and run it? For compiling you'd need to use the [compiler API](http://docs.oracle.com/javase/6/docs/api/javax/tools/JavaCompiler.html) and then you'd need to load the compiled class dynamically and call it using reflection. – Jesper Feb 18 '14 at 09:26
  • Yes exactly. As I wrote in the main comments:"Imagine it as a textarea on a page where user can insert his code and the press execute". Would it work with in the way you specified, please? – Dropout Feb 18 '14 at 09:29
  • Yes, as I said you'd need to use the compiler API and reflection. – Jesper Feb 18 '14 at 10:00
  • 1
    Thanks a lot! I've managed to get it working. Also @Karci10 provided an tutorial, which demonstrates it in a similar way http://www.accordess.com/wpblog/an-overview-of-java-compilation-api-jsr-199/ – Dropout Feb 18 '14 at 10:21
  • Good answer, upvoting. Note this will include timing of some extra thread startup costs. Not a huge deal (a) if you're just comparing times or (b) if there's a lot in `run()` – Barett Mar 28 '14 at 21:19
  • @Barett No separate threads are involved here. The `run` method of `Runnable` is called directly, the code in the `Runnable` is not executed in a separate thread. – Jesper Mar 30 '14 at 08:39
2

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);
}
Carlos Cuesta
  • 1,032
  • 1
  • 15
  • 20
0

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.

Salah
  • 8,304
  • 3
  • 24
  • 41