8163116: jlink exclude VM plugin does not fully support cross platform image creation
Reviewed-by: redestad, alanb, mchung
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java Thu Aug 04 14:29:27 2016 -0700
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java Fri Aug 05 09:42:05 2016 +0530
@@ -38,6 +38,7 @@
import jdk.tools.jlink.plugin.Plugin;
import jdk.tools.jlink.plugin.ResourcePool;
import jdk.tools.jlink.plugin.ResourcePoolBuilder;
+import jdk.tools.jlink.plugin.ResourcePoolModule;
import jdk.tools.jlink.plugin.ResourcePoolEntry;
import jdk.tools.jlink.plugin.PluginException;
@@ -98,9 +99,8 @@
* e.g.: /java.base/native/amd64/server/libjvm.so
* /java.base/native/server/libjvm.dylib
*/
- private List<ResourcePoolEntry> getVMs(ResourcePool in) {
- String jvmlib = jvmlib();
- List<ResourcePoolEntry> ret = in.moduleView().findModule("java.base").get().entries().filter((t) -> {
+ private List<ResourcePoolEntry> getVMs(ResourcePoolModule javaBase, String jvmlib) {
+ List<ResourcePoolEntry> ret = javaBase.entries().filter((t) -> {
return t.path().endsWith("/" + jvmlib);
}).collect(Collectors.toList());
return ret;
@@ -108,12 +108,13 @@
@Override
public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
- String jvmlib = jvmlib();
+ ResourcePoolModule javaBase = in.moduleView().findModule("java.base").get();
+ String jvmlib = jvmlib(javaBase.descriptor().osName().get());
TreeSet<Jvm> existing = new TreeSet<>(new JvmComparator());
TreeSet<Jvm> removed = new TreeSet<>(new JvmComparator());
if (!keepAll) {
// First retrieve all available VM names and removed VM
- List<ResourcePoolEntry> jvms = getVMs(in);
+ List<ResourcePoolEntry> jvms = getVMs(javaBase, jvmlib);
for (Jvm jvm : Jvm.values()) {
for (ResourcePoolEntry md : jvms) {
if (md.path().endsWith("/" + jvm.getName() + "/" + jvmlib)) {
@@ -247,21 +248,21 @@
return orig.copyWithContent(content);
}
- private static String jvmlib() {
+ private static String jvmlib(String osName) {
String lib = "libjvm.so";
- if (isWindows()) {
+ if (isWindows(osName)) {
lib = "jvm.dll";
- } else if (isMac()) {
+ } else if (isMac(osName)) {
lib = "libjvm.dylib";
}
return lib;
}
- private static boolean isWindows() {
- return System.getProperty("os.name").startsWith("Windows");
+ private static boolean isWindows(String osName) {
+ return osName.startsWith("Windows");
}
- private static boolean isMac() {
- return System.getProperty("os.name").startsWith("Mac OS");
+ private static boolean isMac(String osName) {
+ return osName.startsWith("Mac OS");
}
}
--- a/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java Thu Aug 04 14:29:27 2016 -0700
+++ b/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java Fri Aug 05 09:42:05 2016 +0530
@@ -30,6 +30,9 @@
* @run main ExcludeVMPluginTest
*/
import java.io.ByteArrayInputStream;
+import java.net.URI;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import jdk.tools.jlink.internal.ResourcePoolManager;
@@ -167,6 +170,13 @@
poolMgr.add(
ResourcePoolEntry.create("/java.base/native/jvm.cfg",
ResourcePoolEntry.Type.NATIVE_LIB, jvmcfgContent));
+
+ // java.base/module-info.class is used by exclude vm plugin
+ // to get current osName(). We read it from jrt-fs and add a
+ // ResourcePoolEntry
+ poolMgr.add(
+ ResourcePoolEntry.create("/java.base/module-info.class",
+ ResourcePoolEntry.Type.CLASS_OR_RESOURCE, getJavaBaseModuleInfo()));
for (String in : input) {
poolMgr.add(ResourcePoolEntry.create(in,
ResourcePoolEntry.Type.NATIVE_LIB, new byte[0]));
@@ -187,15 +197,19 @@
throw new Exception("Got content " + newContent + " expected " + expectdJvmCfg);
}
- if (out.entryCount() != (expectedOutput.length + 1)) {
+ // Apart from native resources, we should find jvm.cfg and
+ // java.base/module-info.class. So, we add 2 here to the
+ // expected count!
+ if (out.entryCount() != (expectedOutput.length + 2)) {
out.entries().forEach(m -> {
System.err.println(m.path());
});
- throw new Exception("Invalid output size " + out.entryCount() + " expected " + (expectedOutput.length + 1));
+ throw new Exception("Invalid output size " + out.entryCount() + " expected " + (expectedOutput.length + 2));
}
out.entries().forEach(md -> {
- if (md.path().equals("/java.base/native/jvm.cfg")) {
+ if (md.path().equals("/java.base/native/jvm.cfg") ||
+ md.path().equals("/java.base/module-info.class")) {
return;
}
boolean contained = false;
@@ -209,7 +223,11 @@
throw new RuntimeException(md.path() + " not expected");
}
});
+ }
+ // read java.base/module-info.class from jrt-fs
+ private static Path getJavaBaseModuleInfo() {
+ return Paths.get(URI.create("jrt:/modules/java.base/module-info.class"));
}
private static boolean isWindows() {
--- a/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java Thu Aug 04 14:29:27 2016 -0700
+++ b/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java Fri Aug 05 09:42:05 2016 +0530
@@ -32,8 +32,10 @@
*/
import java.io.File;
+import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -87,6 +89,12 @@
conf.put(FileCopierPlugin.NAME, builder.toString());
plug.configure(conf);
ResourcePoolManager poolMgr = new ResourcePoolManager();
+ // java.base/module-info.class is used to add "release" file
+ // We read it from jrt-fs and add a ResourcePoolEntry
+ poolMgr.add(
+ ResourcePoolEntry.create("/java.base/module-info.class",
+ ResourcePoolEntry.Type.CLASS_OR_RESOURCE, getJavaBaseModuleInfo()));
+ expected++;
ResourcePool pool = plug.transform(
new ResourcePoolManager().resourcePool(),
poolMgr.resourcePoolBuilder());
@@ -94,7 +102,8 @@
throw new AssertionError("Wrong number of added files");
}
pool.entries().forEach(f -> {
- if (!f.type().equals(ResourcePoolEntry.Type.OTHER)) {
+ if (!f.type().equals(ResourcePoolEntry.Type.OTHER) &&
+ !f.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) {
throw new AssertionError("Invalid type " + f.type()
+ " for file " + f.path());
}
@@ -104,18 +113,7 @@
});
Path root = new File(".").toPath();
DefaultImageBuilder imgbuilder = new DefaultImageBuilder(root);
- try {
- imgbuilder.storeFiles(pool);
- } catch (PluginException e) {
- // We didn't add any .class resource of the java.base module!
- // This cannot happen in non-testing scenario as java.base module
- // is minimum mandatory module in a .jimage. jlink depends on java.base
- // to generate 'release' file. If the current exception came from that
- // part of the code, then it is okay.
- if (!e.getMessage().contains("No module-info for java.base module")) {
- throw e;
- }
- }
+ imgbuilder.storeFiles(pool);
if (lic.exists()) {
File license = new File(root.toFile(), "LICENSE");
@@ -157,4 +155,9 @@
throw new AssertionError("Invalid Content in src2 dir");
}
}
+
+ // read java.base/module-info.class from jrt-fs
+ private static Path getJavaBaseModuleInfo() {
+ return Paths.get(URI.create("jrt:/modules/java.base/module-info.class"));
+ }
}