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.9 Handling MathLinkExceptions

Most of the MathLink and KernelLink methods throw a MathLinkException if a MathLink error occurs. This is in contrast to the MathLink C API, where functions return an error code. The methods that do not throw a MathLinkException are generally ones that will often need to be used within a catch block handling a MathLinkException that had already been thrown. If these methods threw their own exceptions, then you would need to nest another try/catch block within the catch block.

A well-formed J/Link program will typically not throw any MathLinkExceptions except in the case of fatal MathLink errors, such as the kernel unexpectedly quitting. What is meant by "well-formed" is that you do not make any overt mistakes when putting or getting expressions, such as specifying an argument count of three in a putFunction() call but only sending two, or calling nextPacket() before you have finished reading the contents of the current packet. The J/Link API helps you avoid such mistakes by providing high-level functions like waitForAnswer() and evaluateToOutputForm() that hide the low-level interaction with the link, but in all but the most trivial J/Link programs it is still possible to make such errors. Just remember that the vast majority of MathLinkExceptions thrown represent logic errors in the code of the program, not user errors or runtime anomalies. They are just bugs to which the programmer needs to be alerted so that they can be fixed.

In a small, well-formed J/Link program, you may be able to put a lot of J/Link calls, perhaps even the entire program, within a single try/catch block because there is no need to know exactly what the program was doing when the error occurred—all you are going to do is print a message and exit. The example program in Section 2.4 has this structure. Many J/Link programs will need to be a little more refined in their treatment of MathLinkExceptions than just quitting. No matter what type of program you are writing, it is strongly recommended that while you are developing the program, you use try/catch blocks in a fine-grained way (that is, only wrapping small, meaningful units of code in each try/catch block), and always put code in your catch block that prints a message or alerts you in some way. Many hours of debugging have been wasted because programmers did not realize a MathLink error had occurred, or they incorrectly identified the region of code where it happened.

Here is a sample of how to handle a MathLinkException in the case where you want to try to recover. The first thing is to call clearError(), as other MathLink calls will fail until the error state is cleared. If clearError() returns false then there is nothing to do but close the link. An example of the type of error that clearError() will fix is the very common mistake of calling nextPacket() before the current packet has been completely read. After clearError() is called, the link is reset to the state it was in before the offending nextPacket(). You can then read the rest of the current packet or call newPacket() to throw it away. Another example of a class of errors where clearError() will work is calling an incorrect "get" method for the type of data waiting on the link—for example, calling getFunction() when an integer is waiting. After calling clearError(), you can read the integer.

try {

    ...

} catch (MathLinkException e) {

    System.err.println(e.toString());

    if (ml.clearError() != true)    {

        System.err.println("MathLinkException was unrecoverable; closing link.");

        ml.close();

        return; // Or whatever cleanup is appropriate

    }

    // How you respond after clearError is up to you.

}

What you do in your catch block after calling clearError() will depend on what you were doing when the exception was thrown. About the only useful general guideline we can provide is that if you are reading from the link when the exception is thrown, call newPacket() to abandon the rest of the packet. At least then you will know that you are ready to read a fresh packet, even if you have lost the contents of the previous packet.

MathLinkException has a few useful methods that will tell you about the cause of the exception. The getErrCode() method will give you the internal MathLink error code, which can be looked up in the MathLink documentation. It is probably more useful to get the internal message associated with the error, which is given by getMessage(). The toString() method gives you all this information, and will be the most useful output for debugging.

// Some useful MathLinkException methods.

public int getErrCode();

public String getMessage();

public String toString();

public Throwable getCause();

Some MathLinkExceptions might not be "native" MathLink errors, but rather special exceptions thrown by implementations of the various link interfaces. J/Link follows the standard "exception chaining" idiom by allowing link implementations to catch these exceptions internally, wrap them in a MathLinkException, and re-throw them. As an example, consider a KernelLink implementation built on top of Java Remote Method Invocation (RMI). Methods called via RMI can throw a RemoteException, so such a link implementation might choose to catch internally every RemoteException and wrap it in a MathLinkException. If it did not do this, and instead all its methods could throw a RemoteException in addition to MathLinkException, all client code that used it would have to be modified. What all this means is that if you catch a MathLinkException, it might be "wrapping" another exception, instead of representing an internal MathLink problem. You can use the getCause() method on the MathLinkException instance to retrieve the wrapped exception that was the actual cause of the problem. The getCause() method will return null in the typical case where the MathLinkException is not wrapping another type of exception.