OpenJDK / jigsaw / jake / jdk
changeset 14210:9e9452626802
Switch java -m to only attempt to load main class from the initial module
author | alanb |
---|---|
date | Fri, 09 Oct 2015 11:06:54 +0100 |
parents | 26f5411f52f4 |
children | cdaf9fbbbc81 |
files | src/java.base/share/classes/sun/launcher/LauncherHelper.java src/java.base/share/classes/sun/launcher/resources/launcher.properties |
diffstat | 2 files changed, 111 insertions(+), 88 deletions(-) [+] |
line wrap: on
line diff
--- a/src/java.base/share/classes/sun/launcher/LauncherHelper.java Fri Oct 09 11:05:37 2015 +0100 +++ b/src/java.base/share/classes/sun/launcher/LauncherHelper.java Fri Oct 09 11:06:54 2015 +0100 @@ -52,6 +52,7 @@ import java.lang.reflect.Layer; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.lang.reflect.Module; import java.math.BigDecimal; import java.math.RoundingMode; import java.net.URI; @@ -68,7 +69,6 @@ import java.util.Collection; import java.util.Collections; import java.util.Comparator; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -77,7 +77,6 @@ import java.util.Properties; import java.util.Map; import java.util.Set; -import java.util.TreeMap; import java.util.TreeSet; import java.util.jar.Attributes; import java.util.jar.JarFile; @@ -453,52 +452,6 @@ return null; } - /** - * Returns the main class for a module. The query is either a module name - * or module-name/main-class. For the former then the module's main class - * is obtained from the module descriptor (MainClass attribute). - */ - static String getMainClassForModule(String query) { - int i = query.indexOf('/'); - String mainModule; - String mainClass; - if (i == -1) { - mainModule = query; - mainClass = null; - } else { - mainModule = query.substring(0, i); - mainClass = query.substring(i+1); - } - - // main module should be in the boot layer - Layer layer = Layer.boot(); - ModuleReference mref - = layer.configuration().get().findModule(mainModule).orElse(null); - if (mref == null) - abort(null, "java.launcher.module.error1", mainModule); - - // if query included the main-class then we return that - if (mainClass != null) { - i = mainClass.lastIndexOf('.'); - if (i > 0) { - String pkg = mainClass.substring(0, i); - if (!mref.descriptor().packages().contains(pkg)) { - // main class not in a package that the module defines - abort(null, "java.launcher.module.error2", mainModule, mainClass); - } - } else { - // main-class cannot be in the unnamed package - abort(null, "java.launcher.module.error2", mainModule, "<unnamed>"); - } - return mainClass; - } - - Optional<String> omc = mref.descriptor().mainClass(); - if (!omc.isPresent()) - abort(null, "java.launcher.module.error3", mainModule); - return omc.get(); - } - // From src/share/bin/java.c: // enum LaunchMode { LM_UNKNOWN = 0, LM_CLASS, LM_JAR, LM_MODULE } @@ -522,34 +475,100 @@ } /** - * This method does the following: - * 1. gets the classname from a Jar's manifest, if necessary - * 2. loads the class using the System ClassLoader - * 3. ensures the availability and accessibility of the main method, - * using signatureDiagnostic method. - * a. does the class exist - * b. is there a main - * c. is the main public - * d. is the main static - * e. does the main take a String array for args - * 4. if no main method and if the class extends FX Application, then call - * on FXHelper to determine the main class to launch - * 5. and off we go...... + * This method: + * 1. Loads the main class from the module or class path + * 2. Checks the public static void main method. + * 3. In the case of no main method and if the class extends FX Application, + * then call on FXHelper to determine the main class to launch * * @param printToStderr if set, all output will be routed to stderr * @param mode LaunchMode as determined by the arguments passed on the - * command line - * @param what either the jar file to launch or the main class when using - * LM_CLASS mode + * command line + * @param what the module name[/class], JAR file, or the main class + * depending on the mode + * * @return the application's main class */ public static Class<?> checkAndLoadMain(boolean printToStderr, int mode, - String what) - { + String what) { initOutput(printToStderr); - // get the main class name + Class<?> mainClass; + if (mode == LM_MODULE) { + mainClass = loadModuleMainClass(what); + } else { + mainClass = loadMainClass(mode, what); + } + + validateMainClass(mainClass); + + // record main class if not already set + if (appClass == null) + appClass = mainClass; + + return mainClass; + } + + /** + * Returns the main class for a module. The query is either a module name + * or module-name/main-class. For the former then the module's main class + * is obtained from the module descriptor (MainClass attribute). + */ + private static Class<?> loadModuleMainClass(String what) { + int i = what.indexOf('/'); + String mainModule; + String mainClass; + if (i == -1) { + mainModule = what; + mainClass = null; + } else { + mainModule = what.substring(0, i); + mainClass = what.substring(i+1); + } + + // main module is in the boot layer + Layer layer = Layer.boot(); + Optional<Module> om = layer.findModule(mainModule); + if (!om.isPresent()) { + // should not happen + throw new InternalError("Module " + mainModule + " not in boot Layer"); + } + Module m = om.get(); + + // get main class + if (mainClass == null) { + Optional<String> omc = m.getDescriptor().mainClass(); + if (!omc.isPresent()) { + abort(null, "java.launcher.module.error1", mainModule); + } + mainClass = omc.get(); + } + + // load the class from the module + Class<?> c = Class.forName(m, mainClass); + if (c == null && System.getProperty("os.name", "").contains("OS X") + && Normalizer.isNormalized(mainClass, Normalizer.Form.NFD)) { + + String cn = Normalizer.normalize(mainClass, Normalizer.Form.NFC); + c = Class.forName(m, cn); + + } + if (c == null) { + abort(null, "java.launcher.cls.error6", mainClass, mainModule); + } + + System.setProperty("jdk.module.main.class", c.getName()); + return c; + } + + /** + * Loads the main class from the class path (LM_CLASS or LM_JAR). + * If the main class extends FX Application then call on FXHelper to + * determine the main class to launch. + */ + private static Class<?> loadMainClass(int mode, String what) { + // get the class name String cn = null; switch (mode) { case LM_CLASS: @@ -558,28 +577,24 @@ case LM_JAR: cn = getMainClassFromJar(what); break; - case LM_MODULE: - cn = getMainClassForModule(what); - break; default: // should never happen throw new InternalError("" + mode + ": Unknown launch mode"); } - - // load the main class + // set to mainClass cn = cn.replace('/', '.'); Class<?> mainClass = null; - ClassLoader scloader = ClassLoader.getSystemClassLoader(); + ClassLoader scl = ClassLoader.getSystemClassLoader(); try { - mainClass = scloader.loadClass(cn); + mainClass = scl.loadClass(cn); } catch (NoClassDefFoundError | ClassNotFoundException cnfe) { if (System.getProperty("os.name", "").contains("OS X") - && Normalizer.isNormalized(cn, Normalizer.Form.NFD)) { + && Normalizer.isNormalized(cn, Normalizer.Form.NFD)) { try { // On Mac OS X since all names with diacretic symbols are given as decomposed it // is possible that main class name comes incorrectly from the command line // and we have to re-compose it - mainClass = scloader.loadClass(Normalizer.normalize(cn, Normalizer.Form.NFC)); + mainClass = scl.loadClass(Normalizer.normalize(cn, Normalizer.Form.NFC)); } catch (NoClassDefFoundError | ClassNotFoundException cnfe1) { abort(cnfe, "java.launcher.cls.error1", cn); } @@ -589,9 +604,6 @@ } // record the main class - if (mode == LM_MODULE) { - System.setProperty("jdk.module.main.class", mainClass.getName()); - } appClass = mainClass; /* @@ -605,8 +617,6 @@ FXHelper.setFXLaunchParameters(what, mode); return FXHelper.class; } - - validateMainClass(mainClass); return mainClass; } @@ -767,6 +777,9 @@ static final class FXHelper { + private static final String JAVAFX_GRAPHICS_MODULE_NAME = + "javafx.graphics"; + private static final String JAVAFX_LAUNCHER_CLASS_NAME = "com.sun.javafx.application.LauncherImpl"; @@ -799,10 +812,20 @@ * issue with loading the FX runtime or with the launcher method. */ private static void setFXLaunchParameters(String what, int mode) { - // Check for the FX launcher classes + + // find the module with the FX launcher + Optional<Module> om = Layer.boot().findModule(JAVAFX_GRAPHICS_MODULE_NAME); + if (!om.isPresent()) { + abort(null, "java.launcher.cls.error5"); + } + + // load the FX launcher class + fxLauncherClass = Class.forName(om.get(), JAVAFX_LAUNCHER_CLASS_NAME); + if (fxLauncherClass == null) { + abort(null, "java.launcher.cls.error5"); + } + try { - fxLauncherClass = ClassLoader.getSystemClassLoader() - .loadClass(JAVAFX_LAUNCHER_CLASS_NAME); /* * signature must be: * public static void launchApplication(String launchName, @@ -819,7 +842,7 @@ if (fxLauncherMethod.getReturnType() != java.lang.Void.TYPE) { abort(null, "java.launcher.javafx.error1"); } - } catch (ClassNotFoundException | NoSuchMethodException ex) { + } catch (NoSuchMethodException ex) { abort(ex, "java.launcher.cls.error5", ex); }
--- a/src/java.base/share/classes/sun/launcher/resources/launcher.properties Fri Oct 09 11:05:37 2015 +0100 +++ b/src/java.base/share/classes/sun/launcher/resources/launcher.properties Fri Oct 09 11:06:54 2015 +0100 @@ -160,6 +160,8 @@ or a JavaFX application class must extend {1} java.launcher.cls.error5=\ Error: JavaFX runtime components are missing, and are required to run this application +java.launcher.cls.error6=\ + Error: Could not find or load main class {0} in module {1} java.launcher.jar.error1=\ Error: An unexpected error occurred while trying to open file {0} java.launcher.jar.error2=manifest not found in {0} @@ -168,7 +170,5 @@ java.launcher.javafx.error1=\ Error: The JavaFX launchApplication method has the wrong signature, it\n\ must be declared static and return a value of type void -java.launcher.module.error1=module {0} not on module path -java.launcher.module.error2=module {0} does not define package for main class {1} -java.launcher.module.error3=\ +java.launcher.module.error1=\ module {0} does not have a MainClass attribute, use -m <module>/<main-class>