8189777: jlink --module-path default value and automatic addition of $JAVA_HOME/jmods if java.base is missing

Reviewed-by: alanb, mchung
This commit is contained in:
Athijegannathan Sundararajan 2017-10-27 08:21:53 +05:30
parent b905e51da7
commit f8b8a16f4b
6 changed files with 96 additions and 69 deletions

View File

@ -27,7 +27,9 @@ package jdk.tools.jlink.internal;
import java.lang.module.Configuration;
import java.lang.module.ModuleFinder;
import java.nio.ByteOrder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -146,10 +148,8 @@ public final class Jlink {
*/
public static final class JlinkConfiguration {
private final List<Path> modulepaths;
private final Path output;
private final Set<String> modules;
private final Set<String> limitmods;
private final ByteOrder endian;
private final ModuleFinder finder;
@ -157,33 +157,18 @@ public final class Jlink {
* jlink configuration,
*
* @param output Output directory, must not exist.
* @param modulepaths Modules paths
* @param modules The possibly-empty set of root modules to resolve
* @param limitmods Limit the universe of observable modules
* @param endian Jimage byte order. Native order by default
* @param finder the ModuleFinder for this configuration
*/
public JlinkConfiguration(Path output,
List<Path> modulepaths,
Set<String> modules,
Set<String> limitmods,
ByteOrder endian) {
if (Objects.requireNonNull(modulepaths).isEmpty()) {
throw new IllegalArgumentException("Empty module path");
}
ByteOrder endian,
ModuleFinder finder) {
this.output = output;
this.modulepaths = modulepaths;
this.modules = Objects.requireNonNull(modules);
this.limitmods = Objects.requireNonNull(limitmods);
this.endian = Objects.requireNonNull(endian);
this.finder = moduleFinder();
}
/**
* @return the modulepaths
*/
public List<Path> getModulepaths() {
return modulepaths;
this.finder = finder;
}
/**
@ -207,13 +192,6 @@ public final class Jlink {
return modules;
}
/**
* @return the limitmods
*/
public Set<String> getLimitmods() {
return limitmods;
}
/**
* Returns {@link ModuleFinder} that finds all observable modules
* for this jlink configuration.
@ -244,37 +222,16 @@ public final class Jlink {
modules);
}
private ModuleFinder moduleFinder() {
Path[] entries = modulepaths.toArray(new Path[0]);
ModuleFinder finder = ModulePath.of(Runtime.version(), true, entries);
if (!limitmods.isEmpty()) {
finder = JlinkTask.limitFinder(finder, limitmods, modules);
}
return finder;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("output=").append(output).append("\n");
StringBuilder pathsBuilder = new StringBuilder();
for (Path p : modulepaths) {
pathsBuilder.append(p).append(",");
}
builder.append("modulepaths=").append(pathsBuilder).append("\n");
StringBuilder modsBuilder = new StringBuilder();
for (String p : modules) {
modsBuilder.append(p).append(",");
}
builder.append("modules=").append(modsBuilder).append("\n");
StringBuilder limitsBuilder = new StringBuilder();
for (String p : limitmods) {
limitsBuilder.append(p).append(",");
}
builder.append("limitmodules=").append(limitsBuilder).append("\n");
builder.append("endian=").append(endian).append("\n");
return builder.toString();
}

View File

@ -251,9 +251,18 @@ public class JlinkTask {
return EXIT_OK;
}
if (options.modulePath.isEmpty()) {
throw taskHelper.newBadArgs("err.modulepath.must.be.specified")
.showUsage(true);
// no --module-path specified - try to set $JAVA_HOME/jmods if that exists
Path jmods = getDefaultModulePath();
if (jmods != null) {
options.modulePath.add(jmods);
}
if (options.modulePath.isEmpty()) {
throw taskHelper.newBadArgs("err.modulepath.must.be.specified")
.showUsage(true);
}
}
JlinkConfiguration config = initJlinkConfig();
@ -347,14 +356,7 @@ public class JlinkTask {
Set<String> roots = new HashSet<>();
for (String mod : options.addMods) {
if (mod.equals(ALL_MODULE_PATH)) {
Path[] entries = options.modulePath.toArray(new Path[0]);
ModuleFinder finder = ModulePath.of(Runtime.version(), true, entries);
if (!options.limitMods.isEmpty()) {
// finder for the observable modules specified in
// the --module-path and --limit-modules options
finder = limitFinder(finder, options.limitMods, Collections.emptySet());
}
ModuleFinder finder = newModuleFinder(options.modulePath, options.limitMods, Set.of());
// all observable modules are roots
finder.findAll()
.stream()
@ -366,11 +368,19 @@ public class JlinkTask {
}
}
ModuleFinder finder = newModuleFinder(options.modulePath, options.limitMods, roots);
if (!finder.find("java.base").isPresent()) {
Path defModPath = getDefaultModulePath();
if (defModPath != null) {
options.modulePath.add(defModPath);
}
finder = newModuleFinder(options.modulePath, options.limitMods, roots);
}
return new JlinkConfiguration(options.output,
options.modulePath,
roots,
options.limitMods,
options.endian);
options.endian,
finder);
}
private void createImage(JlinkConfiguration config) throws Exception {
@ -398,6 +408,14 @@ public class JlinkTask {
stack.operate(imageProvider);
}
/**
* @return the system module path or null
*/
public static Path getDefaultModulePath() {
Path jmods = Paths.get(System.getProperty("java.home"), "jmods");
return Files.isDirectory(jmods)? jmods : null;
}
/*
* Returns a module finder of the given module path that limits
* the observable modules to those in the transitive closure of
@ -408,12 +426,15 @@ public class JlinkTask {
Set<String> limitMods,
Set<String> roots)
{
if (Objects.requireNonNull(paths).isEmpty()) {
throw new IllegalArgumentException("Empty module path");
}
Path[] entries = paths.toArray(new Path[0]);
ModuleFinder finder = ModulePath.of(Runtime.version(), true, entries);
// if limitmods is specified then limit the universe
if (!limitMods.isEmpty()) {
finder = limitFinder(finder, limitMods, roots);
if (limitMods != null && !limitMods.isEmpty()) {
finder = limitFinder(finder, limitMods, Objects.requireNonNull(roots));
}
return finder;
}

View File

@ -96,10 +96,10 @@ public final class AppRuntimeImageBuilder {
// jlink main arguments
Jlink.JlinkConfiguration jlinkConfig =
new Jlink.JlinkConfiguration(new File("").toPath(), // Unused
modulePath,
addModules,
limitModules,
ByteOrder.nativeOrder());
ByteOrder.nativeOrder(),
moduleFinder(modulePath,
limitModules, addModules));
// plugin configuration
List<Plugin> plugins = new ArrayList<Plugin>();

View File

@ -39,6 +39,7 @@ import java.util.Properties;
import java.util.Set;
import java.util.function.Function;
import jdk.tools.jlink.internal.Jlink;
import jdk.tools.jlink.internal.JlinkTask;
import jdk.tools.jlink.builder.DefaultImageBuilder;
import jdk.tools.jlink.plugin.ResourcePool;
import jdk.tools.jlink.plugin.ResourcePoolBuilder;
@ -159,7 +160,8 @@ public class IntegrationTest {
Set<String> limits = new HashSet<>();
limits.add("java.management");
JlinkConfiguration config = new Jlink.JlinkConfiguration(output,
modulePaths, mods, limits, ByteOrder.nativeOrder());
mods, ByteOrder.nativeOrder(),
JlinkTask.newModuleFinder(modulePaths, limits, mods));
List<Plugin> lst = new ArrayList<>();

View File

@ -42,6 +42,7 @@ import tests.JImageGenerator;
/*
* @test
* @summary Test image creation
* @bug 8189777
* @author Jean-Francois Denise
* @library ../lib
* @modules java.base/jdk.internal.jimage
@ -105,6 +106,37 @@ public class JLinkTest {
}
}
{
// No --module-path specified. $JAVA_HOME/jmods should be assumed.
// The following should succeed as it uses only system modules.
String imageDir = "bug818977-no-modulepath";
JImageGenerator.getJLinkTask()
.output(helper.createNewImageDir(imageDir))
.addMods("jdk.scripting.nashorn")
.call().assertSuccess();
}
{
// invalid --module-path specified. java.base not found it it.
// $JAVA_HOME/jmods should be added automatically.
// The following should succeed as it uses only system modules.
String imageDir = "bug8189777-invalid-modulepath";
JImageGenerator.getJLinkTask()
.modulePath("does_not_exist_path")
.output(helper.createNewImageDir(imageDir))
.addMods("jdk.scripting.nashorn")
.call().assertSuccess();
}
{
// No --module-path specified. --add-modules ALL-MODULE-PATH specified.
String imageDir = "bug8189777-all-module-path";
JImageGenerator.getJLinkTask()
.output(helper.createNewImageDir(imageDir))
.addMods("ALL-MODULE-PATH")
.call().assertSuccess();
}
{
String moduleName = "bug8134651";
JImageGenerator.getJLinkTask()
@ -122,6 +154,17 @@ public class JLinkTest {
.output(helper.createNewImageDir(moduleName))
.addMods("leaf1")
.call().assertFailure("Error: no value given for --module-path");
// do not include standard module path - should be added automatically
JImageGenerator.getJLinkTask()
.modulePath(helper.defaultModulePath(false))
.output(helper.createNewImageDir(moduleName))
.addMods("leaf1")
.call().assertSuccess();
// no --module-path. default sys mod path is assumed - but that won't contain 'leaf1' module
JImageGenerator.getJLinkTask()
.output(helper.createNewImageDir(moduleName))
.addMods("leaf1")
.call().assertFailure("Error: Module leaf1 not found");
}
{

View File

@ -136,7 +136,11 @@ public class Helper {
}
public String defaultModulePath() {
return stdjmods.toAbsolutePath().toString() + File.pathSeparator
return defaultModulePath(true);
}
public String defaultModulePath(boolean includeStdMods) {
return (includeStdMods? stdjmods.toAbsolutePath().toString() : "") + File.pathSeparator
+ jmods.toAbsolutePath().toString() + File.pathSeparator
+ jars.toAbsolutePath().toString() + File.pathSeparator
+ explodedmodsclasses.toAbsolutePath().toString();