Home

June 2008

S M T W T F S
1234567
891011121314
15161718192021
22232425262728
2930     
Powered by LiveJournal.com

Four languages - one process

The previous entry was cut slightly short because I had to head out to dinner. What I was trying to finish was a bit of code to experiment with JRuby, Jython, Rhino, and the new JSR 223 scripting framework.


My first step was to build JRuby from trunk and the Jython 2.5 branch, as well as JSR223 trunk. After a small patch, I got some code working:


package org.verbum;

import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleScriptContext;

public class LangFun {
  public static class Hello {
    public void sayHello() {
      System.out.println("Hello world!");
    }
  }
  public static void main(String[] args) throws ScriptException {
    ScriptEngineManager mgr = new ScriptEngineManager();
        
    Hello greeting = new Hello();
        
    greeting.sayHello();
      
    ScriptContext context = new SimpleScriptContext();
    context.setAttribute("greeting", greeting, ScriptContext.ENGINE_SCOPE);          
        
    ScriptEngine javaScript = mgr.getEngineByExtension("js");
    javaScript.setContext(context);
    javaScript.eval("greeting.sayHello()");
       
    ScriptEngine ruby = mgr.getEngineByExtension("rb");
    ruby.setContext(context);
    ruby.eval("$greeting.sayHello");
        
    ScriptEngine python = mgr.getEngineByExtension("py");
    python.setContext(context);
    python.eval("greeting.sayHello()");        
  }
}


To run this, you'll need to link to jruby.jar, jython.jar, rhino.jar, as well as the respective engines from JSR223: jruby-engine.jar, jython-engine.jar, js-engine.jar.
The idea behind this code is pretty simple - we first create a Java object, with a single method. Then we use the JSR223 interface to instantiate an engine for each of the languages, hook up a context object which maps the variable greeting into the global namespace for each language, then call their respective eval methods. The result is what you'd expect:


Hello world!
Hello world!
Hello world!
Hello world!

Pretty cool! Of course, I'm not really stressing the system here with these simple scripts; but given the dramatic progress (really, look at that graph!) of projects like JRuby, the future approaching very quickly.


"Ok, but...", you might say, "what's this useful for besides sharing libraries?" The general answer is that the single process, shared memory model is fundamentally more powerful than the multi-process, communicating over bytestream pipes model. You can just do more, with fewer hacks. An example is software like Reinteract - before, it could only support Python. Now, not only could you add an input language chooser to Reinteract; you could actually pass the results from a Python computation increasingly seamlessly into Groovy, Java, or whatever. Personally, I specifically want this for Hotwire. Right now we only support Python well, because the project is based on CPython.


Many new languages for the Free Software community


There was a comment on the last entry mentioning Scala. I've only looked at it very briefly. But this is just one of many languages that are now truly, finally part of the Free Software community. The Scripting project has a list of the engines written. But that list is far from complete, because some don't have the engine glue written yet, and because other languages like Scala are more designed as Java replacements that run on the JVM, rather than "scripting".


And of course through all of this, venerable Java isn't standing still - it will likely gain closures. And remember - all of this will soon be available (if it isn't already) via yum install or apt-get install, etc., all of it entirely Free Software, and increasingly integrated with the operating system and your favorite libraries.

Comments

I wonder whether it will be possible to have one uber-JVM process running as a daemon which you can IPC to run scripts in whatever language you please. I suggested rewriting fast-user-switch-applet in Python a while ago, but people downstream said they didn't want one extra Python interpreter process adding extra megabytes to the standard install footprint.
I think it definitely makes sense for the next-generation panel type thing to be one VM, with the applets in-process.

(Anonymous)

Thread focus

I always get the feeling that java pushes you towards (ab)using a threaded model for your application. I don't know if it is the language itself, its library or the JVM.

I generally prefer asynchronous APIs where you register a callback and only when you actually have to do a long running calculation fire a thread for that.

Without ever having used the java-gnome bindings I hope that they haven't gone down the "threads for everything" approach.

Still, I really hope that in the future our common runtime is the JVM (or similar) where we can use libraries written in other languages. Maybe even someday glib can go away and gtk can be implemented on a managed language, but keeping its awesome API ;-)

Re: Thread focus

Yeah, I agree; the concept of a main thread which manages all the data, with specific worker threads is much better than the free-threaded model that Java offers by default.

But this is something that a lot of languages and runtimes fail on; CPython doesn't ship one by default either.

I think it would be pretty interesting to try to get a mainloop into the Java core libraries.