diff -r d038148778cc -r e14a3b3536cd jdk/src/share/bin/java.c --- a/jdk/src/share/bin/java.c Wed Sep 24 15:19:07 2008 +0200 +++ b/jdk/src/share/bin/java.c Wed Sep 24 15:07:41 2008 -0700 @@ -102,8 +102,7 @@ InvocationFunctions *ifn); static jstring NewPlatformString(JNIEnv *env, char *s); static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc); -static jclass LoadClass(JNIEnv *env, char *name); -static jstring GetMainClassName(JNIEnv *env, char *jarname); +static jclass LoadMainClass(JNIEnv *env, jboolean isJar, char *name); static void TranslateApplicationArgs(int jargc, const char **jargv, int *pargc, char ***pargv); static jboolean AddApplicationOptions(int cpathc, const char **cpathv); @@ -301,6 +300,22 @@ } +#define CHECK_EXCEPTION_NULL_LEAVE(e) \ + if ((*env)->ExceptionOccurred(env)) { \ + JLI_ReportExceptionDescription(env); \ + goto leave; \ + } \ + if ((e) == NULL) { \ + JLI_ReportErrorMessage(JNI_ERROR); \ + goto leave; \ + } + +#define CHECK_EXCEPTION_LEAVE(rv) \ + if ((*env)->ExceptionOccurred(env)) { \ + JLI_ReportExceptionDescription(env); \ + ret = (rv); \ + goto leave; \ + } int JNICALL JavaMain(void * _args) @@ -321,9 +336,7 @@ int ret = 0; jlong start, end; - /* Initialize the virtual machine */ - start = CounterGet(); if (!InitializeJVM(&vm, &env, &ifn)) { JLI_ReportErrorMessage(JVM_ERROR1); @@ -332,11 +345,7 @@ if (printVersion || showVersion) { PrintJavaVersion(env, showVersion); - if ((*env)->ExceptionOccurred(env)) { - JLI_ReportExceptionDescription(env); - JLI_ReportErrorMessage(JNI_ERROR); - goto leave; - } + CHECK_EXCEPTION_LEAVE(0); if (printVersion) { ret = 0; goto leave; @@ -346,11 +355,7 @@ /* If the user specified neither a class name nor a JAR file */ if (printXUsage || printUsage || (jarfile == 0 && classname == 0)) { PrintUsage(env, printXUsage); - if ((*env)->ExceptionOccurred(env)) { - JLI_ReportExceptionDescription(env); - JLI_ReportErrorMessage(JNI_ERROR); - ret=1; - } + CHECK_EXCEPTION_LEAVE(1); goto leave; } @@ -395,99 +400,25 @@ * the environment (and remove these comments). */ if (jarfile != 0) { - mainClassName = GetMainClassName(env, jarfile); - if ((*env)->ExceptionOccurred(env)) { - JLI_ReportExceptionDescription(env); - JLI_ReportErrorMessage(JNI_ERROR); - goto leave; - } - if (mainClassName == NULL) { - JLI_ReportErrorMessage(JAR_ERROR1,jarfile, GEN_ERROR); - goto leave; - } - classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0); - if (classname == NULL) { - JLI_ReportExceptionDescription(env); - JLI_ReportErrorMessage(JNI_ERROR); - goto leave; - } - mainClass = LoadClass(env, classname); - if(mainClass == NULL) { /* exception occured */ - JLI_ReportExceptionDescription(env); - JLI_ReportErrorMessage(CLS_ERROR1, classname); - goto leave; - } - (*env)->ReleaseStringUTFChars(env, mainClassName, classname); + mainClass = LoadMainClass(env, JNI_TRUE, jarfile); } else { - mainClassName = NewPlatformString(env, classname); - if (mainClassName == NULL) { - JLI_ReportErrorMessage(CLS_ERROR2, classname, GEN_ERROR); - goto leave; - } - classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0); - if (classname == NULL) { - JLI_ReportExceptionDescription(env); - JLI_ReportErrorMessage(JNI_ERROR); - goto leave; - } - mainClass = LoadClass(env, classname); - if(mainClass == NULL) { /* exception occured */ - JLI_ReportExceptionDescription(env); - JLI_ReportErrorMessage(CLS_ERROR1, classname); - goto leave; - } - (*env)->ReleaseStringUTFChars(env, mainClassName, classname); + mainClass = LoadMainClass(env, JNI_FALSE, classname); } + CHECK_EXCEPTION_NULL_LEAVE(mainClass); - /* Get the application's main method */ + /* + * The LoadMainClass not only loads the main class, it will also ensure + * that the main method's signature is correct, therefore further checking + * is not required. The main method is invoked here so that extraneous java + * stacks are not in the application stack trace. + */ mainID = (*env)->GetStaticMethodID(env, mainClass, "main", "([Ljava/lang/String;)V"); - if (mainID == NULL) { - if ((*env)->ExceptionOccurred(env)) { - JLI_ReportExceptionDescription(env); - JLI_ReportErrorMessage(JNI_ERROR); - } else { - JLI_ReportErrorMessage(CLS_ERROR3); - } - 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 */ - JLI_ReportExceptionDescription(env); - JLI_ReportErrorMessage(JNI_ERROR); - goto leave; - } - - mid = - (*env)->GetMethodID(env, - (*env)->GetObjectClass(env, obj), - "getModifiers", "()I"); - if ((*env)->ExceptionOccurred(env)) { - JLI_ReportExceptionDescription(env); - JLI_ReportErrorMessage(JNI_ERROR); - goto leave; - } - - mods = (*env)->CallIntMethod(env, obj, mid); - if ((mods & 1) == 0) { /* if (!Modifier.isPublic(mods)) ... */ - JLI_ReportErrorMessage(CLS_ERROR4); - goto leave; - } - } + CHECK_EXCEPTION_NULL_LEAVE(mainID); /* Build argument array */ mainArgs = NewPlatformStringArray(env, argv, argc); - if (mainArgs == NULL) { - JLI_ReportExceptionDescription(env); - JLI_ReportErrorMessage(JNI_ERROR); - goto leave; - } + CHECK_EXCEPTION_NULL_LEAVE(mainArgs); /* Invoke main method. */ (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs); @@ -498,8 +429,9 @@ */ ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1; +leave: /* - * Detach the main thread so that it appears to have ended when + * Always detach the main thread so that it appears to have ended when * the application's main method exits. This will invoke the * uncaught exception handler machinery if main threw an * exception. An uncaught exception handler cannot change the @@ -508,10 +440,7 @@ if ((*vm)->DetachCurrentThread(vm) != 0) { JLI_ReportErrorMessage(JVM_ERROR2); ret = 1; - goto leave; } - - leave: /* * Wait for all non-daemon threads to end, then destroy the VM. * This will actually create a trivial new Java waiter thread @@ -525,7 +454,6 @@ return ret; } - /* * Checks the command line options to find which JVM type was * specified. If no command line option was given for the JVM type, @@ -1159,7 +1087,7 @@ if (propname) { jclass cls; jmethodID mid; - NULL_CHECK0 (cls = (*env)->FindClass(env, "java/lang/System")); + NULL_CHECK0 (cls = FindBootStrapClass(env, "java/lang/System")); NULL_CHECK0 (mid = (*env)->GetStaticMethodID( env, cls, "getProperty", @@ -1174,7 +1102,7 @@ static jboolean isEncodingSupported(JNIEnv *env, jstring enc) { jclass cls; jmethodID mid; - NULL_CHECK0 (cls = (*env)->FindClass(env, "java/nio/charset/Charset")); + NULL_CHECK0 (cls = FindBootStrapClass(env, "java/nio/charset/Charset")); NULL_CHECK0 (mid = (*env)->GetStaticMethodID( env, cls, "isSupported", @@ -1203,8 +1131,8 @@ jstring str = 0; (*env)->SetByteArrayRegion(env, ary, 0, len, (jbyte *)s); if (!(*env)->ExceptionOccurred(env)) { + NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String")); if (isEncodingSupported(env, enc) == JNI_TRUE) { - NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String")); NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "", "([BLjava/lang/String;)V")); str = (*env)->NewObject(env, cls, mid, ary, enc); @@ -1215,7 +1143,6 @@ the encoding name, in which the StringCoding class will pickup the iso-8859-1 as the fallback converter for us. */ - NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String")); NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "", "([B)V")); str = (*env)->NewObject(env, cls, mid, ary); @@ -1238,7 +1165,7 @@ jarray ary; int i; - NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String")); + NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String")); NULL_CHECK0(ary = (*env)->NewObjectArray(env, strc, cls, 0)); for (i = 0; i < strc; i++) { jstring str = NewPlatformString(env, *strv++); @@ -1250,25 +1177,26 @@ } /* - * Loads a class, convert the '.' to '/'. + * Loads a class and verifies that the main class is present and it is ok to + * call it for more details refer to the java implementation. */ static jclass -LoadClass(JNIEnv *env, char *name) +LoadMainClass(JNIEnv *env, jboolean isJar, char *name) { - char *buf = JLI_MemAlloc(JLI_StrLen(name) + 1); - char *s = buf, *t = name, c; jclass cls; + jmethodID mid; + jstring str; + jobject result; jlong start, end; - if (JLI_IsTraceLauncher()) + if (JLI_IsTraceLauncher()) { start = CounterGet(); - - do { - c = *t++; - *s++ = (c == '.') ? '/' : c; - } while (c != '\0'); - cls = (*env)->FindClass(env, buf); - JLI_MemFree(buf); + } + NULL_CHECK0(cls = FindBootStrapClass(env, "sun/launcher/LauncherHelper")); + NULL_CHECK0(mid = (*env)->GetStaticMethodID(env, cls, "checkAndLoadMain", + "(ZZLjava/lang/String;)Ljava/lang/Object;")); + str = (*env)->NewStringUTF(env, name); + result = (*env)->CallStaticObjectMethod(env, cls, mid, JNI_TRUE, isJar, str); if (JLI_IsTraceLauncher()) { end = CounterGet(); @@ -1277,49 +1205,9 @@ printf("----_JAVA_LAUNCHER_DEBUG----\n"); } - return cls; + return (jclass)result; } - -/* - * Returns the main class name for the specified jar file. - */ -static jstring -GetMainClassName(JNIEnv *env, char *jarname) -{ -#define MAIN_CLASS "Main-Class" - jclass cls; - jmethodID mid; - jobject jar, man, attr; - jstring str, result = 0; - - NULL_CHECK0(cls = (*env)->FindClass(env, "java/util/jar/JarFile")); - NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "", - "(Ljava/lang/String;)V")); - NULL_CHECK0(str = NewPlatformString(env, jarname)); - NULL_CHECK0(jar = (*env)->NewObject(env, cls, mid, str)); - NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "getManifest", - "()Ljava/util/jar/Manifest;")); - man = (*env)->CallObjectMethod(env, jar, mid); - if (man != 0) { - NULL_CHECK0(mid = (*env)->GetMethodID(env, - (*env)->GetObjectClass(env, man), - "getMainAttributes", - "()Ljava/util/jar/Attributes;")); - attr = (*env)->CallObjectMethod(env, man, mid); - if (attr != 0) { - NULL_CHECK0(mid = (*env)->GetMethodID(env, - (*env)->GetObjectClass(env, attr), - "getValue", - "(Ljava/lang/String;)Ljava/lang/String;")); - NULL_CHECK0(str = NewPlatformString(env, MAIN_CLASS)); - result = (*env)->CallObjectMethod(env, attr, mid, str); - } - } - return result; -} - - /* * For tools, convert command line args thus: * javac -cp foo:foo/"*" -J-ms32m ... @@ -1522,7 +1410,7 @@ jclass ver; jmethodID print; - NULL_CHECK(ver = (*env)->FindClass(env, "sun/misc/Version")); + NULL_CHECK(ver = FindBootStrapClass(env, "sun/misc/Version")); NULL_CHECK(print = (*env)->GetStaticMethodID(env, ver, (extraLF == JNI_TRUE) ? "println" : "print", @@ -1534,7 +1422,7 @@ } /* - * Prints default usage or the Xusage message, see sun.launcher.LauncherHelp.java + * Prints default usage or the Xusage message, see sun.launcher.LauncherHelper.java */ static void PrintUsage(JNIEnv* env, jboolean doXUsage) @@ -1544,7 +1432,7 @@ jstring jprogname, vm1, vm2; int i; - NULL_CHECK(cls = (*env)->FindClass(env, "sun/launcher/LauncherHelp")); + NULL_CHECK(cls = FindBootStrapClass(env, "sun/launcher/LauncherHelper")); if (doXUsage) {