Skip to content

Commit 35da063

Browse files
author
duke
committedDec 20, 2024
Automatic merge of jdk:master into master
2 parents 3d057e4 + bcb1bda commit 35da063

File tree

6 files changed

+214
-107
lines changed

6 files changed

+214
-107
lines changed
 

‎src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java

+35-14
Original file line numberDiff line numberDiff line change
@@ -277,14 +277,6 @@ int run(String[] args) {
277277
return EXIT_OK;
278278
}
279279

280-
if (options.modulePath.isEmpty()) {
281-
// no --module-path specified - try to set $JAVA_HOME/jmods if that exists
282-
Path jmods = getDefaultModulePath();
283-
if (jmods != null) {
284-
options.modulePath.add(jmods);
285-
}
286-
}
287-
288280
JlinkConfiguration config = initJlinkConfig();
289281
outputPath = config.getOutput();
290282
if (options.suggestProviders) {
@@ -377,8 +369,13 @@ public static void createImage(JlinkConfiguration config,
377369
// the token for "all modules on the module path"
378370
private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
379371
private JlinkConfiguration initJlinkConfig() throws BadArgs {
372+
// Empty module path not allowed with ALL-MODULE-PATH in --add-modules
373+
if (options.addMods.contains(ALL_MODULE_PATH) && options.modulePath.isEmpty()) {
374+
throw taskHelper.newBadArgs("err.no.module.path");
375+
}
380376
ModuleFinder appModuleFinder = newModuleFinder(options.modulePath);
381377
ModuleFinder finder = appModuleFinder;
378+
382379
boolean isLinkFromRuntime = false;
383380
if (!appModuleFinder.find("java.base").isPresent()) {
384381
// If the application module finder doesn't contain the
@@ -393,8 +390,9 @@ private JlinkConfiguration initJlinkConfig() throws BadArgs {
393390
// include the java.base module.
394391
Path defModPath = getDefaultModulePath();
395392
if (defModPath != null) {
396-
options.modulePath.add(defModPath);
397-
finder = newModuleFinder(options.modulePath);
393+
List<Path> combinedPaths = new ArrayList<>(options.modulePath);
394+
combinedPaths.add(defModPath);
395+
finder = newModuleFinder(combinedPaths);
398396
}
399397
// We've just added the default module path ('jmods'). If we still
400398
// don't find java.base, we must resolve JDK modules from the
@@ -419,8 +417,31 @@ private JlinkConfiguration initJlinkConfig() throws BadArgs {
419417
Set<String> roots = new HashSet<>();
420418
for (String mod : options.addMods) {
421419
if (mod.equals(ALL_MODULE_PATH)) {
422-
ModuleFinder mf = newLimitedFinder(finder, options.limitMods,
423-
Set.of());
420+
// Using --limit-modules with ALL-MODULE-PATH is an error
421+
if (!options.limitMods.isEmpty()) {
422+
throw taskHelper.newBadArgs("err.limit.modules");
423+
}
424+
// all observable modules in the app module path are roots
425+
Set<String> initialRoots = appModuleFinder.findAll()
426+
.stream()
427+
.map(ModuleReference::descriptor)
428+
.map(ModuleDescriptor::name)
429+
.collect(Collectors.toSet());
430+
431+
// Error if no module is found on the app module path
432+
if (initialRoots.isEmpty()) {
433+
String modPath = options.modulePath.stream()
434+
.map(a -> a.toString())
435+
.collect(Collectors.joining(", "));
436+
throw taskHelper.newBadArgs("err.empty.module.path", modPath);
437+
}
438+
439+
// Use a module finder with limited observability, as determined
440+
// by initialRoots, to find the observable modules from the
441+
// application module path (--module-path option) only. We must
442+
// not include JDK modules from the default module path or the
443+
// run-time image.
444+
ModuleFinder mf = limitFinder(finder, initialRoots, Set.of());
424445
mf.findAll()
425446
.stream()
426447
.map(ModuleReference::descriptor)
@@ -430,7 +451,7 @@ private JlinkConfiguration initJlinkConfig() throws BadArgs {
430451
roots.add(mod);
431452
}
432453
}
433-
finder = newLimitedFinder(finder, options.limitMods, roots);
454+
finder = limitFinder(finder, options.limitMods, roots);
434455

435456
// --keep-packaged-modules doesn't make sense as we are not linking
436457
// from packaged modules to begin with.
@@ -497,7 +518,7 @@ public static Path getDefaultModulePath() {
497518
* specified in {@code limitMods} plus other modules specified in the
498519
* {@code roots} set.
499520
*/
500-
public static ModuleFinder newLimitedFinder(ModuleFinder finder,
521+
public static ModuleFinder limitFinder(ModuleFinder finder,
501522
Set<String> limitMods,
502523
Set<String> roots) {
503524
// if limitMods is specified then limit the universe

‎src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties

+3-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,9 @@ err.runtime.link.packaged.mods=This JDK has no packaged modules.\
127127
err.runtime.link.modified.file={0} has been modified
128128
err.runtime.link.patched.module=jlink does not support linking from the run-time image\
129129
\ when running on a patched runtime with --patch-module
130-
err.empty.module.path=empty module path
130+
err.no.module.path=--module-path option must be specified with --add-modules ALL-MODULE-PATH
131+
err.empty.module.path=No module found in module path ''{0}'' with --add-modules ALL-MODULE-PATH
132+
err.limit.modules=--limit-modules not allowed with --add-modules ALL-MODULE-PATH
131133
err.jlink.version.mismatch=jlink version {0}.{1} does not match target java.base version {2}.{3}
132134
err.automatic.module:automatic module cannot be used with jlink: {0} from {1}
133135
err.unknown.byte.order:unknown byte order {0}

‎test/jdk/tools/jlink/IntegrationTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ private static void test() throws Exception {
157157
boolean linkFromRuntime = false;
158158
JlinkConfiguration config = new Jlink.JlinkConfiguration(output,
159159
mods,
160-
JlinkTask.newLimitedFinder(JlinkTask.newModuleFinder(modulePaths), limits, mods),
160+
JlinkTask.limitFinder(JlinkTask.newModuleFinder(modulePaths), limits, mods),
161161
linkFromRuntime,
162162
false /* ignore modified runtime */,
163163
false /* generate run-time image */);

‎test/jdk/tools/jlink/JLinkTest.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,15 @@
2727
import java.lang.module.ModuleDescriptor;
2828
import java.nio.file.Files;
2929
import java.nio.file.Path;
30-
import java.nio.file.Paths;
3130
import java.util.ArrayList;
32-
import java.util.Collections;
3331
import java.util.List;
3432
import java.util.spi.ToolProvider;
3533
import java.util.stream.Collectors;
3634
import java.util.stream.IntStream;
3735
import java.util.stream.Stream;
3836

39-
import jdk.tools.jlink.plugin.Plugin;
4037
import jdk.tools.jlink.internal.PluginRepository;
38+
import jdk.tools.jlink.plugin.Plugin;
4139
import tests.Helper;
4240
import tests.JImageGenerator;
4341

@@ -135,11 +133,11 @@ public static void main(String[] args) throws Exception {
135133

136134
{
137135
// No --module-path specified. --add-modules ALL-MODULE-PATH specified.
138-
String imageDir = "bug8189777-all-module-path";
136+
String imageDir = "bug8345259-all-module-path";
139137
JImageGenerator.getJLinkTask()
140138
.output(helper.createNewImageDir(imageDir))
141139
.addMods("ALL-MODULE-PATH")
142-
.call().assertSuccess();
140+
.call().assertFailure();
143141
}
144142

145143
{
+134-60
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -21,58 +21,75 @@
2121
* questions.
2222
*/
2323

24-
/*
25-
* @test
26-
* @summary jlink test of --add-module ALL-MODULE-PATH
27-
* @library /test/lib
28-
* @modules jdk.compiler
29-
* @build jdk.test.lib.process.ProcessTools
30-
* jdk.test.lib.process.OutputAnalyzer
31-
* jdk.test.lib.compiler.CompilerUtils
32-
* @run testng AllModulePath
33-
*/
24+
import static org.testng.Assert.assertEquals;
25+
import static org.testng.Assert.assertTrue;
3426

35-
import java.io.File;
27+
import java.io.ByteArrayOutputStream;
3628
import java.io.IOException;
3729
import java.io.PrintWriter;
3830
import java.nio.file.Files;
3931
import java.nio.file.Path;
4032
import java.nio.file.Paths;
41-
import java.nio.file.attribute.BasicFileAttributes;
4233
import java.util.ArrayList;
43-
import java.util.Arrays;
4434
import java.util.HashSet;
4535
import java.util.List;
4636
import java.util.Set;
47-
import java.util.stream.Collectors;
48-
import java.util.stream.Stream;
4937
import java.util.spi.ToolProvider;
50-
51-
import jdk.test.lib.compiler.CompilerUtils;
52-
import jdk.test.lib.process.ProcessTools;
38+
import java.util.stream.Collectors;
5339

5440
import org.testng.annotations.BeforeClass;
5541
import org.testng.annotations.Test;
56-
import static org.testng.Assert.*;
5742

43+
import jdk.test.lib.compiler.CompilerUtils;
44+
import jdk.test.lib.process.ProcessTools;
45+
import jdk.tools.jlink.internal.LinkableRuntimeImage;
46+
import tests.Helper;
47+
import tests.Result;
48+
49+
/*
50+
* @test
51+
* @bug 8345259
52+
* @summary jlink test of --add-module ALL-MODULE-PATH
53+
* @library ../../lib /test/lib
54+
* @modules jdk.compiler
55+
* java.base/jdk.internal.jimage
56+
* jdk.jlink/jdk.tools.jlink.internal
57+
* jdk.jlink/jdk.tools.jimage
58+
* @build jdk.test.lib.process.ProcessTools
59+
* jdk.test.lib.process.OutputAnalyzer
60+
* jdk.test.lib.compiler.CompilerUtils
61+
* @run testng/othervm -Duser.language=en -Duser.country=US AllModulePath
62+
*/
5863
public class AllModulePath {
5964

60-
private final Path JMODS = Paths.get(System.getProperty("test.jdk")).resolve("jmods");
61-
private final Path SRC = Paths.get(System.getProperty("test.src")).resolve("src");
62-
private final Path MODS = Paths.get("mods");
65+
private static final Path JMODS = Paths.get(System.getProperty("test.jdk")).resolve("jmods");
66+
private static final Path SRC = Paths.get(System.getProperty("test.src")).resolve("src");
67+
private static final Path MODS = Paths.get("mods");
68+
private static final boolean LINKABLE_RUNTIME = LinkableRuntimeImage.isLinkableRuntime();
69+
private static final boolean JMODS_EXIST = Files.exists(JMODS);
6370

6471
private final static Set<String> MODULES = Set.of("test", "m1");
6572

6673
static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink")
6774
.orElseThrow(() ->
6875
new RuntimeException("jlink tool not found")
6976
);
77+
private static Helper HELPER;
78+
79+
private static boolean isExplodedJDKImage() {
80+
if (!JMODS_EXIST && !LINKABLE_RUNTIME) {
81+
System.err.println("Test skipped. Not a linkable runtime and no JMODs");
82+
return true;
83+
}
84+
return false;
85+
}
7086

7187
@BeforeClass
7288
public void setup() throws Throwable {
73-
if (Files.notExists(JMODS)) {
89+
if (isExplodedJDKImage()) {
7490
return;
7591
}
92+
HELPER = Helper.newHelper(LINKABLE_RUNTIME);
7693

7794
Files.createDirectories(MODS);
7895

@@ -84,60 +101,114 @@ public void setup() throws Throwable {
84101
}
85102
}
86103

104+
/*
105+
* --add-modules ALL-MODULE-PATH with an existing module-path.
106+
*/
87107
@Test
88108
public void testAllModulePath() throws Throwable {
89-
if (Files.notExists(JMODS)) {
109+
if (isExplodedJDKImage()) {
90110
return;
91111
}
92112

93-
// create custom image
94-
Path image = Paths.get("image");
95-
createImage(image, "--add-modules", "ALL-MODULE-PATH");
113+
Path image = HELPER.createNewImageDir("image");
114+
List<String> opts = List.of("--module-path", MODS.toString(),
115+
"--output", image.toString(),
116+
"--add-modules", "ALL-MODULE-PATH");
117+
createImage(image, opts, true /* success */);
96118

97119
Set<String> modules = new HashSet<>();
98-
Files.find(JMODS, 1, (Path p, BasicFileAttributes attr) ->
99-
p.toString().endsWith(".jmod"))
100-
.map(p -> JMODS.relativize(p).toString())
101-
.map(n -> n.substring(0, n.length()-5))
102-
.forEach(modules::add);
120+
// java.base is a dependency of any external module
121+
modules.add("java.base");
103122
modules.add("m1");
104123
modules.add("test");
105124
checkModules(image, modules);
106125
}
107126

127+
/*
128+
* --add-modules ALL-MODULE-PATH with --limit-modules is an error
129+
*/
108130
@Test
109131
public void testLimitModules() throws Throwable {
110-
if (Files.notExists(JMODS)) {
132+
if (isExplodedJDKImage()) {
111133
return;
112134
}
113-
114-
// create custom image
115-
Path image = Paths.get("image1");
116-
createImage(image,
117-
"--add-modules", "ALL-MODULE-PATH",
118-
"--limit-modules", "m1");
119-
120-
checkModules(image, Set.of("m1", "java.base"));
135+
Path targetPath = HELPER.createNewImageDir("all-mods-limit-mods");
136+
String moduleName = "com.baz.runtime";
137+
Result result = HELPER.generateDefaultJModule(moduleName, "jdk.jfr");
138+
Path customModulePath = result.getFile().getParent();
139+
List<String> allArgs = List.of("--add-modules", "ALL-MODULE-PATH",
140+
"--limit-modules", "jdk.jfr",
141+
"--module-path", customModulePath.toString(),
142+
"--output", targetPath.toString());
143+
JlinkOutput allOut = createImage(targetPath, allArgs, false /* success */);
144+
String actual = allOut.stdout.trim();
145+
String expected = "Error: --limit-modules not allowed with --add-modules ALL-MODULE-PATH";
146+
assertEquals(actual, expected);
121147
}
122148

149+
150+
/*
151+
* --add-modules *includes* ALL-MODULE-PATH with an existing module path
152+
*/
123153
@Test
124154
public void testAddModules() throws Throwable {
125-
if (Files.notExists(JMODS)) {
155+
if (isExplodedJDKImage()) {
126156
return;
127157
}
128158

129159
// create custom image
130-
Path image = Paths.get("image2");
131-
createImage(image,
132-
"--add-modules", "m1,test",
133-
"--add-modules", "ALL-MODULE-PATH",
134-
"--limit-modules", "java.base");
160+
Path image = HELPER.createNewImageDir("image2");
161+
List<String> opts = List.of("--module-path", MODS.toString(),
162+
"--output", image.toString(),
163+
"--add-modules", "m1",
164+
"--add-modules", "ALL-MODULE-PATH");
165+
createImage(image, opts, true /* success */);
135166

136167
checkModules(image, Set.of("m1", "test", "java.base"));
137168
}
138169

139170
/*
140-
* check the modules linked in the image
171+
* No --module-path with --add-modules ALL-MODULE-PATH is an error.
172+
*/
173+
@Test
174+
public void noModulePath() throws IOException {
175+
if (isExplodedJDKImage()) {
176+
return;
177+
}
178+
Path targetPath = HELPER.createNewImageDir("all-mod-path-no-mod-path");
179+
List<String> allArgs = List.of("--add-modules", "ALL-MODULE-PATH",
180+
"--output", targetPath.toString());
181+
JlinkOutput allOut = createImage(targetPath, allArgs, false /* expect failure */);
182+
String expected = "Error: --module-path option must be specified with --add-modules ALL-MODULE-PATH";
183+
assertEquals(allOut.stdout.trim(), expected);
184+
}
185+
186+
/*
187+
* --module-path not-exist and --add-modules ALL-MODULE-PATH is an error.
188+
*/
189+
@Test
190+
public void modulePathEmpty() throws IOException {
191+
if (isExplodedJDKImage()) {
192+
return;
193+
}
194+
Path targetPath = HELPER.createNewImageDir("all-mod-path-not-existing");
195+
String strNotExists = "not-exist";
196+
Path notExists = Path.of(strNotExists);
197+
if (Files.exists(notExists)) {
198+
throw new AssertionError("Test setup error, path must not exist!");
199+
}
200+
List<String> allArgs = List.of("--add-modules", "ALL-MODULE-PATH",
201+
"--module-path", notExists.toString(),
202+
"--output", targetPath.toString());
203+
204+
JlinkOutput allOut = createImage(targetPath, allArgs, false /* expect failure */);
205+
String actual = allOut.stdout.trim();
206+
assertTrue(actual.startsWith("Error: No module found in module path"));
207+
assertTrue(actual.contains(strNotExists));
208+
}
209+
210+
/*
211+
* check the modules linked in the image using m1/p.ListModules
141212
*/
142213
private void checkModules(Path image, Set<String> modules) throws Throwable {
143214
Path cmd = findTool(image, "java");
@@ -164,16 +235,19 @@ private Path findTool(Path image, String tool) {
164235
return cmd;
165236
}
166237

167-
private void createImage(Path image, String... options) throws IOException {
168-
String modulepath = JMODS.toString() + File.pathSeparator + MODS.toString();
169-
List<String> opts = List.of("--module-path", modulepath,
170-
"--output", image.toString());
171-
String[] args = Stream.concat(opts.stream(), Arrays.stream(options))
172-
.toArray(String[]::new);
173-
174-
System.out.println("jlink " + Arrays.stream(args).collect(Collectors.joining(" ")));
175-
PrintWriter pw = new PrintWriter(System.out);
176-
int rc = JLINK_TOOL.run(pw, pw, args);
177-
assertTrue(rc == 0);
238+
private JlinkOutput createImage(Path image, List<String> args, boolean success) throws IOException {
239+
System.out.println("jlink " + args.stream().collect(Collectors.joining(" ")));
240+
241+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
242+
PrintWriter out = new PrintWriter(baos);
243+
ByteArrayOutputStream berrOs = new ByteArrayOutputStream();
244+
PrintWriter err = new PrintWriter(berrOs);
245+
int rc = JLINK_TOOL.run(out, err, args.toArray(String[]::new));
246+
String stdOut = new String(baos.toByteArray());
247+
String stdErr = new String(berrOs.toByteArray());
248+
assertEquals(rc == 0, success, String.format("Output was: %nstdout: %s%nstderr: %s%n", stdOut, stdErr));
249+
return new JlinkOutput(stdErr, stdOut);
178250
}
251+
252+
private static record JlinkOutput(String stderr, String stdout) {};
179253
}

‎test/jdk/tools/jlink/basic/BasicTest.java

+38-26
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -21,21 +21,6 @@
2121
* questions.
2222
*/
2323

24-
/*
25-
* @test
26-
* @summary Basic test of jlink to create jmods and images
27-
* @author Andrei Eremeev
28-
* @library /test/lib
29-
* @modules java.base/jdk.internal.module
30-
* jdk.jlink
31-
* jdk.compiler
32-
* @build jdk.test.lib.process.ProcessTools
33-
* jdk.test.lib.process.OutputAnalyzer
34-
* jdk.test.lib.compiler.CompilerUtils
35-
* jdk.test.lib.util.JarUtils
36-
* @run main BasicTest
37-
*/
38-
3924
import java.io.File;
4025
import java.io.PrintWriter;
4126
import java.nio.file.Files;
@@ -50,7 +35,22 @@
5035
import jdk.test.lib.process.OutputAnalyzer;
5136
import jdk.test.lib.process.ProcessTools;
5237
import jdk.test.lib.util.JarUtils;
38+
import jdk.tools.jlink.internal.LinkableRuntimeImage;
5339

40+
/*
41+
* @test
42+
* @summary Basic test of jlink to create jmods and images
43+
* @author Andrei Eremeev
44+
* @library /test/lib
45+
* @modules java.base/jdk.internal.module
46+
* jdk.jlink/jdk.tools.jlink.internal
47+
* jdk.compiler
48+
* @build jdk.test.lib.process.ProcessTools
49+
* jdk.test.lib.process.OutputAnalyzer
50+
* jdk.test.lib.compiler.CompilerUtils
51+
* jdk.test.lib.util.JarUtils
52+
* @run main/othervm BasicTest
53+
*/
5454
public class BasicTest {
5555
static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod")
5656
.orElseThrow(() ->
@@ -62,21 +62,31 @@ public class BasicTest {
6262
new RuntimeException("jlink tool not found")
6363
);
6464

65-
private final String TEST_MODULE = "test";
66-
private final Path jdkHome = Paths.get(System.getProperty("test.jdk"));
67-
private final Path jdkMods = jdkHome.resolve("jmods");
68-
private final Path testSrc = Paths.get(System.getProperty("test.src"));
69-
private final Path src = testSrc.resolve("src").resolve(TEST_MODULE);
70-
private final Path classes = Paths.get("classes");
71-
private final Path jmods = Paths.get("jmods");
72-
private final Path jars = Paths.get("jars");
65+
private static final String TEST_MODULE = "test";
66+
private static final Path jdkHome = Paths.get(System.getProperty("test.jdk"));
67+
private static final Path jdkMods = jdkHome.resolve("jmods");
68+
private static final boolean JMODS_EXIST = Files.exists(jdkMods);
69+
private static final boolean LINKABLE_RUNTIME = LinkableRuntimeImage.isLinkableRuntime();
70+
private static final Path testSrc = Paths.get(System.getProperty("test.src"));
71+
private static final Path src = testSrc.resolve("src").resolve(TEST_MODULE);
72+
private static final Path classes = Paths.get("classes");
73+
private static final Path jmods = Paths.get("jmods");
74+
private static final Path jars = Paths.get("jars");
7375

7476
public static void main(String[] args) throws Throwable {
7577
new BasicTest().run();
7678
}
7779

80+
private static boolean isExplodedJDKImage() {
81+
if (!JMODS_EXIST && !LINKABLE_RUNTIME) {
82+
System.err.println("Test skipped. Not a linkable runtime and no JMODs");
83+
return true;
84+
}
85+
return false;
86+
}
87+
7888
public void run() throws Throwable {
79-
if (Files.notExists(jdkMods)) {
89+
if (isExplodedJDKImage()) {
8090
return;
8191
}
8292

@@ -146,8 +156,10 @@ private void execute(Path image, String scriptName) throws Throwable {
146156

147157
private void runJlink(Path image, String modName, String... options) {
148158
List<String> args = new ArrayList<>();
159+
String modPathArg = (JMODS_EXIST ? jdkMods + File.pathSeparator : "") +
160+
jmods;
149161
Collections.addAll(args,
150-
"--module-path", jdkMods + File.pathSeparator + jmods,
162+
"--module-path", modPathArg,
151163
"--add-modules", modName,
152164
"--output", image.toString());
153165
Collections.addAll(args, options);

0 commit comments

Comments
 (0)
Please sign in to comment.