in src/main/cpp/bootstrap/jvmlauncher.cpp [185:348]
bool JvmLauncher::startInProcJvm(const char *mainClassName, const std::list<std::string> &args, const std::list<std::string> &options) {
class Jvm {
public:
Jvm(JvmLauncher *jvmLauncher)
: hDll(0)
, hSplash(0)
, jvm(0)
, env(0)
, jvmOptions(0)
, jvmLauncher(jvmLauncher)
{
}
~Jvm() {
if (env && env->ExceptionOccurred()) {
env->ExceptionDescribe();
}
if (jvm) {
logMsg("Destroying JVM");
jvm->DestroyJavaVM();
}
if (jvmOptions) {
delete[] jvmOptions;
}
if (hDll) {
FreeLibrary(hDll);
}
if (hSplash) {
FreeLibrary(hSplash);
}
}
bool init(const list<string> &options) {
logMsg("JvmLauncher::Jvm::init()");
logMsg("LoadLibrary(\"%s\")", jvmLauncher->javaDllPath.c_str());
{
PrepareDllPath prepare(jvmLauncher->javaBinPath.c_str());
hDll = LoadLibrary(jvmLauncher->javaDllPath.c_str());
if (!hDll) {
logErr(true, true, "Cannot load %s.", jvmLauncher->javaDllPath.c_str());
return false;
}
string pref = jvmLauncher->javaBinPath;
pref += "\\splashscreen.dll";
const string splash = pref;
logMsg("Trying to load %s", splash.c_str());
hSplash = LoadLibrary(splash.c_str());
logMsg("Splash loaded as %d", hSplash);
}
CreateJavaVM createJavaVM = (CreateJavaVM) GetProcAddress(hDll, JNI_CREATEVM_FUNC);
if (!createJavaVM) {
logErr(true, true, "GetProcAddress for %s failed.", JNI_CREATEVM_FUNC);
return false;
}
logMsg("JVM options:");
jvmOptions = new JavaVMOption[options.size() + 1];
int i = 0;
for (list<string>::const_iterator it = options.begin(); it != options.end(); ++it, ++i) {
const string &option = *it;
logMsg("\t%s", option.c_str());
if (option.find("-splash:") == 0 && hSplash > 0) {
const string splash = option.substr(8);
logMsg("splash at %s", splash.c_str());
SplashInit splashInit = (SplashInit)GetProcAddress(hSplash, "SplashInit");
SplashLoadFile splashLoadFile = (SplashLoadFile)GetProcAddress(hSplash, "SplashLoadFile");
logMsg("splash init %d and load %d", splashInit, splashLoadFile);
if (splashInit && splashLoadFile) {
splashInit();
splashLoadFile(splash.c_str());
}
}
jvmOptions[i].optionString = (char *) option.c_str();
jvmOptions[i].extraInfo = 0;
}
JavaVMInitArgs jvmArgs;
jvmOptions[options.size()].optionString = (char *) "exit";
jvmOptions[options.size()].extraInfo = (void *) &exitHook;
jvmArgs.options = jvmOptions;
jvmArgs.nOptions = options.size() + 1;
jvmArgs.version = JNI_VERSION_1_4;
jvmArgs.ignoreUnrecognized = JNI_TRUE;
logMsg("Creating JVM...");
if (createJavaVM(&jvm, &env, &jvmArgs) < 0) {
logErr(false, true, "JVM creation failed");
return false;
}
logMsg("JVM created.");
return true;
}
typedef jint (CALLBACK *CreateJavaVM)(JavaVM **jvm, JNIEnv **env, void *args);
typedef void (CALLBACK *SplashInit)();
typedef int (CALLBACK *SplashLoadFile)(const char* file);
HMODULE hDll;
HMODULE hSplash;
JavaVM *jvm;
JNIEnv *env;
JavaVMOption *jvmOptions;
JvmLauncher *jvmLauncher;
};
Jvm jvm(this);
if (!jvm.init(options)) {
return false;
}
jclass mainClass = jvm.env->FindClass(mainClassName);
if (!mainClass) {
logErr(false, true, "Cannot find class %s.", mainClassName);
return false;
}
jmethodID mainMethod = jvm.env->GetStaticMethodID(mainClass, "main", "([Ljava/lang/String;)V");
if (!mainMethod) {
logErr(false, true, "Cannot get main method.");
return false;
}
jclass jclassString = jvm.env->FindClass("java/lang/String");
if (!jclassString) {
logErr(false, true, "Cannot find java/lang/String class");
return false;
}
jstring jstringArg = jvm.env->NewStringUTF("");
if (!jstringArg) {
logErr(false, true, "NewStringUTF() failed");
return false;
}
jobjectArray mainArgs = jvm.env->NewObjectArray(args.size(), jclassString, jstringArg);
if (!mainArgs) {
logErr(false, true, "NewObjectArray() failed");
return false;
}
int i = 0;
for (list<string>::const_iterator it = args.begin(); it != args.end(); ++it, ++i) {
const string &arg = *it;
const int len = 32*1024;
char utf8[len] = "";
if (convertAnsiToUtf8(arg.c_str(), utf8, len))
logMsg("Conversion to UTF8 failed");
jstring jstringArg = jvm.env->NewStringUTF(utf8);
if (!jstringArg) {
logErr(false, true, "NewStringUTF() failed");
return false;
}
jvm.env->SetObjectArrayElement(mainArgs, i, jstringArg);
}
jvm.env->CallStaticVoidMethod(mainClass, mainMethod, mainArgs);
return true;
}