6968053: (launcher) hide exceptions under certain launcher failures
authorksrini
Thu, 03 Feb 2011 15:41:23 -0800
changeset 8174 89e3a22d4cd7
parent 8173 a3a39b98e05a
child 8176 8836ea1be1ab
6968053: (launcher) hide exceptions under certain launcher failures Reviewed-by: mchung
jdk/src/share/bin/java.c
jdk/src/share/classes/sun/launcher/LauncherHelper.java
jdk/src/share/classes/sun/launcher/resources/launcher.properties
jdk/src/share/classes/sun/misc/VM.java
jdk/test/tools/launcher/Arrrghs.java
--- 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.
--- 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;
     }
--- 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:<directories and zip/jar files separated by {0}>\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:<file>    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}
--- 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
--- 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);