if (debug) {
printf("JVM path is %s\n", jvmpath);
}
/* Load the Java VM DLL */
if ((handle = LoadLibrary(jvmpath)) == 0) {
ReportErrorMessage2("Error loading: %s", (char *)jvmpath, JNI_TRUE);
return JNI_FALSE;
}
/* Now get the function addresses */
ifn->CreateJavaVM =
(void *)GetProcAddress(handle, "JNI_CreateJavaVM");
ifn->GetDefaultJavaVMInitArgs =
(void *)GetProcAddress(handle, "JNI_GetDefaultJavaVMInitArgs");
if (ifn->CreateJavaVM == 0 || ifn->GetDefaultJavaVMInitArgs == 0) {
ReportErrorMessage2("Error: can't find JNI interfaces in: %s",
(char *)jvmpath, JNI_TRUE);
return JNI_FALSE;
}
return JNI_TRUE;
}
装载class文件
static jclass
LoadClass(JNIEnv *env, char *name)
{
char *buf = MemAlloc(strlen(name) + 1);
char *s = buf, *t = name, c;
jclass cls;
jlong start, end;
if (debug)
start = CounterGet();
do {
c = *t++;
*s++ = (c == '.') ? '/' : c;
} while (c != '\0');
cls = (*env)->FindClass(env, buf);
free(buf);
if (debug) {
end = CounterGet();
printf("%ld micro seconds to load main class\n",
(long)(jint)Counter2Micros(end-start));
printf("----_JAVA_LAUNCHER_DEBUG----\n");
}
return cls;
}
装载类运行
int
main(int argc, char ** argv)
{
JavaVM *vm = 0;
JNIEnv *env = 0;
char *jarfile = 0;
char *classname = 0;
char *s = 0;
jstring mainClassName;
jclass mainClass;
jmethodID mainID;
jobjectArray mainArgs;
int ret;
InvocationFunctions ifn;
char *jvmtype = 0;
jlong start, end;
char jrepath[MAXPATHLEN], jvmpath[MAXPATHLEN];
char ** original_argv = argv;
/* Error message to print or display; by default the message will
only be displayed in a window. */
char * message = "Fatal exception occurred. Program will exit.";
jboolean messageDest = JNI_FALSE;
/* copy original argv */
{
int i;
original_argv = (char**)MemAlloc(sizeof(char*)*(argc+1));
for(i = 0; i < argc+1; i++)
original_argv[i] = argv[i];
}
if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) {
debug = JNI_TRUE;
printf("----_JAVA_LAUNCHER_DEBUG----\n");
}
CreateExecutionEnvironment(&argc, &argv, jrepath, sizeof(jrepath),
jvmpath, sizeof(jvmpath), &jvmtype,
original_argv);
ifn.CreateJavaVM = 0;
ifn.GetDefaultJavaVMInitArgs = 0;
if (debug)
start = CounterGet();
if (!LoadJavaVM(jvmpath, &ifn)) {
exit(6);
}
if (debug) {
end = CounterGet();
printf("%ld micro seconds to LoadJavaVM\n",
(long)(jint)Counter2Micros(end-start));
}
#ifdef JAVA_ARGS /* javac, jar and friends. */
progname = "java";
#else /* java, oldjava, javaw and friends */
#ifdef PROGNAME
progname = PROGNAME;
#else
progname = *argv;
if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) {
progname = s + 1;
}
#endif /* PROGNAME */
#endif /* JAVA_ARGS */
++argv;
--argc;
#ifdef JAVA_ARGS
/* Preprocess wrapper arguments */
TranslateDashJArgs(&argc, &argv);
if (!AddApplicationOptions()) {
exit(1);
}
#endif
/* Set default CLASSPATH */
if ((s = getenv("CLASSPATH")) == 0) {
s = ".";
}
#ifndef JAVA_ARGS
SetClassPath(s);
#endif
/*
* Parse command line options; if the return value of
* ParseArguments is false, the program should exit.
*/
if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret)) {
exit(ret);
}
/* Override class path if -jar flag was specified */
if (jarfile != 0) {
SetClassPath(jarfile);
}
/* set the -Dsun.java.command pseudo property */
SetJavaCommandLineProp(classname, jarfile, argc, argv);
/* Initialize the virtual machine */
if (debug)
start = CounterGet();
if (!InitializeJVM(&vm, &env, &ifn)) {
ReportErrorMessage("Could not create the Java virtual machine.",
JNI_TRUE);
exit(1);
}
if (printVersion || showVersion) {
PrintJavaVersion(env);
if ((*env)->ExceptionOccurred(env)) {
(*env)->ExceptionDescribe(env);
goto leave;
}
if (printVersion) {
ret = 0;
message = NULL;
goto leave;
}
if (showVersion) {
fprintf(stderr, "\n");
}
}
/* If the user specified neither a class name nor a JAR file */
if (jarfile == 0 && classname == 0) {
PrintUsage();
message = NULL;
goto leave;
}
FreeKnownVMs(); /* after last possible PrintUsage() */
if (debug) {
end = CounterGet();
printf("%ld micro seconds to InitializeJVM\n",
(long)(jint)Counter2Micros(end-start));
}
/* At this stage, argc/argv have the applications' arguments */
if (debug) {
int i = 0;
printf("Main-Class is '%s'\n", classname ? classname : "");
printf("Apps' argc is %d\n", argc);
for (; i < argc; i++) {
printf(" argv[%2d] = '%s'\n", i, argv[i]);
}
}
ret = 1;
/* Get the application's main class */
if (jarfile != 0) {
mainClassName = GetMainClassName(env, jarfile);
if ((*env)->ExceptionOccurred(env)) {
(*env)->ExceptionDescribe(env);
goto leave;
}
if (mainClassName == NULL) {
const char * format = "Failed to load Main-Class manifest "
"attribute from\n%s";
message = (char*)MemAlloc((strlen(format) + strlen(jarfile)) *
sizeof(char));
sprintf(message, format, jarfile);
messageDest = JNI_TRUE;
goto leave;
}
classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
if (classname == NULL) {
(*env)->ExceptionDescribe(env);
goto leave;
}
mainClass = LoadClass(env, classname);
if(mainClass == NULL) { /* exception occured */
(*env)->ExceptionDescribe(env);
message = "Could not find the main class. Program will exit.";
goto leave;
}
(*env)->ReleaseStringUTFChars(env, mainClassName, classname);
} else {
mainClassName = NewPlatformString(env, classname);
if (mainClassName == NULL) {
const char * format = "Failed to load Main Class: %s";
message = (char *)MemAlloc((strlen(format) + strlen(classname)) *
sizeof(char) );
sprintf(message, format, classname);
messageDest = JNI_TRUE;
goto leave;
}
classname = (char *)(*env)->GetStringUTFChars(env, mainClassName,
0);
if (classname == NULL) {
(*env)->ExceptionDescribe(env);
goto leave;
}
mainClass = LoadClass(env, classname);
if(mainClass == NULL) { /* exception occured */
(*env)->ExceptionDescribe(env);
message = "Could not find the main class. Program will exit.";
goto leave;
}
(*env)->ReleaseStringUTFChars(env, mainClassName, classname);
}
/* Get the application's main method */
mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
"([Ljava/lang/String;)V");
if (mainID == NULL) {
if ((*env)->ExceptionOccurred(env)) {
(*env)->ExceptionDescribe(env);
} else {
message = "No main method found in specified class.";
messageDest = JNI_TRUE;
}
goto leave;
}
{ /* Make sure the main method is public */
jint mods;
jmethodID mid;
jobject obj = (*env)->ToReflectedMethod(env, mainClass,
mainID, JNI_TRUE);
if( obj == NULL) { /* exception occurred */
(*env)->ExceptionDescribe(env);
goto leave;
}
mid =
(*env)->GetMethodID(env,
(*env)->GetObjectClass(env, obj),
"getModifiers", "()I");
if ((*env)->ExceptionOccurred(env)) {
(*env)->ExceptionDescribe(env);
goto leave;
}
mods = (*env)->CallIntMethod(env, obj, mid);
if ((mods & 1) == 0) { /* if (!Modifier.isPublic(mods)) ... */
message = "Main method not public.";
messageDest = JNI_TRUE;
goto leave;
}
}
/* Build argument array */
mainArgs = NewPlatformStringArray(env, argv, argc);
if (mainArgs == NULL) {
(*env)->ExceptionDescribe(env);
goto leave;
}
/* Invoke main method. */
(*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
if ((*env)->ExceptionOccurred(env)) {
/* Formerly, we used to call the "uncaughtException" method of the
main thread group, but this was later shown to be unnecessary
since the default definition merely printed out the same exception
stack trace as ExceptionDescribe and could never actually be
overridden by application programs. */
(*env)->ExceptionDescribe(env);
goto leave;
}
/*
* Detach the current thread so that it appears to have exited when
* the application's main method exits.
*/
if ((*vm)->DetachCurrentThread(vm) != 0) {
message = "Could not detach main thread.";
messageDest = JNI_TRUE;
goto leave;
}
ret = 0;
message = NULL;
leave:
(*vm)->DestroyJavaVM(vm);
if(message != NULL)
ReportErrorMessage(message, messageDest);
exit(ret);
}