void createVm( const VmLoader& loader, const OptionList& options, bool ignoreUnrecognized ) { globalLoader = std::unique_ptr<VmLoader>( loader.clone() ); globalLoader->loadVm(); JavaVM* vm; JNIEnv* env; JavaVMInitArgs vm_args; JavaVMOption* jniOptions = options.createJniOptions(); vm_args.version = globalLoader->version(); vm_args.options = jniOptions; vm_args.nOptions = jint( options.size() ); vm_args.ignoreUnrecognized = ignoreUnrecognized; jint rc = globalLoader->createJavaVM( &vm, reinterpret_cast<void**>( &env ), &vm_args ); options.destroyJniOptions( jniOptions ); if ( rc != 0 ) { string msg = "Unable to create the virtual machine. The error was " + std::to_string( rc ); throw JNIException( msg ); } jclass runtimeClass = env->FindClass( "java/lang/Runtime" ); if ( ! runtimeClass ) { string msg = "Assert failed: Unable to find the class, java.lang.Runtime."; throw JNIException( msg ); } jmethodID runtimeGetRuntime = env->GetStaticMethodID( runtimeClass, "getRuntime", "()Ljava/lang/Runtime;" ); if ( ! runtimeGetRuntime ) { deleteLocalRef( env, runtimeClass ); string msg = "Assert failed: Unable to find the method, Runtime.getRuntime()."; throw JNIException( msg ); } jobject runtimeObject = env->CallStaticObjectMethod( runtimeClass, runtimeGetRuntime ); if ( ! runtimeObject ) { deleteLocalRef( env, runtimeClass ); string msg = "Unable to invoke Runtime.getRuntime()"; try { helper::catchAndThrow(); } catch (JNIException& e) { msg.append("\ncaused by:\n"); msg.append(e.what()); } throw JNIException( msg ); } jmethodID runtimeAddShutdownHook = env->GetMethodID( runtimeClass, "addShutdownHook", "(Ljava/lang/Thread;)V" ); if ( ! runtimeAddShutdownHook ) { deleteLocalRef( env, runtimeObject ); deleteLocalRef( env, runtimeClass ); string msg = "Assert failed: Unable to find the method, Runtime.addShutdownHook()."; throw JNIException( msg ); } jclass shutdownHookClass = env->FindClass( "jace/util/ShutdownHook" ); if ( ! shutdownHookClass ) { deleteLocalRef( env, runtimeObject ); deleteLocalRef( env, runtimeClass ); string msg = "Assert failed: Unable to find the class, jace.util.ShutdownHook. Did you forget to include " "jace-runtime.jar in your classpath at runtime?"; throw JNIException( msg ); } // Register the native method jace.util.ShutdownHook.signalVMShutdown JNINativeMethod signalVMShutdown; signalVMShutdown.fnPtr = reinterpret_cast<void*>(Java_jace_util_ShutdownHook_signalVMShutdown); signalVMShutdown.name = const_cast<char*>("signalVMShutdown"); signalVMShutdown.signature = const_cast<char*>("()V"); jint result = env->RegisterNatives(shutdownHookClass, &signalVMShutdown, 1); if (result != JNI_OK) { deleteLocalRef( env, runtimeObject ); deleteLocalRef( env, runtimeClass ); deleteLocalRef( env, shutdownHookClass ); string msg = "Assert failed: Unable to register native method, jace.util.ShutdownHook.signalVMShutdown()"; throw JNIException( msg ); } jmethodID shutdownHookGetInstance = env->GetStaticMethodID( shutdownHookClass, "getInstance", "()Ljace/util/ShutdownHook;" ); if ( ! shutdownHookGetInstance ) { deleteLocalRef( env, runtimeObject ); deleteLocalRef( env, runtimeClass ); deleteLocalRef( env, shutdownHookClass ); string msg = "Assert failed: Unable to find the method, jace.util.ShutdownHook.getInstance()"; throw JNIException( msg ); } jobject shutdownHookObject = env->CallStaticObjectMethod( shutdownHookClass, shutdownHookGetInstance ); if ( ! shutdownHookObject ) { deleteLocalRef( env, runtimeObject ); deleteLocalRef( env, runtimeClass ); deleteLocalRef( env, shutdownHookClass ); string msg = "Unable to invoke jace.util.ShutdownHook.getInstance()"; try { helper::catchAndThrow(); } catch (JNIException& e) { msg.append("\ncaused by:\n"); msg.append(e.what()); } throw JNIException( msg ); } env->CallVoidMethod( runtimeObject, runtimeAddShutdownHook, shutdownHookObject ); try { helper::catchAndThrow(); } catch (JNIException& e) { string msg = "Exception thrown invoking Runtime.addShutdownHook(shutdownHook)"; msg.append("\ncaused by:\n"); msg.append(e.what()); throw JNIException( msg ); } deleteLocalRef( env, runtimeObject ); deleteLocalRef( env, runtimeClass ); deleteLocalRef( env, shutdownHookClass ); }