Continuation is an object that represents the execution state of a program at a certain point. We can use continuation to restart the execution from the point stored in it.
How about continuations for the Java platform? There are atleast two different implementations of continuations:
I've experimented with javaflow. I checked out javaflow sources under, say %JAVAFLOW_HOME% directory (no pre-built binaries available in the site). I tried building it by maven. But failed ... because I need parent pom file! (never mind if you don't understand that -- that is just a build step). Because I am only interested in playing with continuation, I ignored maven build. I just created a NetBeans project and added all source directories of javaflow. I copied dependent libraries (ant.jar, commons-logging-1.0.4.jar, junit-3.8.2.bar, junit-addons-1.4.jar -- I just copied the versions that I had -- check for proper dependency or use maven to build!) under %JAVAFLOW_HOME%\lib directory and added all jars under this directory to netbeans project. I managed to build and produce javaflow.jar under %JAVAFLOW_HOME%\dist. The following is a simple program that uses continuations [this is just slightly modified version of the one in the javaflow tutorial]
import org.apache.commons.javaflow.*;
class Test {
static class MyRunnable implements Runnable {
public void run() {
System.out.println("run started!");
for( int i=0; i < 10; i++ ) {
echo(i);
}
}
private void echo(int x) {
System.out.println("echo " + x);
Continuation.suspend();
}
}
public static void main(String[] args) {
System.out.println("main started");
Continuation c = Continuation.startWith(new MyRunnable());
System.out.println("in main after continuation return");
while (c != null) {
c = Continuation.continueWith(c);
System.out.println("in main");
}
}
}
The output of the above program is shown below:
main started run started! echo 0 in main after continuation return echo 1 in main echo 2 in main echo 3 in main echo 4 in main echo 5 in main echo 6 in main echo 7 in main echo 8 in main echo 9 in main in main
The execution seems to "flip-flop" between Test.main and
Test.MyRunnable.echo methods!. No, there are no
multiple threads here. Single thread of execution produces
the output shown above. That is because of continuation. If you don't get that,
you may want to read this.
The steps used in build, run the above program:
javac -cp %JAVAFLOW_HOME%\dist\javaflow.jar Test.javaThe above step created two .class files - Test.class, Test$MyRunnable.class.
Continuation implementation works by bytecode instrumenting of the .class files of your application. Either you can instrument the program ahead of execution (during build) or do it at runtime using a special class loader. This being a simple hack exercise for learning, I instrumented these .class files using the following commands:
java -cp .;%JAVAFLOW_HOME%\dist\javaflow.jar;%JAVAFLOW_HOME%\lib\* RewriteTool <Test.class >mTest.class java -cp .;%JAVAFLOW_HOME%\dist\javaflow.jar;%JAVAFLOW_HOME%\lib\* RewriteTool <Test$MyRunnable.class >mTest$MyRunnable.class move mTest.class Test.class move mTest$MyRunnable.class Test$MyRunnable.class
Actually, there is a better way to pre-instrument .class files for continuation support: there is a javaflow ant task. (the ones that use continuations need to be instrumented. You can leave the other jar files)
java -cp .;%JAVAFLOW_HOME%\dist\javaflow.jar;%JAVAFLOW_HOME%\lib\* Test
As you may know already, JDK 6 includes javax.script API
and Mozilla Rhino based
JavaScript engine. There is continuation support in Rhino. But then, that is
a topic for another blog entry
Posted by Nico on January 20, 2007 at 12:32 AM IST #
Posted by Doug Daniels on January 20, 2007 at 03:34 AM IST #
Hi Nico: Yes, doing bytecode instrumentation at classload is interesting. javaflow has ContinuationClassLoader class for this.
Hi Doug Daniels: It is great that scripting gets attention in the Java platform. Thanks for the references on scripting with games! I'll check out these resources.
Posted by A. Sundararajan on January 20, 2007 at 11:05 AM IST #
Posted by Doug Daniels on January 21, 2007 at 12:40 AM IST #
Posted by Ranjan Bhandari on January 23, 2007 at 04:21 AM IST #
Posted by Ranjan Bhandari on January 23, 2007 at 04:22 AM IST #
Posted by Jochen "blackdrag" Theodorou on January 25, 2007 at 05:18 AM IST #
Hi Ranjan Bhandari: If continuations are implemented as API (like it is done with javaflow or RIFE) there is no change in Java programming language anyway - and therefore no bloating language. Also, if Java VM would support continuations at VM level (as VM primitive so that bytecode instrumentation is not needed), that would help implementing languages that need continuation primitive (like Scheme). Alternate languages on top of JVM is interesting by itself.
Hi Jochen "blackdrag" Theodorou": Yes you are right. We need to instrument all the classes whose methods will appear on the stack. Both javaflow and RIFE-continuations implement continuations by bytecode instrumentation. Yes, I agree - the solution is to support continuations at JVM level. But then you may want to read http://blogs.sun.com/gbracha/entry/will_continuations_continue as well.
Posted by A. Sundararajan on January 25, 2007 at 09:58 AM IST #
Posted by Jochen "blackdrag" Theodorou on January 25, 2007 at 05:38 PM IST #
Posted by A. Sundararajan on January 25, 2007 at 07:46 PM IST #