8159596: Add java --dry-run
authormchung
Mon, 27 Jun 2016 20:22:04 -0700
changeset 39303 5aefc354587e
parent 39302 aa8d0bc2a6d2
child 39304 8d9ceb81a46e
8159596: Add java --dry-run Reviewed-by: alanb, ksrini
jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties
jdk/src/java.base/share/native/libjli/java.c
jdk/test/tools/launcher/modules/dryrun/DryRunTest.java
jdk/test/tools/launcher/modules/dryrun/src/m/module-info.java
jdk/test/tools/launcher/modules/dryrun/src/m/p/Lib.java
jdk/test/tools/launcher/modules/dryrun/src/test/jdk/test/Main.java
jdk/test/tools/launcher/modules/dryrun/src/test/module-info.java
--- a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties	Tue Jun 28 00:39:26 2016 +0200
+++ b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties	Mon Jun 27 20:22:04 2016 -0700
@@ -60,6 +60,9 @@
 \                  limit the universe of observable modules\n\
 \    -listmods[:<modulename>[,<modulename>...]]\n\
 \                  list the observable modules and exit\n\
+\    --dry-run     create VM but do not execute main method.\n\
+\                  This --dry-run option may be useful for validating the\n\
+\                  command-line options such as the module system configuration.\n\
 \    -D<name>=<value>\n\
 \                  set a system property\n\
 \    -verbose:[class|gc|jni]\n\
--- a/jdk/src/java.base/share/native/libjli/java.c	Tue Jun 28 00:39:26 2016 +0200
+++ b/jdk/src/java.base/share/native/libjli/java.c	Mon Jun 27 20:22:04 2016 -0700
@@ -68,6 +68,7 @@
 static jboolean showVersion = JNI_FALSE;  /* print but continue */
 static jboolean printUsage = JNI_FALSE;   /* print and exit*/
 static jboolean printXUsage = JNI_FALSE;  /* print and exit*/
+static jboolean dryRun = JNI_FALSE;       /* initialize VM and exit */
 static char     *showSettings = NULL;      /* print but continue */
 static char     *listModules = NULL;
 
@@ -489,14 +490,18 @@
     mainArgs = CreateApplicationArgs(env, argv, argc);
     CHECK_EXCEPTION_NULL_LEAVE(mainArgs);
 
