Category: Java/C++ Runtime

Q

When is the JVM loaded into my C++ process?

A

If you do nothing explicit, the JVM is loaded the first time you perform an activity with a proxy type that requires access to the Java side.

This is not as simple a statement as it sounds. Consider the following C++ snippet:

// creates a global instance that is used as a singleton
static MyJavaType SINGLETON( true, 42 );  
 
int main( int argc, char * argv[] )
{
    xmog_jvm_loader & loader = xmog_jvm_loader::get_jvm_loader();
 
    // set up the classpath to find our types 
    loader.setClassPath( "../lib/myapp.jar" );
 
    ...
} 

The above snippet is deeply flawed and will crash on startup. You start debugging and find that you don't even get to a breakpoint that you set on the first line of main(). What's going on here? The answer is that the global variable that you declared is initialized before your main() starts to execute. If this were a pure C++ type, that wouldn't be so bad, but it's a proxy type. Calling its constructor requires a JVM to be loaded, so the framework takes care of that. Unfortunately, the framework doesn't know that you're going to set the classpath later, so it will initialize the JVM with a default classpath (only built-in types). Your constructor call will fail with a ClassNotFoundException that is thrown from within the C++ initialization function, which would eventually have called your main() function. Avoid global proxy objects for this reason.

You can also explicitly load the JVM, which is something that we recommend as a best practice. Whichever factory method you might be using, have a function that does nothing but load the JVM and handle any initialization errors you can find before you start going deep into your application and end up with a hard-to-debug partial failure. Your initialization function might look something like this:

xmog_jvm *  initJvm()
{
    xmog_jvm * result = NULL;

    try
    {
        // get a loader and configure it with the proper init settings
        xmog_jvm_loader & loader = xmog_jvm_loader::get_jvm_loader( ... );

        loader.setJvmPath( ... );
        loader.appendToClassPath( ... );
        loader.setMaximumHeapSizeInMB( 512 );

        // check whether we already loaded a JVM and return it if yes
        result = loader.get_jvm();
        if( result == NULL )
        {
            // otherwise attempt to load a JVM explicitly
            result = loader.load();
        }    
    }
    catch( xmog_exception & xe )
    {
        // handle the error in an application-specific way
    }
 
    // return the loaded JVM or NULL; your application can use the
    // return value to test for successful initialization
    return result;
} 

With a function such as the above, you can simply invoke it in your main() and it handles all the JVM interactions.


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

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