Codemesh Runtime v3 C++ API Reference  3.9.205
Classes | Typedefs | Enumerations | Functions | Variables
Error Handling

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. More...

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. More...
 
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. More...
 

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. More...
 

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

◆ XMOG_ECB

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
tthe Java exception that was thrown. Might be NULL is the exception was a framework exception that does not have a corresponding Java exception.
error_codean error code, usually used to signal framework error conditions.
anoptional error message. Might be NULL.
Returns
0

◆ XMOG_THROW_METHOD

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.

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
excan existing JNI reference to a Throwable instance.
flagsbitflags describing the type of reference we have.

Enumeration Type Documentation

◆ xmog_exception_policy

The exception handling policy.

Enumerator
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

◆ throw_()

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.

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
throwablea reference to a Throwable instance.
flagsthe type of the reference.
error_codean error code to use if we don't have a JNI reference.
enva local environment pointer.
xmog_exception_impl
The type that is used when the GenericException policy is in effect or for exceptions epresenting fra...
Definition: xmog_exception.h:144
xmog_java_string::to_char
static char * to_char(jstring _str, xmog_localenv *env=NULL, xmog_base *pStr=NULL, char **pCache=NULL)
Returns a char string for the given Java string.
xmog_base
The baseclass for all proxy types in the framework.
Definition: xmog_base.h:29
xmog_java_int_array
The wrapper type for the Java int[] type.
Definition: xmog_java_array.h:2022
xmog_java_string::free
static void free(char *&str)
Frees a previously allocated string.

Copyright (c) 1999-2020 by Codemesh, Inc., ALL RIGHTS RESERVED.