Category: Java/C++ Runtime
When is the JVM loaded into my C++ process?
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.
