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 * @requires test.thread.factory != "Virtual"
44 * @library /test/lib
45 * @build jdk.test.lib.process.ProcessTools jdk.test.lib.JDKToolFinder
46 * jdk.test.lib.process.OutputAnalyzer
47 * @run junit ${test.main.class}
48 */
49 public class MiscTests {
50
51 private static final ToolProvider JAVAC = ToolProvider.findFirst("javac")
52 .orElseThrow(() -> new RuntimeException("javac not found"));
53
54 /**
55 * Launch "java" with class path set on the command line via -Djava.class.path
56 * and verify that the launcher correctly launches the main application
57 */
58 @Test
59 void testWithClassPathSetViaProperty() throws Exception {
60 final String mainClass = "Foo";
61 // create the .java file
62 final Path sourceFile = Path.of(mainClass + ".java");
63 final String content = """
64 public class Foo {
65 public static void main(String... args) {}
66 }
67 """;
68 Files.writeString(sourceFile, content);
69 // compile it
70 final int compilationExitVal = JAVAC.run(System.out, System.err, sourceFile.toString());
71 assertEquals(0, compilationExitVal, "compilation of " + sourceFile + " failed");
72 final Path compiledFile = sourceFile.toAbsolutePath().getParent()
73 .resolve(mainClass + ".class");
74 assertTrue(Files.isRegularFile(compiledFile), "missing or not a regular" +
75 " file " + compiledFile);
76 // directory into which the .class was compiled to
77 final Path classPathDir = compiledFile.getParent();
78 // launch "java" with the classpath system property
79 final List<String> javaCmdArgs = List.of(
80 "-Djava.class.path=" + classPathDir,
81 mainClass
82 );
83 final OutputAnalyzer oa = ProcessTools.executeTestJava(javaCmdArgs);
84 oa.reportDiagnosticSummary();
85 oa.shouldHaveExitValue(0);
86 }
87
88 /**
89 * Verify that the "_JAVA_LAUNCHER_DEBUG" can be configured to enable
90 * debug logging for the "java" and "javac" launchers
91 */
92 @Test
93 void testJavaLauncherDebugEnvVar() throws Exception {
94 for (String cmd : new String[]{"java", "javac"}) {
95 final String toolLocation = JDKToolFinder.getJDKTool(cmd);
96 System.err.println("running test against " + toolLocation);
97 final ProcessBuilder pb = new ProcessBuilder(List.of(toolLocation, "-version"));
98 pb.environment().put("_JAVA_LAUNCHER_DEBUG", "true");
99 final OutputAnalyzer oa = ProcessTools.executeCommand(pb);
100 oa.reportDiagnosticSummary();
101 oa.shouldHaveExitValue(0);
102 final String javargs = cmd.equals("javac") ? "on" : "off";
103 final String progname = cmd.equals("javac") ? "javac" : "java";
104 assertTrue(oa.matches("\\s*debug:on$"), "missing debug:on in output");
105 assertTrue(oa.matches("\\s*javargs:" + javargs + "$"), "missing javargs in output");
106 assertTrue(oa.matches("\\s*program name:" + progname + "$"),
107 "missing program name in output");
108 }
109 }
110
111 /**
112 * Verify that when a JAR file with no META-INF/MANIFEST.MF file is launched
113 * using "java -jar" then the launch fails
114 */
115 @Test
116 void testExecutableJARNoManifest() throws Exception {
117 final Path jarFile = Files.createTempFile(Path.of("."), "8392966-", ".jar");
118 // create a JAR file without any manifest
119 try (JarOutputStream noManifest = new JarOutputStream(Files.newOutputStream(jarFile))) {
120 final JarEntry entry = new JarEntry("foo.txt");
121 noManifest.putNextEntry(entry);
122 noManifest.write("bar".getBytes(US_ASCII));
123 noManifest.closeEntry();
124 }
125 // run "java -jar" against that JAR file and expect the launch to fail.
126 // once in headless mode and once headful
127 for (boolean headless : new boolean[]{true, false}) {
128 System.err.println("running with -Djava.awt.headless=" + headless);
129 final OutputAnalyzer oa = ProcessTools.executeTestJava(
130 "-Djava.awt.headless=" + headless,
131 // force the error message from the launcher to be in English
132 "-Duser.language=en", "-Duser.country=US",
133 "-jar", jarFile.toString());
134 oa.shouldNotHaveExitValue(0); // expected to fail with non-zero exit code
135 // verify it failed for the right reason
136 oa.shouldContain("Error: No manifest in JAR file");
137 }
138 }
139 }