Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | Related Pages

Error Handling


Classes

class  xmog_error_handler
 The type responsible for error handling. More...
class  xmog_exception
 The wrapper for exceptions that occur on the Java side. More...
class  xmog_exception_impl
 The type that is used when the GenericException policy is in effect or for exceptions epresenting framework exceptions that are not based on Java exceptions. More...

Typedefs

typedef void(XMOG_CALLING_CONVENTION * xmog_java_class::XMOG_THROW_METHOD )(jobject exc, xmog_flags flags)
 A typedef for the method that can be used to throw an exception.
typedef jint(JNICALL * XMOG_ECB )(jthrowable t, int error_code, char *msg)
 The method signature that an errorhandling callback has to conform to in the case of an ExceptionCallback policy.

Enumerations

enum  xmog_exception_policy {
  IgnoreAndContinue = 0, TypedException = 1, GenericException = 2, FatalError = 3,
  ExceptionCallback = 4
}
 The exception handling policy. More...

Functions

void xmog_java_class::throw_ (jthrowable throwable, xmog_flags flags, int error_code=0, xmog_localenv *env=NULL)
 Throws an instance of the proxy type represented by this instance.

Variables

static XMOG_THROW_METHOD xmog_java_class::NULL_THROW_METHOD
 An instance that can be used in places where no exception factory is required.

Detailed Description

Error handling is a complex field. A native process that calls Java methods and accesses native fields has to deal with the exceptions that might be thrown by these activities, whether they be in-process via JNI or out-of-process in Codemesh's shared JVM server.

The quality of a wrapper API is directly dependent on the quality of its error handling. Codemesh's products support a variety of errorhandling modes that give you complete flexibility in how you write your application.

TypedException

The default mode of errorhandling is that a proxy type exception is thrown whenever a Java exception occurred. This policy is called TypedException and it is usually the policy that you will wish to use for your application.

When you use this policy, the runtime will search for the best matching proxy exception type that is available. This match will not always be exact. Many Java operations can throw RuntimeException instances, or more exactly, instances of a subclass of type RuntimeException. Very often, you don't have a proxy type for the exact subclass of RuntimeException that was thrown by a Java method. In this case, the runtime library will search for the best possible type that is available. It will traverse the inheritance chain all the way to the proxy type for Throwable. It will pick the proxy type that is closest to the exact exception type in the inheritance chain. This means that the following code will work even if you do not have a proxy type for ArrayIndexOutOfBoundsException :

      try
      {
          //create an integer array with 10 elements
          xmog_java_int_array   arrInt( 10 );
   
          //try accessing the 12th element in the array, causing  
          //an ArrayIndexOutOfBoundsException to be thrown in the JVM
          jint   temp = arrInt[ 12 ];
      }
      catch( java::lang::RuntimeException & rte )
      {
          cout << rte.getMessage() << endl;
      }

To be on the safe side, you might always want to add a catch block for type xmog_exception_impl after your typed exception catch blocks. While a correctly deployed application shouldn't need them, it might allow you to catch some misconfigurations that would otherwise simply cause your application to crash.

Please note that exceptions should always be caught by reference (using the ampersand symbol in the catch block) and never thrown by pointer. Please resist the temptation to throw C++ proxy exceptions the same way you would do it in Java, namely using the keyword new.

Never do the following:

      try
      {
          throw new RuntimeException( "Something didn't work out" );
      }
      catch( java::lang::RuntimeException & rte )
      {
          cout << rte.getMessage() << endl;
      }

This will compile and link, but it will never catch your exceptions because it expects a reference to a RuntimeException and you are throwing a pointer to a RuntimeException. C++ distinguishes between pointers, references and instances. You can even throw and catch primitives in a C++ application (not that I particularly recommend that).

GenericException

The next most useful errorhandling policy is called GenericException and converts all Java exceptions into xmog_exception_impl instances. This gives you basic errorhandling capabilities without having to generate a lot of proxy exception types. This policy is useful if you need to minimize your proxy set and eliminiating all exception proxy types is a convenient way to do that without losing too much functionality. The example from the TypedException section above would look like this if we're using the GenericException policy:

      try
      {
          //create an integer array with 10 elements
          xmog_java_int_array   arrInt( 10 );
   
          //try accessing the 12th element in the array, causing  
          //an ArrayIndexOutOfBoundsException to be thrown in the JVM
          jint   temp = arrInt[ 12 ];
      }
      catch( xmog_exception_impl & rte )
      {
          xmog_base   msg( rte.getMessage(), xmog_base::LOCAL );
          const char* strMsg = xmog_java_string::to_char( msg.get_jobject_() );
   
          cout << strMsg << endl;
   
          xmog_java_string::free( msg, strMsg );
      }

