ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

The Mustang Meets the Rhino: Scripting in Java 6
Pages: 1, 2, 3, 4

Compilable and Invocable Engines

Some script engine implementations support script compilation, which allows considerable performance gains. Scripts can be compiled and reused, rather than being interpreted at each execution. The compile() method returns a CompiledScript instance, which can then be used to evaluate the compiled expression via the eval() method:

        ScriptEngineManager manager
                 = new ScriptEngineManager();
        ScriptEngine engine
                 = manager.getEngineByName("js");
        Compilable compilable
                 = (Compilable) engine;

        CompiledScript script
            = compilable.compile(
                 "if (age < 25){ " +
                 "    riskFactor = 1.5;" +
                 "} else if (noClaims) {" +
                 "    riskFactor = 0.75;" +
                 "} else {" +
                 "    riskFactor = 1.0;" +

        Bindings bindings
            = engine.createBindings();
        bindings.put("age", 26);
        bindings.put("noClaims", Boolean.TRUE);
        bindings.put("riskFactor", 1);

The equivalent Java code would be something along the following lines:

    public double calculateRiskFactor(int age, boolean noClaims) {
        double riskFactor;
        if (age < 25) {
            riskFactor = 1.5;
        } else if (noClaims) {
            riskFactor = 0.75;
        } else {
            riskFactor = 1.0;
        return riskFactor;

How much is to be gained by script compilation is something you need to evaluate and benchmark in each particular circumstance. Some simple benchmarks using the script illustrated here show performance gains of around 60%. In general, the more complex the script, the more you can expect to gain from compilation. Just as a rough test, I ran the above script 10,000 times, along with the equivalent Java code shown above. I obtained the following cumulative results:

Interpreted JS: 1,550ms
Compiled JS: 579ms
Compiled Java: 0.0172ms

So, the compiled JavaScript ran roughly three times faster than the interpreted JavaScript. The interpreted code took an average of 15ms to run, whereas the compiled code averaged at about 6ms. Of course, as would be expected, real compiled Java code is roughly 100,000 times faster than the interpreted JavaScript. However, as mentioned above, the advantages of scripting languages to be found elsewhere.

The Invocable interface lets you call individual functions defined in the script from your Java code. The invoke() method takes the name of the function to be invoked, and an array of parameters, and returns the result of the call.

        ScriptEngineManager manager
            = new ScriptEngineManager();
        ScriptEngine engine
            = manager.getEngineByName("js");
          "function increment(i) {return i + 1;}");
        Invocable invocable = (Invocable) engine;
        Object result
            = invocable.invoke("increment",
                               new Object[] {10});
        System.out.print("result = " + result);
    > result = 11

This approach allows libraries to be written and maintained in JavaScript (or in some other scripting language), and called from a Java application. In business, it is important to be able to quickly update pricing policies that are subject to market pressures. An insurance company, for example, might want actuaries to be able to directly design and maintain insurance policies and premium calculation algorithms using an easy scripting language, which could then be invoked from within a larger J2EE enterprise architecture. Such an architecture might include an online quoting system, an extranet application for insurance brokers, as well as back-office business applications, all invoking the same centralized scripts.

Pages: 1, 2, 3, 4

Next Pagearrow