1 /*
2 * Copyright (c) 2010, 2026, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 import java.nio.file.Files;
25 import java.nio.file.Path;
26 import java.util.List;
27 import java.util.jar.JarEntry;
28 import java.util.jar.JarOutputStream;
29 import java.util.spi.ToolProvider;
30
31 import jdk.test.lib.JDKToolFinder;
32 import jdk.test.lib.process.OutputAnalyzer;
33 import jdk.test.lib.process.ProcessTools;
34 import org.junit.jupiter.api.Test;
35 import static java.nio.charset.StandardCharsets.US_ASCII;
36 import static org.junit.jupiter.api.Assertions.assertEquals;
37 import static org.junit.jupiter.api.Assertions.assertTrue;
38
39 /*
40 * @test
41 * @bug 8154212 8154470 8392966
42 * @summary Miscellaneous tests for java launcher
43 * @library /test/lib
44 * @build jdk.test.lib.process.ProcessTools jdk.test.lib.JDKToolFinder
45 * jdk.test.lib.process.OutputAnalyzer
46 * @run junit ${test.main.class}
47 */
48 public class MiscTests {
49
50 private static final ToolProvider JAVAC = ToolProvider.findFirst("javac")
51 .orElseThrow(() -> new RuntimeException("javac not found"));
52
53 /**
54 * Launch "java" with class path set on the command line via -Djava.class.path
55 * and verify that the launcher correctly launches the main application
56 */
57 @Test
58 void testWithClassPathSetViaProperty() throws Exception {
59 final String mainClass = "Foo";
60 // create the .java file
61 final Path sourceFile = Path.of(mainClass + ".java");
62 final String content = """
63 public class Foo {
64 public static void main(String... args) {}
65 }
66 """;
67 Files.writeString(sourceFile, content);
68 // compile it
69 final int compilationExitVal = JAVAC.run(System.out, System.err, sourceFile.toString());
70 assertEquals(0, compilationExitVal, "compilation of " + sourceFile + " failed");
71 final Path compiledFile = sourceFile.toAbsolutePath().getParent()
72 .resolve(mainClass + ".class");
73 assertTrue(Files.isRegularFile(compiledFile), "missing or not a regular" +
74 " file " + compiledFile);
75 // directory into which the .class was compiled to
76 final Path classPathDir = compiledFile.getParent();
77 // launch "java" with the classpath system property
78 final List<String> javaCmdArgs = List.of(
79 "-Djava.class.path=" + classPathDir,
80 mainClass
81 );
82 final OutputAnalyzer oa = ProcessTools.executeTestJava(javaCmdArgs);
83 oa.reportDiagnosticSummary();
84 oa.shouldHaveExitValue(0);
85 }
86
87 /**
88 * Verify that the "_JAVA_LAUNCHER_DEBUG" can be configured to enable
89 * debug logging for the "java" and "javac" launchers
90 */
91 @Test
92 void testJavaLauncherDebugEnvVar() throws Exception {
93 for (String cmd : new String[]{"java", "javac"}) {
94 final String toolLocation = JDKToolFinder.getJDKTool(cmd);
95 System.err.println("running test against " + toolLocation);
96 final ProcessBuilder pb = new ProcessBuilder(List.of(toolLocation, "-version"));
97 pb.environment().put("_JAVA_LAUNCHER_DEBUG", "true");
98 final OutputAnalyzer oa = ProcessTools.executeCommand(pb);
99 oa.reportDiagnosticSummary();
100 oa.shouldHaveExitValue(0);
101 final String javargs = cmd.equals("javac") ? "on" : "off";
102 final String progname = cmd.equals("javac") ? "javac" : "java";
103 assertTrue(oa.matches("\\s*debug:on$"), "missing debug:on in output");
104 assertTrue(oa.matches("\\s*javargs:" + javargs + "$"), "missing javargs in output");
105 assertTrue(oa.matches("\\s*program name:" + progname + "$"),
106 "missing program name in output");
107 }
108 }
109
110 /**
111 * Verify that when a JAR file with no META-INF/MANIFEST.MF file is launched
112 * using "java -jar" then the launch fails
113 */
114 @Test
115 void testExecutableJARNoManifest() throws Exception {
116 final Path jarFile = Files.createTempFile(Path.of("."), "8392966-", ".jar");
117 // create a JAR file without any manifest
118 try (JarOutputStream noManifest = new JarOutputStream(Files.newOutputStream(jarFile))) {
119 final JarEntry entry = new JarEntry("foo.txt");
120 noManifest.putNextEntry(entry);
121 noManifest.write("bar".getBytes(US_ASCII));
122 noManifest.closeEntry();
123 }
124 // run "java -jar" against that JAR file and expect the launch to fail.
125 // once in headless mode and once headful
126 for (boolean headless : new boolean[]{true, false}) {
127 System.err.println("running with -Djava.awt.headless=" + headless);
128 final OutputAnalyzer oa = ProcessTools.executeTestJava(
129 "-Djava.awt.headless=" + headless,
130 // force the error message from the launcher to be in English
131 "-Duser.language=en", "-Duser.country=US",
132 "-jar", jarFile.toString());
133 oa.shouldNotHaveExitValue(0); // expected to fail with non-zero exit code
134 // verify it failed for the right reason
135 oa.shouldContain("Error: No manifest in JAR file");
136 }
137 }
138 }