ExceptionCallback

The third useful errorhandling policy is called ExceptionCallback and allows you to register a callback function with the runtime library. This policy is less desirable than the first two policies because the flow of execution will not be changed in case of an error and you definitely need to write your application in a style that is different from the style in which you would write a Java application. Nevertheless, it is a useful policy in cases where your calling process cannot handle exceptions and you need more information about an error than just the fact that something didn't work.

If a framework error occurs or a Java exception is thrown, an object in the error handler will receive all information that is known about the problem and your registered callback will be called with a pointer to that information. You can then do with that information whatever you wish before execution returns to the code that caused the problem to occur. As already mentioned: the chief disadvantage of this policy is that the flow of execution does not change and that you will have to manually check for errors to make sure that you don't try to execute more code after a prior error which dooms the following code to certain failure.

configuration

The errorhandling policy can be set prior to starting the JVM by using the xmog_jvm_loader class, in which case the entire framework will use your specified errorhandling policy from the moment the JVM is loaded. Please note at this point that we're not configuring what the JVM does in the case of errors or exceptions; the errorhandling policy only governs how JVM error conditions are handled on the C++ side. You can also change the errorhandling policy for a loaded xmog_jvm instance and even for a specific thread via the xmog_localenv type. This can be useful if you want to temporarily override the errorhandling policy for a specifc activity without affecting errorhandling for the entire application. To summarize:


Typedef Documentation

typedef jint(JNICALL * XMOG_ECB)(jthrowable t, int error_code, char *msg)
 

The method signature that an errorhandling callback has to conform to in the case of an ExceptionCallback policy.

You implement a method of this type and register it with the framework if you wish to perform a custom action each time an exception is thrown or an error occurs in the framework. The most frequent use case for this mechanism is a C application that uses generated C++ proxy types via a shared library with C entry points. You might want to make more than just an error code indicating that "something went wrong" available to the caller. By registering a mehtod of this signature with the framework, you can for example:

  • log an exception to an error log
  • set a global error flag for your application
  • perform some calculations to see whether you can handle the error

At the time that his method is invoked, the possibly underlying Java exception has been cleared from the JVM, so you will be able to execute Java methods successfully.

Parameters:
t the Java exception that was thrown. Might be NULL is the exception was a framework exception that does not have a corresponding Java exception.
error_code an error code, usually used to signal framework error conditions.
an optional error message. Might be NULL.
Returns:
0

typedef void(XMOG_CALLING_CONVENTION * xmog_java_class::XMOG_THROW_METHOD)(jobject exc, xmog_flags flags) [inherited]
 

A typedef for the method that can be used to throw an exception.

Every generated proxy class maintains a pointer to a function of this type that can be used as a factory method for exceptions of that proxy type. Non-exception proxy types have a NULL pointer.

Parameters:
exc an existing JNI reference to a Throwable instance.
flags bitflags describing the type of reference we have.


Enumeration Type Documentation

enum xmog_exception_policy
 

The exception handling policy.

Enumeration values:
IgnoreAndContinue  Clear the exception from the JVM and continue without doing anything about it.
TypedException  Find the best matching proxy type for the Java exception and throw an instance of it. If there is no matching type, throw an xmog_exception_impl instance.
GenericException  Throw an xmog_exception_impl instance that wraps around the Java exception.
FatalError  Terminate the JVM by calling the JNI function FatalError.
ExceptionCallback  Call a callback method that was registered with the framework.


Function Documentation

void xmog_java_class::throw_ jthrowable  throwable,
xmog_flags  flags,
int  error_code = 0,
xmog_localenv env = NULL
[inherited]
 

Throws an instance of the proxy type represented by this instance.

Every generated proxy class maintains a pointer to a function of this type that can be used as a factory method for exceptions of that proxy type. Non-exception proxy types have a NULL pointer.

Parameters:
throwable a reference to a Throwable instance.
flags the type of the reference.
error_code an error code to use if we don't have a JNI reference.
env a local environment pointer.


Variable Documentation

XMOG_THROW_METHOD xmog_java_class::NULL_THROW_METHOD [static, inherited]
 

An instance that can be used in places where no exception factory is required.


Generated on Wed May 31 14:01:35 2006 for Shared Codemesh Runtime Library API Reference by  doxygen 1.4.1