8161067: jlink: Enable plugins to use the module pool for class lookup
Reviewed-by: sundar, psandoz
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java Tue Jul 12 11:29:01 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java Tue Jul 12 10:58:58 2016 -0300
@@ -400,6 +400,14 @@
}
@Override
+ public Optional<ModuleEntry> findEntryInContext(String path, ModuleEntry context) {
+ Objects.requireNonNull(path);
+ Objects.requireNonNull(context);
+ Optional<ModuleEntry> res = pool.findEntryInContext(path, context);
+ return res.map(this::getUncompressed);
+ }
+
+ @Override
public boolean contains(ModuleEntry res) {
return pool.contains(res);
}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleEntryFactory.java Tue Jul 12 11:29:01 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleEntryFactory.java Tue Jul 12 10:58:58 2016 -0300
@@ -51,16 +51,32 @@
original.getPath(), original.getType(), file);
}
- private static String moduleFrom(String path) {
+ static String moduleFrom(String path) {
Objects.requireNonNull(path);
if (path.isEmpty() || path.charAt(0) != '/') {
throw new IllegalArgumentException(path + " must start with /");
}
- String noRoot = path.substring(1);
- int idx = noRoot.indexOf('/');
+ int idx = path.indexOf('/', 1);
if (idx == -1) {
throw new IllegalArgumentException("/ missing after module: " + path);
}
- return noRoot.substring(0, idx);
+ return path.substring(1, idx);
+ }
+
+ static String packageFrom(String path) {
+ Objects.requireNonNull(path);
+ int idx = path.lastIndexOf('/');
+ if (idx == -1) {
+ throw new IllegalArgumentException("/ missing from path: " + path);
+ }
+ if (path.startsWith("/")) {
+ int jdx = path.indexOf('/', 1);
+ if (jdx == -1) {
+ throw new IllegalArgumentException("/ missing after module: " + path);
+ }
+ return path.substring(jdx + 1, idx);
+ } else {
+ return path.substring(0, idx);
+ }
}
}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModulePoolImpl.java Tue Jul 12 11:29:01 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModulePoolImpl.java Tue Jul 12 10:58:58 2016 -0300
@@ -265,6 +265,25 @@
}
/**
+ * Get the ModuleEntry for the passed path restricted to supplied context.
+ *
+ * @param path A data path
+ * @param context A context of the search
+ * @return A ModuleEntry instance or null if the data is not found
+ */
+ @Override
+ public Optional<ModuleEntry> findEntryInContext(String path, ModuleEntry context) {
+ Objects.requireNonNull(path);
+ Objects.requireNonNull(context);
+ LinkModule module = modules.get(context.getModule());
+ Objects.requireNonNull(module);
+ Optional<ModuleEntry> entry = module.findEntry(path);
+ // Navigating other modules via requires and exports is problematic
+ // since we cannot construct the runtime model of loaders and layers.
+ return entry;
+ }
+
+ /**
* Check if the ModulePool contains the given ModuleEntry.
*
* @param data The module data to check existence for.
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ClassForNamePlugin.java Tue Jul 12 11:29:01 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ClassForNamePlugin.java Tue Jul 12 10:58:58 2016 -0300
@@ -28,7 +28,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.stream.Collectors;
+import java.util.Optional;
import jdk.tools.jlink.plugin.ModulePool;
import jdk.tools.jlink.plugin.Plugin.Category;
import jdk.internal.org.objectweb.asm.ClassReader;
@@ -67,7 +67,7 @@
return index == -1 ? "" : binaryName.substring(0, index);
}
- private ModuleEntry transform(ModuleEntry resource, Map<String, ModuleEntry> classes) {
+ private ModuleEntry transform(ModuleEntry resource, ModulePool pool) {
byte[] inBytes = resource.getBytes();
ClassReader cr = new ClassReader(inBytes);
ClassNode cn = new ClassNode();
@@ -96,10 +96,11 @@
min.desc.equals("(Ljava/lang/String;)Ljava/lang/Class;")) {
String ldcClassName = ldc.cst.toString();
String thatClassName = ldcClassName.replaceAll("\\.", "/");
- ModuleEntry thatClass = classes.get(thatClassName);
+ Optional<ModuleEntry> thatClass =
+ pool.findEntryInContext(thatClassName + ".class", resource);
- if (thatClass != null) {
- int thatAccess = getAccess(thatClass);
+ if (thatClass.isPresent()) {
+ int thatAccess = getAccess(thatClass.get());
String thatPackage = getPackage(thatClassName);
if ((thatAccess & Opcodes.ACC_PRIVATE) != Opcodes.ACC_PRIVATE &&
@@ -142,19 +143,13 @@
public void visit(ModulePool in, ModulePool out) {
Objects.requireNonNull(in);
Objects.requireNonNull(out);
- Map<String, ModuleEntry> classes = in.entries()
- .filter(resource -> resource != null &&
- resource.getPath().endsWith(".class") &&
- !resource.getPath().endsWith("/module-info.class"))
- .collect(Collectors.toMap(resource -> binaryClassName(resource.getPath()),
- resource -> resource));
+
in.entries()
- .filter(resource -> resource != null)
.forEach(resource -> {
String path = resource.getPath();
if (path.endsWith(".class") && !path.endsWith("/module-info.class")) {
- out.add(transform(resource, classes));
+ out.add(transform(resource, in));
} else {
out.add(resource);
}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModulePool.java Tue Jul 12 11:29:01 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModulePool.java Tue Jul 12 10:58:58 2016 -0300
@@ -89,7 +89,16 @@
* @param path A data path
* @return A ModuleEntry instance or null if the data is not found
*/
- public Optional<ModuleEntry> findEntry(String path);
+ public Optional<ModuleEntry> findEntry(String path);
+
+ /**
+ * Get the ModuleEntry for the passed path restricted to supplied context.
+ *
+ * @param path A data path
+ * @param context A context of the search
+ * @return A ModuleEntry instance or null if the data is not found
+ */
+ public Optional<ModuleEntry> findEntryInContext(String path, ModuleEntry context);
/**
* Check if the ModulePool contains the given ModuleEntry.
--- a/jdk/test/tools/jlink/JLinkPluginsTest.java Tue Jul 12 11:29:01 2016 +0100
+++ b/jdk/test/tools/jlink/JLinkPluginsTest.java Tue Jul 12 10:58:58 2016 -0300
@@ -75,5 +75,13 @@
Path imageDir = helper.generateDefaultImage(userOptions, moduleName).assertSuccess();
helper.checkImage(imageDir, moduleName, res, null);
}
+ {
+ // Optimize Class.forName
+ String[] userOptions = {"--class-for-name"};
+ String moduleName = "classforname";
+ helper.generateDefaultJModule(moduleName, "composite2");
+ Path imageDir = helper.generateDefaultImage(userOptions, moduleName).assertSuccess();
+ helper.checkImage(imageDir, moduleName, null, null);
+ }
}
}