mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-27 11:24:51 +00:00
8161067: jlink: Enable plugins to use the module pool for class lookup
Reviewed-by: sundar, psandoz
This commit is contained in:
parent
d5e84de014
commit
e4226ff2f2
@ -399,6 +399,14 @@ public final class ImagePluginStack {
|
||||
return res.isPresent()? Optional.of(getUncompressed(res.get())) : Optional.empty();
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
@ -51,16 +51,32 @@ public final class ModuleEntryFactory {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,6 +264,25 @@ public class ModulePoolImpl implements ModulePool {
|
||||
return Optional.ofNullable(resources.get(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
|
||||
*/
|
||||
@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.
|
||||
*
|
||||
|
||||
@ -28,7 +28,7 @@ import java.util.Iterator;
|
||||
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 @@ public final class ClassForNamePlugin implements Plugin {
|
||||
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 @@ public final class ClassForNamePlugin implements Plugin {
|
||||
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 final class ClassForNamePlugin implements Plugin {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -89,7 +89,16 @@ public interface ModulePool {
|
||||
* @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.
|
||||
|
||||
@ -75,5 +75,13 @@ public class JLinkPluginsTest {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user