-    /* Invoke main method. */
-    (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
+    if (dryRun) {
+        ret = 0;
+    } else {
+        /* Invoke main method. */
+        (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
 
-    /*
-     * The launcher's exit code (in the absence of calls to
-     * System.exit) will be non-zero if main threw an exception.
-     */
-    ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
+        /*
+         * The launcher's exit code (in the absence of calls to
+         * System.exit) will be non-zero if main threw an exception.
+         */
+        ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
+    }
     LEAVE();
 }
 
@@ -1203,6 +1208,8 @@
             return JNI_TRUE;
         } else if (JLI_StrCmp(arg, "-showversion") == 0) {
             showVersion = JNI_TRUE;
+        } else if (JLI_StrCmp(arg, "--dry-run") == 0) {
+            dryRun = JNI_TRUE;
         } else if (JLI_StrCmp(arg, "-X") == 0) {
             printXUsage = JNI_TRUE;
             return JNI_TRUE;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/dryrun/DryRunTest.java	Mon Jun 27 20:22:04 2016 -0700
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8159596
+ * @library /lib/testlibrary
+ * @modules jdk.compiler
+ *          jdk.jartool/sun.tools.jar
+ * @build DryRunTest CompilerUtils jdk.testlibrary.ProcessTools
+ * @run testng DryRunTest
+ * @summary Test java --dry-run
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import jdk.testlibrary.ProcessTools;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+
+@Test
+public class DryRunTest {
+
+    private static final String TEST_SRC = System.getProperty("test.src");
+
+    private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+    private static final Path MODS_DIR = Paths.get("mods");
+    private static final Path LIBS_DIR = Paths.get("libs");
+
+    // the module name of the test module
+    private static final String TEST_MODULE = "test";
+    private static final String M_MODULE = "m";
+
+    // the module main class
+    private static final String MAIN_CLASS = "jdk.test.Main";
+
+
+    @BeforeTest
+    public void compileTestModule() throws Exception {
+
+        // javac -d mods/$TESTMODULE src/$TESTMODULE/**
+        assertTrue(CompilerUtils.compile(SRC_DIR.resolve(M_MODULE),
+                                         MODS_DIR,
+                                         "-modulesourcepath", SRC_DIR.toString()));
+
+        assertTrue(CompilerUtils.compile(SRC_DIR.resolve(TEST_MODULE),
+                                         MODS_DIR,
+                                         "-modulesourcepath", SRC_DIR.toString()));
+
+        Files.createDirectories(LIBS_DIR);
+
+        // create JAR files with no module-info.class
+        assertTrue(jar(M_MODULE, "p/Lib.class"));
+        assertTrue(jar(TEST_MODULE, "jdk/test/Main.class"));
+    }
+
+    /**
+     * Execute "java" with the given arguments, returning the exit code.
+     */
+    private int exec(String... args) throws Exception {
+       return ProcessTools.executeTestJava(args)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+    }
+
+
+    /**
+     * Launch module main
+     */
+    public void testModule() throws Exception {
+        String dir = MODS_DIR.toString();
+        String mid = TEST_MODULE + "/" + MAIN_CLASS;
+
+        // java -modulepath mods -module $TESTMODULE/$MAINCLASS
+        // no resolution failure
+        int exitValue = exec("--dry-run", "-modulepath", dir, "-m", mid);
+        assertTrue(exitValue == 0);
+    }
+
+    /**
+     * Test non-existence module in -addmods
+     */
+    public void testNonExistAddModules() throws Exception {
+        String dir = MODS_DIR.toString();
+        String mid = TEST_MODULE + "/" + MAIN_CLASS;
+
+        int exitValue = exec("--dry-run", "-modulepath", dir,
+                             "-addmods", "non.existence",
+                             "-m", mid);
+        assertTrue(exitValue != 0);
+    }
+
+    /**
+     * Launch main class from class path
+     */
+    public void testClassPath() throws Exception {
+        Path testJar = LIBS_DIR.resolve(TEST_MODULE + ".jar");
+        String libs = testJar.toString() + File.pathSeparator +
+                        LIBS_DIR.resolve(M_MODULE + ".jar").toString();
+
+        // test pass with m.jar:test.jar
+        int exitValue = exec("-classpath", libs, MAIN_CLASS);
+        assertTrue(exitValue == 0);
+
+        // m.jar is not on classpath and fails with p.Lib not found
+        exitValue = exec("-classpath", testJar.toString(), MAIN_CLASS);
+        assertTrue(exitValue != 0);
+
+        // dry pass passes since main is not executed
+        exitValue = exec("--dry-run", "-classpath", testJar.toString(), MAIN_CLASS);
+        assertTrue(exitValue == 0);
+    }
+
+    /**
+     * Test automatic modules
+     */
+    public void testAutomaticModule() throws Exception {
+        String libs = LIBS_DIR.resolve(M_MODULE + ".jar").toString() +
+                        File.pathSeparator +
+                        LIBS_DIR.resolve(TEST_MODULE + ".jar").toString();
+        String mid = TEST_MODULE + "/" + MAIN_CLASS;
+
+        // test main method with and without -addmods mm
+        int exitValue = exec("-modulepath", LIBS_DIR.toString(),
+                             "-m", mid);
+        assertTrue(exitValue != 0);
+
+        exitValue = exec("-modulepath", LIBS_DIR.toString(),
+                         "-addmods", M_MODULE,
+                         "-m", mid);
+        assertTrue(exitValue == 0);
+
+        // test dry run with and without -addmods m
+        // no resolution failure
+        exitValue = exec("--dry-run", "-modulepath", LIBS_DIR.toString(),
+                         "-m", mid);
+        assertTrue(exitValue == 0);
+
+        exitValue = exec("--dry-run", "-modulepath", LIBS_DIR.toString(),
+                         "-addmods", M_MODULE,
+                         "-m", mid);
+        assertTrue(exitValue == 0);
+    }
+
+    /**
+     * module m not found
+     */
+    public void testMissingModule() throws Exception {
+        String subdir = MODS_DIR.resolve(TEST_MODULE).toString();
+        String mid = TEST_MODULE + "/" + MAIN_CLASS;
+
+        // resolution failure
+        int exitValue = exec("--dry-run", "-modulepath", subdir, "-m", mid);
+        assertTrue(exitValue != 0);
+    }
+
+    private static boolean jar(String name, String entries) throws IOException {
+        Path jar = LIBS_DIR.resolve(name + ".jar");
+
+        // jar --create ...
+        String classes = MODS_DIR.resolve(name).toString();
+        String[] args = {
+            "--create",
+            "--file=" + jar,
+            "-C", classes, entries
+        };
+        boolean success
+            = new sun.tools.jar.Main(System.out, System.out, "jar").run(args);
+        return success;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/dryrun/src/m/module-info.java	Mon Jun 27 20:22:04 2016 -0700
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m {
+    exports p;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/dryrun/src/m/p/Lib.java	Mon Jun 27 20:22:04 2016 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p;
+
+public class Lib {
+    public static void sayHi() {
+        System.out.println("Hello world");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/dryrun/src/test/jdk/test/Main.java	Mon Jun 27 20:22:04 2016 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test;
+
+public class Main {
+    public static void main(String[] args) {
+        p.Lib.sayHi();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/dryrun/src/test/module-info.java	Mon Jun 27 20:22:04 2016 -0700
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module test {
+    requires m;
+}