8233922: Service binding augments module graph with observable incubator modules

Reviewed-by: mchung
This commit is contained in:
Alan Bateman 2019-11-19 11:35:29 +00:00
parent ec51784c0d
commit 745feb207c
11 changed files with 380 additions and 20 deletions

View file

@ -312,7 +312,7 @@ public final class Configuration {
{
List<Configuration> parents = List.of(empty());
Resolver resolver = new Resolver(finder, parents, ModuleFinder.of(), traceOutput);
resolver.resolve(roots).bind();
resolver.resolve(roots).bind(/*bindIncubatorModules*/false);
return new Configuration(parents, resolver);
}

View file

@ -28,7 +28,6 @@ package java.lang.module;
import java.io.PrintStream;
import java.lang.module.ModuleDescriptor.Provides;
import java.lang.module.ModuleDescriptor.Requires.Modifier;
import java.net.URI;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
@ -45,6 +44,7 @@ import java.util.stream.Collectors;
import jdk.internal.module.ModuleHashes;
import jdk.internal.module.ModuleReferenceImpl;
import jdk.internal.module.ModuleResolution;
import jdk.internal.module.ModuleTarget;
/**
@ -215,15 +215,32 @@ final class Resolver {
* service-use relation.
*/
Resolver bind() {
return bind(/*bindIncubatorModules*/true);
}
/**
* Augments the set of resolved modules with modules induced by the
* service-use relation.
*
* @param bindIncubatorModules true if incubator modules are candidates to
* add to the module graph
*/
Resolver bind(boolean bindIncubatorModules) {
// Scan the finders for all available service provider modules. As
// java.base uses services then the module finders will be scanned
// anyway.
Map<String, Set<ModuleReference>> availableProviders = new HashMap<>();
for (ModuleReference mref : findAll()) {
ModuleDescriptor descriptor = mref.descriptor();
if (!descriptor.provides().isEmpty()) {
boolean candidate;
if (!bindIncubatorModules && (mref instanceof ModuleReferenceImpl)) {
ModuleResolution mres = ((ModuleReferenceImpl) mref).moduleResolution();
candidate = (mres == null) || (mres.hasIncubatingWarning() == false);
} else {
candidate = true;
}
if (candidate && !descriptor.provides().isEmpty()) {
for (Provides provides : descriptor.provides()) {
String sn = provides.service();

View file

@ -352,7 +352,7 @@ public final class ModuleBootstrap {
Configuration cf;
if (needResolution) {
cf = JLMA.resolveAndBind(finder, roots, traceOutput);
cf = Modules.newBootLayerConfiguration(finder, roots, traceOutput);
} else {
if (archivedModuleGraph != null) {
cf = archivedModuleGraph.configuration();

View file

@ -34,6 +34,7 @@ import java.util.stream.Stream;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.commons.ModuleResolutionAttribute;
import jdk.internal.org.objectweb.asm.commons.ModuleTargetAttribute;
import static jdk.internal.org.objectweb.asm.Opcodes.*;
@ -78,7 +79,9 @@ public final class ModuleInfoWriter {
* Writes the given module descriptor to a module-info.class file,
* returning it in a byte array.
*/
private static byte[] toModuleInfo(ModuleDescriptor md, ModuleTarget target) {
private static byte[] toModuleInfo(ModuleDescriptor md,
ModuleResolution mres,
ModuleTarget target) {
ClassWriter cw = new ClassWriter(0);
cw.visit(Opcodes.V10, ACC_MODULE, "module-info", null, null, null);
@ -147,6 +150,11 @@ public final class ModuleInfoWriter {
mv.visitEnd();
// write ModuleResolution attribute if specified
if (mres != null) {
cw.visitAttribute(new ModuleResolutionAttribute(mres.value()));
}
// write ModuleTarget attribute if there is a target platform
if (target != null && target.targetPlatform().length() > 0) {
cw.visitAttribute(new ModuleTargetAttribute(target.targetPlatform()));
@ -161,14 +169,39 @@ public final class ModuleInfoWriter {
* module-info.class.
*/
public static void write(ModuleDescriptor descriptor,
ModuleResolution mres,
ModuleTarget target,
OutputStream out)
throws IOException
{
byte[] bytes = toModuleInfo(descriptor, target);
byte[] bytes = toModuleInfo(descriptor, mres, target);
out.write(bytes);
}
/**
* Writes a module descriptor to the given output stream as a
* module-info.class.
*/
public static void write(ModuleDescriptor descriptor,
ModuleResolution mres,
OutputStream out)
throws IOException
{
write(descriptor, mres, null, out);
}
/**
* Writes a module descriptor to the given output stream as a
* module-info.class.
*/
public static void write(ModuleDescriptor descriptor,
ModuleTarget target,
OutputStream out)
throws IOException
{
write(descriptor, null, target, out);
}
/**
* Writes a module descriptor to the given output stream as a
* module-info.class.
@ -176,7 +209,7 @@ public final class ModuleInfoWriter {
public static void write(ModuleDescriptor descriptor, OutputStream out)
throws IOException
{
write(descriptor, null, out);
write(descriptor, null, null, out);
}
/**
@ -184,7 +217,7 @@ public final class ModuleInfoWriter {
* in module-info.class format.
*/
public static ByteBuffer toByteBuffer(ModuleDescriptor descriptor) {
byte[] bytes = toModuleInfo(descriptor, null);
byte[] bytes = toModuleInfo(descriptor, null, null);
return ByteBuffer.wrap(bytes);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@
package jdk.internal.module;
import java.io.PrintStream;
import java.lang.module.Configuration;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleFinder;
@ -33,6 +34,7 @@ import java.lang.module.ResolvedModule;
import java.net.URI;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@ -40,6 +42,7 @@ import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import jdk.internal.access.JavaLangModuleAccess;
import jdk.internal.loader.BootLoader;
import jdk.internal.loader.BuiltinClassLoader;
import jdk.internal.loader.ClassLoaders;
@ -61,6 +64,7 @@ public class Modules {
private Modules() { }
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
private static final JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess();
/**
* Creates a new Module. The module has the given ModuleDescriptor and
@ -158,6 +162,20 @@ public class Modules {
}
}
/**
* Resolves a collection of root modules, with service binding and the empty
* Configuration as the parent to create a Configuration for the boot layer.
*
* This method is intended to be used to create the Configuration for the
* boot layer during startup or at a link-time.
*/
public static Configuration newBootLayerConfiguration(ModuleFinder finder,
Collection<String> roots,
PrintStream traceOutput)
{
return JLMA.resolveAndBind(finder, roots, traceOutput);
}
/**
* Called by the VM when code in the given Module has been transformed by
* an agent and so may have been instrumented to call into supporting