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,653
  • 10
  • 56
  • 109
  • 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) <-- it does not handle execution but does handle compilation. Execution should be easy enough to add, but you need to know the method name to execute. Also, be careful about the execution context! – 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
  • 202,709
  • 46
  • 318
  • 350
  • 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,262
  • 1
  • 17
  • 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,567
  • 3
  • 26
  • 43