This is documentation for Mathematica 5, which was
based on an earlier version of the Wolfram Language.
View current documentation (Version 11.2)

Documentation / Mathematica / Add-ons & Links / J/Link / Part 2. Writing Java Programs That Use Mathematica /

2.11 Aborting and Interrupting Computations

J/Link provides two ways in which you can interrupt or abort computations. The first technique uses the low-level putMessage() function to send the desired MathLink message. The second and preferred technique is to use a new set of KernelLink methods introduced in J/Link 2.0. These are listed below.

void abortEvaluation();

void interruptEvaluation()    

void abandonEvaluation();

void terminateKernel();

The abortEvaluation() method will send an abort request to Mathematica, identical to what happens in the notebook front end when you select the Kernel/Abort Evaluation menu command. Mathematica responds to this command by terminating the current evaluation and returning the symbol $Aborted. Be aware that sometimes the kernel is in a state where it cannot respond immediately to interrupts or aborts.

The interruptEvaluation() method will send an interrupt request to Mathematica, identical to what happens in the notebook front end when you select the Kernel/Interrupt Evaluation menu command. Mathematica responds to this command by interrupting the current evaluation and sending back a special packet that contains choices for what to do next. The choices can depend on what the kernel is doing at the moment, but in most cases they include aborting, continuing, or entering a dialog. It is not likely that you will want to have to deal with this list of choices on your own, so you might choose instead to call abortEvaluation() and just stop the computation. If you are developing an interactive front end, however, you might decide that you want your users to see the same types of choices that the notebook front end provides. If this is the case, then you can use the new InterruptDialog class, which provides a dialog box very similar to the front end's "Interrupt Evaluation" dialog. The InterruptDialog class is discussed in a later section.

The abandonEvaluation() method does exactly what its name suggests—it causes any command that is currently waiting for something to arrive on the link to back out immediately and throw a MathLinkException. This MathLinkException is recoverable (meaning that clearError() will return true), so in theory you could call waitForAnswer() again later and get the result when it arrives. In practice, however, you should generally not use this method unless you plan to close the link. You should think of abandonEvaluation() method is an "emergency exit" function that lets your program back out of waiting for a result no matter what state the kernel is in. Remember that the abortEvaluation() method simply sends an abort request to Mathematica, and thus it requires some cooperation from the kernel; there is no guarantee that the current evaluation will abort in a timely manner, if ever. If you call close() right after abandonEvaluation(), the kernel will typically not die, because it is still busy with a computation. You should call terminateKernel() before close() to ensure that the kernel shuts down. A code fragment below demonstrates this.

The terminateKernel() method will send a terminate request to Mathematica. It does this by sending the low-level MathLink message MLTERMINATEMESSAGE. This is the strongest step you can take to tell the kernel to shut down, short of killing the kernel process with operating system commands. In "normal" operation of the kernel, when you call close() on the link, the kernel will quit. In some cases, however, generally only if the kernel is currently busy computing, it will not quit. In such cases you can generally force the kernel to quit immediately by calling terminateKernel(). You should always call close() immediately afterward. In a server environment, where a Java program that starts and stops Mathematica kernels needs to run unattended for a very long period of time with the highest reliability possible, you might consider always calling terminateKernel() before close(), if there is any chance that close() needs to be called while the kernel is still busy. In some rare circumstances (generally only if something has gone wrong with Mathematica), even calling terminateKernel() will not force the kernel to quit, and you might need to use facilities of your operating system (perhaps invoked via Java's Runtime.exec() method) to kill the kernel process.

If you want to be able to abort, interrupt, or abandon computations, your program will need to have at least two threads. The thread on which the computation is called will probably look like all the sample programs we have seen. You would call one of the "evaluateTo" methods, or perhaps evaluate() followed by waitForAnswer(). This thread will block, waiting for the result. On a separate thread, such as the user interface thread, you could periodically check for some event, like a time out period elapsing. Or, you could use an event listener to be notified when the EscapeKey key was pressed. Whichever way you want to detect the abort request, all you need to do is call putMessage(MathLink.MLABORTMESSAGE). If the kernel receives the message before it finishes, and it is doing something that can be aborted, the computation will end and return the symbol $Aborted. You typically will not need to do anything special in the computation thread. You wait for the answer as usual; it might come back as $Aborted instead of the final result, that's all. Here are some typical code fragments that demonstrate aborting a computation:

// On thread 1

ml.evaluate("Do[2+2, {20000000}]");

ml.waitForAnswer();

// If user aborted, the result will be the symbol $Aborted.

    

// On thread 2

if (userPressedEscKey() || timeoutElapsed())

    ml.abortEvaluation();

Here is some code that demonstrates how to abandon a computation and force an immediate shutdown of the kernel:

// On thread 1

try {

    ml.evaluate("While[True]");

    ml.discardAnswer();

} catch (MathLinkException e) {

    // We will get here when abandonEvaluation() is called on the other thread.

    System.err.println("MathLinkException occurred: " + e.toString());

    if (!ml.clearError()) {

        // clearError() will always fail when abandonEvaluation() was called.

        ml.terminateKernel();

        ml.close();

    }

}

    

// On thread 2

if (timeoutElapsedAndReallyNeedToShutdownKernel())

    ml.abandonEvaluation();

The discussion so far has focused on the high-level interface for interrupting and aborting computations. The alternative is to use the low-level method putMessage() and pass one of the constants MathLink.MLINTERRUPTMESSAGE, MathLink.MLABORTMESSAGE, or MathLink.MLTERMINATEMESSAGE. There is no reason to do this, however, as interruptEvaluation(), abortEvaluation(), and terminateKernel() are just one-line methods that put the appropriate message. Use these higher-level methods unless you are concerned about compatibility with versions of J/Link prior to 2.0. The "messages" referred to in the MathLink methods putMessage(), messageReady(), and getMessage() are not related to the familiar Mathematica error and warning messages. Instead, they are a special type of communication between two MathLink programs. This communication takes place on a different channel from the normal flow of expressions, which is why you can call putMessage() while the kernel is in the middle of a computation and not reading from the link.

There are several other MathLink methods with "message" in their names. These are messageReady(), getMessage(), addMessageHandler(), and removeMessageHandler(). These methods are only useful if you want to be able to detect messages the kernel sends to you. J/Link programmers will rarely want to do this, so we will not discuss them in detail. Please note that messageReady() and getMessage() no longer work in J/Link 2.0. If you want to be able to receive messages from Mathematica, you must use addMessageHandler() and removeMessageHandler(). There is more information in the JavaDocs for these methods.