Exceptions are a nice feature of the Java language, which is available to Java Card developers. The nice thing about exceptions is that you don’t have to deal with error codes. We here recall a few good practices about the use of exceptions in Java Card applications.
In Java Card like in Java, exceptions have two main uses:
- The runtime environment uses exceptions to signal errors such as null pointers, attempts to access an array outside of its bounds, or more specific details like attempting to allocate a crypto engine that is not supported.
- The application uses exceptions to signal its own errors, and abort the execution of the currently executing code.
In the case of Java Card, there is one additional use for exceptions:
- The
ISOExceptiontype is used to return a status word to the card terminal if the execution of the application ends with an instance of it. Any other exception yields a6F00status word (meaning “Unknown error”, not very useful).
We will here focus on the use of exceptions by applications as means of internal communication (i.e., excluding the use of ISOException). The following rules can be considered as good practice:
- Catch all the exceptions you throw.
As a stray exception will trigger a6F00status word, this seems quite natural. - Use checked exceptions / Don’t use runtime exceptions.
These two guidelines are the same. Using checked exceptions guarantees that exceptions must be declared. Runtime exceptions, beyond the fact that they are not checked, are the exceptions used by the runtime environment, and it is better not to confuse the exceptions. - Don’t define new exception classes.
Defining an exception class is difficult in Java Card. In addition, the exception instances managed by the JCRE are all JCRE entry-point objects, which can be very practical in many situations.
This sounds quite difficult, but Java Card offers a solution, which is to use the UserException class. It is a standard exception, it is a checked exception, and you have to catch all instances. The following example can be considered as good practice:
public static final short RS_LOW_BALANCE ;
public short debit(short value) throws UserException
{
if (value > balance)
UserException.throwIt(RS_LOW_BALANCE) ;
balance -= value ;
}
The important thing is here that the throws UserException clause is mandatory (otherwise the compiler wil fail). Since the Applet.process method does not have such a clause, it means that the compiler will ensure that all exceptions are caught, enforcing the good usage guidelines all by itself.
Exceptions also need to be caught. It is possible to do it as soon as possible (in the same method, or in the calling method), or to do it much later. But this is another discussion, for another post.
No Comments