Skip to content

Commit

Permalink
8345259: Disallow ALL-MODULE-PATH without explicit --module-path
Browse files Browse the repository at this point in the history
  • Loading branch information
jerboaa committed Dec 9, 2024
1 parent 7c20377 commit 15116a6
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 10 deletions.
32 changes: 22 additions & 10 deletions src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -277,14 +277,6 @@ int run(String[] args) {
return EXIT_OK;
}

if (options.modulePath.isEmpty()) {
// no --module-path specified - try to set $JAVA_HOME/jmods if that exists
Path jmods = getDefaultModulePath();
if (jmods != null) {
options.modulePath.add(jmods);
}
}

JlinkConfiguration config = initJlinkConfig();
outputPath = config.getOutput();
if (options.suggestProviders) {
Expand Down Expand Up @@ -377,6 +369,10 @@ public static void createImage(JlinkConfiguration config,
// the token for "all modules on the module path"
private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
private JlinkConfiguration initJlinkConfig() throws BadArgs {
// Empty module path not allowed with ALL-MODULE-PATH in --add-modules
if (options.modulePath.isEmpty() && options.addMods.contains(ALL_MODULE_PATH)) {
throw taskHelper.newBadArgs("err.all.module.path.empty.mod.path");
}
ModuleFinder initialFinder = createFinderFromPath(options.modulePath);
boolean isLinkFromRuntime = determineLinkFromRuntime(initialFinder, options.modulePath);
ModuleFinder rootsFinder = isLinkFromRuntime ? ModuleFinder.compose(ModuleFinder.ofSystem(),
Expand All @@ -386,7 +382,8 @@ private JlinkConfiguration initJlinkConfig() throws BadArgs {
assert !isLinkFromRuntime : "Expected regular JMODs based link";
// External module linked into a custom runtime, but JDK modules
// not observable on the module path. Add the default module path
// if that exists.
// if that exists. Adding it here is OK, because we limit the set
// in the ALL-MODULE-PATH case using initialFinder.
Path defModPath = getDefaultModulePath();
if (defModPath != null) {
options.modulePath.add(defModPath);
Expand All @@ -397,7 +394,22 @@ private JlinkConfiguration initJlinkConfig() throws BadArgs {
Set<String> roots = new HashSet<>();
for (String mod : options.addMods) {
if (mod.equals(ALL_MODULE_PATH) && options.modulePath.size() > 0) {
ModuleFinder mf = newModuleFinder(rootsFinder, options.limitMods, Set.of(), isLinkFromRuntime);
// Apply a module limit for the roots finder if it was otherwise empty.
// Since we are using the same finder for determining the roots set as
// for the actual link, we need to apply this trick so as to not
// include all modules of the JDK plus the extra module path in
// the roots set.
Set<String> allModsLimits = options.limitMods;
if (options.limitMods.isEmpty()) {
Set<String> modsLimits = new HashSet<>();
initialFinder.findAll()
.stream()
.map(ModuleReference::descriptor)
.map(ModuleDescriptor::name)
.forEach(mn -> modsLimits.add(mn));
allModsLimits = modsLimits;
}
ModuleFinder mf = newModuleFinder(rootsFinder, allModsLimits, Set.of(), isLinkFromRuntime);
// all observable modules are roots
mf.findAll()
.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ err.runtime.link.packaged.mods=This JDK has no packaged modules.\
err.runtime.link.modified.file={0} has been modified
err.runtime.link.patched.module=jlink does not support linking from the run-time image\
\ when running on a patched runtime with --patch-module
err.all.module.path.empty.mod.path=ALL-MODULE-PATH requires --module-path option
err.empty.module.path=empty module path
err.jlink.version.mismatch=jlink version {0}.{1} does not match target java.base version {2}.{3}
err.automatic.module:automatic module cannot be used with jlink: {0} from {1}
Expand Down
155 changes: 155 additions & 0 deletions test/jdk/tools/jlink/AllModulePathTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*
* Copyright (c) 2024, Red Hat, Inc.
* 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.
*/

import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.List;
import java.util.regex.Pattern;
import java.util.spi.ToolProvider;
import java.util.stream.Stream;

import jdk.test.lib.Platform;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import jdk.tools.jlink.internal.LinkableRuntimeImage;
import tests.Helper;
import tests.Result;

/*
* @test
* @summary Test ALL-MODULE-PATH option
* @bug 8345259 8345573
* @requires (vm.compMode != "Xcomp" & os.maxMemory >= 2g)
* @library ../lib /test/lib
* @enablePreview
* @modules java.base/jdk.internal.jimage
* jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.plugin
* jdk.jlink/jdk.tools.jimage
* @run main/othervm -Xmx1g AllModulePathTest
*/
public class AllModulePathTest {
private static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink")
.orElseThrow(() ->
new RuntimeException("jlink tool not found")
);

private final Helper helper;

public AllModulePathTest(Helper helper) {
this.helper = helper;
}

private void noModulePath() {
Path targetPath = helper.createNewImageDir("all-mod-path-no-mod-path");
List<String> allArgs = List.of("--add-modules", "ALL-MODULE-PATH",
"--output", targetPath.toString());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintWriter out = new PrintWriter(baos);
ByteArrayOutputStream berrOs = new ByteArrayOutputStream();
PrintWriter err = new PrintWriter(berrOs);
JLINK_TOOL.run(out, err, allArgs.toArray(new String[] {}));
OutputAnalyzer analyzer = new OutputAnalyzer(new String(baos.toByteArray(), StandardCharsets.UTF_8),
new String(berrOs.toByteArray(), StandardCharsets.UTF_8));
analyzer.stdoutShouldContain("Error");
analyzer.stdoutShouldContain("ALL-MODULE-PATH requires --module-path option");
}

private void modulePathWithLimitMods() throws Exception {
Path targetPath = helper.createNewImageDir("all-mods-limit-mods");
String moduleName = "com.baz.runtime";
Result result = helper.generateDefaultJModule(moduleName, "jdk.jfr");
Path customModulePath = result.getFile().getParent();
List<String> allArgs = List.of("--add-modules", "ALL-MODULE-PATH",
"--limit-modules", "jdk.jfr", // A dependency of com.baz.runtime
"--module-path", customModulePath.toString(),
"--output", targetPath.toString());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintWriter out = new PrintWriter(baos);
ByteArrayOutputStream berrOs = new ByteArrayOutputStream();
PrintWriter err = new PrintWriter(berrOs);
JLINK_TOOL.run(out, err, allArgs.toArray(new String[] {}));
OutputAnalyzer analyzer = new OutputAnalyzer(new String(baos.toByteArray(), StandardCharsets.UTF_8),
new String(berrOs.toByteArray(), StandardCharsets.UTF_8));
analyzer.shouldBeEmpty();
List<String> expected = List.of("java.base", "jdk.jfr");
verifyListModules(targetPath, expected);
}

private void modulePath() throws Exception {
Path targetPath = helper.createNewImageDir("all-mod-path-w-mod-path");
String moduleName = "com.foo.runtime";
Result result = helper.generateDefaultJModule(moduleName, "jdk.jfr");
Path customModulePath = result.getFile().getParent();
List<String> allArgs = List.of("--add-modules", "ALL-MODULE-PATH",
"--module-path", customModulePath.toString(),
"--output", targetPath.toString(),
"--verbose");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintWriter out = new PrintWriter(baos);
ByteArrayOutputStream berrOs = new ByteArrayOutputStream();
PrintWriter err = new PrintWriter(berrOs);
JLINK_TOOL.run(out, err, allArgs.toArray(new String[] {}));
OutputAnalyzer analyzer = new OutputAnalyzer(new String(baos.toByteArray(), StandardCharsets.UTF_8),
new String(berrOs.toByteArray(), StandardCharsets.UTF_8));
analyzer.stderrShouldBeEmpty();
analyzer.stdoutShouldContain(moduleName);
analyzer.stdoutShouldContain("java.base");
analyzer.stdoutShouldContain("jdk.jfr");
// Verify the output image's modules
List<String> expected = List.of(moduleName, "java.base", "jdk.jfr");
verifyListModules(targetPath, expected);
}

private void verifyListModules(Path targetPath, List<String> expected) throws Exception {
String jlink = "java" + (Platform.isWindows() ? ".exe" : "");
Path javaExe = targetPath.resolve(Path.of("bin"), Path.of(jlink));
List<String> listMods = List.of(javaExe.toString(), "--list-modules");
OutputAnalyzer out = ProcessTools.executeCommand(listMods.toArray(new String[] {}));
if (out.getExitValue() != 0) {
throw new AssertionError("java --list-modules failed");
}
List<String> actual = Stream.of(out.getStdout().split(Pattern.quote(System.lineSeparator())))
.map(s -> { return s.split("@")[0]; })
.sorted()
.toList();
if (!expected.equals(actual)) {
throw new RuntimeException("Unexpected list of modules: " + actual + " expected: " + expected);
}
}

public static void main(String[] args) throws Exception {
boolean linkableRuntime = LinkableRuntimeImage.isLinkableRuntime();
Helper helper = Helper.newHelper(linkableRuntime);
if (helper == null) {
System.err.println("Test not run");
return;
}
AllModulePathTest test = new AllModulePathTest(helper);
test.noModulePath();
test.modulePath();
test.modulePathWithLimitMods();
}
}

0 comments on commit 15116a6

Please sign in to comment.