Share

From this page you can share Jumping in Java to a social bookmarking site or email a link to the page.
Social WebE-mail
Enter multiple addresses on separate lines or separate them with commas.
Jumping in Java
(Your Name) has forwarded a page to you from Ajaxonomy
(Your Name) thought you would like to see this page from the Ajaxonomy web site.

Jumping in Java

Tagged:  

Anyone who has ever programmed (hopefully briefly) in some type of assembly language has gone to the bare metal in implementing loops, if statements, and other programming language features. When programming in assembly, these constructs use some form of J* jump instruction together with labels to accomplish the task. In higher-level languages, jump instructions are usually associated with the infamous and properly banned goto statements (which are unrestricted jumps), but restricted jumps are far more common: return statements, the throw keyword (for exceptions), and of course the standard loops, if statements, and the like.

Being mainly a Java programmer, I occasionally miss language features such as continuations and co-routines. I came upon just such a situation recently, and I wondered if it was possible to imitate a continuation in Java without needing to resort to more sophisticated techniques such as Javaflow or RIFE's own continuation library. What I found out was that I could, albeit in a limited way.

The use case was this: I needed to perform a certain sequence of operations in a rather linear order, but I needed to be able to pause the execution anywhere in the middle and be able to re-resume the operations exactly where I had left off. Here's an initial pass:

public void myOperations() {
     doOperation1();
     if(isPaused())
          return;
     doOperation2();
     if(isPaused())
          return;
     doOperation3();
     if(isPaused())
          return;
     doOperation4();
}

What I am doing is executing each operation, then checking to see if a paused flag has been set. If it has, I simply call return to exit the method (and return control to the calling method). But how to resume where I left off? Well, turns out there is another form of limited jumping in Java, inherited directly from C/C++: the switch statement. So here's a revised version with an implementation of re-entry:

public void myOperations() {
     doOperations(1);
}

public void reenterOperations(int phase) {
     doOperations(phase);
}

private void doOperations(int phase) 
{
     switch(phase) {
          case 1:   doOperation1();
                           if(isPaused())
                                return;
          case 2:   doOperation2();
                           if(isPaused())
                                return;
          case 3:   doOperation3();
                           if(isPaused())
                                return;
          case 4:   doOperation4();
                           if(isPaused())
                                return;
     }
}

What am I doing here? Well, I am simply jumping to the appropriate case based upon where I want to re-enter/continue. Notice here the lack of any break statement, because I am taking advantage of an odd "feature" in C/C++/Java switch statements, which is the ability to "fall through" to the next case unless the break is called. Hence, the method call reenterOperations(2) here would be the equivalent of executing this (assuming no pause):

doOperation2();
doOperation3();
doOperation4();

If I now alter the method signature to include a "context" object--a Map for holding variables (in a way similar to Commons Chain)--I can save variables into this object and re-access them when I re-enter the sequence of operations. Now all of my operations take the form:

public void doOperationXXX(Map context) { ... }

There, I've done it! It's not a real continuation or even co-routine, of course, but it's accomplished what I've wanted to do without resorting to bytecode manipulation or customized classloaders. And I've kept it relatively simple. A more sophisticated version would use an enum instead of an int, callbacks in order to set this enum value on the "visitor" or execution, plus a more flexible design using the "chain of responsibility" pattern a la Commons Chain. Which is what I am working on now...