Codemesh Runtime v3 C++ API Reference
3.9.205
|
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. | |
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.
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
:
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:
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).
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:
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.
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 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:
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.
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 . |
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.
exc | an existing JNI reference to a Throwable instance. |
flags | bitflags describing the type of reference we have. |
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. |
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.
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. |