Dropout
Dropout

Reputation: 13866

Executing Java code inside a Java program

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

Answers (3)

Carlos Cuesta
Carlos Cuesta

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

Salah
Salah

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

Jesper
Jesper

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

Related Questions