6968053: (launcher) hide exceptions under certain launcher failures
Reviewed-by: mchung
--- 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);