8163116: jlink exclude VM plugin does not fully support cross platform image creation

Reviewed-by: redestad, alanb, mchung
This commit is contained in:
Athijegannathan Sundararajan 2016-08-05 09:42:05 +05:30
parent 0af4f24e45
commit f622ccd42d
3 changed files with 50 additions and 28 deletions

View File

@ -38,6 +38,7 @@ import java.util.stream.Collectors;
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 @@ public final class ExcludeVMPlugin implements Plugin {
* 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 @@ public final class ExcludeVMPlugin implements Plugin {
@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 @@ public final class ExcludeVMPlugin implements Plugin {
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");
}
}

View File

@ -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 @@ public class ExcludeVMPluginTest {
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 @@ public class ExcludeVMPluginTest {
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 @@ public class ExcludeVMPluginTest {
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() {

View File

@ -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 @@ public class FileCopierPluginTest {
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 @@ public class FileCopierPluginTest {
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 @@ public class FileCopierPluginTest {
});
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 @@ public class FileCopierPluginTest {
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"));
}
}