Category: Proxy usage

Q

How do I handle Java exceptions in C++?

A

You can handle Java exceptions through their corresponding proxy types or through their super types. Take the following C++ snippet as an example:

try
{
    String::array1D     arr( 4 );


    arr[ 1867 ] = "test";
}
catch( ArrayIndexOutOfBoundsException & oob )
{
    cerr << oob.getMessage().to_chars() << endl;
}

The code in the try block throws a Java ArrayIndexOutOfBoundsException. This Java exception is detected by the Codemesh runtime and translated into its corresponding C++ proxy type. An instance of that proxy exception type is then thrown and can be caught by a C++ catch block.

It is important to understand what happens when there is no corresponding C++ exception type available. You (or whoever gave you the C++ classes you are using) might not have included the ArrayIndexOutOfBoundsException in the set of C++ classes. In such a case, the Codemesh runtime will search up the Java exception's inheritance hierarchy until it finds an exception type for which a C++ proxy type exists. If no exception proxy type at all is found, the runtime will throw an xmog_exception instance which provides some limited, very basic information about the the corresponding Java exception.

The Codemesh runtime does a lot of very sophisticated work for you here. If you wanted to implement the same exception handling model via the JNI API, you would probably be looking at several months of work. Making exceptions work more or less transparently across the language boundary represented a major technical victory for us.

We recommend that you handle xmog_exception instances as well as Java exception instances. xmog_exceptions might also be thrown by the Codemesh runtime to signal framework failures (for example the inability to laod a JVM or connect to a Shared JVM server).

To prevent application crashes, you should surround your entire thread procedure (including your main()) with a try/catch block that handles at least the framework exceptions in a meaningful way. Your main() might look something like this:

int main( int argc, char * argv[] )
{
    int  rc = 0;
 
    try
    {
        // here's where you do your actual work
    }
    catch( Throwable & t )
    {
        rc = 1;
        cerr << t.toString().to_chars() << endl;
    }
    catch( xmog_exception & xe )
    {
        rc = 2;
        const char * msg = xe.get_message_chars();
        if( msg != NULL )
        {
            cerr << msg << endl;
            xmog_java_string::free( msg );
        }
        else
        {
            cerr << "Unknown framework failure" << endl;
        }
    }
 
    return rc;
} 

Using such a pattern makes sure that you're not faced with an application crash and that you're receiving some information that is useful for debugging the problem that caused the exception.

Be careful about how you handle exceptions. C++ distinguishes between pointers and references. If you throw an exception instance (vs. a pointer to an exception instance) you cannot catch it with a catch clause that catches pointers.


Copyright 2006-2011 by Codemesh, Inc., ALL RIGHTS RESERVED

:
frequently asked questions
home products support customers partners newsroom about us contact us