# HG changeset patch # User ksrini # Date 1296776483 28800 # Node ID 89e3a22d4cd7270022cfe2312579becf3ae827b1 # Parent a3a39b98e05ac5f4a449c9236bb4b5dd9b33f323 6968053: (launcher) hide exceptions under certain launcher failures Reviewed-by: mchung diff -r a3a39b98e05a -r 89e3a22d4cd7 jdk/src/share/bin/java.c --- a/jdk/src/share/bin/java.c Thu Feb 03 13:49:25 2011 -0800 +++ b/jdk/src/share/bin/java.c Thu Feb 03 15:41:23 2011 -0800 @@ -244,6 +244,7 @@ for (i = 0; i < argc ; i++) { printf("argv[%d] = %s\n", i, argv[i]); } + AddOption("-Dsun.java.launcher.diag=true", NULL); } CreateExecutionEnvironment(&argc, &argv, @@ -1009,6 +1010,8 @@ } else if (JLI_StrCmp(arg, "-XshowSettings") == 0 || JLI_StrCCmp(arg, "-XshowSettings:") == 0) { showSettings = arg; + } else if (JLI_StrCmp(arg, "-Xdiag") == 0) { + AddOption("-Dsun.java.launcher.diag=true", NULL); /* * The following case provide backward compatibility with old-style * command line options. diff -r a3a39b98e05a -r 89e3a22d4cd7 jdk/src/share/classes/sun/launcher/LauncherHelper.java --- a/jdk/src/share/classes/sun/launcher/LauncherHelper.java Thu Feb 03 13:49:25 2011 -0800 +++ b/jdk/src/share/classes/sun/launcher/LauncherHelper.java Thu Feb 03 15:41:23 2011 -0800 @@ -63,8 +63,6 @@ public enum LauncherHelper { INSTANCE; - private static final String defaultBundleName = - "sun.launcher.resources.launcher"; private static final String MAIN_CLASS = "Main-Class"; private static StringBuilder outBuf = new StringBuilder(); @@ -76,11 +74,14 @@ private static final String PROP_SETTINGS = "Property settings:"; private static final String LOCALE_SETTINGS = "Locale settings:"; - private static synchronized ResourceBundle getLauncherResourceBundle() { - if (javarb == null) { - javarb = ResourceBundle.getBundle(defaultBundleName); - } - return javarb; + // sync with java.c and sun.misc.VM + private static final String diagprop = "sun.java.launcher.diag"; + + private static final String defaultBundleName = + "sun.launcher.resources.launcher"; + private static class ResourceBundleHolder { + private static final ResourceBundle RB = + ResourceBundle.getBundle(defaultBundleName); } /* @@ -308,7 +309,7 @@ * apply any arguments that we might pass. */ private static String getLocalizedMessage(String key, Object... args) { - String msg = getLauncherResourceBundle().getString(key); + String msg = ResourceBundleHolder.RB.getString(key); return (args != null) ? MessageFormat.format(msg, args) : msg; } @@ -380,25 +381,29 @@ File.pathSeparator)); } - static String getMainClassFromJar(String jarname) throws IOException { - JarFile jarFile = null; + static String getMainClassFromJar(PrintStream ostream, String jarname) { try { - jarFile = new JarFile(jarname); - Manifest manifest = jarFile.getManifest(); - if (manifest == null) { - throw new IOException("manifest not found in " + jarname); + JarFile jarFile = null; + try { + jarFile = new JarFile(jarname); + Manifest manifest = jarFile.getManifest(); + if (manifest == null) { + abort(ostream, null, "java.launcher.jar.error2", jarname); + } + Attributes mainAttrs = manifest.getMainAttributes(); + if (mainAttrs == null) { + abort(ostream, null, "java.launcher.jar.error3", jarname); + } + return mainAttrs.getValue(MAIN_CLASS).trim(); + } finally { + if (jarFile != null) { + jarFile.close(); + } } - Attributes mainAttrs = manifest.getMainAttributes(); - if (mainAttrs == null) { - throw new IOException("no main mainifest attributes, in " + - jarname); - } - return mainAttrs.getValue(MAIN_CLASS).trim(); - } finally { - if (jarFile != null) { - jarFile.close(); - } + } catch (IOException ioe) { + abort(ostream, ioe, "java.launcher.jar.error1", jarname); } + return null; } @@ -409,6 +414,20 @@ private static final int LM_CLASS = 1; private static final int LM_JAR = 2; + static void abort(PrintStream ostream, Throwable t, String msgKey, Object... args) { + if (msgKey != null) { + ostream.println(getLocalizedMessage(msgKey, args)); + } + if (sun.misc.VM.getSavedProperty(diagprop) != null) { + if (t != null) { + t.printStackTrace(); + } else { + Thread.currentThread().dumpStack(); + } + } + System.exit(1); + } + /** * This method does the following: * 1. gets the classname from a Jar's manifest, if necessary @@ -426,39 +445,31 @@ * @param isJar * @param name * @return - * @throws java.io.IOException */ public static Class checkAndLoadMain(boolean printToStderr, int mode, - String what) throws IOException - { - - ClassLoader ld = ClassLoader.getSystemClassLoader(); - + String what) { + final PrintStream ostream = (printToStderr) ? System.err : System.out; + final ClassLoader ld = ClassLoader.getSystemClassLoader(); // get the class name String cn = null; switch (mode) { - case LM_CLASS: - cn = what; - break; - case LM_JAR: - cn = getMainClassFromJar(what); - break; - default: - throw new InternalError("" + mode + ": Unknown launch mode"); + case LM_CLASS: + cn = what; + break; + case LM_JAR: + cn = getMainClassFromJar(ostream, what); + break; + default: + // should never happen + throw new InternalError("" + mode + ": Unknown launch mode"); } cn = cn.replace('/', '.'); - - PrintStream ostream = (printToStderr) ? System.err : System.out; Class c = null; try { c = ld.loadClass(cn); } catch (ClassNotFoundException cnfe) { - ostream.println(getLocalizedMessage("java.launcher.cls.error1", - cn)); - NoClassDefFoundError ncdfe = new NoClassDefFoundError(cn); - ncdfe.initCause(cnfe); - throw ncdfe; + abort(ostream, cnfe, "java.launcher.cls.error1", cn); } signatureDiagnostic(ostream, c); return c; @@ -470,9 +481,7 @@ try { method = clazz.getMethod("main", String[].class); } catch (NoSuchMethodException nsme) { - ostream.println(getLocalizedMessage("java.launcher.cls.error4", - classname)); - throw new RuntimeException("Main method not found in " + classname); + abort(ostream, null, "java.launcher.cls.error4", classname); } /* * getMethod (above) will choose the correct method, based @@ -481,17 +490,10 @@ */ int mod = method.getModifiers(); if (!Modifier.isStatic(mod)) { - ostream.println(getLocalizedMessage("java.launcher.cls.error2", - "static", classname)); - throw new RuntimeException("Main method is not static in class " + - classname); + abort(ostream, null, "java.launcher.cls.error2", "static", classname); } if (method.getReturnType() != java.lang.Void.TYPE) { - ostream.println(getLocalizedMessage("java.launcher.cls.error3", - classname)); - throw new RuntimeException("Main method must return a value" + - " of type void in class " + - classname); + abort(ostream, null, "java.launcher.cls.error3", classname); } return; } diff -r a3a39b98e05a -r 89e3a22d4cd7 jdk/src/share/classes/sun/launcher/resources/launcher.properties --- a/jdk/src/share/classes/sun/launcher/resources/launcher.properties Thu Feb 03 13:49:25 2011 -0800 +++ b/jdk/src/share/classes/sun/launcher/resources/launcher.properties Thu Feb 03 15:41:23 2011 -0800 @@ -84,6 +84,7 @@ \ append to end of bootstrap class path\n\ \ -Xbootclasspath/p:\n\ \ prepend in front of bootstrap class path\n\ +\ -Xdiag show additional diagnostic messages\n\ \ -Xnoclassgc disable class garbage collection\n\ \ -Xincgc enable incremental garbage collection\n\ \ -Xloggc: log GC status to a file with time stamps\n\ @@ -109,7 +110,7 @@ The -X options are non-standard and subject to change without notice.\n java.launcher.cls.error1=\ - Error: Could not find main class {0} + Error: Could not find or load main class {0} java.launcher.cls.error2=\ Error: Main method is not {0} in class {1}, please define the main method as:\n\ \ public static void main(String[] args) @@ -120,5 +121,7 @@ java.launcher.cls.error4=\ Error: Main method not found in class {0}, please define the main method as:\n\ \ public static void main(String[] args) - - +java.launcher.jar.error1=\ + Error: An unexpected error occurred while trying to open file {0} +java.launcher.jar.error2=manifest not found in {0} +java.launcher.jar.error3=no main manifest attribute, in {0} diff -r a3a39b98e05a -r 89e3a22d4cd7 jdk/src/share/classes/sun/misc/VM.java --- a/jdk/src/share/classes/sun/misc/VM.java Thu Feb 03 13:49:25 2011 -0800 +++ b/jdk/src/share/classes/sun/misc/VM.java Thu Feb 03 15:41:23 2011 -0800 @@ -235,6 +235,9 @@ return savedProps.getProperty(key); } + // TODO: the Property Management needs to be refactored and + // the appropriate prop keys need to be accessible to the + // calling classes to avoid duplication of keys. private static final Properties savedProps = new Properties(); // Save a private copy of the system properties and remove @@ -283,6 +286,9 @@ // used by java.util.zip.ZipFile props.remove("sun.zip.disableMemoryMapping"); + + // used by sun.launcher.LauncherHelper + props.remove("sun.java.launcher.diag"); } // Initialize any miscellenous operating system settings that need to be diff -r a3a39b98e05a -r 89e3a22d4cd7 jdk/test/tools/launcher/Arrrghs.java --- a/jdk/test/tools/launcher/Arrrghs.java Thu Feb 03 13:49:25 2011 -0800 +++ b/jdk/test/tools/launcher/Arrrghs.java Thu Feb 03 15:41:23 2011 -0800 @@ -24,7 +24,7 @@ /** * @test * @bug 5030233 6214916 6356475 6571029 6684582 6742159 4459600 6758881 6753938 - * 6894719 + * 6894719 6968053 * @summary Argument parsing validation. * @compile -XDignore.symbol.file Arrrghs.java TestHelper.java * @run main Arrrghs @@ -250,13 +250,11 @@ TestHelper.createJar("MIA", new File("some.jar"), new File("Foo"), (String[])null); tr = TestHelper.doExec(TestHelper.javaCmd, "-jar", "some.jar"); - tr.contains("Error: Could not find main class MIA"); - tr.contains("java.lang.NoClassDefFoundError: MIA"); + tr.contains("Error: Could not find or load main class MIA"); System.out.println(tr); // use classpath to check tr = TestHelper.doExec(TestHelper.javaCmd, "-cp", "some.jar", "MIA"); - tr.contains("Error: Could not find main class MIA"); - tr.contains("java.lang.NoClassDefFoundError: MIA"); + tr.contains("Error: Could not find or load main class MIA"); System.out.println(tr); // incorrect method access @@ -305,12 +303,12 @@ // amongst a potpourri of kindred main methods, is the right one chosen ? TestHelper.createJar(new File("some.jar"), new File("Foo"), - "void main(Object[] args){}", - "int main(Float[] args){return 1;}", - "private void main() {}", - "private static void main(int x) {}", - "public int main(int argc, String[] argv) {return 1;}", - "public static void main(String[] args) {System.out.println(\"THE_CHOSEN_ONE\");}"); + "void main(Object[] args){}", + "int main(Float[] args){return 1;}", + "private void main() {}", + "private static void main(int x) {}", + "public int main(int argc, String[] argv) {return 1;}", + "public static void main(String[] args) {System.out.println(\"THE_CHOSEN_ONE\");}"); tr = TestHelper.doExec(TestHelper.javaCmd, "-jar", "some.jar"); tr.contains("THE_CHOSEN_ONE"); System.out.println(tr); @@ -326,6 +324,30 @@ tr.checkPositive(); System.out.println(tr); } + // tests 6968053, ie. we turn on the -Xdiag (for now) flag and check if + // the suppressed stack traces are exposed. + static void runDiagOptionTests() throws FileNotFoundException { + TestHelper.TestResult tr = null; + // a missing class + TestHelper.createJar("MIA", new File("some.jar"), new File("Foo"), + (String[])null); + tr = TestHelper.doExec(TestHelper.javaCmd, "-Xdiag", "-jar", "some.jar"); + tr.contains("Error: Could not find or load main class MIA"); + tr.contains("java.lang.ClassNotFoundException: MIA"); + System.out.println(tr); + + // use classpath to check + tr = TestHelper.doExec(TestHelper.javaCmd, "-Xdiag", "-cp", "some.jar", "MIA"); + tr.contains("Error: Could not find or load main class MIA"); + tr.contains("java.lang.ClassNotFoundException: MIA"); + System.out.println(tr); + + // a missing class on the classpath + tr = TestHelper.doExec(TestHelper.javaCmd, "-Xdiag", "NonExistentClass"); + tr.contains("Error: Could not find or load main class NonExistentClass"); + tr.contains("java.lang.ClassNotFoundException: NonExistentClass"); + System.out.println(tr); + } static void test6894719() { // test both arguments to ensure they exist @@ -352,6 +374,7 @@ runBasicErrorMessageTests(); runMainMethodTests(); test6894719(); + runDiagOptionTests(); if (TestHelper.testExitValue > 0) { System.out.println("Total of " + TestHelper.testExitValue + " failed"); System.exit(1);