loaders = new HashSet<>();
+ boolean hasPlatformModules = false;
// map each module to a class loader
for (ResolvedModule resolvedModule : cf.modules()) {
String name = resolvedModule.name();
ClassLoader loader = clf.apply(name);
- if (loader != null) {
- moduleToLoader.put(name, loader);
+ moduleToLoader.put(name, loader);
+ if (loader == null || loader == ClassLoaders.platformClassLoader()) {
+ if (!(clf instanceof ModuleLoaderMap.Mapper)) {
+ throw new IllegalArgumentException("loader can't be 'null'"
+ + " or the platform class loader");
+ }
+ hasPlatformModules = true;
+ } else {
loaders.add(loader);
- } else if (!(clf instanceof ModuleLoaderMap.Mapper)) {
- throw new IllegalArgumentException("loader can't be 'null'");
}
}
@@ -1098,7 +1090,7 @@ public final class Module implements AnnotatedElement {
URI uri = mref.location().orElse(null);
ClassLoader loader = moduleToLoader.get(resolvedModule.name());
Module m;
- if (loader == null && isBootLayer && name.equals("java.base")) {
+ if (loader == null && name.equals("java.base")) {
// java.base is already defined to the VM
m = Object.class.getModule();
} else {
@@ -1157,8 +1149,12 @@ public final class Module implements AnnotatedElement {
initExportsAndOpens(m, nameToSource, nameToModule, layer.parents());
}
- // register the modules in the boot layer
- if (isBootLayer) {
+ // if there are modules defined to the boot or platform class loaders
+ // then register the modules in the class loader's services catalog
+ if (hasPlatformModules) {
+ ClassLoader pcl = ClassLoaders.platformClassLoader();
+ ServicesCatalog bootCatalog = BootLoader.getServicesCatalog();
+ ServicesCatalog pclCatalog = ServicesCatalog.getServicesCatalog(pcl);
for (ResolvedModule resolvedModule : cf.modules()) {
ModuleReference mref = resolvedModule.reference();
ModuleDescriptor descriptor = mref.descriptor();
@@ -1166,13 +1162,11 @@ public final class Module implements AnnotatedElement {
String name = descriptor.name();
Module m = nameToModule.get(name);
ClassLoader loader = moduleToLoader.get(name);
- ServicesCatalog catalog;
if (loader == null) {
- catalog = BootLoader.getServicesCatalog();
- } else {
- catalog = ServicesCatalog.getServicesCatalog(loader);
+ bootCatalog.register(m);
+ } else if (loader == pcl) {
+ pclCatalog.register(m);
}
- catalog.register(m);
}
}
}
@@ -1587,7 +1581,4 @@ public final class Module implements AnnotatedElement {
// JVM_AddModuleExportsToAllUnnamed
private static native void addExportsToAllUnnamed0(Module from, String pn);
-
- // JVM_AddModulePackage
- private static native void addPackage0(Module m, String pn);
}
diff --git a/jdk/src/java.base/share/classes/java/lang/ModuleLayer.java b/jdk/src/java.base/share/classes/java/lang/ModuleLayer.java
index 70fbd8bce81..d0487f21214 100644
--- a/jdk/src/java.base/share/classes/java/lang/ModuleLayer.java
+++ b/jdk/src/java.base/share/classes/java/lang/ModuleLayer.java
@@ -244,6 +244,32 @@ public final class ModuleLayer {
return this;
}
+ /**
+ * Updates module {@code source} in the layer to export a package to
+ * module {@code target}. This method is a no-op if {@code source}
+ * already exports the package to at least {@code target}.
+ *
+ * @param source
+ * The source module
+ * @param pn
+ * The package name
+ * @param target
+ * The target module
+ *
+ * @return This controller
+ *
+ * @throws IllegalArgumentException
+ * If {@code source} is not in the module layer or the package
+ * is not in the source module
+ *
+ * @see Module#addExports
+ */
+ public Controller addExports(Module source, String pn, Module target) {
+ ensureInLayer(source);
+ source.implAddExports(pn, target);
+ return this;
+ }
+
/**
* Updates module {@code source} in the layer to open a package to
* module {@code target}. This method is a no-op if {@code source}
@@ -254,7 +280,7 @@ public final class ModuleLayer {
* @param pn
* The package name
* @param target
- * The target module to read
+ * The target module
*
* @return This controller
*
@@ -397,7 +423,7 @@ public final class ModuleLayer {
* class loader and defines all modules to that class loader.
*
* The class loader created by this method implements direct
- * delegation when loading types from modules. When its {@link
+ * delegation when loading classes from modules. If the {@link
* ClassLoader#loadClass(String, boolean) loadClass} method is invoked to
* load a class then it uses the package name of the class to map it to a
* module. This may be a module in this layer and hence defined to the same
@@ -408,6 +434,12 @@ public final class ModuleLayer {
* When {@code loadClass} is invoked to load classes that do not map to a
* module then it delegates to the parent class loader.
*
+ * The class loader created by this method locates resources
+ * ({@link ClassLoader#getResource(String) getResource}, {@link
+ * ClassLoader#getResources(String) getResources}, and other resource
+ * methods) in all modules in the layer before searching the parent class
+ * loader.
+ *
* Attempting to create a layer with all modules defined to the same
* class loader can fail for the following reasons:
*
@@ -417,8 +449,8 @@ public final class ModuleLayer {
* configuration have the same package.
*
* Split delegation: The resulting class loader would
- * need to delegate to more than one class loader in order to load types
- * in a specific package.
+ * need to delegate to more than one class loader in order to load
+ * classes in a specific package.
*
*
*
@@ -481,7 +513,7 @@ public final class ModuleLayer {
* class loader.
*
* The class loaders created by this method implement direct
- * delegation when loading types from modules. When {@link
+ * delegation when loading classes from modules. If the {@link
* ClassLoader#loadClass(String, boolean) loadClass} method is invoked to
* load a class then it uses the package name of the class to map it to a
* module. The package may be in the module defined to the class loader.
@@ -489,9 +521,15 @@ public final class ModuleLayer {
* module defined to the class loader. It may be in a package exported by a
* module in a parent layer. The class loader delegates to the class loader
* of the module, throwing {@code ClassNotFoundException} if not found by
- * that class loader.
- * When {@code loadClass} is invoked to load classes that do not map to a
- * module then it delegates to the parent class loader.
+ * that class loader. When {@code loadClass} is invoked to load a class
+ * that does not map to a module then it delegates to the parent class
+ * loader.
+ *
+ * The class loaders created by this method locate resources
+ * ({@link ClassLoader#getResource(String) getResource}, {@link
+ * ClassLoader#getResources(String) getResources}, and other resource
+ * methods) in the module defined to the class loader before searching
+ * the parent class loader.
*
* If there is a security manager then the class loaders created by
* this method will load classes and resources with privileges that are
@@ -576,10 +614,9 @@ public final class ModuleLayer {
*
In addition, a layer cannot be created if the configuration contains
* a module named "{@code java.base}", a configuration contains a module
* with a package named "{@code java}" or a package name starting with
- * "{@code java.}" and the module is mapped to a class loader other than
- * the {@link ClassLoader#getPlatformClassLoader() platform class loader},
- * or the function to map a module name to a class loader returns
- * {@code null}.
+ * "{@code java.}", or the function to map a module name to a class loader
+ * returns {@code null} or the {@linkplain ClassLoader#getPlatformClassLoader()
+ * platform class loader}.
*
* If the function to map a module name to class loader throws an error
* or runtime exception then it is propagated to the caller of this method.
diff --git a/jdk/src/java.base/share/classes/java/lang/System.java b/jdk/src/java.base/share/classes/java/lang/System.java
index 10664819e4f..c8d807a3d13 100644
--- a/jdk/src/java.base/share/classes/java/lang/System.java
+++ b/jdk/src/java.base/share/classes/java/lang/System.java
@@ -47,6 +47,8 @@ import java.security.AccessController;
import java.security.PrivilegedAction;
import java.nio.channels.Channel;
import java.nio.channels.spi.SelectorProvider;
+import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
@@ -2067,8 +2069,8 @@ public final class System {
private static void setJavaLangAccess() {
// Allow privileged classes outside of java.lang
SharedSecrets.setJavaLangAccess(new JavaLangAccess() {
- public Method getMethodOrNull(Class> klass, String name, Class>... parameterTypes) {
- return klass.getMethodOrNull(name, parameterTypes);
+ public List getDeclaredPublicMethods(Class> klass, String name, Class>... parameterTypes) {
+ return klass.getDeclaredPublicMethods(name, parameterTypes);
}
public jdk.internal.reflect.ConstantPool getConstantPool(Class> klass) {
return klass.getConstantPool();
@@ -2092,7 +2094,7 @@ public final class System {
return Class.getExecutableTypeAnnotationBytes(executable);
}
public >
- E[] getEnumConstantsShared(Class klass) {
+ E[] getEnumConstantsShared(Class klass) {
return klass.getEnumConstantsShared();
}
public void blockedOn(Thread t, Interruptible b) {
@@ -2120,9 +2122,6 @@ public final class System {
public Class> findBootstrapClassOrNull(ClassLoader cl, String name) {
return cl.findBootstrapClassOrNull(name);
}
- public Stream packages(ClassLoader cl) {
- return cl.packages();
- }
public Package definePackage(ClassLoader cl, String name, Module module) {
return cl.definePackage(name, module);
}
@@ -2161,9 +2160,18 @@ public final class System {
public void addOpensToAllUnnamed(Module m, String pn) {
m.implAddOpensToAllUnnamed(pn);
}
+ public void addOpensToAllUnnamed(Module m, Iterator packages) {
+ m.implAddOpensToAllUnnamed(packages);
+ }
public void addUses(Module m, Class> service) {
m.implAddUses(service);
}
+ public boolean isReflectivelyExported(Module m, String pn, Module other) {
+ return m.isReflectivelyExported(pn, other);
+ }
+ public boolean isReflectivelyOpened(Module m, String pn, Module other) {
+ return m.isReflectivelyOpened(pn, other);
+ }
public ServicesCatalog getServicesCatalog(ModuleLayer layer) {
return layer.getServicesCatalog();
}
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
index d53d9d4ecca..df76d3dbbcf 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
@@ -212,7 +212,7 @@ public class MethodHandles {
if (!callerModule.isNamed() && targetModule.isNamed()) {
IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger();
if (logger != null) {
- logger.logIfOpenedByBackdoor(lookup, targetClass);
+ logger.logIfOpenedForIllegalAccess(lookup, targetClass);
}
}
return new Lookup(targetClass);
diff --git a/jdk/src/java.base/share/classes/java/lang/module/Configuration.java b/jdk/src/java.base/share/classes/java/lang/module/Configuration.java
index ef7e44a114d..f989aae7fe6 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/Configuration.java
+++ b/jdk/src/java.base/share/classes/java/lang/module/Configuration.java
@@ -43,11 +43,10 @@ import java.util.stream.Stream;
/**
* A configuration that is the result of
- * resolution or resolution with
- * service binding.
+ * resolution or resolution with service binding.
*
* A configuration encapsulates the readability graph that is the
- * output of resolution. A readability graph is a directed graph where the nodes
+ * output of resolution. A readability graph is a directed graph whose vertices
* are of type {@link ResolvedModule} and the edges represent the readability
* amongst the modules. {@code Configuration} defines the {@link #modules()
* modules()} method to get the set of resolved modules in the graph. {@code
@@ -176,8 +175,8 @@ public final class Configuration {
* If resolution fails for any of the observability-related reasons
* specified by the static {@code resolve} method
* @throws ResolutionException
- * If any of the post-resolution consistency checks specified by
- * the static {@code resolve} method fail
+ * If resolution fails any of the consistency checks specified by
+ * the static {@code resolve} method
* @throws SecurityException
* If locating a module is denied by the security manager
*/
@@ -219,8 +218,8 @@ public final class Configuration {
* If resolution fails for any of the observability-related reasons
* specified by the static {@code resolve} method
* @throws ResolutionException
- * If any of the post-resolution consistency checks specified by
- * the static {@code resolve} method fail
+ * If resolution fails any of the consistency checks specified by
+ * the static {@code resolve} method
* @throws SecurityException
* If locating a module is denied by the security manager
*/
@@ -234,7 +233,7 @@ public final class Configuration {
/**
* Resolves a collection of root modules, with service binding, and with
- * the empty configuration as its parent. The post resolution checks
+ * the empty configuration as its parent. The consistency checks
* are optionally run.
*
* This method is used to create the configuration for the boot layer.
@@ -264,10 +263,9 @@ public final class Configuration {
* or dependences that are located in a parent configuration are resolved
* no further and are not included in the resulting configuration.
*
- * When all modules have been resolved then the resulting dependency
- * graph is checked to ensure that it does not contain cycles. A
- * readability graph is constructed, and in conjunction with the module
- * exports and service use, checked for consistency.
+ * When all modules have been enumerated then a readability graph
+ * is computed, and in conjunction with the module exports and service use,
+ * checked for consistency.
*
* Resolution may fail with {@code FindException} for the following
* observability-related reasons:
@@ -284,8 +282,8 @@ public final class Configuration {
*
*
*
- * Post-resolution consistency checks may fail with {@code
- * ResolutionException} for the following reasons:
+ * Resolution may fail with {@code ResolutionException} if any of the
+ * following consistency checks fail:
*
*
*
@@ -329,9 +327,11 @@ public final class Configuration {
* root modules
*
* @throws FindException
- * If resolution fails for an observability-related reason
+ * If resolution fails for any of observability-related reasons
+ * specified above
* @throws ResolutionException
- * If a post-resolution consistency checks fails
+ * If resolution fails for any of the consistency checks specified
+ * above
* @throws IllegalArgumentException
* If the list of parents is empty, or the list has two or more
* parents with modules for different target operating systems,
@@ -368,11 +368,11 @@ public final class Configuration {
* resolve} except that the graph of resolved modules is augmented
* with modules induced by the service-use dependence relation.
*
- * More specifically, the root modules are resolved as if by calling
- * {@code resolve}. The resolved modules, and all modules in the
- * parent configurations, with {@link ModuleDescriptor#uses() service
- * dependences} are then examined. All modules found by the given module
- * finders that {@link ModuleDescriptor#provides() provide} an
+ *
More specifically, the root modules are
+ * resolved as if by calling {@code resolve}. The resolved modules, and
+ * all modules in the parent configurations, with {@link ModuleDescriptor#uses()
+ * service dependences} are then examined. All modules found by the given
+ * module finders that {@link ModuleDescriptor#provides() provide} an
* implementation of one or more of the service types are added to the
* module graph and then resolved as if by calling the {@code
* resolve} method. Adding modules to the module graph may introduce new
@@ -402,8 +402,8 @@ public final class Configuration {
* If resolution fails for any of the observability-related reasons
* specified by the static {@code resolve} method
* @throws ResolutionException
- * If any of the post-resolution consistency checks specified by
- * the static {@code resolve} method fail
+ * If resolution fails any of the consistency checks specified by
+ * the static {@code resolve} method
* @throws IllegalArgumentException
* If the list of parents is empty, or the list has two or more
* parents with modules for different target operating systems,
diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java
index e0e6d883550..5a8b8cb63f3 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java
@@ -48,7 +48,7 @@ import jdk.internal.module.SystemModuleFinder;
/**
* A finder of modules. A {@code ModuleFinder} is used to find modules during
* resolution or
- * service binding.
+ * service binding.
*
*
A {@code ModuleFinder} can only find one module with a given name. A
* {@code ModuleFinder} that finds modules in a sequence of directories, for
@@ -239,30 +239,35 @@ public interface ModuleFinder {
*
*
*
- * The module {@link ModuleDescriptor#name() name}, and {@link
- * ModuleDescriptor#version() version} if applicable, is derived from
- * the file name of the JAR file as follows:
+ * If the JAR file has the attribute "{@code Automatic-Module-Name}"
+ * in its main manifest then its value is the {@linkplain
+ * ModuleDescriptor#name() module name}. The module name is otherwise
+ * derived from the name of the JAR file.
+ *
+ * The {@link ModuleDescriptor#version() version}, and the
+ * module name when the attribute "{@code Automatic-Module-Name}" is not
+ * present, are derived from the file name of the JAR file as follows:
*
*
*
- * The {@code .jar} suffix is removed.
+ * The "{@code .jar}" suffix is removed.
*
* If the name matches the regular expression {@code
* "-(\\d+(\\.|$))"} then the module name will be derived from the
* subsequence preceding the hyphen of the first occurrence. The
* subsequence after the hyphen is parsed as a {@link
- * ModuleDescriptor.Version} and ignored if it cannot be parsed as
- * a {@code Version}.
+ * ModuleDescriptor.Version Version} and ignored if it cannot be
+ * parsed as a {@code Version}.
*
* All non-alphanumeric characters ({@code [^A-Za-z0-9]})
* in the module name are replaced with a dot ({@code "."}), all
* repeating dots are replaced with one dot, and all leading and
* trailing dots are removed.
*
- * As an example, a JAR file named {@code foo-bar.jar} will
- * derive a module name {@code foo.bar} and no version. A JAR file
- * named {@code foo-bar-1.2.3-SNAPSHOT.jar} will derive a module
- * name {@code foo.bar} and {@code 1.2.3-SNAPSHOT} as the version.
+ *
As an example, a JAR file named "{@code foo-bar.jar}" will
+ * derive a module name "{@code foo.bar}" and no version. A JAR file
+ * named "{@code foo-bar-1.2.3-SNAPSHOT.jar}" will derive a module
+ * name "{@code foo.bar}" and "{@code 1.2.3-SNAPSHOT}" as the version.
*
*
*
@@ -295,11 +300,12 @@ public interface ModuleFinder {
* If a {@code ModuleDescriptor} cannot be created (by means of the
* {@link ModuleDescriptor.Builder ModuleDescriptor.Builder} API) for an
* automatic module then {@code FindException} is thrown. This can arise
- * when a legal module name cannot be derived from the file name of the JAR
- * file, where the JAR file contains a {@code .class} in the top-level
- * directory of the JAR file, where an entry in a service configuration
- * file is not a legal class name or its package name is not in the set of
- * packages derived for the module.
+ * when the value of the "{@code Automatic-Module-Name}" attribute is not a
+ * legal module name, a legal module name cannot be derived from the file
+ * name of the JAR file, where the JAR file contains a {@code .class} in
+ * the top-level directory of the JAR file, where an entry in a service
+ * configuration file is not a legal class name or its package name is not
+ * in the set of packages derived for the module.
*
* In addition to JAR files, an implementation may also support modules
* that are packaged in other implementation specific module formats. If
diff --git a/jdk/src/java.base/share/classes/java/lang/module/package-info.java b/jdk/src/java.base/share/classes/java/lang/module/package-info.java
index c8e2c04d975..902019b8ce4 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/package-info.java
+++ b/jdk/src/java.base/share/classes/java/lang/module/package-info.java
@@ -27,118 +27,178 @@
* Classes to support module descriptors and creating configurations of modules
* by means of resolution and service binding.
*
- *
- *
- * Resolution is the process of computing the transitive closure of a set
- * of root modules over a set of observable modules by resolving the
- * dependences expressed by {@link
- * java.lang.module.ModuleDescriptor.Requires requires} clauses.
- * The dependence graph is augmented with edges that take account of
- * implicitly declared dependences ({@code requires transitive}) to create a
- * readability graph. The result of resolution is a {@link
- * java.lang.module.Configuration Configuration} that encapsulates the
- * readability graph.
- *
- * As an example, suppose we have the following observable modules:
- * {@code
- * module m1 { requires m2; }
- * module m2 { requires transitive m3; }
- * module m3 { }
- * module m4 { }
- * }
- *
- * If the module {@code m1} is resolved then the resulting configuration
- * contains three modules ({@code m1}, {@code m2}, {@code m3}). The edges in
- * its readability graph are:
- * {@code
- * m1 --> m2 (meaning m1 reads m2)
- * m1 --> m3
- * m2 --> m3
- * }
- *
- * Resolution is an additive process. When computing the transitive closure
- * then the dependence relation may include dependences on modules in {@link
- * java.lang.module.Configuration#parents() parent} configurations. The result
- * is a relative configuration that is relative to one or more parent
- * configurations and where the readability graph may have edges from modules
- * in the configuration to modules in parent configurations.
- *
- * As an example, suppose we have the following observable modules:
- * {@code
- * module m1 { requires m2; requires java.xml; }
- * module m2 { }
- * }
- *
- * If module {@code m1} is resolved with the configuration for the {@link
- * java.lang.ModuleLayer#boot() boot} layer as the parent then the resulting
- * configuration contains two modules ({@code m1}, {@code m2}). The edges in
- * its readability graph are:
- *
{@code
- * m1 --> m2
- * m1 --> java.xml
- * }
- * where module {@code java.xml} is in the parent configuration. For
- * simplicity, this example omits the implicitly declared dependence on the
- * {@code java.base} module.
- *
- * Requires clauses that are "{@code requires static}" express an optional
- * dependence (except at compile-time). If a module declares that it
- * "{@code requires static M}" then resolution does not search the observable
- * modules for "{@code M}". However, if "{@code M}" is resolved (because resolution
- * resolves a module that requires "{@code M}" without the {@link
- * java.lang.module.ModuleDescriptor.Requires.Modifier#STATIC static} modifier)
- * then the readability graph will contain read edges for each module that
- * "{@code requires static M}".
- *
- * {@link java.lang.module.ModuleDescriptor#isAutomatic() Automatic} modules
- * receive special treatment during resolution. Each automatic module is resolved
- * as if it "{@code requires transitive}" all observable automatic modules and
- * all automatic modules in the parent configurations. Each automatic module is
- * resolved so that it reads all other modules in the resulting configuration and
- * all modules in parent configurations.
- *
- *
- *
- * Service binding is the process of augmenting a graph of resolved modules
- * from the set of observable modules induced by the service-use dependence
- * ({@code uses} and {@code provides} clauses). Any module that was not
- * previously in the graph requires resolution to compute its transitive
- * closure. Service binding is an iterative process in that adding a module
- * that satisfies some service-use dependence may introduce new service-use
- * dependences.
- *
- * Suppose we have the following observable modules:
- * {@code
- * module m1 { exports p; uses p.S; }
- * module m2 { requires m1; provides p.S with p2.S2; }
- * module m3 { requires m1; requires m4; provides p.S with p3.S3; }
- * module m4 { }
- * }
- *
- * If the module {@code m1} is resolved then the resulting graph of modules
- * has one module ({@code m1}). If the graph is augmented with modules induced
- * by the service-use dependence relation then the configuration will contain
- * four modules ({@code m1}, {@code m2}, {@code m3}, {@code m4}). The edges in
- * its readability graph are:
- * {@code
- * m2 --> m1
- * m3 --> m1
- * m3 --> m4
- * }
- * The edges in the conceptual service-use graph are:
- * {@code
- * m1 --> m2 (meaning m1 uses a service that is provided by m2)
- * m1 --> m3
- * }
- *
- * General Exceptions
- *
* Unless otherwise noted, passing a {@code null} argument to a constructor
* or method of any class or interface in this package will cause a {@link
* java.lang.NullPointerException NullPointerException} to be thrown. Additionally,
* invoking a method with an array or collection containing a {@code null} element
* will cause a {@code NullPointerException}, unless otherwise specified.
*
+ *
+ *
+ *
+ * Resolution is the process of computing how modules depend on each other.
+ * The process occurs at compile time and run time.
+ *
+ * Resolution is a two-step process. The first step recursively enumerates
+ * the 'requires' directives of a set of root modules. If all the enumerated
+ * modules are observable, then the second step computes their readability graph.
+ * The readability graph embodies how modules depend on each other, which in
+ * turn controls access across module boundaries.
+ *
+ * Step 1: Recursive enumeration
+ *
+ * Recursive enumeration takes a set of module names, looks up each of their
+ * module declarations, and for each module declaration, recursively enumerates:
+ *
+ *
+ * -
the module names given by the 'requires' directives with the
+ * 'transitive' modifier, and
+ * -
at the discretion of the host system, the module names given by
+ * the 'requires' directives without the 'transitive' modifier.
+ *
+ *
+ * Module declarations are looked up in a set of observable modules. The set
+ * of observable modules is determined in an implementation specific manner. The
+ * set of observable modules may include modules with explicit declarations
+ * (that is, with a {@code module-info.java} source file or {@code module-info.class}
+ * file) and modules with implicit declarations (that is,
+ * automatic modules).
+ * Because an automatic module has no explicit module declaration, it has no
+ * 'requires' directives of its own, although its name may be given by a
+ * 'requires' directive of an explicit module declaration.
+
+ * The set of root modules, whose names are the initial input to this
+ * algorithm, is determined in an implementation specific manner. The set of
+ * root modules may include automatic modules.
+ *
+ * If at least one automatic module is enumerated by this algorithm, then
+ * every observable automatic module must be enumerated, regardless of whether
+ * any of their names are given by 'requires' directives of explicit module
+ * declarations.
+ *
+ * If any of the following conditions occur, then resolution fails:
+ *
+ * Any root module is not observable.
+ * Any module whose name is given by a 'requires' directive with the
+ * 'transitive' modifier is not observable.
+ * At the discretion of the host system, any module whose name is given
+ * by a 'requires' directive without the 'transitive' modifier is not
+ * observable.
+ * The algorithm in this step enumerates the same module name twice. This
+ * indicates a cycle in the 'requires' directives, disregarding any 'transitive'
+ * modifiers.
+ *
+ *
+ * Otherwise, resolution proceeds to step 2.
+ *
+ * Step 2: Computing the readability graph
+ *
+ * A 'requires' directive (irrespective of 'transitive') expresses that
+ * one module depends on some other module. The effect of the 'transitive'
+ * modifier is to cause additional modules to also depend on the other module.
+ * If module M 'requires transitive N', then not only does M depend on N, but
+ * any module that depends on M also depends on N. This allows M to be
+ * refactored so that some or all of its content can be moved to a new module N
+ * without breaking modules that have a 'requires M' directive.
+ *
+ * Module dependencies are represented by the readability graph. The
+ * readability graph is a directed graph whose vertices are the modules
+ * enumerated in step 1 and whose edges represent readability between pairs of
+ * modules. The edges are specified as follows:
+ *
+ *
First, readability is determined by the 'requires' directives of the
+ * enumerated modules, disregarding any 'transitive' modifiers:
+ *
+ *
+ * For each enumerated module A that 'requires' B: A "reads" B.
+ * For each enumerated module X that is automatic: X "reads" every
+ * other enumerated module (it is "as if" an automatic module has 'requires'
+ * directives for every other enumerated module).
+ *
+ *
+ * Second, readability is augmented to account for 'transitive' modifiers:
+ *
+ *
+ * Finally, every module "reads" itself.
+ *
+ * If any of the following conditions occur in the readability graph, then
+ * resolution fails:
+ *
+ * A module "reads" two or more modules with the same name. This includes
+ * the case where a module "reads" another with the same name as itself.
+ * Two or more modules export a package with the same name to a module
+ * that "reads" both. This includes the case where a module M containing package
+ * p "reads" another module that exports p to M.
+ * A module M declares that it 'uses p.S' or 'provides p.S with ...' but
+ * package p is neither in module M nor exported to M by any module that M
+ * "reads".
+ *
+ * Otherwise, resolution succeeds, and the result of resolution is the
+ * readability graph.
+ *
+ *
Root modules
+ *
+ * The set of root modules at compile-time is usually the set of modules
+ * being compiled. At run-time, the set of root modules is usually the
+ * application module specified to the 'java' launcher. When compiling code in
+ * the unnamed module, or at run-time when the main application class is loaded
+ * from the class path, then the default set of root modules is implementation
+ * specific (In the JDK implementation it is the module "java.se", if observable,
+ * and every observable module that exports an API).
+ *
+ * Observable modules
+ *
+ * The set of observable modules at both compile-time and run-time is determined
+ * by searching an abstract module path. The module path is typically composed
+ * of search paths that are searched in order:
+ *
+ *
+ * At compile-time only, a compilation module path that contains module
+ * definitions in source form.
+ * The upgrade module path containing compiled definitions of modules
+ * intended to be used in place of upgradeable modules built-in to the
+ * environment.
+ * The system modules which are the compiled modules built-in to the
+ * environment.
+ * The application module path which contains compiled definitions of
+ * library and application modules.
+ *
+ *
+ * 'requires' directives with 'static' modifier
+ *
+ * 'requires' directives that have the 'static' modifier express an optional
+ * dependence at run time. If a module declares that it 'requires static M' then
+ * resolution does not search the observable modules for M to satisfy the dependency.
+ * However, if M is recursively enumerated at step 1 then all modules that are
+ * enumerated and `requires static M` will read M.
+ *
+ * Completeness
+ *
+ * Resolution may be partial at compile-time in that the complete transitive
+ * closure may not be required to compile a set of modules. Minimally, the
+ * readability graph that is constructed and validated at compile-time includes
+ * the modules being compiled, their direct dependences, and all implicitly
+ * declared dependences (requires transitive).
+ *
+ * At run-time, resolution is an additive process. The recursive enumeration
+ * at step 1 may be relative to previous resolutions so that a root module,
+ * or a module named in a 'requires' directive, is not enumerated when it was
+ * enumerated by a previous (or parent) resolution. The readability graph that
+ * is the result of resolution may therefore have a vertex for a module enumerated
+ * in step 1 but with an edge to represent that the module reads a module that
+ * was enumerated by previous (or parent) resolution.
+ *
* @since 9
* @spec JPMS
*/
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java b/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
index 35c689d56cc..f725eb35e6a 100644
--- a/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
@@ -304,7 +304,7 @@ public class AccessibleObject implements AnnotatedElement {
if (isClassPublic && declaringModule.isExported(pn, callerModule)) {
// member is public
if (Modifier.isPublic(modifiers)) {
- logIfExportedByBackdoor(caller, declaringClass);
+ logIfExportedForIllegalAccess(caller, declaringClass);
return true;
}
@@ -312,14 +312,14 @@ public class AccessibleObject implements AnnotatedElement {
if (Modifier.isProtected(modifiers)
&& Modifier.isStatic(modifiers)
&& isSubclassOf(caller, declaringClass)) {
- logIfExportedByBackdoor(caller, declaringClass);
+ logIfExportedForIllegalAccess(caller, declaringClass);
return true;
}
}
// package is open to caller
if (declaringModule.isOpen(pn, callerModule)) {
- logIfOpenedByBackdoor(caller, declaringClass);
+ logIfOpenedForIllegalAccess(caller, declaringClass);
return true;
}
@@ -353,26 +353,26 @@ public class AccessibleObject implements AnnotatedElement {
return false;
}
- private void logIfOpenedByBackdoor(Class> caller, Class> declaringClass) {
+ private void logIfOpenedForIllegalAccess(Class> caller, Class> declaringClass) {
Module callerModule = caller.getModule();
Module targetModule = declaringClass.getModule();
// callerModule is null during early startup
if (callerModule != null && !callerModule.isNamed() && targetModule.isNamed()) {
IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger();
if (logger != null) {
- logger.logIfOpenedByBackdoor(caller, declaringClass, this::toShortString);
+ logger.logIfOpenedForIllegalAccess(caller, declaringClass, this::toShortString);
}
}
}
- private void logIfExportedByBackdoor(Class> caller, Class> declaringClass) {
+ private void logIfExportedForIllegalAccess(Class> caller, Class> declaringClass) {
Module callerModule = caller.getModule();
Module targetModule = declaringClass.getModule();
// callerModule is null during early startup
if (callerModule != null && !callerModule.isNamed() && targetModule.isNamed()) {
IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger();
if (logger != null) {
- logger.logIfExportedByBackdoor(caller, declaringClass, this::toShortString);
+ logger.logIfExportedForIllegalAccess(caller, declaringClass, this::toShortString);
}
}
}
@@ -634,7 +634,7 @@ public class AccessibleObject implements AnnotatedElement {
}
// access okay
- logIfExportedByBackdoor(caller, memberClass);
+ logIfExportedForIllegalAccess(caller, memberClass);
// Success: Update the cache.
Object cache = (targetClass != null
diff --git a/jdk/src/java.base/share/classes/java/util/ServiceConfigurationError.java b/jdk/src/java.base/share/classes/java/util/ServiceConfigurationError.java
index 42db72d2d48..2852384eb4b 100644
--- a/jdk/src/java.base/share/classes/java/util/ServiceConfigurationError.java
+++ b/jdk/src/java.base/share/classes/java/util/ServiceConfigurationError.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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
@@ -27,33 +27,12 @@ package java.util;
/**
- * Error thrown when something goes wrong while loading a service provider.
- *
- * This error will be thrown in the following situations:
- *
- *
- *
- * - The format of a provider-configuration file violates the specification;
- *
- * - An {@link java.io.IOException IOException} occurs while reading a
- * provider-configuration file;
- *
- * - A concrete provider class named in a provider-configuration file
- * cannot be found;
- *
- * - A concrete provider class is not a subclass of the service class;
- *
- *
- * - A concrete provider class cannot be instantiated; or
- *
- *
- Some other kind of error occurs.
- *
- *
- *
+ * Error thrown when something goes wrong while locating, loading, or
+ * instantiating a service provider.
*
* @author Mark Reinhold
* @since 1.6
+ * @see ServiceLoader
*/
public class ServiceConfigurationError
diff --git a/jdk/src/java.base/share/classes/java/util/ServiceLoader.java b/jdk/src/java.base/share/classes/java/util/ServiceLoader.java
index 8d4cd8de611..58961a0661d 100644
--- a/jdk/src/java.base/share/classes/java/util/ServiceLoader.java
+++ b/jdk/src/java.base/share/classes/java/util/ServiceLoader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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
@@ -81,16 +81,82 @@ import jdk.internal.reflect.Reflection;
* single class or interface could possibly unify them, so no such type is
* defined here.
*
- * Providers deployed as explicit modules on the module path are
- * instantiated by a provider factory or directly via the provider's
- * constructor. In the module declaration then the class name specified in the
- * provides clause is a provider factory if it is public and defines a
- * public static no-args method named "{@code provider}". The return type of
- * the method must be assignable to the service type. If the class is
- * not a provider factory then it is public with a public zero-argument
- * constructor. The requirement that the provider factory or provider class
- * be public helps to document the intent that the provider will be
- * instantiated by the service-provider loading facility.
+ *
A service loader is created by invoking one of the static {@code load}
+ * methods that {@code ServiceLoader} defines. The resulting service loader
+ * can be used to locate and instantiate service provider implementations by
+ * means of its {@link #iterator() iterator} ({@code ServiceLoader} implements
+ * {@code Iterable}) or by consuming elements from its {@link #stream() stream}.
+ *
+ *
As an example, suppose the service type is {@code com.example.CodecSet}
+ * and it defines two abstract methods to obtain encoders and decoders:
+ *
{@code
+ * package com.example;
+ * public interface CodecSet {
+ * Encoder getEncoder(String encodingName);
+ * Decoder getDecoder(String encodingName);
+ * }
+ * }
+ * With this example, the following uses the service loader's iterator to find
+ * a provider that supports a specific encoding:
+ * {@code
+ * public Encoder getEncoder(String encodingName) {
+ * ServiceLoader loader = ServiceLoader.load(CodeSet.class);
+ * for (CodecSet cs : loader) {
+ * Encoder encoder = cs.getEncoder(encodingName);
+ * if (encoder != null)
+ * return encoder;
+ * }
+ * return null;
+ * }
+ * }
+ *
+ * Selecting a provider or filtering providers will usually involve invoking
+ * a provider method. In the {@code CodeSet} example, the {@code getEncoder}
+ * method is used to select the implementation. Where selection or filtering based
+ * on the provider class is needed then it can be done when consuming the elements
+ * of the service loader's stream. As an example, the following collects the
+ * {@code CodeSet} implementations that have a specific annotation:
+ *
{@code
+ * Set providers = ServiceLoader.load(CodecSet.class)
+ * .stream()
+ * .filter(p -> p.type().isAnnotationPresent(Managed.class))
+ * .map(Provider::get)
+ * .collect(Collectors.toSet());
+ * }
+ *
+ * Providers are located and instantiated lazily, that is, on demand. A
+ * service loader maintains a cache of the providers that have been loaded so
+ * far. Each invocation of the {@code iterator} method returns an iterator that
+ * first yields all of the elements cached from previous iteration, in
+ * instantiation order, and then lazily locates and instantiates any remaining
+ * providers, adding each one to the cache in turn. Similarly, each invocation
+ * of the {@code stream} method returns a stream that first processes all
+ * providers loaded by previous stream operations, in load order, and then lazily
+ * locates any remaining providers. Caches are cleared via the {@link #reload
+ * reload} method.
+ *
+ *
Deploying provider classes in modules
+ *
+ * A provider deployed as an explicit module must have an appropriate
+ * provides clause in its module descriptor to declare that the module
+ * provides an implementation of the service.
+ *
+ *
A provider deployed as an explicit module is instantiated by a
+ * provider factory or directly via the provider's constructor. In the
+ * module declaration then the class name specified in the provides clause
+ * is a provider factory if it is public and explicitly declares a public static
+ * no-args method named "{@code provider}". The return type of the method must be
+ * assignable to the service type. If the class is not a provider factory
+ * then it is public with a public zero-argument constructor. The requirement
+ * that the provider factory or provider class be public helps to document the
+ * intent that the provider will be instantiated by the service-provider loading
+ * facility.
+ *
+ *
Providers deployed as {@link
+ * java.lang.module.ModuleDescriptor#isAutomatic automatic-modules} on the
+ * module path must have a public zero-argument constructor. If the provider
+ * also declares a public static method named "{@code provider}" then it is
+ * ignored.
*
*
As an example, suppose a module declares the following:
*
@@ -99,38 +165,33 @@ import jdk.internal.reflect.Reflection;
* provides com.example.CodecSet with com.example.impl.ExtendedCodecsFactory;
* }
*
- *
where {@code com.example.CodecSet} is the service type, {@code
- * com.example.impl.StandardCodecs} is a provider class that is public with a
- * public no-args constructor, {@code com.example.impl.ExtendedCodecsFactory}
- * is a public class that defines a public static no-args method named
- * "{@code provider}" with a return type that is {@code CodecSet} or a subtype
- * of. For this example then {@code StandardCodecs}'s no-arg constructor will
+ * where
+ *
+ * - {@code com.example.CodecSet} is the service type as above
+ * - {@code com.example.impl.StandardCodecs} is a provider class
+ * (implements {@code CodecSet}) that is public with a public no-args
+ * constructor
+ * - {@code com.example.impl.ExtendedCodecsFactory} is a public class
+ * that explicitly declares a public static no-args method named
+ * "{@code provider}" with a return type that is {@code CodecSet} or a
+ * subtype of.
+ *
+ *
+ * For this example then {@code StandardCodecs}'s no-arg constructor will
* be used to instantiate {@code StandardCodecs}. {@code ExtendedCodecsFactory}
* will be treated as a provider factory and {@code
* ExtendedCodecsFactory.provider()} will be invoked to obtain the provider.
*
- *
Providers deployed on the class path or as {@link
- * java.lang.module.ModuleDescriptor#isAutomatic automatic-modules} on the
- * module path must have a public zero-argument constructor.
+ *
Deploying provider classes on the class path
*
- * An application or library using this loading facility and developed
- * and deployed as an explicit module must have an appropriate uses
- * clause in its module descriptor to declare that the module uses
- * implementations of the service. A corresponding requirement is that a
- * provider deployed as an explicit module must have an appropriate
- * provides clause in its module descriptor to declare that the module
- * provides an implementation of the service. The uses and
- * provides allow consumers of a service to be linked to modules
- * containing providers of the service.
- *
- *
A service provider that is packaged as a JAR file for the class path is
- * identified by placing a provider-configuration file in the resource
- * directory {@code META-INF/services}. The file's name is the fully-qualified
- * binary name of the service's
- * type. The file contains a list of fully-qualified binary names of concrete
- * provider classes, one per line. Space and tab characters surrounding each
- * name, as well as blank lines, are ignored. The comment character is
- * {@code '#'} ('\u0023'
,
+ *
A service provider that is packaged as a JAR file for
+ * the class path is identified by placing a provider-configuration file
+ * in the resource directory {@code META-INF/services}. The file's name is
+ * the fully-qualified binary name
+ * of the service's type. The file contains a list of fully-qualified binary
+ * names of concrete provider classes, one per line. Space and tab characters
+ * surrounding each name, as well as blank lines, are ignored. The comment
+ * character is {@code '#'} ('\u0023'
,
* NUMBER SIGN); on
* each line all characters following the first comment character are ignored.
* The file must be encoded in UTF-8.
@@ -141,103 +202,88 @@ import jdk.internal.reflect.Reflection;
* unit as the provider itself. The provider must be visible from the same
* class loader that was initially queried to locate the configuration file;
* note that this is not necessarily the class loader from which the file was
- * actually loaded.
+ * actually located.
*
- *
Providers are located and instantiated lazily, that is, on demand. A
- * service loader maintains a cache of the providers that have been loaded so
- * far. Each invocation of the {@link #iterator iterator} method returns an
- * iterator that first yields all of the elements cached from previous
- * iteration, in instantiation order, and then lazily locates and instantiates
- * any remaining providers, adding each one to the cache in turn. Similarly,
- * each invocation of the {@link #stream stream} method returns a stream that
- * first processes all providers loaded by previous stream operations, in load
- * order, and then lazily locates any remaining providers. Caches are cleared
- * via the {@link #reload reload} method.
+ *
For the example, then suppose {@code com.example.impl.StandardCodecs} is
+ * packaged in a JAR file for the class path then the JAR file will contain a
+ * file named:
+ *
{@code
+ * META-INF/services/com.example.CodecSet
+ * }
+ * that contains the line:
+ * {@code
+ * com.example.impl.StandardCodecs # Standard codecs
+ * }
*
- * Locating providers
+ * Using ServiceLoader from code in modules
*
- * The {@code load} methods locate providers using a class loader or module
- * {@link ModuleLayer layer}. When locating providers using a class loader then
- * providers in both named and unnamed modules may be located. When locating
- * providers using a module layer then only providers in named modules in
- * the layer (or parent layers) are located.
+ *
An application or library using this loading facility and developed
+ * and deployed as an explicit module must have an appropriate uses
+ * clause in its module descriptor to declare that the module uses
+ * implementations of the service. Combined with the requirement is that a
+ * provider deployed as an explicit module must have an appropriate
+ * provides clause allows consumers of a service to be linked
+ * to modules containing providers of the service.
*
- *
When locating providers using a class loader then any providers in named
- * modules defined to the class loader, or any class loader that is reachable
- * via parent delegation, are located. Additionally, providers in module layers
- * other than the {@link ModuleLayer#boot() boot} layer, where the module layer
- * contains modules defined to the class loader, or any class loader reachable
- * via parent delegation, are also located. For example, suppose there is a
- * module layer where each module is defined to its own class loader (see {@link
- * ModuleLayer#defineModulesWithManyLoaders defineModulesWithManyLoaders}). If the
- * {@code load} method is invoked to locate providers using any of these class
- * loaders for this layer then it will locate all of the providers in that
- * layer, irrespective of their defining class loader.
+ *
For the example, if code in a module uses a service loader to load
+ * implementations of {@code com.example.CodecSet} then its module will declare
+ * the usage with:
{@code uses com.example.CodecSet; }
*
- * In the case of unnamed modules then the service configuration files are
- * located using the class loader's {@link ClassLoader#getResources(String)
- * ClassLoader.getResources(String)} method. Any providers listed should be
- * visible via the class loader specified to the {@code load} method. If a
- * provider in a named module is listed then it is ignored - this is to avoid
- * duplicates that would otherwise arise when a module has both a
- * provides clause and a service configuration file in {@code
- * META-INF/services} that lists the same provider.
+ *
Errors
*
- * Ordering
+ * When using the service loader's {@code iterator} then its {@link
+ * Iterator#hasNext() hasNext} and {@link Iterator#next() next} methods will
+ * fail with {@link ServiceConfigurationError} if an error occurs locating or
+ * instantiating a provider. When processing the service loader's stream then
+ * {@code ServiceConfigurationError} is thrown by whatever method causes a
+ * provider class to be loaded.
+ *
+ *
When loading or instantiating a provider class in a named module then
+ * {@code ServiceConfigurationError} can be thrown for the following reasons:
*
- * Service loaders created to locate providers using a {@code ClassLoader}
- * locate providers as follows:
*
- * - Providers in named modules are located before providers on the
- * class path (or more generally, unnamed modules).
*
- * - When locating providers in named modules then the service loader
- * will locate providers in modules defined to the class loader, then its
- * parent class loader, its parent parent, and so on to the bootstrap class
- * loader. If a {@code ClassLoader}, or any class loader in the parent
- * delegation chain, defines modules in a custom module {@link ModuleLayer} then
- * all providers in that layer are located, irrespective of their class
- * loader. The ordering of modules defined to the same class loader, or the
- * ordering of modules in a layer, is not defined.
+ * - The provider class cannot be loaded.
*
- * - If a named module declares more than one provider then the providers
- * are located in the iteration order of the {@link
- * java.lang.module.ModuleDescriptor.Provides#providers() providers} list.
- * Providers added dynamically by instrumentation agents ({@link
- * java.lang.instrument.Instrumentation#redefineModule redefineModule})
- * are always located after providers declared by the module.
+ * - The provider class is not a provider factory or is not a subclass of
+ * the service type with a public zero-argument constructor.
+ *
+ * - The provider class explicitly declares a public static no-args method
+ * named "{@code provider}" with a return type that is not a subclass of the
+ * service type.
+ *
+ * - The provider class explicitly declares more than one public static
+ * no-args method named "{@code provider}".
+ *
+ * - The provider class is a provider factory and its public static no-args
+ * method "{@code provider}" method returns {@code null} or throws an
+ * exception.
+ *
+ * - The provider class is not a provider factory and cannot be instantiated
+ * with its public zero-argument constructor.
*
- * - When locating providers in unnamed modules then the ordering is
- * based on the order that the class loader's {@link
- * ClassLoader#getResources(String) ClassLoader.getResources(String)}
- * method finds the service configuration files.
*
*
- * Service loaders created to locate providers in a {@linkplain ModuleLayer
- * module layer} will first locate providers in the layer, before locating
- * providers in parent layers. Traversal of parent layers is depth-first with
- * each layer visited at most once. For example, suppose L0 is the boot layer,
- * L1 and L2 are custom layers with L0 as their parent. Now suppose that L3 is
- * created with L1 and L2 as the parents (in that order). Using a service
- * loader to locate providers with L3 as the content will locate providers
- * in the following order: L3, L1, L0, L2. The ordering of modules in a layer
- * is not defined.
+ *
When reading a provider-configuration file, or loading or instantiating a
+ * provider class named in a provider-configuration file, then {@code
+ * ServiceConfigurationError} can be thrown for the following reasons:
*
- *
Selection and filtering
+ *
*
- * Selecting a provider or filtering providers will usually involve invoking
- * a provider method. Where selection or filtering based on the provider class is
- * needed then it can be done using a {@link #stream() stream}. For example, the
- * following collects the providers that have a specific annotation:
- *
{@code
- * Set providers = ServiceLoader.load(CodecSet.class)
- * .stream()
- * .filter(p -> p.type().isAnnotationPresent(Managed.class))
- * .map(Provider::get)
- * .collect(Collectors.toSet());
- * }
+ * The format of the provider-configuration file violates the format specified above;
*
- * Security
+ * An {@link IOException IOException} occurs while reading the
+ * provider-configuration file;
+ *
+ * The provider class cannot be loaded;
+ *
+ * The provider class is not a subclass of the service type, does not
+ * define a public zero-argument constructor, or cannot be instantiated;
+ *
+ *
+ *
+ * Security
*
* Service loaders always execute in the security context of the caller
* of the iterator or stream methods and may also be restricted by the security
@@ -246,91 +292,16 @@ import jdk.internal.reflect.Reflection;
* the methods of the iterators which they return, from within a privileged
* security context.
*
- *
Concurrency
+ * Concurrency
*
* Instances of this class are not safe for use by multiple concurrent
* threads.
*
- *
Null handling
+ * Null handling
*
* Unless otherwise specified, passing a {@code null} argument to any
* method in this class will cause a {@link NullPointerException} to be thrown.
*
- *
Example
- * Suppose we have a service type {@code com.example.CodecSet} which is
- * intended to represent sets of encoder/decoder pairs for some protocol. In
- * this case it is an abstract class with two abstract methods:
- *
- *
- * public abstract Encoder getEncoder(String encodingName);
- * public abstract Decoder getDecoder(String encodingName);
- *
- * Each method returns an appropriate object or {@code null} if the provider
- * does not support the given encoding. Typical providers support more than
- * one encoding.
- *
- * The {@code CodecSet} class creates and saves a single service instance
- * at initialization:
- *
- *
{@code
- * private static ServiceLoader codecSetLoader
- * = ServiceLoader.load(CodecSet.class);
- * }
- *
- * To locate an encoder for a given encoding name it defines a static
- * factory method which iterates through the known and available providers,
- * returning only when it has located a suitable encoder or has run out of
- * providers.
- *
- *
{@code
- * public static Encoder getEncoder(String encodingName) {
- * for (CodecSet cp : codecSetLoader) {
- * Encoder enc = cp.getEncoder(encodingName);
- * if (enc != null)
- * return enc;
- * }
- * return null;
- * }}
- *
- * A {@code getDecoder} method is defined similarly.
- *
- *
If the code creating and using the service loader is developed as
- * a module then its module descriptor will declare the usage with:
- *
{@code uses com.example.CodecSet;}
- *
- * Now suppose that {@code com.example.impl.StandardCodecs} is an
- * implementation of the {@code CodecSet} service and developed as a module.
- * In that case then the module with the service provider module will declare
- * this in its module descriptor:
- *
{@code provides com.example.CodecSet with com.example.impl.StandardCodecs;
- * }
- *
- * On the other hand, suppose {@code com.example.impl.StandardCodecs} is
- * packaged in a JAR file for the class path then the JAR file will contain a
- * file named:
- *
{@code META-INF/services/com.example.CodecSet}
- * that contains the single line:
- * {@code com.example.impl.StandardCodecs # Standard codecs}
- *
- * Usage Note If
- * the class path of a class loader that is used for provider loading includes
- * remote network URLs then those URLs will be dereferenced in the process of
- * searching for provider-configuration files.
- *
- *
This activity is normal, although it may cause puzzling entries to be
- * created in web-server logs. If a web server is not configured correctly,
- * however, then this activity may cause the provider-loading algorithm to fail
- * spuriously.
- *
- *
A web server should return an HTTP 404 (Not Found) response when a
- * requested resource does not exist. Sometimes, however, web servers are
- * erroneously configured to return an HTTP 200 (OK) response along with a
- * helpful HTML error page in such cases. This will cause a {@link
- * ServiceConfigurationError} to be thrown when this class attempts to parse
- * the HTML page as a provider-configuration file. The best solution to this
- * problem is to fix the misconfigured web server to return the correct
- * response code (HTTP 404) along with the HTML error page.
- *
* @param
* The type of the service to be loaded by this loader
*
@@ -548,32 +519,83 @@ public final class ServiceLoader
}
/**
- * Uses Class.forName to load a provider class in a module.
- *
- * @throws ServiceConfigurationError
- * If the class cannot be loaded
+ * Returns {@code true} if the provider is in an explicit module
*/
- private Class> loadProviderInModule(Module module, String cn) {
- Class> clazz = null;
- if (acc == null) {
- try {
- clazz = Class.forName(module, cn);
- } catch (LinkageError e) {
- fail(service, "Unable to load " + cn, e);
- }
- } else {
- PrivilegedExceptionAction> pa = () -> Class.forName(module, cn);
- try {
- clazz = AccessController.doPrivileged(pa);
- } catch (PrivilegedActionException pae) {
- Throwable x = pae.getCause();
- fail(service, "Unable to load " + cn, x);
- return null;
+ private boolean inExplicitModule(Class> clazz) {
+ Module module = clazz.getModule();
+ return module.isNamed() && !module.getDescriptor().isAutomatic();
+ }
+
+ /**
+ * Returns the public static "provider" method if found.
+ *
+ * @throws ServiceConfigurationError if there is an error finding the
+ * provider method or there is more than one public static
+ * provider method
+ */
+ private Method findStaticProviderMethod(Class> clazz) {
+ List methods = null;
+ try {
+ methods = LANG_ACCESS.getDeclaredPublicMethods(clazz, "provider");
+ } catch (Throwable x) {
+ fail(service, "Unable to get public provider() method", x);
+ }
+ if (methods.isEmpty()) {
+ // does not declare a public provider method
+ return null;
+ }
+
+ // locate the static methods, can be at most one
+ Method result = null;
+ for (Method method : methods) {
+ int mods = method.getModifiers();
+ assert Modifier.isPublic(mods);
+ if (Modifier.isStatic(mods)) {
+ if (result != null) {
+ fail(service, clazz + " declares more than one"
+ + " public static provider() method");
+ }
+ result = method;
}
}
- if (clazz == null)
- fail(service, "Provider " + cn + " not found");
- return clazz;
+ if (result != null) {
+ Method m = result;
+ PrivilegedAction pa = () -> {
+ m.setAccessible(true);
+ return null;
+ };
+ AccessController.doPrivileged(pa);
+ }
+ return result;
+ }
+
+ /**
+ * Returns the public no-arg constructor of a class.
+ *
+ * @throws ServiceConfigurationError if the class does not have
+ * public no-arg constructor
+ */
+ private Constructor> getConstructor(Class> clazz) {
+ PrivilegedExceptionAction> pa
+ = new PrivilegedExceptionAction<>() {
+ @Override
+ public Constructor> run() throws Exception {
+ Constructor> ctor = clazz.getConstructor();
+ if (inExplicitModule(clazz))
+ ctor.setAccessible(true);
+ return ctor;
+ }
+ };
+ Constructor> ctor = null;
+ try {
+ ctor = AccessController.doPrivileged(pa);
+ } catch (Throwable x) {
+ if (x instanceof PrivilegedActionException)
+ x = x.getCause();
+ String cn = clazz.getName();
+ fail(service, cn + " Unable to get public no-arg constructor", x);
+ }
+ return ctor;
}
/**
@@ -581,65 +603,33 @@ public final class ServiceLoader
* permissions, the static factory to obtain the provider or the
* provider's no-arg constructor.
*/
- private final static class ProviderImpl implements Provider {
+ private static class ProviderImpl implements Provider {
final Class service;
+ final Class extends S> type;
+ final Method factoryMethod; // factory method or null
+ final Constructor extends S> ctor; // public no-args constructor or null
final AccessControlContext acc;
- final Method factoryMethod; // factory method or null
- final Class extends S> type;
- final Constructor extends S> ctor; // public no-args constructor or null
-
- /**
- * Creates a Provider.
- *
- * @param service
- * The service type
- * @param clazz
- * The provider (or provider factory) class
- * @param acc
- * The access control context when running with security manager
- *
- * @throws ServiceConfigurationError
- * If the class is not public; If the class defines a public
- * static provider() method with a return type that is assignable
- * to the service type or the class is not a provider class with
- * a public no-args constructor.
- */
- @SuppressWarnings("unchecked")
- ProviderImpl(Class> service, Class> clazz, AccessControlContext acc) {
- this.service = (Class) service;
- this.acc = acc;
-
- int mods = clazz.getModifiers();
- if (!Modifier.isPublic(mods)) {
- fail(service, clazz + " is not public");
- }
-
- // if the class is in an explicit module then see if it is
- // a provider factory class
- Method factoryMethod = null;
- if (inExplicitModule(clazz)) {
- factoryMethod = findStaticProviderMethod(clazz);
- if (factoryMethod != null) {
- Class> returnType = factoryMethod.getReturnType();
- if (!service.isAssignableFrom(returnType)) {
- fail(service, factoryMethod + " return type not a subtype");
- }
- }
- }
+ ProviderImpl(Class service,
+ Class extends S> type,
+ Method factoryMethod,
+ AccessControlContext acc) {
+ this.service = service;
+ this.type = type;
this.factoryMethod = factoryMethod;
+ this.ctor = null;
+ this.acc = acc;
+ }
- if (factoryMethod == null) {
- // no factory method so must have a public no-args constructor
- if (!service.isAssignableFrom(clazz)) {
- fail(service, clazz.getName() + " not a subtype");
- }
- this.type = (Class extends S>) clazz;
- this.ctor = (Constructor extends S>) getConstructor(clazz);
- } else {
- this.type = (Class extends S>) factoryMethod.getReturnType();
- this.ctor = null;
- }
+ ProviderImpl(Class service,
+ Class extends S> type,
+ Constructor extends S> ctor,
+ AccessControlContext acc) {
+ this.service = service;
+ this.type = type;
+ this.factoryMethod = null;
+ this.ctor = ctor;
+ this.acc = acc;
}
@Override
@@ -656,72 +646,6 @@ public final class ServiceLoader
}
}
- /**
- * Returns {@code true} if the provider is in an explicit module
- */
- private boolean inExplicitModule(Class> clazz) {
- Module module = clazz.getModule();
- return module.isNamed() && !module.getDescriptor().isAutomatic();
- }
-
- /**
- * Returns the public static provider method if found.
- *
- * @throws ServiceConfigurationError if there is an error finding the
- * provider method
- */
- private Method findStaticProviderMethod(Class> clazz) {
- Method method = null;
- try {
- method = LANG_ACCESS.getMethodOrNull(clazz, "provider");
- } catch (Throwable x) {
- fail(service, "Unable to get public provider() method", x);
- }
- if (method != null) {
- int mods = method.getModifiers();
- if (Modifier.isStatic(mods)) {
- assert Modifier.isPublic(mods);
- Method m = method;
- PrivilegedAction pa = () -> {
- m.setAccessible(true);
- return null;
- };
- AccessController.doPrivileged(pa);
- return method;
- }
- }
- return null;
- }
-
- /**
- * Returns the public no-arg constructor of a class.
- *
- * @throws ServiceConfigurationError if the class does not have
- * public no-arg constructor
- */
- private Constructor> getConstructor(Class> clazz) {
- PrivilegedExceptionAction> pa
- = new PrivilegedExceptionAction<>() {
- @Override
- public Constructor> run() throws Exception {
- Constructor> ctor = clazz.getConstructor();
- if (inExplicitModule(clazz))
- ctor.setAccessible(true);
- return ctor;
- }
- };
- Constructor> ctor = null;
- try {
- ctor = AccessController.doPrivileged(pa);
- } catch (Throwable x) {
- if (x instanceof PrivilegedActionException)
- x = x.getCause();
- String cn = clazz.getName();
- fail(service, cn + " Unable to get public no-arg constructor", x);
- }
- return ctor;
- }
-
/**
* Invokes the provider's "provider" method to instantiate a provider.
* When running with a security manager then the method runs with
@@ -808,7 +732,7 @@ public final class ServiceLoader
@Override
public int hashCode() {
- return Objects.hash(type, acc);
+ return Objects.hash(service, type, acc);
}
@Override
@@ -817,11 +741,83 @@ public final class ServiceLoader
return false;
@SuppressWarnings("unchecked")
ProviderImpl> that = (ProviderImpl>)ob;
- return this.type == that.type
+ return this.service == that.service
+ && this.type == that.type
&& Objects.equals(this.acc, that.acc);
}
}
+ /**
+ * Loads a service provider in a module.
+ *
+ * Returns {@code null} if the service provider's module doesn't read
+ * the module with the service type.
+ *
+ * @throws ServiceConfigurationError if the class cannot be loaded or
+ * isn't the expected sub-type (or doesn't define a provider
+ * factory method that returns the expected type)
+ */
+ private Provider loadProvider(ServiceProvider provider) {
+ Module module = provider.module();
+ if (!module.canRead(service.getModule())) {
+ // module does not read the module with the service type
+ return null;
+ }
+
+ String cn = provider.providerName();
+ Class> clazz = null;
+ if (acc == null) {
+ try {
+ clazz = Class.forName(module, cn);
+ } catch (LinkageError e) {
+ fail(service, "Unable to load " + cn, e);
+ }
+ } else {
+ PrivilegedExceptionAction> pa = () -> Class.forName(module, cn);
+ try {
+ clazz = AccessController.doPrivileged(pa);
+ } catch (PrivilegedActionException pae) {
+ Throwable x = pae.getCause();
+ fail(service, "Unable to load " + cn, x);
+ return null;
+ }
+ }
+ if (clazz == null) {
+ fail(service, "Provider " + cn + " not found");
+ }
+
+ int mods = clazz.getModifiers();
+ if (!Modifier.isPublic(mods)) {
+ fail(service, clazz + " is not public");
+ }
+
+ // if provider in explicit module then check for static factory method
+ if (inExplicitModule(clazz)) {
+ Method factoryMethod = findStaticProviderMethod(clazz);
+ if (factoryMethod != null) {
+ Class> returnType = factoryMethod.getReturnType();
+ if (!service.isAssignableFrom(returnType)) {
+ fail(service, factoryMethod + " return type not a subtype");
+ }
+
+ @SuppressWarnings("unchecked")
+ Class extends S> type = (Class extends S>) returnType;
+ return new ProviderImpl(service, type, factoryMethod, acc);
+ }
+ }
+
+ // no factory method so must be a subtype
+ if (!service.isAssignableFrom(clazz)) {
+ fail(service, clazz.getName() + " not a subtype");
+ }
+
+ @SuppressWarnings("unchecked")
+ Class extends S> type = (Class extends S>) clazz;
+ @SuppressWarnings("unchecked")
+ Constructor extends S> ctor = (Constructor extends S> ) getConstructor(clazz);
+ return new ProviderImpl(service, type, ctor, acc);
+ }
+
/**
* Implements lazy service provider lookup of service providers that
* are provided by modules in a module layer (or parent layers)
@@ -832,7 +828,9 @@ public final class ServiceLoader
Deque stack = new ArrayDeque<>();
Set visited = new HashSet<>();
Iterator iterator;
- ServiceProvider next; // next provider to load
+
+ Provider nextProvider;
+ ServiceConfigurationError nextError;
LayerLookupIterator() {
visited.add(layer);
@@ -846,33 +844,36 @@ public final class ServiceLoader
@Override
public boolean hasNext() {
- // already have the next provider cached
- if (next != null)
- return true;
+ while (nextProvider == null && nextError == null) {
+ // get next provider to load
+ while (iterator == null || !iterator.hasNext()) {
+ // next layer (DFS order)
+ if (stack.isEmpty())
+ return false;
- while (true) {
-
- // next provider (or provider factory)
- if (iterator != null && iterator.hasNext()) {
- next = iterator.next();
- return true;
- }
-
- // next layer (DFS order)
- if (stack.isEmpty())
- return false;
-
- ModuleLayer layer = stack.pop();
- List parents = layer.parents();
- for (int i = parents.size() - 1; i >= 0; i--) {
- ModuleLayer parent = parents.get(i);
- if (!visited.contains(parent)) {
- visited.add(parent);
- stack.push(parent);
+ ModuleLayer layer = stack.pop();
+ List parents = layer.parents();
+ for (int i = parents.size() - 1; i >= 0; i--) {
+ ModuleLayer parent = parents.get(i);
+ if (!visited.contains(parent)) {
+ visited.add(parent);
+ stack.push(parent);
+ }
}
+ iterator = providers(layer);
+ }
+
+ // attempt to load provider
+ ServiceProvider provider = iterator.next();
+ try {
+ @SuppressWarnings("unchecked")
+ Provider next = (Provider) loadProvider(provider);
+ nextProvider = next;
+ } catch (ServiceConfigurationError e) {
+ nextError = e;
}
- iterator = providers(layer);
}
+ return true;
}
@Override
@@ -880,15 +881,16 @@ public final class ServiceLoader
if (!hasNext())
throw new NoSuchElementException();
- // take next provider
- ServiceProvider provider = next;
- next = null;
-
- // attempt to load provider
- Module module = provider.module();
- String cn = provider.providerName();
- Class> clazz = loadProviderInModule(module, cn);
- return new ProviderImpl(service, clazz, acc);
+ Provider provider = nextProvider;
+ if (provider != null) {
+ nextProvider = null;
+ return provider;
+ } else {
+ ServiceConfigurationError e = nextError;
+ assert e != null;
+ nextError = null;
+ throw e;
+ }
}
}
@@ -902,7 +904,9 @@ public final class ServiceLoader
{
ClassLoader currentLoader;
Iterator iterator;
- ServiceProvider next; // next provider to load
+
+ Provider nextProvider;
+ ServiceConfigurationError nextError;
ModuleServicesLookupIterator() {
this.currentLoader = loader;
@@ -918,14 +922,26 @@ public final class ServiceLoader
return catalog.findServices(serviceName);
}
+ /**
+ * Returns the class loader that a module is defined to
+ */
+ private ClassLoader loaderFor(Module module) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm == null) {
+ return module.getClassLoader();
+ } else {
+ PrivilegedAction pa = module::getClassLoader;
+ return AccessController.doPrivileged(pa);
+ }
+ }
+
/**
* Returns an iterator to iterate over the implementations of {@code
* service} in modules defined to the given class loader or in custom
* layers with a module defined to this class loader.
*/
private Iterator iteratorFor(ClassLoader loader) {
-
- // modules defined to this class loader
+ // modules defined to the class loader
ServicesCatalog catalog;
if (loader == null) {
catalog = BootLoader.getServicesCatalog();
@@ -939,17 +955,20 @@ public final class ServiceLoader
providers = catalog.findServices(serviceName);
}
- // modules in custom layers that define modules to the class loader
- if (loader == null) {
+ // modules in layers that define modules to the class loader
+ ClassLoader platformClassLoader = ClassLoaders.platformClassLoader();
+ if (loader == null || loader == platformClassLoader) {
return providers.iterator();
} else {
List allProviders = new ArrayList<>(providers);
- ModuleLayer bootLayer = ModuleLayer.boot();
Iterator iterator = LANG_ACCESS.layers(loader).iterator();
while (iterator.hasNext()) {
ModuleLayer layer = iterator.next();
- if (layer != bootLayer) {
- allProviders.addAll(providers(layer));
+ for (ServiceProvider sp : providers(layer)) {
+ ClassLoader l = loaderFor(sp.module());
+ if (l != null && l != platformClassLoader) {
+ allProviders.add(sp);
+ }
}
}
return allProviders.iterator();
@@ -958,24 +977,28 @@ public final class ServiceLoader
@Override
public boolean hasNext() {
- // already have the next provider cached
- if (next != null)
- return true;
-
- while (true) {
- if (iterator.hasNext()) {
- next = iterator.next();
- return true;
+ while (nextProvider == null && nextError == null) {
+ // get next provider to load
+ while (!iterator.hasNext()) {
+ if (currentLoader == null) {
+ return false;
+ } else {
+ currentLoader = currentLoader.getParent();
+ iterator = iteratorFor(currentLoader);
+ }
}
- // move to the next class loader if possible
- if (currentLoader == null) {
- return false;
- } else {
- currentLoader = currentLoader.getParent();
- iterator = iteratorFor(currentLoader);
+ // attempt to load provider
+ ServiceProvider provider = iterator.next();
+ try {
+ @SuppressWarnings("unchecked")
+ Provider next = (Provider) loadProvider(provider);
+ nextProvider = next;
+ } catch (ServiceConfigurationError e) {
+ nextError = e;
}
}
+ return true;
}
@Override
@@ -983,15 +1006,16 @@ public final class ServiceLoader
if (!hasNext())
throw new NoSuchElementException();
- // take next provider
- ServiceProvider provider = next;
- next = null;
-
- // attempt to load provider
- Module module = provider.module();
- String cn = provider.providerName();
- Class> clazz = loadProviderInModule(module, cn);
- return new ProviderImpl(service, clazz, acc);
+ Provider provider = nextProvider;
+ if (provider != null) {
+ nextProvider = null;
+ return provider;
+ } else {
+ ServiceConfigurationError e = nextError;
+ assert e != null;
+ nextError = null;
+ throw e;
+ }
}
}
@@ -1008,8 +1032,9 @@ public final class ServiceLoader
Set providerNames = new HashSet<>(); // to avoid duplicates
Enumeration configs;
Iterator pending;
- Class> nextClass;
- String nextErrorMessage; // when hasNext fails with CNFE
+
+ Provider nextProvider;
+ ServiceConfigurationError nextError;
LazyClassPathLookupIterator() { }
@@ -1068,51 +1093,71 @@ public final class ServiceLoader
return names.iterator();
}
- private boolean hasNextService() {
- if (nextClass != null || nextErrorMessage != null) {
- return true;
- }
-
- Class> clazz;
- do {
- if (configs == null) {
- try {
- String fullName = PREFIX + service.getName();
- if (loader == null) {
- configs = ClassLoader.getSystemResources(fullName);
- } else if (loader == ClassLoaders.platformClassLoader()) {
- // The platform classloader doesn't have a class path,
- // but the boot loader might.
- if (BootLoader.hasClassPath()) {
- configs = BootLoader.findResources(fullName);
- } else {
- configs = Collections.emptyEnumeration();
- }
- } else {
- configs = loader.getResources(fullName);
- }
- } catch (IOException x) {
- fail(service, "Error locating configuration files", x);
- }
- }
- while ((pending == null) || !pending.hasNext()) {
- if (!configs.hasMoreElements()) {
- return false;
- }
- pending = parse(configs.nextElement());
- }
- String cn = pending.next();
+ /**
+ * Loads and returns the next provider class.
+ */
+ private Class> nextProviderClass() {
+ if (configs == null) {
try {
- clazz = Class.forName(cn, false, loader);
- } catch (ClassNotFoundException x) {
- // don't throw SCE here to long standing behavior
- nextErrorMessage = "Provider " + cn + " not found";
- return true;
+ String fullName = PREFIX + service.getName();
+ if (loader == null) {
+ configs = ClassLoader.getSystemResources(fullName);
+ } else if (loader == ClassLoaders.platformClassLoader()) {
+ // The platform classloader doesn't have a class path,
+ // but the boot loader might.
+ if (BootLoader.hasClassPath()) {
+ configs = BootLoader.findResources(fullName);
+ } else {
+ configs = Collections.emptyEnumeration();
+ }
+ } else {
+ configs = loader.getResources(fullName);
+ }
+ } catch (IOException x) {
+ fail(service, "Error locating configuration files", x);
}
+ }
+ while ((pending == null) || !pending.hasNext()) {
+ if (!configs.hasMoreElements()) {
+ return null;
+ }
+ pending = parse(configs.nextElement());
+ }
+ String cn = pending.next();
+ try {
+ return Class.forName(cn, false, loader);
+ } catch (ClassNotFoundException x) {
+ fail(service, "Provider " + cn + " not found");
+ return null;
+ }
+ }
- } while (clazz.getModule().isNamed()); // ignore if in named module
+ @SuppressWarnings("unchecked")
+ private boolean hasNextService() {
+ while (nextProvider == null && nextError == null) {
+ try {
+ Class> clazz = nextProviderClass();
+ if (clazz == null)
+ return false;
- nextClass = clazz;
+ if (clazz.getModule().isNamed()) {
+ // ignore class if in named module
+ continue;
+ }
+
+ if (service.isAssignableFrom(clazz)) {
+ Class extends S> type = (Class extends S>) clazz;
+ Constructor extends S> ctor
+ = (Constructor extends S>)getConstructor(clazz);
+ ProviderImpl p = new ProviderImpl(service, type, ctor, acc);
+ nextProvider = (ProviderImpl) p;
+ } else {
+ fail(service, clazz.getName() + " not a subtype");
+ }
+ } catch (ServiceConfigurationError e) {
+ nextError = e;
+ }
+ }
return true;
}
@@ -1120,17 +1165,16 @@ public final class ServiceLoader
if (!hasNextService())
throw new NoSuchElementException();
- // throw any SCE with error recorded by hasNext
- if (nextErrorMessage != null) {
- String msg = nextErrorMessage;
- nextErrorMessage = null;
- fail(service, msg);
+ Provider provider = nextProvider;
+ if (provider != null) {
+ nextProvider = null;
+ return provider;
+ } else {
+ ServiceConfigurationError e = nextError;
+ assert e != null;
+ nextError = null;
+ throw e;
}
-
- // return next provider
- Class> clazz = nextClass;
- nextClass = null;
- return new ProviderImpl(service, clazz, acc);
}
@Override
@@ -1420,7 +1464,86 @@ public final class ServiceLoader
/**
* Creates a new service loader for the given service type and class
- * loader.
+ * loader. The service loader locates service providers in both named and
+ * unnamed modules:
+ *
+ *
+ * Service providers are located in named modules defined to the
+ * class loader, or any class loader that is reachable via parent
+ * delegation.
+ *
+ * Additionally, and with the exception of the bootstrap and {@linkplain
+ * ClassLoader#getPlatformClassLoader() platform} class loaders, if the
+ * class loader, or any class loader reachable via parent delegation,
+ * defines modules in a module layer then the providers in the module layer
+ * are located. For example, suppose there is a module layer where each
+ * module is defined to its own class loader (see {@link
+ * ModuleLayer#defineModulesWithManyLoaders defineModulesWithManyLoaders}).
+ * If this {@code ServiceLoader.load} method is invoked to locate providers
+ * using any of the class loaders created for this layer then it will locate
+ * all of the providers in that layer, irrespective of their defining class
+ * loader.
+ *
+ * A provider is an unnamed modules is located if its class
+ * name is listed in a service configuration file located by the the class
+ * loader's {@link ClassLoader#getResources(String) getResources} method.
+ * The provider class must be visible to the class loader. If a provider
+ * class is in a named module is listed then it is ignored (this is to
+ * avoid duplicates that would otherwise arise when a module has both a
+ * provides clause and a service configuration file in {@code
+ * META-INF/services} that lists the same provider).
+ *
+ *
+ * The ordering that the service loader's iterator and stream locate
+ * providers and yield elements is as follows:
+ *
+ *
+ * Providers in named modules are located before service
+ * providers in unnamed modules.
+ *
+ * When locating providers in named modules then the service
+ * loader will first locate any service providers in modules defined to
+ * the class loader, then its parent class loader, its parent parent,
+ * and so on to the bootstrap class loader. If a class loader or any
+ * class loader in the parent delegation chain, defines modules in a
+ * module layer then all providers in that layer are located
+ * (irrespective of their class loader) before providers in the parent
+ * class loader are located. The ordering of modules defined to the
+ * same class loader, or the ordering of modules in a layer, is not
+ * defined.
+ *
+ * If a named module declares more than one provider then the
+ * providers are located in the order that its module descriptor
+ * {@linkplain java.lang.module.ModuleDescriptor.Provides#providers()
+ * lists the providers}. Providers added dynamically by instrumentation
+ * agents (see {@link java.lang.instrument.Instrumentation#redefineModule
+ * redefineModule}) are always located after providers declared by the
+ * module.
+ *
+ * When locating providers in unnamed modules then the
+ * ordering is based on the order that the class loader's {@link
+ * ClassLoader#getResources(String) getResources} method finds the
+ * service configuration files and within that, the order that the class
+ * names are listed in the file.
+ *
+ *
+ * @apiNote If the class path of the class loader includes remote network
+ * URLs then those URLs may be dereferenced in the process of searching for
+ * provider-configuration files.
+ *
+ * This activity is normal, although it may cause puzzling entries to be
+ * created in web-server logs. If a web server is not configured correctly,
+ * however, then this activity may cause the provider-loading algorithm to fail
+ * spuriously.
+ *
+ *
A web server should return an HTTP 404 (Not Found) response when a
+ * requested resource does not exist. Sometimes, however, web servers are
+ * erroneously configured to return an HTTP 200 (OK) response along with a
+ * helpful HTML error page in such cases. This will cause a {@link
+ * ServiceConfigurationError} to be thrown when this class attempts to parse
+ * the HTML page as a provider-configuration file. The best solution to this
+ * problem is to fix the misconfigured web server to return the correct
+ * response code (HTTP 404) along with the HTML error page.
*
* @param the class of the service type
*
@@ -1457,13 +1580,13 @@ public final class ServiceLoader
*
*
An invocation of this convenience method of the form
*
{@code
- * ServiceLoader.load(service)
+ * ServiceLoader.load(service)
* }
*
* is equivalent to
*
* {@code
- * ServiceLoader.load(service, Thread.currentThread().getContextClassLoader())
+ * ServiceLoader.load(service, Thread.currentThread().getContextClassLoader())
* }
*
* @apiNote Service loader objects obtained with this method should not be
@@ -1502,7 +1625,7 @@ public final class ServiceLoader
* This convenience method is equivalent to:
*
* {@code
- * ServiceLoader.load(service, ClassLoader.getPlatformClassLoader())
+ * ServiceLoader.load(service, ClassLoader.getPlatformClassLoader())
* }
*
* This method is intended for use when only installed providers are
@@ -1532,9 +1655,30 @@ public final class ServiceLoader
}
/**
- * Creates a new service loader for the given service type that loads
- * service providers from modules in the given {@code ModuleLayer} and its
- * ancestors.
+ * Creates a new service loader for the given service type to load service
+ * providers from modules in the given module layer and its ancestors. It
+ * does not locate providers in unnamed modules.
+ *
+ *
The ordering that the service loader's iterator and stream locate
+ * providers and yield elements is as follows:
+ *
+ *
+ * Providers are located in a module layer before locating providers
+ * in parent layers. Traversal of parent layers is depth-first with each
+ * layer visited at most once. For example, suppose L0 is the boot layer, L1
+ * and L2 are modules layers with L0 as their parent. Now suppose that L3 is
+ * created with L1 and L2 as the parents (in that order). Using a service
+ * loader to locate providers with L3 as the context will locate providers
+ * in the following order: L3, L1, L0, L2.
+ *
+ * If a named module declares more than one provider then the
+ * providers are located in the order that its module descriptor
+ * {@linkplain java.lang.module.ModuleDescriptor.Provides#providers()
+ * lists the providers}. Providers added dynamically by instrumentation
+ * agents are always located after providers declared by the module.
+ *
+ * The ordering of modules in a module layer is not defined.
+ *
*
* @apiNote Unlike the other load methods defined here, the service type
* is the second parameter. The reason for this is to avoid source
diff --git a/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java b/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java
index 5d1c97c6d25..95b65f646d8 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java
@@ -49,8 +49,10 @@ import java.security.SecureClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.jar.Attributes;
@@ -336,16 +338,43 @@ public class BuiltinClassLoader
}
}
- // search class path
+ // class path (not checked)
Enumeration e = findResourcesOnClassPath(name);
- while (e.hasMoreElements()) {
- URL url = checkURL(e.nextElement());
- if (url != null) {
- checked.add(url);
- }
- }
- return Collections.enumeration(checked);
+ // concat the checked URLs and the (not checked) class path
+ return new Enumeration<>() {
+ final Iterator iterator = checked.iterator();
+ URL next;
+ private boolean hasNext() {
+ if (next != null) {
+ return true;
+ } else if (iterator.hasNext()) {
+ next = iterator.next();
+ return true;
+ } else {
+ // need to check each URL
+ while (e.hasMoreElements() && next == null) {
+ next = checkURL(e.nextElement());
+ }
+ return next != null;
+ }
+ }
+ @Override
+ public boolean hasMoreElements() {
+ return hasNext();
+ }
+ @Override
+ public URL nextElement() {
+ if (hasNext()) {
+ URL result = next;
+ next = null;
+ return result;
+ } else {
+ throw new NoSuchElementException();
+ }
+ }
+ };
+
}
/**
diff --git a/jdk/src/java.base/share/classes/jdk/internal/loader/Loader.java b/jdk/src/java.base/share/classes/jdk/internal/loader/Loader.java
index 0eb249de0d9..dc46f6630b0 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/Loader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/Loader.java
@@ -28,6 +28,7 @@ package jdk.internal.loader;
import java.io.File;
import java.io.FilePermission;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.lang.module.Configuration;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleReader;
@@ -52,11 +53,17 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
+import java.util.Spliterator;
+import java.util.Spliterators;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Supplier;
import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.module.Resources;
@@ -79,8 +86,8 @@ import jdk.internal.module.Resources;
* loader. This allows automatic modules (for example) to link to types in the
* unnamed module of the parent class loader.
*
- * @see ModuleModuleLayer#defineModulesWithOneLoader
- * @see ModuleModuleLayer#defineModulesWithManyLoaders
+ * @see ModuleLayer#defineModulesWithOneLoader
+ * @see ModuleLayer#defineModulesWithManyLoaders
*/
public final class Loader extends SecureClassLoader {
@@ -303,7 +310,6 @@ public final class Loader extends SecureClassLoader {
// -- resources --
-
/**
* Returns a URL to a resource of the given name in a module defined to
* this class loader.
@@ -388,33 +394,96 @@ public final class Loader extends SecureClassLoader {
@Override
public Enumeration findResources(String name) throws IOException {
- List urls = new ArrayList<>();
+ return Collections.enumeration(findResourcesAsList(name));
+ }
+
+ @Override
+ public URL getResource(String name) {
+ Objects.requireNonNull(name);
+
+ // this loader
+ URL url = findResource(name);
+ if (url != null) {
+ return url;
+ } else {
+ // parent loader
+ return parent.getResource(name);
+ }
+ }
+
+ @Override
+ public Enumeration getResources(String name) throws IOException {
+ Objects.requireNonNull(name);
+
+ // this loader
+ List urls = findResourcesAsList(name);
+
+ // parent loader
+ Enumeration e = parent.getResources(name);
+
+ // concat the URLs with the URLs returned by the parent
+ return new Enumeration<>() {
+ final Iterator iterator = urls.iterator();
+ @Override
+ public boolean hasMoreElements() {
+ return (iterator.hasNext() || e.hasMoreElements());
+ }
+ @Override
+ public URL nextElement() {
+ if (iterator.hasNext()) {
+ return iterator.next();
+ } else {
+ return e.nextElement();
+ }
+ }
+ };
+ }
+
+ @Override
+ public Stream resources(String name) {
+ Objects.requireNonNull(name);
+ // ordering not specified
+ int characteristics = (Spliterator.NONNULL | Spliterator.IMMUTABLE |
+ Spliterator.SIZED | Spliterator.SUBSIZED);
+ Supplier> supplier = () -> {
+ try {
+ List urls = findResourcesAsList(name);
+ return Spliterators.spliterator(urls, characteristics);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ };
+ Stream s1 = StreamSupport.stream(supplier, characteristics, false);
+ Stream s2 = parent.resources(name);
+ return Stream.concat(s1, s2);
+ }
+
+ /**
+ * Finds the resources with the given name in this class loader.
+ */
+ private List findResourcesAsList(String name) throws IOException {
String pn = Resources.toPackageName(name);
LoadedModule module = localPackageToModule.get(pn);
if (module != null) {
- try {
- URL url = findResource(module.name(), name);
- if (url != null
+ URL url = findResource(module.name(), name);
+ if (url != null
&& (name.endsWith(".class")
- || url.toString().endsWith("/")
- || isOpen(module.mref(), pn))) {
- urls.add(url);
- }
- } catch (IOException ioe) {
- // ignore
+ || url.toString().endsWith("/")
+ || isOpen(module.mref(), pn))) {
+ return List.of(url);
+ } else {
+ return Collections.emptyList();
}
} else {
+ List urls = new ArrayList<>();
for (ModuleReference mref : nameToModule.values()) {
- try {
- URL url = findResource(mref.descriptor().name(), name);
- if (url != null)
- urls.add(url);
- } catch (IOException ioe) {
- // ignore
+ URL url = findResource(mref.descriptor().name(), name);
+ if (url != null) {
+ urls.add(url);
}
}
+ return urls;
}
- return Collections.enumeration(urls);
}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java
index 92b60d70777..ab92b03c856 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java
@@ -32,6 +32,8 @@ import java.lang.reflect.Method;
import java.net.URI;
import java.security.AccessControlContext;
import java.security.ProtectionDomain;
+import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;
@@ -44,13 +46,15 @@ import sun.nio.ch.Interruptible;
public interface JavaLangAccess {
/**
- * Returns a {@code Method} object that reflects the specified public
- * member method of the given class. Returns {@code null} if the
- * method is not defined.
+ * Returns the list of {@code Method} objects for the declared public
+ * methods of this class or interface that have the specified method name
+ * and parameter types.
*/
- Method getMethodOrNull(Class> klass, String name, Class>... parameterTypes);
+ List getDeclaredPublicMethods(Class> klass, String name, Class>... parameterTypes);
- /** Return the constant pool for a class. */
+ /**
+ * Return the constant pool for a class.
+ */
ConstantPool getConstantPool(Class> klass);
/**
@@ -95,7 +99,9 @@ public interface JavaLangAccess {
*/
> E[] getEnumConstantsShared(Class klass);
- /** Set thread's blocker field. */
+ /**
+ * Set thread's blocker field.
+ */
void blockedOn(Thread t, Interruptible b);
/**
@@ -154,11 +160,6 @@ public interface JavaLangAccess {
*/
Class> findBootstrapClassOrNull(ClassLoader cl, String name);
- /**
- * Returns the Packages for the given class loader.
- */
- Stream packages(ClassLoader cl);
-
/**
* Define a Package of the given name and module by the given class loader.
*/
@@ -223,15 +224,30 @@ public interface JavaLangAccess {
void addOpens(Module m1, String pkg, Module m2);
/**
- * Updates a module m to open a package to all unnamed modules.
+ * Updates module m to open a package to all unnamed modules.
*/
void addOpensToAllUnnamed(Module m, String pkg);
/**
- * Updates a module m to use a service.
+ * Updates module m to open all packages returned by the given iterator.
+ */
+ void addOpensToAllUnnamed(Module m, Iterator packages);
+
+ /**
+ * Updates module m to use a service.
*/
void addUses(Module m, Class> service);
+ /**
+ * Returns true if module m reflectively exports a package to other
+ */
+ boolean isReflectivelyExported(Module module, String pn, Module other);
+
+ /**
+ * Returns true if module m reflectively opens a package to other
+ */
+ boolean isReflectivelyOpened(Module module, String pn, Module other);
+
/**
* Returns the ServicesCatalog for the given Layer.
*/
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/IllegalAccessLogger.java b/jdk/src/java.base/share/classes/jdk/internal/module/IllegalAccessLogger.java
index 3914ce923fc..45170c07c97 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/IllegalAccessLogger.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/IllegalAccessLogger.java
@@ -33,146 +33,240 @@ import java.security.CodeSource;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.HashMap;
-import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.StringJoiner;
import java.util.WeakHashMap;
import java.util.function.Supplier;
import java.util.stream.Collectors;
+import static java.util.Collections.*;
-import jdk.internal.loader.BootLoader;
-import sun.security.action.GetPropertyAction;
+import jdk.internal.misc.JavaLangAccess;
+import jdk.internal.misc.SharedSecrets;
/**
- * Supports logging of access to members of API packages that are exported or
- * opened via backdoor mechanisms to code in unnamed modules.
+ * Supports logging of access to members of exported and concealed packages
+ * that are opened to code in unnamed modules for illegal access.
*/
public final class IllegalAccessLogger {
/**
- * Holder class to lazily create the StackWalker object and determine
- * if the stack trace should be printed
+ * Logger modes
*/
- static class Holder {
- static final StackWalker STACK_WALKER;
- static final boolean PRINT_STACK_TRACE;
+ public static enum Mode {
+ /**
+ * Prints a warning when an illegal access succeeds and then
+ * discards the logger so that there is no further output.
+ */
+ ONESHOT,
+ /**
+ * Print warnings when illegal access succeeds
+ */
+ WARN,
+ /**
+ * Prints warnings and a stack trace when illegal access succeeds
+ */
+ DEBUG,
+ }
- static {
- PrivilegedAction pa = () ->
- StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
- STACK_WALKER = AccessController.doPrivileged(pa);
+ /**
+ * A builder for IllegalAccessLogger objects.
+ */
+ public static class Builder {
+ private final Mode mode;
+ private final PrintStream warningStream;
+ private final Map> moduleToConcealedPackages;
+ private final Map> moduleToExportedPackages;
+ private boolean complete;
- String name = "sun.reflect.debugModuleAccessChecks";
- String value = GetPropertyAction.privilegedGetProperty(name, null);
- PRINT_STACK_TRACE = "access" .equals(value);
+ private void ensureNotComplete() {
+ if (complete) throw new IllegalStateException();
+ }
+
+ /**
+ * Creates a builder.
+ */
+ public Builder(Mode mode, PrintStream warningStream) {
+ this.mode = mode;
+ this.warningStream = warningStream;
+ this.moduleToConcealedPackages = new HashMap<>();
+ this.moduleToExportedPackages = new HashMap<>();
+ }
+
+ /**
+ * Adding logging of reflective-access to any member of a type in
+ * otherwise concealed packages.
+ */
+ public Builder logAccessToConcealedPackages(Module m, Set packages) {
+ ensureNotComplete();
+ moduleToConcealedPackages.put(m, unmodifiableSet(packages));
+ return this;
+ }
+
+ /**
+ * Adding logging of reflective-access to non-public members/types in
+ * otherwise exported (not open) packages.
+ */
+ public Builder logAccessToExportedPackages(Module m, Set packages) {
+ ensureNotComplete();
+ moduleToExportedPackages.put(m, unmodifiableSet(packages));
+ return this;
+ }
+
+ /**
+ * Builds the IllegalAccessLogger and sets it as the system-wise logger.
+ */
+ public void complete() {
+ Map> map1 = unmodifiableMap(moduleToConcealedPackages);
+ Map> map2 = unmodifiableMap(moduleToExportedPackages);
+ logger = new IllegalAccessLogger(mode, warningStream, map1, map2);
+ complete = true;
}
}
- // the maximum number of frames to capture
- private static final int MAX_STACK_FRAMES = 32;
+ // need access to java.lang.Module
+ private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
- // lock to avoid interference when printing stack traces
- private static final Object OUTPUT_LOCK = new Object();
+ // system-wide IllegalAccessLogger
+ private static volatile IllegalAccessLogger logger;
- // caller -> usages
- private final Map, Set> callerToUsages = new WeakHashMap<>();
-
- // module -> (package name -> CLI option)
- private final Map> exported;
- private final Map> opened;
+ // logger mode
+ private final Mode mode;
// the print stream to send the warnings
private final PrintStream warningStream;
- private IllegalAccessLogger(Map> exported,
- Map> opened,
- PrintStream warningStream) {
- this.exported = deepCopy(exported);
- this.opened = deepCopy(opened);
+ // module -> packages open for illegal access
+ private final Map> moduleToConcealedPackages;
+ private final Map> moduleToExportedPackages;
+
+ // caller -> usages
+ private final Map, Usages> callerToUsages = new WeakHashMap<>();
+
+ private IllegalAccessLogger(Mode mode,
+ PrintStream warningStream,
+ Map> moduleToConcealedPackages,
+ Map> moduleToExportedPackages)
+ {
+ this.mode = mode;
this.warningStream = warningStream;
+ this.moduleToConcealedPackages = moduleToConcealedPackages;
+ this.moduleToExportedPackages = moduleToExportedPackages;
}
/**
- * Returns that a Builder that is seeded with the packages known to this logger.
+ * Returns the system-wide IllegalAccessLogger or {@code null} if there is
+ * no logger.
*/
- public Builder toBuilder() {
- return new Builder(exported, opened);
+ public static IllegalAccessLogger illegalAccessLogger() {
+ return logger;
+ }
+
+ /**
+ * Returns true if the module exports a concealed package for illegal
+ * access.
+ */
+ public boolean isExportedForIllegalAccess(Module module, String pn) {
+ Set packages = moduleToConcealedPackages.get(module);
+ if (packages != null && packages.contains(pn))
+ return true;
+ return false;
+ }
+
+ /**
+ * Returns true if the module opens a concealed or exported package for
+ * illegal access.
+ */
+ public boolean isOpenForIllegalAccess(Module module, String pn) {
+ if (isExportedForIllegalAccess(module, pn))
+ return true;
+ Set packages = moduleToExportedPackages.get(module);
+ if (packages != null && packages.contains(pn))
+ return true;
+ return false;
}
/**
* Logs access to the member of a target class by a caller class if the class
- * is in a package that is exported via a backdoor mechanism.
+ * is in a package that is exported for illegal access.
*
* The {@code whatSupplier} supplies the message that describes the member.
*/
- public void logIfExportedByBackdoor(Class> caller,
- Class> target,
- Supplier whatSupplier) {
- Map packages = exported.get(target.getModule());
- if (packages != null) {
- String how = packages.get(target.getPackageName());
- if (how != null) {
- log(caller, whatSupplier.get(), how);
+ public void logIfExportedForIllegalAccess(Class> caller,
+ Class> target,
+ Supplier whatSupplier) {
+ Module targetModule = target.getModule();
+ String targetPackage = target.getPackageName();
+ if (isExportedForIllegalAccess(targetModule, targetPackage)) {
+ Module callerModule = caller.getModule();
+ if (!JLA.isReflectivelyExported(targetModule, targetPackage, callerModule)) {
+ log(caller, whatSupplier.get());
}
}
}
/**
* Logs access to the member of a target class by a caller class if the class
- * is in a package that is opened via a backdoor mechanism.
+ * is in a package that is opened for illegal access.
*
* The {@code what} parameter supplies the message that describes the member.
*/
- public void logIfOpenedByBackdoor(Class> caller,
- Class> target,
- Supplier whatSupplier) {
- Map packages = opened.get(target.getModule());
- if (packages != null) {
- String how = packages.get(target.getPackageName());
- if (how != null) {
- log(caller, whatSupplier.get(), how);
+ public void logIfOpenedForIllegalAccess(Class> caller,
+ Class> target,
+ Supplier whatSupplier) {
+ Module targetModule = target.getModule();
+ String targetPackage = target.getPackageName();
+ if (isOpenForIllegalAccess(targetModule, targetPackage)) {
+ Module callerModule = caller.getModule();
+ if (!JLA.isReflectivelyOpened(targetModule, targetPackage, callerModule)) {
+ log(caller, whatSupplier.get());
+ }
+ }
+ }
+
+ /**
+ * Logs access by caller lookup if the target class is in a package that is
+ * opened for illegal access.
+ */
+ public void logIfOpenedForIllegalAccess(MethodHandles.Lookup caller, Class> target) {
+ Module targetModule = target.getModule();
+ String targetPackage = target.getPackageName();
+ if (isOpenForIllegalAccess(targetModule, targetPackage)) {
+ Class> callerClass = caller.lookupClass();
+ Module callerModule = callerClass.getModule();
+ if (!JLA.isReflectivelyOpened(targetModule, targetPackage, callerModule)) {
+ URL url = codeSource(callerClass);
+ final String source;
+ if (url == null) {
+ source = callerClass.getName();
+ } else {
+ source = callerClass.getName() + " (" + url + ")";
+ }
+ log(callerClass, target.getName(), () ->
+ "WARNING: Illegal reflective access using Lookup on " + source
+ + " to " + target);
}
}
}
/**
* Logs access by a caller class. The {@code what} parameter describes
- * the member is accessed, the {@code how} parameter is the means by which
- * access is allocated (CLI option for example).
+ * the member being accessed.
*/
- private void log(Class> caller, String what, String how) {
+ private void log(Class> caller, String what) {
log(caller, what, () -> {
- PrivilegedAction pa = caller::getProtectionDomain;
- CodeSource cs = AccessController.doPrivileged(pa).getCodeSource();
- URL url = (cs != null) ? cs.getLocation() : null;
+ URL url = codeSource(caller);
String source = caller.getName();
if (url != null)
source += " (" + url + ")";
- return "WARNING: Illegal access by " + source + " to " + what
- + " (permitted by " + how + ")";
+ return "WARNING: Illegal reflective access by " + source + " to " + what;
});
}
-
- /**
- * Logs access to caller class if the class is in a package that is opened via
- * a backdoor mechanism.
- */
- public void logIfOpenedByBackdoor(MethodHandles.Lookup caller, Class> target) {
- Map packages = opened.get(target.getModule());
- if (packages != null) {
- String how = packages.get(target.getPackageName());
- if (how != null) {
- log(caller.lookupClass(), target.getName(), () ->
- "WARNING: Illegal access using Lookup on " + caller.lookupClass()
- + " to " + target + " (permitted by " + how + ")");
- }
- }
- }
-
/**
* Log access by a caller. The {@code what} parameter describes the class or
* member that is being accessed. The {@code msgSupplier} supplies the log
@@ -184,53 +278,73 @@ public final class IllegalAccessLogger {
* keys so it can be expunged when the caller is GC'ed/unloaded.
*/
private void log(Class> caller, String what, Supplier msgSupplier) {
+ if (mode == Mode.ONESHOT) {
+ synchronized (IllegalAccessLogger.class) {
+ // discard the system wide logger
+ if (logger == null)
+ return;
+ logger = null;
+ }
+ warningStream.println(loudWarning(caller, msgSupplier));
+ return;
+ }
+
// stack trace without the top-most frames in java.base
- List stack = Holder.STACK_WALKER.walk(s ->
+ List stack = StackWalkerHolder.INSTANCE.walk(s ->
s.dropWhile(this::isJavaBase)
- .limit(MAX_STACK_FRAMES)
+ .limit(32)
.collect(Collectors.toList())
);
- // check if the access has already been recorded
+ // record usage if this is the first (or not recently recorded)
Usage u = new Usage(what, hash(stack));
- boolean firstUsage;
+ boolean added;
synchronized (this) {
- firstUsage = callerToUsages.computeIfAbsent(caller, k -> new HashSet<>()).add(u);
+ added = callerToUsages.computeIfAbsent(caller, k -> new Usages()).add(u);
}
- // log message if first usage
- if (firstUsage) {
+ // print warning if this is the first (or not a recent) usage
+ if (added) {
String msg = msgSupplier.get();
- if (Holder.PRINT_STACK_TRACE) {
- synchronized (OUTPUT_LOCK) {
- warningStream.println(msg);
- stack.forEach(f -> warningStream.println("\tat " + f));
- }
- } else {
- warningStream.println(msg);
+ if (mode == Mode.DEBUG) {
+ StringBuilder sb = new StringBuilder(msg);
+ stack.forEach(f ->
+ sb.append(System.lineSeparator()).append("\tat " + f)
+ );
+ msg = sb.toString();
}
+ warningStream.println(msg);
}
}
- private static class Usage {
- private final String what;
- private final int stack;
- Usage(String what, int stack) {
- this.what = what;
- this.stack = stack;
- }
- @Override
- public int hashCode() {
- return what.hashCode() ^ stack;
- }
- @Override
- public boolean equals(Object ob) {
- if (ob instanceof Usage) {
- Usage that = (Usage)ob;
- return what.equals(that.what) && stack == (that.stack);
- } else {
- return false;
- }
+ /**
+ * Returns the code source for the given class or null if there is no code source
+ */
+ private URL codeSource(Class> clazz) {
+ PrivilegedAction pa = clazz::getProtectionDomain;
+ CodeSource cs = AccessController.doPrivileged(pa).getCodeSource();
+ return (cs != null) ? cs.getLocation() : null;
+ }
+
+ private String loudWarning(Class> caller, Supplier msgSupplier) {
+ StringJoiner sj = new StringJoiner(System.lineSeparator());
+ sj.add("WARNING: An illegal reflective access operation has occurred");
+ sj.add(msgSupplier.get());
+ sj.add("WARNING: Please consider reporting this to the maintainers of "
+ + caller.getName());
+ sj.add("WARNING: Use --illegal-access=warn to enable warnings of further"
+ + " illegal reflective access operations");
+ sj.add("WARNING: All illegal access operations will be denied in a"
+ + " future release");
+ return sj.toString();
+ }
+
+ private static class StackWalkerHolder {
+ static final StackWalker INSTANCE;
+ static {
+ PrivilegedAction pa = () ->
+ StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
+ INSTANCE = AccessController.doPrivileged(pa);
}
}
@@ -256,89 +370,39 @@ public final class IllegalAccessLogger {
return hash;
}
- // system-wide IllegalAccessLogger
- private static volatile IllegalAccessLogger logger;
-
- /**
- * Sets the system-wide IllegalAccessLogger
- */
- public static void setIllegalAccessLogger(IllegalAccessLogger l) {
- if (l.exported.isEmpty() && l.opened.isEmpty()) {
- logger = null;
- } else {
- logger = l;
+ private static class Usage {
+ private final String what;
+ private final int stack;
+ Usage(String what, int stack) {
+ this.what = what;
+ this.stack = stack;
+ }
+ @Override
+ public int hashCode() {
+ return what.hashCode() ^ stack;
+ }
+ @Override
+ public boolean equals(Object ob) {
+ if (ob instanceof Usage) {
+ Usage that = (Usage)ob;
+ return what.equals(that.what) && stack == (that.stack);
+ } else {
+ return false;
+ }
}
}
- /**
- * Returns the system-wide IllegalAccessLogger or {@code null} if there is
- * no logger.
- */
- public static IllegalAccessLogger illegalAccessLogger() {
- return logger;
- }
-
- /**
- * A builder for IllegalAccessLogger objects.
- */
- public static class Builder {
- private final Module UNNAMED = BootLoader.getUnnamedModule();
- private Map> exported;
- private Map> opened;
- private PrintStream warningStream = System.err;
-
- public Builder() { }
-
- public Builder(Map> exported,
- Map> opened) {
- this.exported = deepCopy(exported);
- this.opened = deepCopy(opened);
+ @SuppressWarnings("serial")
+ private static class Usages extends LinkedHashMap {
+ Usages() { }
+ boolean add(Usage u) {
+ return (putIfAbsent(u, Boolean.TRUE) == null);
}
-
- public Builder logAccessToExportedPackage(Module m, String pn, String how) {
- if (!m.isExported(pn, UNNAMED)) {
- if (exported == null)
- exported = new HashMap<>();
- exported.computeIfAbsent(m, k -> new HashMap<>()).putIfAbsent(pn, how);
- }
- return this;
- }
-
- public Builder logAccessToOpenPackage(Module m, String pn, String how) {
- // opens implies exported at run-time.
- logAccessToExportedPackage(m, pn, how);
-
- if (!m.isOpen(pn, UNNAMED)) {
- if (opened == null)
- opened = new HashMap<>();
- opened.computeIfAbsent(m, k -> new HashMap<>()).putIfAbsent(pn, how);
- }
- return this;
- }
-
- public Builder warningStream(PrintStream warningStream) {
- this.warningStream = Objects.requireNonNull(warningStream);
- return this;
- }
-
- /**
- * Builds the logger.
- */
- public IllegalAccessLogger build() {
- return new IllegalAccessLogger(exported, opened, warningStream);
- }
- }
-
-
- static Map> deepCopy(Map> map) {
- if (map == null || map.isEmpty()) {
- return new HashMap<>();
- } else {
- Map> newMap = new HashMap<>();
- for (Map.Entry> e : map.entrySet()) {
- newMap.put(e.getKey(), new HashMap<>(e.getValue()));
- }
- return newMap;
+ @Override
+ protected boolean removeEldestEntry(Map.Entry oldest) {
+ // prevent map growing too big, say where a utility class
+ // is used by generated code to do illegal access
+ return size() > 16;
}
}
}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/IllegalAccessMaps.java b/jdk/src/java.base/share/classes/jdk/internal/module/IllegalAccessMaps.java
new file mode 100644
index 00000000000..00ed66d2945
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/IllegalAccessMaps.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.module;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UncheckedIOException;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static java.nio.charset.StandardCharsets.*;
+
+/**
+ * Generates the maps of concealed and exported packages to open at run-time.
+ *
+ * This is used at run-time for exploded builds, and at link-time to generate
+ * the maps for the system modules in the run-time image.
+ */
+
+public class IllegalAccessMaps {
+ private final Map> concealedPackagesToOpen;
+ private final Map> exportedPackagesToOpen;
+
+ private IllegalAccessMaps(Map> map1,
+ Map> map2) {
+ this.concealedPackagesToOpen = map1;
+ this.exportedPackagesToOpen = map2;
+ }
+
+ /**
+ * Returns the map of concealed packages to open. The map key is the
+ * module name, the value is the set of concealed packages to open.
+ */
+ public Map> concealedPackagesToOpen() {
+ return concealedPackagesToOpen;
+ }
+
+ /**
+ * Returns the map of exported packages to open. The map key is the
+ * module name, the value is the set of exported packages to open.
+ */
+ public Map> exportedPackagesToOpen() {
+ return exportedPackagesToOpen;
+ }
+
+ /**
+ * Generate the maps of module to concealed and exported packages for
+ * the system modules that are observable with the given module finder.
+ */
+ public static IllegalAccessMaps generate(ModuleFinder finder) {
+ Map map = new HashMap<>();
+ finder.findAll().stream()
+ .map(ModuleReference::descriptor)
+ .forEach(md -> md.packages().forEach(pn -> map.putIfAbsent(pn, md)));
+
+ Map> concealedPackagesToOpen = new HashMap<>();
+ Map> exportedPackagesToOpen = new HashMap<>();
+
+ String rn = "jdk8_packages.dat";
+ InputStream in = IllegalAccessMaps.class.getResourceAsStream(rn);
+ if (in == null) {
+ throw new InternalError(rn + " not found");
+ }
+ try (BufferedReader br = new BufferedReader(new InputStreamReader(in, UTF_8))) {
+ br.lines()
+ .filter(line -> !line.isEmpty() && !line.startsWith("#"))
+ .forEach(pn -> {
+ ModuleDescriptor descriptor = map.get(pn);
+ if (descriptor != null && !isOpen(descriptor, pn)) {
+ String name = descriptor.name();
+ if (isExported(descriptor, pn)) {
+ exportedPackagesToOpen.computeIfAbsent(name,
+ k -> new HashSet<>()).add(pn);
+ } else {
+ concealedPackagesToOpen.computeIfAbsent(name,
+ k -> new HashSet<>()).add(pn);
+ }
+ }
+ });
+
+ } catch (IOException ioe) {
+ throw new UncheckedIOException(ioe);
+ }
+
+ return new IllegalAccessMaps(concealedPackagesToOpen, exportedPackagesToOpen);
+ }
+
+ private static boolean isExported(ModuleDescriptor descriptor, String pn) {
+ return descriptor.exports()
+ .stream()
+ .anyMatch(e -> e.source().equals(pn) && !e.isQualified());
+ }
+
+ private static boolean isOpen(ModuleDescriptor descriptor, String pn) {
+ return descriptor.opens()
+ .stream()
+ .anyMatch(e -> e.source().equals(pn) && !e.isQualified());
+ }
+}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java
index d083ead7801..619b03b3596 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java
@@ -39,14 +39,17 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import jdk.internal.loader.BootLoader;
import jdk.internal.loader.BuiltinClassLoader;
+import jdk.internal.misc.JavaLangAccess;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.perf.PerfCounter;
@@ -59,7 +62,7 @@ import jdk.internal.perf.PerfCounter;
* -m and --add-modules options. The modules are located on a module path that
* is constructed from the upgrade module path, system modules, and application
* module path. The Configuration is instantiated as the boot layer with each
- * module in the the configuration defined to one of the built-in class loaders.
+ * module in the the configuration defined to a class loader.
*/
public final class ModuleBootstrap {
@@ -119,20 +122,20 @@ public final class ModuleBootstrap {
*/
public static ModuleLayer boot() {
- long t0 = System.nanoTime();
-
- // system modules (may be patched)
- ModuleFinder systemModules = ModuleFinder.ofSystem();
-
- PerfCounters.systemModulesTime.addElapsedTimeFrom(t0);
-
+ // Step 1: Locate system modules (may be patched)
long t1 = System.nanoTime();
+ ModuleFinder systemModules = ModuleFinder.ofSystem();
+ PerfCounters.systemModulesTime.addElapsedTimeFrom(t1);
+
+
+ // Step 2: Define and load java.base. This patches all classes loaded
+ // to date so that they are members of java.base. Once java.base is
+ // loaded then resources in java.base are available for error messages
+ // needed from here on.
+
+ long t2 = System.nanoTime();
- // Once we have the system modules then we define the base module to
- // the VM. We do this here so that java.base is defined as early as
- // possible and also that resources in the base module can be located
- // for error messages that may happen from here on.
ModuleReference base = systemModules.find(JAVA_BASE).orElse(null);
if (base == null)
throw new InternalError(JAVA_BASE + " not found");
@@ -142,15 +145,23 @@ public final class ModuleBootstrap {
BootLoader.loadModule(base);
Modules.defineModule(null, base.descriptor(), baseUri);
- PerfCounters.defineBaseTime.addElapsedTimeFrom(t1);
+ PerfCounters.defineBaseTime.addElapsedTimeFrom(t2);
+
+
+ // Step 2a: If --validate-modules is specified then the VM needs to
+ // start with only java.base, all other options are ignored.
- // special mode to boot with only java.base, ignores other options
String propValue = getAndRemoveProperty("jdk.module.minimumBoot");
if (propValue != null) {
return createMinimalBootLayer();
}
- long t2 = System.nanoTime();
+
+ // Step 3: Construct the module path and the set of root modules to
+ // resolve. If --limit-modules is specified then it limits the set
+ // modules that are observable.
+
+ long t3 = System.nanoTime();
// --upgrade-module-path option specified to launcher
ModuleFinder upgradeModulePath
@@ -269,10 +280,13 @@ public final class ModuleBootstrap {
.forEach(mn -> roots.add(mn));
}
- PerfCounters.optionsAndRootsTime.addElapsedTimeFrom(t2);
+ PerfCounters.optionsAndRootsTime.addElapsedTimeFrom(t3);
- long t3 = System.nanoTime();
+ // Step 4: Resolve the root modules, with service binding, to create
+ // the configuration for the boot layer.
+
+ long t4 = System.nanoTime();
// determine if post resolution checks are needed
boolean needPostResolutionChecks = true;
@@ -295,11 +309,17 @@ public final class ModuleBootstrap {
needPostResolutionChecks,
traceOutput);
- // time to create configuration
- PerfCounters.resolveTime.addElapsedTimeFrom(t3);
+ PerfCounters.resolveTime.addElapsedTimeFrom(t4);
- // check module names and incubating status
- checkModuleNamesAndStatus(cf);
+
+ // Step 5: Map the modules in the configuration to class loaders.
+ // The static configuration provides the mapping of standard and JDK
+ // modules to the boot and platform loaders. All other modules (JDK
+ // tool modules, and both explicit and automatic modules on the
+ // application module path) are defined to the application class
+ // loader.
+
+ long t5 = System.nanoTime();
// mapping of modules to class loaders
Function clf = ModuleLoaderMap.mappingFunction(cf);
@@ -312,11 +332,9 @@ public final class ModuleBootstrap {
String name = mref.descriptor().name();
ClassLoader cl = clf.apply(name);
if (cl == null) {
-
if (upgradeModulePath != null
&& upgradeModulePath.find(name).isPresent())
fail(name + ": cannot be loaded from upgrade module path");
-
if (!systemModules.find(name).isPresent())
fail(name + ": cannot be loaded from application module path");
}
@@ -330,55 +348,38 @@ public final class ModuleBootstrap {
}
}
- // if needed check that there are no split packages in the set of
- // resolved modules for the boot layer
+ // check for split packages in the modules mapped to the built-in loaders
if (SystemModules.hasSplitPackages() || needPostResolutionChecks) {
- Map packageToModule = new HashMap<>();
- for (ResolvedModule resolvedModule : cf.modules()) {
- ModuleDescriptor descriptor = resolvedModule.reference().descriptor();
- String name = descriptor.name();
- for (String p : descriptor.packages()) {
- String other = packageToModule.putIfAbsent(p, name);
- if (other != null) {
- String msg = "Package " + p + " in both module "
- + name + " and module " + other;
- throw new LayerInstantiationException(msg);
- }
- }
- }
+ checkSplitPackages(cf, clf);
}
- long t4 = System.nanoTime();
-
- // define modules to VM/runtime
- ModuleLayer bootLayer = ModuleLayer.empty().defineModules(cf, clf);
-
- PerfCounters.layerCreateTime.addElapsedTimeFrom(t4);
-
-
- long t5 = System.nanoTime();
-
- // define the module to its class loader, except java.base
- for (ResolvedModule resolvedModule : cf.modules()) {
- ModuleReference mref = resolvedModule.reference();
- String name = mref.descriptor().name();
- ClassLoader cl = clf.apply(name);
- if (cl == null) {
- if (!name.equals(JAVA_BASE)) BootLoader.loadModule(mref);
- } else {
- ((BuiltinClassLoader)cl).loadModule(mref);
- }
- }
+ // load/register the modules with the built-in class loaders
+ loadModules(cf, clf);
PerfCounters.loadModulesTime.addElapsedTimeFrom(t5);
- // --add-reads, --add-exports/--add-opens
+ // Step 6: Define all modules to the VM
+
+ long t6 = System.nanoTime();
+ ModuleLayer bootLayer = ModuleLayer.empty().defineModules(cf, clf);
+ PerfCounters.layerCreateTime.addElapsedTimeFrom(t6);
+
+
+ // Step 7: Miscellaneous
+
+ // check incubating status
+ checkIncubatingStatus(cf);
+
+ // --add-reads, --add-exports/--add-opens, and -illegal-access
+ long t7 = System.nanoTime();
addExtraReads(bootLayer);
- addExtraExportsAndOpens(bootLayer);
+ boolean extraExportsOrOpens = addExtraExportsAndOpens(bootLayer);
+ addIllegalAccess(bootLayer, upgradeModulePath, extraExportsOrOpens);
+ PerfCounters.adjustModulesTime.addElapsedTimeFrom(t7);
// total time to initialize
- PerfCounters.bootstrapTime.addElapsedTimeFrom(t0);
+ PerfCounters.bootstrapTime.addElapsedTimeFrom(t1);
return bootLayer;
}
@@ -397,6 +398,51 @@ public final class ModuleBootstrap {
return ModuleLayer.empty().defineModules(cf, clf);
}
+ /**
+ * Load/register the modules to the built-in class loaders.
+ */
+ private static void loadModules(Configuration cf,
+ Function clf) {
+ for (ResolvedModule resolvedModule : cf.modules()) {
+ ModuleReference mref = resolvedModule.reference();
+ String name = resolvedModule.name();
+ ClassLoader loader = clf.apply(name);
+ if (loader == null) {
+ // skip java.base as it is already loaded
+ if (!name.equals(JAVA_BASE)) {
+ BootLoader.loadModule(mref);
+ }
+ } else if (loader instanceof BuiltinClassLoader) {
+ ((BuiltinClassLoader) loader).loadModule(mref);
+ }
+ }
+ }
+
+ /**
+ * Checks for split packages between modules defined to the built-in class
+ * loaders.
+ */
+ private static void checkSplitPackages(Configuration cf,
+ Function clf) {
+ Map packageToModule = new HashMap<>();
+ for (ResolvedModule resolvedModule : cf.modules()) {
+ ModuleDescriptor descriptor = resolvedModule.reference().descriptor();
+ String name = descriptor.name();
+ ClassLoader loader = clf.apply(name);
+ if (loader == null || loader instanceof BuiltinClassLoader) {
+ for (String p : descriptor.packages()) {
+ String other = packageToModule.putIfAbsent(p, name);
+ if (other != null) {
+ String msg = "Package " + p + " in both module "
+ + name + " and module " + other;
+ throw new LayerInstantiationException(msg);
+ }
+ }
+ }
+
+ }
+ }
+
/**
* Returns a ModuleFinder that limits observability to the given root
* modules, their transitive dependences, plus a set of other modules.
@@ -458,15 +504,14 @@ public final class ModuleBootstrap {
}
}
-
/**
* Initialize the module patcher for the initial configuration passed on the
* value of the --patch-module options.
*/
private static ModulePatcher initModulePatcher() {
Map> map = decode("jdk.module.patch.",
- File.pathSeparator,
- false);
+ File.pathSeparator,
+ false);
return new ModulePatcher(map);
}
@@ -538,38 +583,27 @@ public final class ModuleBootstrap {
* Process the --add-exports and --add-opens options to export/open
* additional packages specified on the command-line.
*/
- private static void addExtraExportsAndOpens(ModuleLayer bootLayer) {
+ private static boolean addExtraExportsAndOpens(ModuleLayer bootLayer) {
+ boolean extraExportsOrOpens = false;
+
// --add-exports
String prefix = "jdk.module.addexports.";
Map> extraExports = decode(prefix);
if (!extraExports.isEmpty()) {
addExtraExportsOrOpens(bootLayer, extraExports, false);
+ extraExportsOrOpens = true;
}
+
// --add-opens
prefix = "jdk.module.addopens.";
Map> extraOpens = decode(prefix);
if (!extraOpens.isEmpty()) {
addExtraExportsOrOpens(bootLayer, extraOpens, true);
+ extraExportsOrOpens = true;
}
- // --permit-illegal-access
- if (getAndRemoveProperty("jdk.module.permitIllegalAccess") != null) {
- warn("--permit-illegal-access will be removed in the next major release");
- IllegalAccessLogger.Builder builder = new IllegalAccessLogger.Builder();
- Module unnamed = BootLoader.getUnnamedModule();
- bootLayer.modules().stream().forEach(m -> {
- m.getDescriptor()
- .packages()
- .stream()
- .filter(pn -> !m.isOpen(pn, unnamed)) // skip if opened by --add-opens
- .forEach(pn -> {
- builder.logAccessToOpenPackage(m, pn, "--permit-illegal-access");
- Modules.addOpensToAllUnnamed(m, pn);
- });
- });
- IllegalAccessLogger.setIllegalAccessLogger(builder.build());
- }
+ return extraExportsOrOpens;
}
private static void addExtraExportsOrOpens(ModuleLayer bootLayer,
@@ -638,6 +672,102 @@ public final class ModuleBootstrap {
}
}
+ /**
+ * Process the --illegal-access option (and its default) to open packages
+ * of system modules in the boot layer to code in unnamed modules.
+ */
+ private static void addIllegalAccess(ModuleLayer bootLayer,
+ ModuleFinder upgradeModulePath,
+ boolean extraExportsOrOpens) {
+ String value = getAndRemoveProperty("jdk.module.illegalAccess");
+ IllegalAccessLogger.Mode mode = IllegalAccessLogger.Mode.ONESHOT;
+ if (value != null) {
+ switch (value) {
+ case "deny":
+ return;
+ case "permit":
+ break;
+ case "warn":
+ mode = IllegalAccessLogger.Mode.WARN;
+ break;
+ case "debug":
+ mode = IllegalAccessLogger.Mode.DEBUG;
+ break;
+ default:
+ fail("Value specified to --illegal-access not recognized:"
+ + " '" + value + "'");
+ return;
+ }
+ }
+ IllegalAccessLogger.Builder builder
+ = new IllegalAccessLogger.Builder(mode, System.err);
+
+ Map> map1 = SystemModules.concealedPackagesToOpen();
+ Map> map2 = SystemModules.exportedPackagesToOpen();
+ if (map1.isEmpty() && map2.isEmpty()) {
+ // need to generate maps when on exploded build
+ IllegalAccessMaps maps = IllegalAccessMaps.generate(limitedFinder());
+ map1 = maps.concealedPackagesToOpen();
+ map2 = maps.exportedPackagesToOpen();
+ }
+
+ // open specific packages in the system modules
+ for (Module m : bootLayer.modules()) {
+ ModuleDescriptor descriptor = m.getDescriptor();
+ String name = m.getName();
+
+ // skip open modules
+ if (descriptor.isOpen()) {
+ continue;
+ }
+
+ // skip modules loaded from the upgrade module path
+ if (upgradeModulePath != null
+ && upgradeModulePath.find(name).isPresent()) {
+ continue;
+ }
+
+ Set concealedPackages = map1.getOrDefault(name, Set.of());
+ Set exportedPackages = map2.getOrDefault(name, Set.of());
+
+ // refresh the set of concealed and exported packages if needed
+ if (extraExportsOrOpens) {
+ concealedPackages = new HashSet<>(concealedPackages);
+ exportedPackages = new HashSet<>(exportedPackages);
+ Iterator iterator = concealedPackages.iterator();
+ while (iterator.hasNext()) {
+ String pn = iterator.next();
+ if (m.isExported(pn, BootLoader.getUnnamedModule())) {
+ // concealed package is exported to ALL-UNNAMED
+ iterator.remove();
+ exportedPackages.add(pn);
+ }
+ }
+ iterator = exportedPackages.iterator();
+ while (iterator.hasNext()) {
+ String pn = iterator.next();
+ if (m.isOpen(pn, BootLoader.getUnnamedModule())) {
+ // exported package is opened to ALL-UNNAMED
+ iterator.remove();
+ }
+ }
+ }
+
+ // log reflective access to all types in concealed packages
+ builder.logAccessToConcealedPackages(m, concealedPackages);
+
+ // log reflective access to non-public members/types in exported packages
+ builder.logAccessToExportedPackages(m, exportedPackages);
+
+ // open the packages to unnamed modules
+ JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
+ jla.addOpensToAllUnnamed(m, concat(concealedPackages.iterator(),
+ exportedPackages.iterator()));
+ }
+
+ builder.complete();
+ }
+
/**
* Decodes the values of --add-reads, -add-exports, --add-opens or
* --patch-modules options that are encoded in system properties.
@@ -708,17 +838,16 @@ public final class ModuleBootstrap {
}
/**
- * Checks the names and resolution bit of each module in the configuration,
- * emitting warnings if needed.
+ * Checks incubating status of modules in the configuration
*/
- private static void checkModuleNamesAndStatus(Configuration cf) {
+ private static void checkIncubatingStatus(Configuration cf) {
String incubating = null;
- for (ResolvedModule rm : cf.modules()) {
- ModuleReference mref = rm.reference();
- String mn = mref.descriptor().name();
+ for (ResolvedModule resolvedModule : cf.modules()) {
+ ModuleReference mref = resolvedModule.reference();
// emit warning if the WARN_INCUBATING module resolution bit set
if (ModuleResolution.hasIncubatingWarning(mref)) {
+ String mn = mref.descriptor().name();
if (incubating == null) {
incubating = mn;
} else {
@@ -777,6 +906,21 @@ public final class ModuleBootstrap {
}
}
+ static Iterator concat(Iterator iterator1, Iterator iterator2) {
+ return new Iterator() {
+ @Override
+ public boolean hasNext() {
+ return iterator1.hasNext() || iterator2.hasNext();
+ }
+ @Override
+ public T next() {
+ if (iterator1.hasNext()) return iterator1.next();
+ if (iterator2.hasNext()) return iterator2.next();
+ throw new NoSuchElementException();
+ }
+ };
+ }
+
static class PerfCounters {
static PerfCounter systemModulesTime
@@ -791,6 +935,8 @@ public final class ModuleBootstrap {
= PerfCounter.newPerfCounter("jdk.module.bootstrap.layerCreateTime");
static PerfCounter loadModulesTime
= PerfCounter.newPerfCounter("jdk.module.bootstrap.loadModulesTime");
+ static PerfCounter adjustModulesTime
+ = PerfCounter.newPerfCounter("jdk.module.bootstrap.adjustModulesTime");
static PerfCounter bootstrapTime
= PerfCounter.newPerfCounter("jdk.module.bootstrap.totalTime");
}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModulePath.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModulePath.java
index 750ac801fe3..330117a8f37 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModulePath.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModulePath.java
@@ -35,6 +35,7 @@ import java.io.UncheckedIOException;
import java.lang.module.FindException;
import java.lang.module.InvalidModuleDescriptorException;
import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Builder;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.net.URI;
@@ -404,6 +405,9 @@ public class ModulePath implements ModuleFinder {
private static final String SERVICES_PREFIX = "META-INF/services/";
+ private static final Attributes.Name AUTOMATIC_MODULE_NAME
+ = new Attributes.Name("Automatic-Module-Name");
+
/**
* Returns the service type corresponding to the name of a services
* configuration file if it is a legal type name.
@@ -445,48 +449,68 @@ public class ModulePath implements ModuleFinder {
/**
* Treat the given JAR file as a module as follows:
*
- * 1. The module name (and optionally the version) is derived from the file
- * name of the JAR file
- * 2. All packages are derived from the .class files in the JAR file
- * 3. The contents of any META-INF/services configuration files are mapped
+ * 1. The value of the Automatic-Module-Name attribute is the module name
+ * 2. The version, and the module name when the Automatic-Module-Name
+ * attribute is not present, is derived from the file ame of the JAR file
+ * 3. All packages are derived from the .class files in the JAR file
+ * 4. The contents of any META-INF/services configuration files are mapped
* to "provides" declarations
- * 4. The Main-Class attribute in the main attributes of the JAR manifest
+ * 5. The Main-Class attribute in the main attributes of the JAR manifest
* is mapped to the module descriptor mainClass if possible
*/
private ModuleDescriptor deriveModuleDescriptor(JarFile jf)
throws IOException
{
- // Derive module name and version from JAR file name
+ // Read Automatic-Module-Name attribute if present
+ Manifest man = jf.getManifest();
+ Attributes attrs = null;
+ String moduleName = null;
+ if (man != null) {
+ attrs = man.getMainAttributes();
+ if (attrs != null) {
+ moduleName = attrs.getValue(AUTOMATIC_MODULE_NAME);
+ }
+ }
+ // Derive the version, and the module name if needed, from JAR file name
String fn = jf.getName();
int i = fn.lastIndexOf(File.separator);
if (i != -1)
- fn = fn.substring(i+1);
+ fn = fn.substring(i + 1);
- // drop .jar
- String mn = fn.substring(0, fn.length()-4);
+ // drop ".jar"
+ String name = fn.substring(0, fn.length() - 4);
String vs = null;
// find first occurrence of -${NUMBER}. or -${NUMBER}$
- Matcher matcher = Patterns.DASH_VERSION.matcher(mn);
+ Matcher matcher = Patterns.DASH_VERSION.matcher(name);
if (matcher.find()) {
int start = matcher.start();
// attempt to parse the tail as a version string
try {
- String tail = mn.substring(start+1);
+ String tail = name.substring(start + 1);
ModuleDescriptor.Version.parse(tail);
vs = tail;
} catch (IllegalArgumentException ignore) { }
- mn = mn.substring(0, start);
+ name = name.substring(0, start);
}
- // finally clean up the module name
- mn = cleanModuleName(mn);
+ // Create builder, using the name derived from file name when
+ // Automatic-Module-Name not present
+ Builder builder;
+ if (moduleName != null) {
+ try {
+ builder = ModuleDescriptor.newAutomaticModule(moduleName);
+ } catch (IllegalArgumentException e) {
+ throw new FindException(AUTOMATIC_MODULE_NAME + ": " + e.getMessage());
+ }
+ } else {
+ builder = ModuleDescriptor.newAutomaticModule(cleanModuleName(name));
+ }
- // Builder throws IAE if module name is empty or invalid
- ModuleDescriptor.Builder builder = ModuleDescriptor.newAutomaticModule(mn);
+ // module version if present
if (vs != null)
builder.version(vs);
@@ -541,9 +565,7 @@ public class ModulePath implements ModuleFinder {
}
// Main-Class attribute if it exists
- Manifest man = jf.getManifest();
- if (man != null) {
- Attributes attrs = man.getMainAttributes();
+ if (attrs != null) {
String mainClass = attrs.getValue(Attributes.Name.MAIN_CLASS);
if (mainClass != null) {
mainClass = mainClass.replace("/", ".");
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferenceImpl.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferenceImpl.java
index 002930907ba..c3cf0a8beec 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferenceImpl.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferenceImpl.java
@@ -41,6 +41,10 @@ import java.util.function.Supplier;
public class ModuleReferenceImpl extends ModuleReference {
+ // location of module
+ private final URI location;
+
+ // the module reader
private final Supplier readerSupplier;
// non-null if the module is patched
@@ -74,6 +78,7 @@ public class ModuleReferenceImpl extends ModuleReference {
ModuleResolution moduleResolution)
{
super(descriptor, Objects.requireNonNull(location));
+ this.location = location;
this.readerSupplier = readerSupplier;
this.patcher = patcher;
this.target = target;
@@ -148,7 +153,7 @@ public class ModuleReferenceImpl extends ModuleReference {
int hc = hash;
if (hc == 0) {
hc = descriptor().hashCode();
- hc = 43 * hc + Objects.hashCode(location());
+ hc = 43 * hc + Objects.hashCode(location);
hc = 43 * hc + Objects.hashCode(patcher);
if (hc == 0)
hc = -1;
@@ -169,7 +174,7 @@ public class ModuleReferenceImpl extends ModuleReference {
// when the modules have equal module descriptors, are at the
// same location, and are patched by the same patcher.
return Objects.equals(this.descriptor(), that.descriptor())
- && Objects.equals(this.location(), that.location())
+ && Objects.equals(this.location, that.location)
&& Objects.equals(this.patcher, that.patcher);
}
@@ -179,7 +184,7 @@ public class ModuleReferenceImpl extends ModuleReference {
sb.append("[module ");
sb.append(descriptor().name());
sb.append(", location=");
- sb.append(location().orElseThrow(() -> new InternalError()));
+ sb.append(location);
if (isPatched()) sb.append(" (patched)");
sb.append("]");
return sb.toString();
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/Modules.java b/jdk/src/java.base/share/classes/jdk/internal/module/Modules.java
index af784dd944e..dffe5e8c0ff 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/Modules.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/Modules.java
@@ -136,10 +136,12 @@ public class Modules {
public static void addProvides(Module m, Class> service, Class> impl) {
ModuleLayer layer = m.getLayer();
- if (layer == null || layer == ModuleLayer.boot()) {
+ PrivilegedAction pa = m::getClassLoader;
+ ClassLoader loader = AccessController.doPrivileged(pa);
+
+ ClassLoader platformClassLoader = ClassLoaders.platformClassLoader();
+ if (layer == null || loader == null || loader == platformClassLoader) {
// update ClassLoader catalog
- PrivilegedAction pa = m::getClassLoader;
- ClassLoader loader = AccessController.doPrivileged(pa);
ServicesCatalog catalog;
if (loader == null) {
catalog = BootLoader.getServicesCatalog();
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java
index 06e21ba2967..18817cc9bc5 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java
@@ -26,6 +26,9 @@
package jdk.internal.module;
import java.lang.module.ModuleDescriptor;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
/**
* SystemModules class will be generated at link time to create
@@ -57,8 +60,7 @@ public final class SystemModules {
public static int PACKAGES_IN_BOOT_LAYER = 1024;
/**
- * @return {@code false} if there are no split packages in the run-time
- * image, {@code true} if there are or if it's not been checked.
+ * Return true if there are no split packages in the run-time image.
*/
public static boolean hasSplitPackages() {
return true;
@@ -98,4 +100,20 @@ public final class SystemModules {
public static ModuleResolution[] moduleResolutions() {
throw new InternalError("expected to be overridden at link time");
}
+
+ /**
+ * Returns the map of module concealed packages to open. The map key is the
+ * module name, the value is the set of concealed packages to open.
+ */
+ public static Map> concealedPackagesToOpen() {
+ return Collections.emptyMap();
+ }
+
+ /**
+ * Returns the map of module exported packages to open. The map key is the
+ * module name, the value is the set of exported packages to open.
+ */
+ public static Map> exportedPackagesToOpen() {
+ return Collections.emptyMap();
+ }
}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/jdk8_packages.dat b/jdk/src/java.base/share/classes/jdk/internal/module/jdk8_packages.dat
new file mode 100644
index 00000000000..2774f2bb492
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/jdk8_packages.dat
@@ -0,0 +1,1340 @@
+# Copyright (c) 2017, 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
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+apple.applescript
+apple.laf
+apple.launcher
+apple.security
+com.apple.concurrent
+com.apple.eawt
+com.apple.eawt.event
+com.apple.eio
+com.apple.laf
+com.apple.laf.resources
+com.oracle.jrockit.jfr
+com.oracle.jrockit.jfr.client
+com.oracle.jrockit.jfr.management
+com.oracle.security.ucrypto
+com.oracle.util
+com.oracle.webservices.internal.api
+com.oracle.webservices.internal.api.databinding
+com.oracle.webservices.internal.api.message
+com.oracle.webservices.internal.impl.encoding
+com.oracle.webservices.internal.impl.internalspi.encoding
+com.oracle.xmlns.internal.webservices.jaxws_databinding
+com.sun.accessibility.internal.resources
+com.sun.activation.registries
+com.sun.awt
+com.sun.beans
+com.sun.beans.decoder
+com.sun.beans.editors
+com.sun.beans.finder
+com.sun.beans.infos
+com.sun.beans.util
+com.sun.codemodel.internal
+com.sun.codemodel.internal.fmt
+com.sun.codemodel.internal.util
+com.sun.codemodel.internal.writer
+com.sun.corba.se.impl.activation
+com.sun.corba.se.impl.copyobject
+com.sun.corba.se.impl.corba
+com.sun.corba.se.impl.dynamicany
+com.sun.corba.se.impl.encoding
+com.sun.corba.se.impl.interceptors
+com.sun.corba.se.impl.io
+com.sun.corba.se.impl.ior
+com.sun.corba.se.impl.ior.iiop
+com.sun.corba.se.impl.javax.rmi
+com.sun.corba.se.impl.javax.rmi.CORBA
+com.sun.corba.se.impl.legacy.connection
+com.sun.corba.se.impl.logging
+com.sun.corba.se.impl.monitoring
+com.sun.corba.se.impl.naming.cosnaming
+com.sun.corba.se.impl.naming.namingutil
+com.sun.corba.se.impl.naming.pcosnaming
+com.sun.corba.se.impl.oa
+com.sun.corba.se.impl.oa.poa
+com.sun.corba.se.impl.oa.toa
+com.sun.corba.se.impl.orb
+com.sun.corba.se.impl.orbutil
+com.sun.corba.se.impl.orbutil.closure
+com.sun.corba.se.impl.orbutil.concurrent
+com.sun.corba.se.impl.orbutil.fsm
+com.sun.corba.se.impl.orbutil.graph
+com.sun.corba.se.impl.orbutil.threadpool
+com.sun.corba.se.impl.presentation.rmi
+com.sun.corba.se.impl.protocol
+com.sun.corba.se.impl.protocol.giopmsgheaders
+com.sun.corba.se.impl.resolver
+com.sun.corba.se.impl.transport
+com.sun.corba.se.impl.util
+com.sun.corba.se.internal.CosNaming
+com.sun.corba.se.internal.Interceptors
+com.sun.corba.se.internal.POA
+com.sun.corba.se.internal.corba
+com.sun.corba.se.internal.iiop
+com.sun.corba.se.org.omg.CORBA
+com.sun.corba.se.pept.broker
+com.sun.corba.se.pept.encoding
+com.sun.corba.se.pept.protocol
+com.sun.corba.se.pept.transport
+com.sun.corba.se.spi.activation
+com.sun.corba.se.spi.activation.InitialNameServicePackage
+com.sun.corba.se.spi.activation.LocatorPackage
+com.sun.corba.se.spi.activation.RepositoryPackage
+com.sun.corba.se.spi.copyobject
+com.sun.corba.se.spi.encoding
+com.sun.corba.se.spi.extension
+com.sun.corba.se.spi.ior
+com.sun.corba.se.spi.ior.iiop
+com.sun.corba.se.spi.legacy.connection
+com.sun.corba.se.spi.legacy.interceptor
+com.sun.corba.se.spi.logging
+com.sun.corba.se.spi.monitoring
+com.sun.corba.se.spi.oa
+com.sun.corba.se.spi.orb
+com.sun.corba.se.spi.orbutil.closure
+com.sun.corba.se.spi.orbutil.fsm
+com.sun.corba.se.spi.orbutil.proxy
+com.sun.corba.se.spi.orbutil.threadpool
+com.sun.corba.se.spi.presentation.rmi
+com.sun.corba.se.spi.protocol
+com.sun.corba.se.spi.resolver
+com.sun.corba.se.spi.servicecontext
+com.sun.corba.se.spi.transport
+com.sun.crypto.provider
+com.sun.demo.jvmti.hprof
+com.sun.deploy.uitoolkit.impl.fx
+com.sun.deploy.uitoolkit.impl.fx.ui
+com.sun.deploy.uitoolkit.impl.fx.ui.resources
+com.sun.glass.events
+com.sun.glass.events.mac
+com.sun.glass.ui
+com.sun.glass.ui.delegate
+com.sun.glass.ui.gtk
+com.sun.glass.ui.mac
+com.sun.glass.ui.win
+com.sun.glass.utils
+com.sun.image.codec.jpeg
+com.sun.imageio.plugins.bmp
+com.sun.imageio.plugins.common
+com.sun.imageio.plugins.gif
+com.sun.imageio.plugins.jpeg
+com.sun.imageio.plugins.png
+com.sun.imageio.plugins.wbmp
+com.sun.imageio.spi
+com.sun.imageio.stream
+com.sun.istack.internal
+com.sun.istack.internal.localization
+com.sun.istack.internal.logging
+com.sun.istack.internal.tools
+com.sun.jarsigner
+com.sun.java.accessibility
+com.sun.java.accessibility.util
+com.sun.java.accessibility.util.java.awt
+com.sun.java.browser.dom
+com.sun.java.browser.net
+com.sun.java.swing
+com.sun.java.swing.plaf.gtk
+com.sun.java.swing.plaf.gtk.resources
+com.sun.java.swing.plaf.motif
+com.sun.java.swing.plaf.motif.resources
+com.sun.java.swing.plaf.nimbus
+com.sun.java.swing.plaf.windows
+com.sun.java.swing.plaf.windows.resources
+com.sun.java.util.jar.pack
+com.sun.java_cup.internal.runtime
+com.sun.javadoc
+com.sun.javafx
+com.sun.javafx.animation
+com.sun.javafx.applet
+com.sun.javafx.application
+com.sun.javafx.beans
+com.sun.javafx.beans.event
+com.sun.javafx.binding
+com.sun.javafx.charts
+com.sun.javafx.collections
+com.sun.javafx.css
+com.sun.javafx.css.converters
+com.sun.javafx.css.parser
+com.sun.javafx.cursor
+com.sun.javafx.effect
+com.sun.javafx.embed
+com.sun.javafx.event
+com.sun.javafx.font
+com.sun.javafx.font.coretext
+com.sun.javafx.font.directwrite
+com.sun.javafx.font.freetype
+com.sun.javafx.font.t2k
+com.sun.javafx.fxml
+com.sun.javafx.fxml.builder
+com.sun.javafx.fxml.expression
+com.sun.javafx.geom
+com.sun.javafx.geom.transform
+com.sun.javafx.geometry
+com.sun.javafx.iio
+com.sun.javafx.iio.bmp
+com.sun.javafx.iio.common
+com.sun.javafx.iio.gif
+com.sun.javafx.iio.ios
+com.sun.javafx.iio.jpeg
+com.sun.javafx.iio.png
+com.sun.javafx.image
+com.sun.javafx.image.impl
+com.sun.javafx.jmx
+com.sun.javafx.logging
+com.sun.javafx.media
+com.sun.javafx.menu
+com.sun.javafx.perf
+com.sun.javafx.print
+com.sun.javafx.property
+com.sun.javafx.property.adapter
+com.sun.javafx.robot
+com.sun.javafx.robot.impl
+com.sun.javafx.runtime
+com.sun.javafx.runtime.async
+com.sun.javafx.runtime.eula
+com.sun.javafx.scene
+com.sun.javafx.scene.control
+com.sun.javafx.scene.control.behavior
+com.sun.javafx.scene.control.skin
+com.sun.javafx.scene.control.skin.resources
+com.sun.javafx.scene.input
+com.sun.javafx.scene.layout.region
+com.sun.javafx.scene.paint
+com.sun.javafx.scene.shape
+com.sun.javafx.scene.text
+com.sun.javafx.scene.transform
+com.sun.javafx.scene.traversal
+com.sun.javafx.scene.web
+com.sun.javafx.scene.web.behavior
+com.sun.javafx.scene.web.skin
+com.sun.javafx.sg.prism
+com.sun.javafx.sg.prism.web
+com.sun.javafx.stage
+com.sun.javafx.text
+com.sun.javafx.tk
+com.sun.javafx.tk.quantum
+com.sun.javafx.util
+com.sun.javafx.webkit
+com.sun.javafx.webkit.drt
+com.sun.javafx.webkit.prism
+com.sun.javafx.webkit.prism.theme
+com.sun.javafx.webkit.theme
+com.sun.jdi
+com.sun.jdi.connect
+com.sun.jdi.connect.spi
+com.sun.jdi.event
+com.sun.jdi.request
+com.sun.jmx.defaults
+com.sun.jmx.interceptor
+com.sun.jmx.mbeanserver
+com.sun.jmx.remote.internal
+com.sun.jmx.remote.protocol.iiop
+com.sun.jmx.remote.protocol.rmi
+com.sun.jmx.remote.security
+com.sun.jmx.remote.util
+com.sun.jmx.snmp
+com.sun.jmx.snmp.IPAcl
+com.sun.jmx.snmp.agent
+com.sun.jmx.snmp.daemon
+com.sun.jmx.snmp.defaults
+com.sun.jmx.snmp.internal
+com.sun.jmx.snmp.mpm
+com.sun.jmx.snmp.tasks
+com.sun.jndi.cosnaming
+com.sun.jndi.dns
+com.sun.jndi.ldap
+com.sun.jndi.ldap.ext
+com.sun.jndi.ldap.pool
+com.sun.jndi.ldap.sasl
+com.sun.jndi.rmi.registry
+com.sun.jndi.toolkit.corba
+com.sun.jndi.toolkit.ctx
+com.sun.jndi.toolkit.dir
+com.sun.jndi.toolkit.url
+com.sun.jndi.url.corbaname
+com.sun.jndi.url.dns
+com.sun.jndi.url.iiop
+com.sun.jndi.url.iiopname
+com.sun.jndi.url.ldap
+com.sun.jndi.url.ldaps
+com.sun.jndi.url.rmi
+com.sun.management
+com.sun.management.jmx
+com.sun.media.jfxmedia
+com.sun.media.jfxmedia.control
+com.sun.media.jfxmedia.effects
+com.sun.media.jfxmedia.events
+com.sun.media.jfxmedia.locator
+com.sun.media.jfxmedia.logging
+com.sun.media.jfxmedia.track
+com.sun.media.jfxmediaimpl
+com.sun.media.jfxmediaimpl.platform
+com.sun.media.jfxmediaimpl.platform.gstreamer
+com.sun.media.jfxmediaimpl.platform.ios
+com.sun.media.jfxmediaimpl.platform.java
+com.sun.media.jfxmediaimpl.platform.osx
+com.sun.media.sound
+com.sun.naming.internal
+com.sun.net.httpserver
+com.sun.net.httpserver.spi
+com.sun.net.ssl
+com.sun.net.ssl.internal.ssl
+com.sun.net.ssl.internal.www.protocol.https
+com.sun.nio.file
+com.sun.nio.sctp
+com.sun.nio.zipfs
+com.sun.openpisces
+com.sun.org.apache.bcel.internal
+com.sun.org.apache.bcel.internal.classfile
+com.sun.org.apache.bcel.internal.generic
+com.sun.org.apache.bcel.internal.util
+com.sun.org.apache.regexp.internal
+com.sun.org.apache.xalan.internal
+com.sun.org.apache.xalan.internal.extensions
+com.sun.org.apache.xalan.internal.lib
+com.sun.org.apache.xalan.internal.res
+com.sun.org.apache.xalan.internal.templates
+com.sun.org.apache.xalan.internal.utils
+com.sun.org.apache.xalan.internal.xslt
+com.sun.org.apache.xalan.internal.xsltc
+com.sun.org.apache.xalan.internal.xsltc.cmdline
+com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt
+com.sun.org.apache.xalan.internal.xsltc.compiler
+com.sun.org.apache.xalan.internal.xsltc.compiler.util
+com.sun.org.apache.xalan.internal.xsltc.dom
+com.sun.org.apache.xalan.internal.xsltc.runtime
+com.sun.org.apache.xalan.internal.xsltc.runtime.output
+com.sun.org.apache.xalan.internal.xsltc.trax
+com.sun.org.apache.xalan.internal.xsltc.util
+com.sun.org.apache.xerces.internal.dom
+com.sun.org.apache.xerces.internal.dom.events
+com.sun.org.apache.xerces.internal.impl
+com.sun.org.apache.xerces.internal.impl.dtd
+com.sun.org.apache.xerces.internal.impl.dtd.models
+com.sun.org.apache.xerces.internal.impl.dv
+com.sun.org.apache.xerces.internal.impl.dv.dtd
+com.sun.org.apache.xerces.internal.impl.dv.util
+com.sun.org.apache.xerces.internal.impl.dv.xs
+com.sun.org.apache.xerces.internal.impl.io
+com.sun.org.apache.xerces.internal.impl.msg
+com.sun.org.apache.xerces.internal.impl.validation
+com.sun.org.apache.xerces.internal.impl.xpath
+com.sun.org.apache.xerces.internal.impl.xpath.regex
+com.sun.org.apache.xerces.internal.impl.xs
+com.sun.org.apache.xerces.internal.impl.xs.identity
+com.sun.org.apache.xerces.internal.impl.xs.models
+com.sun.org.apache.xerces.internal.impl.xs.opti
+com.sun.org.apache.xerces.internal.impl.xs.traversers
+com.sun.org.apache.xerces.internal.impl.xs.util
+com.sun.org.apache.xerces.internal.jaxp
+com.sun.org.apache.xerces.internal.jaxp.datatype
+com.sun.org.apache.xerces.internal.jaxp.validation
+com.sun.org.apache.xerces.internal.parsers
+com.sun.org.apache.xerces.internal.util
+com.sun.org.apache.xerces.internal.utils
+com.sun.org.apache.xerces.internal.xinclude
+com.sun.org.apache.xerces.internal.xni
+com.sun.org.apache.xerces.internal.xni.grammars
+com.sun.org.apache.xerces.internal.xni.parser
+com.sun.org.apache.xerces.internal.xpointer
+com.sun.org.apache.xerces.internal.xs
+com.sun.org.apache.xerces.internal.xs.datatypes
+com.sun.org.apache.xml.internal.dtm
+com.sun.org.apache.xml.internal.dtm.ref
+com.sun.org.apache.xml.internal.dtm.ref.dom2dtm
+com.sun.org.apache.xml.internal.dtm.ref.sax2dtm
+com.sun.org.apache.xml.internal.res
+com.sun.org.apache.xml.internal.resolver
+com.sun.org.apache.xml.internal.resolver.helpers
+com.sun.org.apache.xml.internal.resolver.readers
+com.sun.org.apache.xml.internal.resolver.tools
+com.sun.org.apache.xml.internal.security
+com.sun.org.apache.xml.internal.security.algorithms
+com.sun.org.apache.xml.internal.security.algorithms.implementations
+com.sun.org.apache.xml.internal.security.c14n
+com.sun.org.apache.xml.internal.security.c14n.helper
+com.sun.org.apache.xml.internal.security.c14n.implementations
+com.sun.org.apache.xml.internal.security.encryption
+com.sun.org.apache.xml.internal.security.exceptions
+com.sun.org.apache.xml.internal.security.keys
+com.sun.org.apache.xml.internal.security.keys.content
+com.sun.org.apache.xml.internal.security.keys.content.keyvalues
+com.sun.org.apache.xml.internal.security.keys.content.x509
+com.sun.org.apache.xml.internal.security.keys.keyresolver
+com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations
+com.sun.org.apache.xml.internal.security.keys.storage
+com.sun.org.apache.xml.internal.security.keys.storage.implementations
+com.sun.org.apache.xml.internal.security.signature
+com.sun.org.apache.xml.internal.security.signature.reference
+com.sun.org.apache.xml.internal.security.transforms
+com.sun.org.apache.xml.internal.security.transforms.implementations
+com.sun.org.apache.xml.internal.security.transforms.params
+com.sun.org.apache.xml.internal.security.utils
+com.sun.org.apache.xml.internal.security.utils.resolver
+com.sun.org.apache.xml.internal.security.utils.resolver.implementations
+com.sun.org.apache.xml.internal.serialize
+com.sun.org.apache.xml.internal.serializer
+com.sun.org.apache.xml.internal.serializer.utils
+com.sun.org.apache.xml.internal.utils
+com.sun.org.apache.xml.internal.utils.res
+com.sun.org.apache.xpath.internal
+com.sun.org.apache.xpath.internal.axes
+com.sun.org.apache.xpath.internal.compiler
+com.sun.org.apache.xpath.internal.domapi
+com.sun.org.apache.xpath.internal.functions
+com.sun.org.apache.xpath.internal.jaxp
+com.sun.org.apache.xpath.internal.objects
+com.sun.org.apache.xpath.internal.operations
+com.sun.org.apache.xpath.internal.patterns
+com.sun.org.apache.xpath.internal.res
+com.sun.org.glassfish.external.amx
+com.sun.org.glassfish.external.arc
+com.sun.org.glassfish.external.probe.provider
+com.sun.org.glassfish.external.probe.provider.annotations
+com.sun.org.glassfish.external.statistics
+com.sun.org.glassfish.external.statistics.annotations
+com.sun.org.glassfish.external.statistics.impl
+com.sun.org.glassfish.gmbal
+com.sun.org.glassfish.gmbal.util
+com.sun.org.omg.CORBA
+com.sun.org.omg.CORBA.ValueDefPackage
+com.sun.org.omg.CORBA.portable
+com.sun.org.omg.SendingContext
+com.sun.org.omg.SendingContext.CodeBasePackage
+com.sun.pisces
+com.sun.prism
+com.sun.prism.d3d
+com.sun.prism.es2
+com.sun.prism.image
+com.sun.prism.impl
+com.sun.prism.impl.packrect
+com.sun.prism.impl.paint
+com.sun.prism.impl.ps
+com.sun.prism.impl.shape
+com.sun.prism.j2d
+com.sun.prism.j2d.paint
+com.sun.prism.j2d.print
+com.sun.prism.paint
+com.sun.prism.ps
+com.sun.prism.shader
+com.sun.prism.shape
+com.sun.prism.sw
+com.sun.rmi.rmid
+com.sun.rowset
+com.sun.rowset.internal
+com.sun.rowset.providers
+com.sun.scenario
+com.sun.scenario.animation
+com.sun.scenario.animation.shared
+com.sun.scenario.effect
+com.sun.scenario.effect.impl
+com.sun.scenario.effect.impl.es2
+com.sun.scenario.effect.impl.hw
+com.sun.scenario.effect.impl.hw.d3d
+com.sun.scenario.effect.impl.prism
+com.sun.scenario.effect.impl.prism.ps
+com.sun.scenario.effect.impl.prism.sw
+com.sun.scenario.effect.impl.state
+com.sun.scenario.effect.impl.sw
+com.sun.scenario.effect.impl.sw.java
+com.sun.scenario.effect.impl.sw.sse
+com.sun.scenario.effect.light
+com.sun.security.auth
+com.sun.security.auth.callback
+com.sun.security.auth.login
+com.sun.security.auth.module
+com.sun.security.cert.internal.x509
+com.sun.security.jgss
+com.sun.security.ntlm
+com.sun.security.sasl
+com.sun.security.sasl.digest
+com.sun.security.sasl.gsskerb
+com.sun.security.sasl.ntlm
+com.sun.security.sasl.util
+com.sun.source.doctree
+com.sun.source.tree
+com.sun.source.util
+com.sun.swing.internal.plaf.basic.resources
+com.sun.swing.internal.plaf.metal.resources
+com.sun.swing.internal.plaf.synth.resources
+com.sun.tools.attach
+com.sun.tools.attach.spi
+com.sun.tools.classfile
+com.sun.tools.corba.se.idl
+com.sun.tools.corba.se.idl.constExpr
+com.sun.tools.corba.se.idl.som.cff
+com.sun.tools.corba.se.idl.som.idlemit
+com.sun.tools.corba.se.idl.toJavaPortable
+com.sun.tools.doclets
+com.sun.tools.doclets.formats.html
+com.sun.tools.doclets.formats.html.markup
+com.sun.tools.doclets.formats.html.resources
+com.sun.tools.doclets.internal.toolkit
+com.sun.tools.doclets.internal.toolkit.builders
+com.sun.tools.doclets.internal.toolkit.resources
+com.sun.tools.doclets.internal.toolkit.taglets
+com.sun.tools.doclets.internal.toolkit.util
+com.sun.tools.doclets.internal.toolkit.util.links
+com.sun.tools.doclets.standard
+com.sun.tools.doclint
+com.sun.tools.doclint.resources
+com.sun.tools.example.debug.expr
+com.sun.tools.example.debug.tty
+com.sun.tools.extcheck
+com.sun.tools.hat
+com.sun.tools.hat.internal.model
+com.sun.tools.hat.internal.oql
+com.sun.tools.hat.internal.parser
+com.sun.tools.hat.internal.server
+com.sun.tools.hat.internal.util
+com.sun.tools.internal.jxc
+com.sun.tools.internal.jxc.ap
+com.sun.tools.internal.jxc.api
+com.sun.tools.internal.jxc.api.impl.j2s
+com.sun.tools.internal.jxc.gen.config
+com.sun.tools.internal.jxc.model.nav
+com.sun.tools.internal.ws
+com.sun.tools.internal.ws.api
+com.sun.tools.internal.ws.api.wsdl
+com.sun.tools.internal.ws.processor
+com.sun.tools.internal.ws.processor.generator
+com.sun.tools.internal.ws.processor.model
+com.sun.tools.internal.ws.processor.model.exporter
+com.sun.tools.internal.ws.processor.model.java
+com.sun.tools.internal.ws.processor.model.jaxb
+com.sun.tools.internal.ws.processor.modeler
+com.sun.tools.internal.ws.processor.modeler.annotation
+com.sun.tools.internal.ws.processor.modeler.wsdl
+com.sun.tools.internal.ws.processor.util
+com.sun.tools.internal.ws.resources
+com.sun.tools.internal.ws.spi
+com.sun.tools.internal.ws.util
+com.sun.tools.internal.ws.util.xml
+com.sun.tools.internal.ws.wscompile
+com.sun.tools.internal.ws.wscompile.plugin.at_generated
+com.sun.tools.internal.ws.wsdl.document
+com.sun.tools.internal.ws.wsdl.document.http
+com.sun.tools.internal.ws.wsdl.document.jaxws
+com.sun.tools.internal.ws.wsdl.document.mime
+com.sun.tools.internal.ws.wsdl.document.schema
+com.sun.tools.internal.ws.wsdl.document.soap
+com.sun.tools.internal.ws.wsdl.framework
+com.sun.tools.internal.ws.wsdl.parser
+com.sun.tools.internal.xjc
+com.sun.tools.internal.xjc.addon.accessors
+com.sun.tools.internal.xjc.addon.at_generated
+com.sun.tools.internal.xjc.addon.code_injector
+com.sun.tools.internal.xjc.addon.episode
+com.sun.tools.internal.xjc.addon.locator
+com.sun.tools.internal.xjc.addon.sync
+com.sun.tools.internal.xjc.api
+com.sun.tools.internal.xjc.api.impl.s2j
+com.sun.tools.internal.xjc.api.util
+com.sun.tools.internal.xjc.generator.annotation.spec
+com.sun.tools.internal.xjc.generator.bean
+com.sun.tools.internal.xjc.generator.bean.field
+com.sun.tools.internal.xjc.generator.util
+com.sun.tools.internal.xjc.model
+com.sun.tools.internal.xjc.model.nav
+com.sun.tools.internal.xjc.outline
+com.sun.tools.internal.xjc.reader
+com.sun.tools.internal.xjc.reader.dtd
+com.sun.tools.internal.xjc.reader.dtd.bindinfo
+com.sun.tools.internal.xjc.reader.gbind
+com.sun.tools.internal.xjc.reader.internalizer
+com.sun.tools.internal.xjc.reader.relaxng
+com.sun.tools.internal.xjc.reader.xmlschema
+com.sun.tools.internal.xjc.reader.xmlschema.bindinfo
+com.sun.tools.internal.xjc.reader.xmlschema.ct
+com.sun.tools.internal.xjc.reader.xmlschema.parser
+com.sun.tools.internal.xjc.runtime
+com.sun.tools.internal.xjc.util
+com.sun.tools.internal.xjc.writer
+com.sun.tools.javac
+com.sun.tools.javac.api
+com.sun.tools.javac.code
+com.sun.tools.javac.comp
+com.sun.tools.javac.file
+com.sun.tools.javac.jvm
+com.sun.tools.javac.main
+com.sun.tools.javac.model
+com.sun.tools.javac.nio
+com.sun.tools.javac.parser
+com.sun.tools.javac.processing
+com.sun.tools.javac.resources
+com.sun.tools.javac.sym
+com.sun.tools.javac.tree
+com.sun.tools.javac.util
+com.sun.tools.javadoc
+com.sun.tools.javadoc.api
+com.sun.tools.javadoc.resources
+com.sun.tools.javah
+com.sun.tools.javah.resources
+com.sun.tools.javap
+com.sun.tools.javap.resources
+com.sun.tools.jconsole
+com.sun.tools.jdeps
+com.sun.tools.jdeps.resources
+com.sun.tools.jdi
+com.sun.tools.jdi.resources
+com.sun.tools.script.shell
+com.sun.tracing
+com.sun.tracing.dtrace
+com.sun.webkit
+com.sun.webkit.dom
+com.sun.webkit.event
+com.sun.webkit.graphics
+com.sun.webkit.network
+com.sun.webkit.network.about
+com.sun.webkit.network.data
+com.sun.webkit.perf
+com.sun.webkit.plugin
+com.sun.webkit.text
+com.sun.xml.internal.bind
+com.sun.xml.internal.bind.annotation
+com.sun.xml.internal.bind.api
+com.sun.xml.internal.bind.api.impl
+com.sun.xml.internal.bind.marshaller
+com.sun.xml.internal.bind.unmarshaller
+com.sun.xml.internal.bind.util
+com.sun.xml.internal.bind.v2
+com.sun.xml.internal.bind.v2.bytecode
+com.sun.xml.internal.bind.v2.model.annotation
+com.sun.xml.internal.bind.v2.model.core
+com.sun.xml.internal.bind.v2.model.impl
+com.sun.xml.internal.bind.v2.model.nav
+com.sun.xml.internal.bind.v2.model.runtime
+com.sun.xml.internal.bind.v2.model.util
+com.sun.xml.internal.bind.v2.runtime
+com.sun.xml.internal.bind.v2.runtime.output
+com.sun.xml.internal.bind.v2.runtime.property
+com.sun.xml.internal.bind.v2.runtime.reflect
+com.sun.xml.internal.bind.v2.runtime.reflect.opt
+com.sun.xml.internal.bind.v2.runtime.unmarshaller
+com.sun.xml.internal.bind.v2.schemagen
+com.sun.xml.internal.bind.v2.schemagen.episode
+com.sun.xml.internal.bind.v2.schemagen.xmlschema
+com.sun.xml.internal.bind.v2.util
+com.sun.xml.internal.dtdparser
+com.sun.xml.internal.fastinfoset
+com.sun.xml.internal.fastinfoset.algorithm
+com.sun.xml.internal.fastinfoset.alphabet
+com.sun.xml.internal.fastinfoset.dom
+com.sun.xml.internal.fastinfoset.org.apache.xerces.util
+com.sun.xml.internal.fastinfoset.sax
+com.sun.xml.internal.fastinfoset.stax
+com.sun.xml.internal.fastinfoset.stax.events
+com.sun.xml.internal.fastinfoset.stax.factory
+com.sun.xml.internal.fastinfoset.stax.util
+com.sun.xml.internal.fastinfoset.tools
+com.sun.xml.internal.fastinfoset.util
+com.sun.xml.internal.fastinfoset.vocab
+com.sun.xml.internal.messaging.saaj
+com.sun.xml.internal.messaging.saaj.client.p2p
+com.sun.xml.internal.messaging.saaj.packaging.mime
+com.sun.xml.internal.messaging.saaj.packaging.mime.internet
+com.sun.xml.internal.messaging.saaj.packaging.mime.util
+com.sun.xml.internal.messaging.saaj.soap
+com.sun.xml.internal.messaging.saaj.soap.dynamic
+com.sun.xml.internal.messaging.saaj.soap.impl
+com.sun.xml.internal.messaging.saaj.soap.name
+com.sun.xml.internal.messaging.saaj.soap.ver1_1
+com.sun.xml.internal.messaging.saaj.soap.ver1_2
+com.sun.xml.internal.messaging.saaj.util
+com.sun.xml.internal.messaging.saaj.util.transform
+com.sun.xml.internal.org.jvnet.fastinfoset
+com.sun.xml.internal.org.jvnet.fastinfoset.sax
+com.sun.xml.internal.org.jvnet.fastinfoset.sax.helpers
+com.sun.xml.internal.org.jvnet.fastinfoset.stax
+com.sun.xml.internal.org.jvnet.mimepull
+com.sun.xml.internal.org.jvnet.staxex
+com.sun.xml.internal.rngom.ast.builder
+com.sun.xml.internal.rngom.ast.om
+com.sun.xml.internal.rngom.ast.util
+com.sun.xml.internal.rngom.binary
+com.sun.xml.internal.rngom.binary.visitor
+com.sun.xml.internal.rngom.digested
+com.sun.xml.internal.rngom.dt
+com.sun.xml.internal.rngom.dt.builtin
+com.sun.xml.internal.rngom.nc
+com.sun.xml.internal.rngom.parse
+com.sun.xml.internal.rngom.parse.compact
+com.sun.xml.internal.rngom.parse.host
+com.sun.xml.internal.rngom.parse.xml
+com.sun.xml.internal.rngom.util
+com.sun.xml.internal.rngom.xml.sax
+com.sun.xml.internal.rngom.xml.util
+com.sun.xml.internal.stream
+com.sun.xml.internal.stream.buffer
+com.sun.xml.internal.stream.buffer.sax
+com.sun.xml.internal.stream.buffer.stax
+com.sun.xml.internal.stream.dtd
+com.sun.xml.internal.stream.dtd.nonvalidating
+com.sun.xml.internal.stream.events
+com.sun.xml.internal.stream.util
+com.sun.xml.internal.stream.writers
+com.sun.xml.internal.txw2
+com.sun.xml.internal.txw2.annotation
+com.sun.xml.internal.txw2.output
+com.sun.xml.internal.ws
+com.sun.xml.internal.ws.addressing
+com.sun.xml.internal.ws.addressing.model
+com.sun.xml.internal.ws.addressing.policy
+com.sun.xml.internal.ws.addressing.v200408
+com.sun.xml.internal.ws.api
+com.sun.xml.internal.ws.api.addressing
+com.sun.xml.internal.ws.api.client
+com.sun.xml.internal.ws.api.config.management
+com.sun.xml.internal.ws.api.config.management.policy
+com.sun.xml.internal.ws.api.databinding
+com.sun.xml.internal.ws.api.fastinfoset
+com.sun.xml.internal.ws.api.ha
+com.sun.xml.internal.ws.api.handler
+com.sun.xml.internal.ws.api.message
+com.sun.xml.internal.ws.api.message.saaj
+com.sun.xml.internal.ws.api.message.stream
+com.sun.xml.internal.ws.api.model
+com.sun.xml.internal.ws.api.model.soap
+com.sun.xml.internal.ws.api.model.wsdl
+com.sun.xml.internal.ws.api.model.wsdl.editable
+com.sun.xml.internal.ws.api.pipe
+com.sun.xml.internal.ws.api.pipe.helper
+com.sun.xml.internal.ws.api.policy
+com.sun.xml.internal.ws.api.policy.subject
+com.sun.xml.internal.ws.api.server
+com.sun.xml.internal.ws.api.streaming
+com.sun.xml.internal.ws.api.wsdl.parser
+com.sun.xml.internal.ws.api.wsdl.writer
+com.sun.xml.internal.ws.assembler
+com.sun.xml.internal.ws.assembler.dev
+com.sun.xml.internal.ws.assembler.jaxws
+com.sun.xml.internal.ws.binding
+com.sun.xml.internal.ws.client
+com.sun.xml.internal.ws.client.dispatch
+com.sun.xml.internal.ws.client.sei
+com.sun.xml.internal.ws.commons.xmlutil
+com.sun.xml.internal.ws.config.management.policy
+com.sun.xml.internal.ws.config.metro.dev
+com.sun.xml.internal.ws.config.metro.util
+com.sun.xml.internal.ws.db
+com.sun.xml.internal.ws.db.glassfish
+com.sun.xml.internal.ws.developer
+com.sun.xml.internal.ws.dump
+com.sun.xml.internal.ws.encoding
+com.sun.xml.internal.ws.encoding.fastinfoset
+com.sun.xml.internal.ws.encoding.policy
+com.sun.xml.internal.ws.encoding.soap
+com.sun.xml.internal.ws.encoding.soap.streaming
+com.sun.xml.internal.ws.encoding.xml
+com.sun.xml.internal.ws.fault
+com.sun.xml.internal.ws.handler
+com.sun.xml.internal.ws.message
+com.sun.xml.internal.ws.message.jaxb
+com.sun.xml.internal.ws.message.saaj
+com.sun.xml.internal.ws.message.source
+com.sun.xml.internal.ws.message.stream
+com.sun.xml.internal.ws.model
+com.sun.xml.internal.ws.model.soap
+com.sun.xml.internal.ws.model.wsdl
+com.sun.xml.internal.ws.org.objectweb.asm
+com.sun.xml.internal.ws.policy
+com.sun.xml.internal.ws.policy.jaxws
+com.sun.xml.internal.ws.policy.jaxws.spi
+com.sun.xml.internal.ws.policy.privateutil
+com.sun.xml.internal.ws.policy.sourcemodel
+com.sun.xml.internal.ws.policy.sourcemodel.attach
+com.sun.xml.internal.ws.policy.sourcemodel.wspolicy
+com.sun.xml.internal.ws.policy.spi
+com.sun.xml.internal.ws.policy.subject
+com.sun.xml.internal.ws.protocol.soap
+com.sun.xml.internal.ws.protocol.xml
+com.sun.xml.internal.ws.resources
+com.sun.xml.internal.ws.runtime.config
+com.sun.xml.internal.ws.server
+com.sun.xml.internal.ws.server.provider
+com.sun.xml.internal.ws.server.sei
+com.sun.xml.internal.ws.spi
+com.sun.xml.internal.ws.spi.db
+com.sun.xml.internal.ws.streaming
+com.sun.xml.internal.ws.transport
+com.sun.xml.internal.ws.transport.http
+com.sun.xml.internal.ws.transport.http.client
+com.sun.xml.internal.ws.transport.http.server
+com.sun.xml.internal.ws.util
+com.sun.xml.internal.ws.util.exception
+com.sun.xml.internal.ws.util.pipe
+com.sun.xml.internal.ws.util.xml
+com.sun.xml.internal.ws.wsdl
+com.sun.xml.internal.ws.wsdl.parser
+com.sun.xml.internal.ws.wsdl.writer
+com.sun.xml.internal.ws.wsdl.writer.document
+com.sun.xml.internal.ws.wsdl.writer.document.http
+com.sun.xml.internal.ws.wsdl.writer.document.soap
+com.sun.xml.internal.ws.wsdl.writer.document.soap12
+com.sun.xml.internal.ws.wsdl.writer.document.xsd
+com.sun.xml.internal.xsom
+com.sun.xml.internal.xsom.impl
+com.sun.xml.internal.xsom.impl.parser
+com.sun.xml.internal.xsom.impl.parser.state
+com.sun.xml.internal.xsom.impl.scd
+com.sun.xml.internal.xsom.impl.util
+com.sun.xml.internal.xsom.parser
+com.sun.xml.internal.xsom.util
+com.sun.xml.internal.xsom.visitor
+java.applet
+java.awt
+java.awt.color
+java.awt.datatransfer
+java.awt.dnd
+java.awt.dnd.peer
+java.awt.event
+java.awt.font
+java.awt.geom
+java.awt.im
+java.awt.im.spi
+java.awt.image
+java.awt.image.renderable
+java.awt.peer
+java.awt.print
+java.beans
+java.beans.beancontext
+java.io
+java.lang
+java.lang.annotation
+java.lang.instrument
+java.lang.invoke
+java.lang.management
+java.lang.ref
+java.lang.reflect
+java.math
+java.net
+java.nio
+java.nio.channels
+java.nio.channels.spi
+java.nio.charset
+java.nio.charset.spi
+java.nio.file
+java.nio.file.attribute
+java.nio.file.spi
+java.rmi
+java.rmi.activation
+java.rmi.dgc
+java.rmi.registry
+java.rmi.server
+java.security
+java.security.acl
+java.security.cert
+java.security.interfaces
+java.security.spec
+java.sql
+java.text
+java.text.spi
+java.time
+java.time.chrono
+java.time.format
+java.time.temporal
+java.time.zone
+java.util
+java.util.concurrent
+java.util.concurrent.atomic
+java.util.concurrent.locks
+java.util.function
+java.util.jar
+java.util.logging
+java.util.prefs
+java.util.regex
+java.util.spi
+java.util.stream
+java.util.zip
+javafx.animation
+javafx.application
+javafx.beans
+javafx.beans.binding
+javafx.beans.property
+javafx.beans.property.adapter
+javafx.beans.value
+javafx.collections
+javafx.collections.transformation
+javafx.concurrent
+javafx.css
+javafx.embed.swing
+javafx.embed.swt
+javafx.event
+javafx.fxml
+javafx.geometry
+javafx.print
+javafx.scene
+javafx.scene.canvas
+javafx.scene.chart
+javafx.scene.control
+javafx.scene.control.cell
+javafx.scene.effect
+javafx.scene.image
+javafx.scene.input
+javafx.scene.layout
+javafx.scene.media
+javafx.scene.paint
+javafx.scene.shape
+javafx.scene.text
+javafx.scene.transform
+javafx.scene.web
+javafx.stage
+javafx.util
+javafx.util.converter
+javax.accessibility
+javax.activation
+javax.activity
+javax.annotation
+javax.annotation.processing
+javax.crypto
+javax.crypto.interfaces
+javax.crypto.spec
+javax.imageio
+javax.imageio.event
+javax.imageio.metadata
+javax.imageio.plugins.bmp
+javax.imageio.plugins.jpeg
+javax.imageio.spi
+javax.imageio.stream
+javax.jws
+javax.jws.soap
+javax.lang.model
+javax.lang.model.element
+javax.lang.model.type
+javax.lang.model.util
+javax.management
+javax.management.loading
+javax.management.modelmbean
+javax.management.monitor
+javax.management.openmbean
+javax.management.relation
+javax.management.remote
+javax.management.remote.rmi
+javax.management.timer
+javax.naming
+javax.naming.directory
+javax.naming.event
+javax.naming.ldap
+javax.naming.spi
+javax.net
+javax.net.ssl
+javax.print
+javax.print.attribute
+javax.print.attribute.standard
+javax.print.event
+javax.rmi
+javax.rmi.CORBA
+javax.rmi.ssl
+javax.script
+javax.security.auth
+javax.security.auth.callback
+javax.security.auth.kerberos
+javax.security.auth.login
+javax.security.auth.spi
+javax.security.auth.x500
+javax.security.cert
+javax.security.sasl
+javax.smartcardio
+javax.sound.midi
+javax.sound.midi.spi
+javax.sound.sampled
+javax.sound.sampled.spi
+javax.sql
+javax.sql.rowset
+javax.sql.rowset.serial
+javax.sql.rowset.spi
+javax.swing
+javax.swing.border
+javax.swing.colorchooser
+javax.swing.event
+javax.swing.filechooser
+javax.swing.plaf
+javax.swing.plaf.basic
+javax.swing.plaf.metal
+javax.swing.plaf.multi
+javax.swing.plaf.nimbus
+javax.swing.plaf.synth
+javax.swing.table
+javax.swing.text
+javax.swing.text.html
+javax.swing.text.html.parser
+javax.swing.text.rtf
+javax.swing.tree
+javax.swing.undo
+javax.tools
+javax.transaction
+javax.transaction.xa
+javax.xml
+javax.xml.bind
+javax.xml.bind.annotation
+javax.xml.bind.annotation.adapters
+javax.xml.bind.attachment
+javax.xml.bind.helpers
+javax.xml.bind.util
+javax.xml.crypto
+javax.xml.crypto.dom
+javax.xml.crypto.dsig
+javax.xml.crypto.dsig.dom
+javax.xml.crypto.dsig.keyinfo
+javax.xml.crypto.dsig.spec
+javax.xml.datatype
+javax.xml.namespace
+javax.xml.parsers
+javax.xml.soap
+javax.xml.stream
+javax.xml.stream.events
+javax.xml.stream.util
+javax.xml.transform
+javax.xml.transform.dom
+javax.xml.transform.sax
+javax.xml.transform.stax
+javax.xml.transform.stream
+javax.xml.validation
+javax.xml.ws
+javax.xml.ws.handler
+javax.xml.ws.handler.soap
+javax.xml.ws.http
+javax.xml.ws.soap
+javax.xml.ws.spi
+javax.xml.ws.spi.http
+javax.xml.ws.wsaddressing
+javax.xml.xpath
+jdk
+jdk.internal.cmm
+jdk.internal.dynalink
+jdk.internal.dynalink.beans
+jdk.internal.dynalink.linker
+jdk.internal.dynalink.support
+jdk.internal.instrumentation
+jdk.internal.org.objectweb.asm
+jdk.internal.org.objectweb.asm.commons
+jdk.internal.org.objectweb.asm.signature
+jdk.internal.org.objectweb.asm.tree
+jdk.internal.org.objectweb.asm.tree.analysis
+jdk.internal.org.objectweb.asm.util
+jdk.internal.org.xml.sax
+jdk.internal.org.xml.sax.helpers
+jdk.internal.util.xml
+jdk.internal.util.xml.impl
+jdk.jfr.events
+jdk.management.cmm
+jdk.management.resource
+jdk.management.resource.internal
+jdk.management.resource.internal.inst
+jdk.nashorn.api.scripting
+jdk.nashorn.internal
+jdk.nashorn.internal.codegen
+jdk.nashorn.internal.codegen.types
+jdk.nashorn.internal.ir
+jdk.nashorn.internal.ir.annotations
+jdk.nashorn.internal.ir.debug
+jdk.nashorn.internal.ir.visitor
+jdk.nashorn.internal.lookup
+jdk.nashorn.internal.objects
+jdk.nashorn.internal.objects.annotations
+jdk.nashorn.internal.parser
+jdk.nashorn.internal.runtime
+jdk.nashorn.internal.runtime.arrays
+jdk.nashorn.internal.runtime.events
+jdk.nashorn.internal.runtime.linker
+jdk.nashorn.internal.runtime.logging
+jdk.nashorn.internal.runtime.options
+jdk.nashorn.internal.runtime.regexp
+jdk.nashorn.internal.runtime.regexp.joni
+jdk.nashorn.internal.runtime.regexp.joni.ast
+jdk.nashorn.internal.runtime.regexp.joni.constants
+jdk.nashorn.internal.runtime.regexp.joni.encoding
+jdk.nashorn.internal.runtime.regexp.joni.exception
+jdk.nashorn.internal.scripts
+jdk.nashorn.tools
+jdk.net
+netscape.javascript
+oracle.jrockit.jfr
+oracle.jrockit.jfr.events
+oracle.jrockit.jfr.jdkevents
+oracle.jrockit.jfr.jdkevents.throwabletransform
+oracle.jrockit.jfr.openmbean
+oracle.jrockit.jfr.parser
+oracle.jrockit.jfr.settings
+oracle.jrockit.jfr.tools
+org.ietf.jgss
+org.jcp.xml.dsig.internal
+org.jcp.xml.dsig.internal.dom
+org.omg.CORBA
+org.omg.CORBA.DynAnyPackage
+org.omg.CORBA.ORBPackage
+org.omg.CORBA.TypeCodePackage
+org.omg.CORBA.portable
+org.omg.CORBA_2_3
+org.omg.CORBA_2_3.portable
+org.omg.CosNaming
+org.omg.CosNaming.NamingContextExtPackage
+org.omg.CosNaming.NamingContextPackage
+org.omg.Dynamic
+org.omg.DynamicAny
+org.omg.DynamicAny.DynAnyFactoryPackage
+org.omg.DynamicAny.DynAnyPackage
+org.omg.IOP
+org.omg.IOP.CodecFactoryPackage
+org.omg.IOP.CodecPackage
+org.omg.Messaging
+org.omg.PortableInterceptor
+org.omg.PortableInterceptor.ORBInitInfoPackage
+org.omg.PortableServer
+org.omg.PortableServer.CurrentPackage
+org.omg.PortableServer.POAManagerPackage
+org.omg.PortableServer.POAPackage
+org.omg.PortableServer.ServantLocatorPackage
+org.omg.PortableServer.portable
+org.omg.SendingContext
+org.omg.stub.java.rmi
+org.omg.stub.javax.management.remote.rmi
+org.relaxng.datatype
+org.relaxng.datatype.helpers
+org.w3c.dom
+org.w3c.dom.bootstrap
+org.w3c.dom.css
+org.w3c.dom.events
+org.w3c.dom.html
+org.w3c.dom.ls
+org.w3c.dom.ranges
+org.w3c.dom.stylesheets
+org.w3c.dom.traversal
+org.w3c.dom.views
+org.w3c.dom.xpath
+org.xml.sax
+org.xml.sax.ext
+org.xml.sax.helpers
+sun.applet
+sun.applet.resources
+sun.audio
+sun.awt
+sun.awt.X11
+sun.awt.datatransfer
+sun.awt.dnd
+sun.awt.event
+sun.awt.geom
+sun.awt.im
+sun.awt.image
+sun.awt.image.codec
+sun.awt.motif
+sun.awt.resources
+sun.awt.shell
+sun.awt.util
+sun.awt.windows
+sun.corba
+sun.dc
+sun.dc.path
+sun.dc.pr
+sun.font
+sun.instrument
+sun.invoke
+sun.invoke.empty
+sun.invoke.util
+sun.io
+sun.java2d
+sun.java2d.cmm
+sun.java2d.cmm.kcms
+sun.java2d.cmm.lcms
+sun.java2d.d3d
+sun.java2d.jules
+sun.java2d.loops
+sun.java2d.opengl
+sun.java2d.pipe
+sun.java2d.pipe.hw
+sun.java2d.pisces
+sun.java2d.windows
+sun.java2d.x11
+sun.java2d.xr
+sun.jvmstat.monitor
+sun.jvmstat.monitor.event
+sun.jvmstat.monitor.remote
+sun.jvmstat.perfdata.monitor
+sun.jvmstat.perfdata.monitor.protocol.file
+sun.jvmstat.perfdata.monitor.protocol.local
+sun.jvmstat.perfdata.monitor.protocol.rmi
+sun.jvmstat.perfdata.monitor.v1_0
+sun.jvmstat.perfdata.monitor.v2_0
+sun.launcher
+sun.launcher.resources
+sun.lwawt
+sun.lwawt.macosx
+sun.management
+sun.management.counter
+sun.management.counter.perf
+sun.management.jdp
+sun.management.jmxremote
+sun.management.resources
+sun.management.snmp
+sun.management.snmp.jvminstr
+sun.management.snmp.jvmmib
+sun.management.snmp.util
+sun.misc
+sun.misc.resources
+sun.net
+sun.net.dns
+sun.net.ftp
+sun.net.ftp.impl
+sun.net.httpserver
+sun.net.idn
+sun.net.sdp
+sun.net.smtp
+sun.net.spi
+sun.net.spi.nameservice
+sun.net.spi.nameservice.dns
+sun.net.util
+sun.net.www
+sun.net.www.content.audio
+sun.net.www.content.image
+sun.net.www.content.text
+sun.net.www.http
+sun.net.www.protocol.file
+sun.net.www.protocol.ftp
+sun.net.www.protocol.http
+sun.net.www.protocol.http.logging
+sun.net.www.protocol.http.ntlm
+sun.net.www.protocol.http.spnego
+sun.net.www.protocol.https
+sun.net.www.protocol.jar
+sun.net.www.protocol.mailto
+sun.net.www.protocol.netdoc
+sun.nio
+sun.nio.ch
+sun.nio.ch.sctp
+sun.nio.cs
+sun.nio.cs.ext
+sun.nio.fs
+sun.print
+sun.print.resources
+sun.reflect
+sun.reflect.annotation
+sun.reflect.generics.factory
+sun.reflect.generics.parser
+sun.reflect.generics.reflectiveObjects
+sun.reflect.generics.repository
+sun.reflect.generics.scope
+sun.reflect.generics.tree
+sun.reflect.generics.visitor
+sun.reflect.misc
+sun.rmi.log
+sun.rmi.registry
+sun.rmi.rmic
+sun.rmi.rmic.iiop
+sun.rmi.rmic.newrmic
+sun.rmi.rmic.newrmic.jrmp
+sun.rmi.runtime
+sun.rmi.server
+sun.rmi.transport
+sun.rmi.transport.proxy
+sun.rmi.transport.tcp
+sun.security.acl
+sun.security.action
+sun.security.ec
+sun.security.internal.interfaces
+sun.security.internal.spec
+sun.security.jca
+sun.security.jgss
+sun.security.jgss.krb5
+sun.security.jgss.spi
+sun.security.jgss.spnego
+sun.security.jgss.wrapper
+sun.security.krb5
+sun.security.krb5.internal
+sun.security.krb5.internal.ccache
+sun.security.krb5.internal.crypto
+sun.security.krb5.internal.crypto.dk
+sun.security.krb5.internal.ktab
+sun.security.krb5.internal.rcache
+sun.security.krb5.internal.tools
+sun.security.krb5.internal.util
+sun.security.mscapi
+sun.security.pkcs
+sun.security.pkcs10
+sun.security.pkcs11
+sun.security.pkcs11.wrapper
+sun.security.pkcs12
+sun.security.provider
+sun.security.provider.certpath
+sun.security.provider.certpath.ldap
+sun.security.provider.certpath.ssl
+sun.security.rsa
+sun.security.smartcardio
+sun.security.ssl
+sun.security.ssl.krb5
+sun.security.timestamp
+sun.security.tools
+sun.security.tools.jarsigner
+sun.security.tools.keytool
+sun.security.tools.policytool
+sun.security.util
+sun.security.validator
+sun.security.x509
+sun.swing
+sun.swing.icon
+sun.swing.plaf
+sun.swing.plaf.synth
+sun.swing.plaf.windows
+sun.swing.table
+sun.swing.text
+sun.swing.text.html
+sun.text
+sun.text.bidi
+sun.text.normalizer
+sun.text.resources
+sun.text.resources.en
+sun.tools.asm
+sun.tools.attach
+sun.tools.jar
+sun.tools.jar.resources
+sun.tools.java
+sun.tools.javac
+sun.tools.jcmd
+sun.tools.jconsole
+sun.tools.jconsole.inspector
+sun.tools.jinfo
+sun.tools.jmap
+sun.tools.jps
+sun.tools.jstack
+sun.tools.jstat
+sun.tools.jstatd
+sun.tools.native2ascii
+sun.tools.native2ascii.resources
+sun.tools.serialver
+sun.tools.tree
+sun.tools.util
+sun.tracing
+sun.tracing.dtrace
+sun.usagetracker
+sun.util
+sun.util.calendar
+sun.util.cldr
+sun.util.locale
+sun.util.locale.provider
+sun.util.logging
+sun.util.logging.resources
+sun.util.resources
+sun.util.resources.en
+sun.util.spi
+sun.util.xml
diff --git a/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java b/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java
index c547836bc1d..ad9925a1a21 100644
--- a/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java
+++ b/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java
@@ -92,7 +92,6 @@ import jdk.internal.misc.VM;
import jdk.internal.module.ModuleBootstrap;
import jdk.internal.module.Modules;
-
public final class LauncherHelper {
// No instantiation
@@ -492,16 +491,16 @@ public final class LauncherHelper {
if (s.length == 2) {
String mn = s[0];
String pn = s[1];
-
- ModuleLayer.boot().findModule(mn).ifPresent(m -> {
- if (m.getDescriptor().packages().contains(pn)) {
+ ModuleLayer.boot()
+ .findModule(mn)
+ .filter(m -> m.getDescriptor().packages().contains(pn))
+ .ifPresent(m -> {
if (open) {
Modules.addOpensToAllUnnamed(m, pn);
} else {
Modules.addExportsToAllUnnamed(m, pn);
}
- }
- });
+ });
}
}
}
@@ -618,7 +617,7 @@ public final class LauncherHelper {
}
} catch (LinkageError le) {
abort(null, "java.launcher.module.error3", mainClass, m.getName(),
- le.getClass().getName() + ": " + le.getLocalizedMessage());
+ le.getClass().getName() + ": " + le.getLocalizedMessage());
}
if (c == null) {
abort(null, "java.launcher.module.error2", mainClass, mainModule);
@@ -719,7 +718,7 @@ public final class LauncherHelper {
mainClass.getName(), mainClass.getModule(),
e.getClass().getName(), e.getLocalizedMessage());
} else {
- abort(e,"java.launcher.cls.error7", mainClass.getName(),
+ abort(e, "java.launcher.cls.error7", mainClass.getName(),
e.getClass().getName(), e.getLocalizedMessage());
}
}
diff --git a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties
index 40b549b9f75..922f4d95a31 100644
--- a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties
+++ b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties
@@ -59,7 +59,7 @@ java.launcher.opt.footer = \
\ ALL-MODULE-PATH.\n\
\ --list-modules\n\
\ list observable modules and exit\n\
-\ --d \n\
+\ -d \n\
\ --describe-module \n\
\ describe a module and exit\n\
\ --dry-run create VM and load main class but do not execute main method.\n\
@@ -166,10 +166,11 @@ java.launcher.X.usage=\n\
\ --add-opens /=(,)*\n\
\ updates to open to\n\
\ , regardless of module declaration.\n\
-\ --permit-illegal-access\n\
-\ permit illegal access to members of types in named modules\n\
-\ by code in unnamed modules. This compatibility option will\n\
-\ be removed in the next release.\n\
+\ --illegal-access=\n\
+\ permit or deny access to members of types in named modules\n\
+\ by code in unnamed modules.\n\
+\ is one of "deny", "permit", "warn", or "debug"\n\
+\ This option will be removed in a future release.\n\
\ --limit-modules [,...]\n\
\ limit the universe of observable modules\n\
\ --patch-module =({0})*\n\
diff --git a/jdk/src/java.base/share/native/include/jvm.h b/jdk/src/java.base/share/native/include/jvm.h
index c90a557de8b..de90fd99dae 100644
--- a/jdk/src/java.base/share/native/include/jvm.h
+++ b/jdk/src/java.base/share/native/include/jvm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -455,14 +455,6 @@ JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, const char* package)
JNIEXPORT void JNICALL
JVM_AddReadsModule(JNIEnv *env, jobject from_module, jobject source_module);
-/*
- * Add a package to a module.
- * module: module that will contain the package
- * package: package to add to the module
- */
-JNIEXPORT void JNICALL
-JVM_AddModulePackage(JNIEnv* env, jobject module, const char* package);
-
/*
* Reflection support functions
*/
diff --git a/jdk/src/java.base/share/native/libjava/Module.c b/jdk/src/java.base/share/native/libjava/Module.c
index f396b8dfc49..f1c13ad0cff 100644
--- a/jdk/src/java.base/share/native/libjava/Module.c
+++ b/jdk/src/java.base/share/native/libjava/Module.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -176,23 +176,3 @@ Java_java_lang_Module_addExportsToAllUnnamed0(JNIEnv *env, jclass cls,
}
}
}
-
-JNIEXPORT void JNICALL
-Java_java_lang_Module_addPackage0(JNIEnv *env, jclass cls, jobject m, jstring pkg)
-{
- char buf[128];
- char* pkg_name;
-
- if (pkg == NULL) {
- JNU_ThrowNullPointerException(env, "package is null");
- return;
- }
-
- pkg_name = GetInternalPackageName(env, pkg, buf, (jsize)sizeof(buf));
- if (pkg_name != NULL) {
- JVM_AddModulePackage(env, m, pkg_name);
- if (pkg_name != buf) {
- free(pkg_name);
- }
- }
-}
diff --git a/jdk/src/java.instrument/share/classes/java/lang/instrument/package-info.java b/jdk/src/java.instrument/share/classes/java/lang/instrument/package-info.java
new file mode 100644
index 00000000000..9519bf21948
--- /dev/null
+++ b/jdk/src/java.instrument/share/classes/java/lang/instrument/package-info.java
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2003, 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the Classpath exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Copyright 2003 Wily Technology, Inc.
+ */
+
+/**
+ * Provides services that allow Java programming language agents to instrument
+ * programs running on the JVM. The mechanism for instrumentation is modification
+ * of the byte-codes of methods.
+ *
+ * An agent is deployed as a JAR file. An attribute in the JAR file manifest
+ * specifies the agent class which will be loaded to start the agent. Agents can
+ * be started in several ways:
+ *
+ *
+ * For implementations that support a command-line interface, an agent
+ * can be started by specifying an option on the command-line.
+ *
+ * An implementation may support a mechanism to start agents some time
+ * after the VM has started. For example, an implementation may provide a
+ * mechanism that allows a tool to attach to a running application, and
+ * initiate the loading of the tool's agent into the running application.
+ *
+ * An agent may be packaged with an application in an executable JAR
+ * file.
+ *
+ *
+ * Each of these ways to start an agent is described below.
+ *
+ *
+ *
Starting an Agent from the Command-Line Interface
+ *
+ * Where an implementation provides a means to start agents from the
+ * command-line interface, an agent is started by adding the following option
+ * to the command-line:
+ *
+ *
{@code
+ * -javaagent:[=]
+ * }
+ *
+ * where {@code } is the path to the agent JAR file and
+ * {@code } is the agent options.
+ *
+ * The manifest of the agent JAR file must contain the attribute {@code
+ * Premain-Class} in its main manifest. The value of this attribute is the
+ * name of the agent class. The agent class must implement a public
+ * static {@code premain} method similar in principle to the {@code main}
+ * application entry point. After the Java Virtual Machine (JVM) has
+ * initialized, the {@code premain} method will be called, then the real
+ * application {@code main} method. The {@code premain} method must return
+ * in order for the startup to proceed.
+ *
+ *
The {@code premain} method has one of two possible signatures. The
+ * JVM first attempts to invoke the following method on the agent class:
+ *
+ *
{@code
+ * public static void premain(String agentArgs, Instrumentation inst)
+ * }
+ *
+ * If the agent class does not implement this method then the JVM will
+ * attempt to invoke:
+ *
{@code
+ * public static void premain(String agentArgs)
+ * }
+
+ * The agent class may also have an {@code agentmain} method for use when
+ * the agent is started after VM startup (see below). When the agent is started
+ * using a command-line option, the {@code agentmain} method is not invoked.
+ *
+ *
Each agent is passed its agent options via the {@code agentArgs} parameter.
+ * The agent options are passed as a single string, any additional parsing
+ * should be performed by the agent itself.
+ *
+ *
If the agent cannot be started (for example, because the agent class
+ * cannot be loaded, or because the agent class does not have an appropriate
+ * {@code premain} method), the JVM will abort. If a {@code premain} method
+ * throws an uncaught exception, the JVM will abort.
+ *
+ *
An implementation is not required to provide a way to start agents
+ * from the command-line interface. When it does, then it supports the
+ * {@code -javaagent} option as specified above. The {@code -javaagent} option
+ * may be used multiple times on the same command-line, thus starting multiple
+ * agents. The {@code premain} methods will be called in the order that the
+ * agents are specified on the command line. More than one agent may use the
+ * same {@code }.
+ *
+ *
There are no modeling restrictions on what the agent {@code premain}
+ * method may do. Anything application {@code main} can do, including creating
+ * threads, is legal from {@code premain}.
+ *
+ *
+ *
Starting an Agent After VM Startup
+ *
+ * An implementation may provide a mechanism to start agents sometime after
+ * the the VM has started. The details as to how this is initiated are
+ * implementation specific but typically the application has already started and
+ * its {@code main} method has already been invoked. In cases where an
+ * implementation supports the starting of agents after the VM has started the
+ * following applies:
+ *
+ *
+ *
+ * The manifest of the agent JAR must contain the attribute {@code
+ * Agent-Class} in its main manfiest. The value of this attribute is the name
+ * of the agent class.
+ *
+ * The agent class must implement a public static {@code agentmain}
+ * method.
+ *
+ *
+ *
+ * The {@code agentmain} method has one of two possible signatures. The JVM
+ * first attempts to invoke the following method on the agent class:
+ *
+ *
{@code
+ * public static void agentmain(String agentArgs, Instrumentation inst)
+ * }
+ *
+ * If the agent class does not implement this method then the JVM will
+ * attempt to invoke:
+ *
+ *
{@code
+ * public static void agentmain(String agentArgs)
+ * }
+ *
+ * The agent class may also have a {@code premain} method for use when the
+ * agent is started using a command-line option. When the agent is started after
+ * VM startup the {@code premain} method is not invoked.
+ *
+ *
The agent is passed its agent options via the {@code agentArgs}
+ * parameter. The agent options are passed as a single string, any additional
+ * parsing should be performed by the agent itself.
+ *
+ *
The {@code agentmain} method should do any necessary initialization
+ * required to start the agent. When startup is complete the method should
+ * return. If the agent cannot be started (for example, because the agent class
+ * cannot be loaded, or because the agent class does not have a conformant
+ * {@code agentmain} method), the JVM will not abort. If the {@code agentmain}
+ * method throws an uncaught exception it will be ignored (but may be logged
+ * by the JVM for troubleshooting purposes).
+ *
+ *
+ *
Including an Agent in an Executable JAR file
+ *
+ * The JAR File Specification defines manifest attributes for standalone
+ * applications that are packaged as executable JAR files. If an
+ * implementation supports a mechanism to start an application as an executable
+ * JAR then the main manifest may include the {@code Launcher-Agent-Class}
+ * attribute to specify the class name of an agent to start before the application
+ * {@code main} method is invoked. The Java virtual machine attempts to
+ * invoke the following method on the agent class:
+ *
+ *
{@code
+ * public static void agentmain(String agentArgs, Instrumentation inst)
+ * }
+ *
+ * If the agent class does not implement this method then the JVM will
+ * attempt to invoke:
+ *
+ *
{@code
+ * public static void agentmain(String agentArgs)
+ * }
+ *
+ * The value of the {@code agentArgs} parameter is always the empty string.
+ *
+ *
The {@code agentmain} method should do any necessary initialization
+ * required to start the agent and return. If the agent cannot be started, for
+ * example the agent class cannot be loaded, the agent class does not define a
+ * conformant {@code agentmain} method, or the {@code agentmain} method throws
+ * an uncaught exception or error, the JVM will abort.
+ *
+ *
+ *
Loading agent classes and the modules/classes available to the agent
+ * class
+ *
+ * Classes loaded from the agent JAR file are loaded by the
+ * {@linkplain ClassLoader#getSystemClassLoader() system class loader} and are
+ * members of the system class loader's {@linkplain ClassLoader#getUnnamedModule()
+ * unnamed module}. The system class loader typically defines the class containing
+ * the application {@code main} method too.
+ *
+ *
The classes visible to the agent class are the classes visible to the system
+ * class loader and minimally include:
+ *
+ *
+ *
+ * The classes in packages exported by the modules in the {@linkplain
+ * ModuleLayer#boot() boot layer}. Whether the boot layer contains all platform
+ * modules or not will depend on the initial module or how the application was
+ * started.
+ *
+ * The classes that can be defined by the system class loader (typically
+ * the class path) to be members of its unnamed module.
+ *
+ * Any classes that the agent arranges to be defined by the bootstrap
+ * class loader to be members of its unnamed module.
+ *
+ *
+ *
+ * If agent classes need to link to classes in platform (or other) modules
+ * that are not in the boot layer then the application may need to be started in
+ * a way that ensures that these modules are in the boot layer. In the JDK
+ * implementation for example, the {@code --add-modules} command line option can
+ * be used to add modules to the set of root modules to resolve at startup.
+ *
+ * Supporting classes that the agent arranges to be loaded by the bootstrap
+ * class loader (by means of {@link Instrumentation#appendToBootstrapClassLoaderSearch
+ * appendToBootstrapClassLoaderSearch} or the {@code Boot-Class-Path} attribute
+ * specified below), must link only to classes defined to the bootstrap class loader.
+ * There is no guarantee that all platform classes can be defined by the boot
+ * class loader.
+ *
+ *
If a custom system class loader is configured (by means of the system property
+ * {@code java.system.class.loader} as specified in the {@link
+ * ClassLoader#getSystemClassLoader() getSystemClassLoader} method) then it must
+ * define the {@code appendToClassPathForInstrumentation} method as specified in
+ * {@link Instrumentation#appendToSystemClassLoaderSearch appendToSystemClassLoaderSearch}.
+ * In other words, a custom system class loader must support the mechanism to
+ * add an agent JAR file to the system class loader search.
+ *
+ *
Manifest Attributes
+ *
+ * The following manifest attributes are defined for an agent JAR file:
+ *
+ *
+ *
+ * - {@code Premain-Class}
+ * - When an agent is specified at JVM launch time this attribute specifies
+ * the agent class. That is, the class containing the {@code premain} method.
+ * When an agent is specified at JVM launch time this attribute is required. If
+ * the attribute is not present the JVM will abort. Note: this is a class name,
+ * not a file name or path.
+ *
+ * - {@code Agent-Class}
+ * - If an implementation supports a mechanism to start agents sometime after
+ * the VM has started then this attribute specifies the agent class. That is,
+ * the class containing the {@code agentmain} method. This attribute is required
+ * if it is not present the agent will not be started. Note: this is a class name,
+ * not a file name or path.
+ *
+ * - {@code Launcher-Agent-Class}
+ * - If an implementation supports a mechanism to start an application as an
+ * executable JAR then the main manifest may include this attribute to specify
+ * the class name of an agent to start before the application {@code main}
+ * method is invoked.
+ *
+ * - {@code Boot-Class-Path}
+ * - A list of paths to be searched by the bootstrap class loader. Paths
+ * represent directories or libraries (commonly referred to as JAR or zip
+ * libraries on many platforms). These paths are searched by the bootstrap class
+ * loader after the platform specific mechanisms of locating a class have failed.
+ * Paths are searched in the order listed. Paths in the list are separated by one
+ * or more spaces. A path takes the syntax of the path component of a hierarchical
+ * URI. The path is absolute if it begins with a slash character ('/'), otherwise
+ * it is relative. A relative path is resolved against the absolute path of the
+ * agent JAR file. Malformed and non-existent paths are ignored. When an agent is
+ * started sometime after the VM has started then paths that do not represent a
+ * JAR file are ignored. This attribute is optional.
+ *
+ * - {@code Can-Redefine-Classes}
+ * - Boolean ({@code true} or {@code false}, case irrelevant). Is the ability
+ * to redefine classes needed by this agent. Values other than {@code true} are
+ * considered {@code false}. This attribute is optional, the default is {@code
+ * false}.
+ *
+ * - {@code Can-Retransform-Classes}
+ * - Boolean ({@code true} or {@code false}, case irrelevant). Is the ability
+ * to retransform classes needed by this agent. Values other than {@code true}
+ * are considered {@code false}. This attribute is optional, the default is
+ * {@code false}.
+ *
+ * - {@code Can-Set-Native-Method-Prefix}
+ * - Boolean ({@code true} or {@code false}, case irrelevant). Is the ability
+ * to set native method prefix needed by this agent. Values other than {@code
+ * true} are considered {@code false}. This attribute is optional, the default
+ * is {@code false}.
+ *
+ *
+ *
+ * An agent JAR file may have both the {@code Premain-Class} and {@code
+ * Agent-Class} attributes present in the manifest. When the agent is started
+ * on the command-line using the {@code -javaagent} option then the {@code
+ * Premain-Class} attribute specifies the name of the agent class and the {@code
+ * Agent-Class} attribute is ignored. Similarly, if the agent is started sometime
+ * after the VM has started, then the {@code Agent-Class} attribute specifies
+ * the name of the agent class (the value of {@code Premain-Class} attribute is
+ * ignored).
+ *
+ *
+ *
Instrumenting code in modules
+ *
+ * As an aid to agents that deploy supporting classes on the search path of
+ * the bootstrap class loader, or the search path of the class loader that loads
+ * the main agent class, the Java virtual machine arranges for the module of
+ * transformed classes to read the unnamed module of both class loaders.
+ *
+ * @since 1.5
+ * @revised 1.6
+ * @revised 9
+ */
+
+package java.lang.instrument;
\ No newline at end of file
diff --git a/jdk/src/java.instrument/share/classes/java/lang/instrument/package.html b/jdk/src/java.instrument/share/classes/java/lang/instrument/package.html
deleted file mode 100644
index 5c40a234c91..00000000000
--- a/jdk/src/java.instrument/share/classes/java/lang/instrument/package.html
+++ /dev/null
@@ -1,356 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-Provides services that allow Java programming language agents to instrument programs running on the JVM.
-The mechanism for instrumentation is modification of the byte-codes of methods.
-
-Package Specification
-
-
-An agent is deployed as a JAR file. An attribute in the JAR file manifest specifies the
-agent class which will be loaded to start the agent. For implementations that support a command-line
-interface, an agent is started by specifying an option on the command-line.
-Implementations may also support a mechanism to start agents some time after the VM has
-started. For example, an implementation may provide a mechanism that allows a tool to
-attach to a running application, and initiate the loading of the tool's agent into
-the running application. The details as to how the load is initiated, is implementation
-dependent.
-
-
Command-Line Interface
-
-
-An implementation is not required to provide a way to start agents from the
-command-line interface. On implementations that do provide a way to start agents
-from the command-line interface, an agent is started by adding this option to
-the command-line:
-
--javaagent:
jarpath[=
options]
-
-jarpath is the path to the agent JAR file.
-options is the agent options.
-This switch may be used multiple times on the same command-line,
-thus creating multiple agents.
-More than one agent may use the same jarpath.
-An agent JAR file must conform to the JAR file specification.
-
-
-The manifest of the agent JAR file must contain the attribute Premain-Class
. The
-value of this attribute is the name of the agent class. The agent class must implement a
-public static premain
method similar in principle to the main
application
-entry point. After the Java Virtual Machine (JVM) has initialized, each premain
method
-will be called in the order the agents were specified, then the real application
-main
method will be called.
-Each premain
method must return in order for the startup sequence to proceed.
-
-
-The premain
method has one of two possible signatures. The JVM first attempts to
-invoke the following method on the agent class:
-
-
-public static void
-premain(String agentArgs, Instrumentation inst);
-
-
-
-
-If the agent class does not implement this method then the JVM will attempt to invoke:
-
-
-public static void
-premain(String agentArgs);
-
-
-
-
-The agent class may also have an agentmain
method for use when the agent is started
-after VM startup. When the agent is started using a command-line option, the agentmain
-method is not invoked.
-
-
-
-The agent class will be loaded by the system class loader
-(see {@link java.lang.ClassLoader#getSystemClassLoader ClassLoader.getSystemClassLoader}). This is
-the class loader which typically loads the class containing the application main
method.
-The system class loader must support a mechanism to add an agent JAR file to the system class path.
-If it is a custom system class loader then it must define the
-appendToClassPathForInstrumentation
method as specified in
-{@link Instrumentation#appendToSystemClassLoaderSearch appendToSystemClassLoaderSearch}.
-The premain
methods will be run under the same security and classloader
-rules as the application main
method.
-There are no modeling restrictions on what the agent premain
method may do.
-Anything application main
can do, including creating threads, is legal from
-premain
.
-
-
-
-Each agent is passed its agent options via the agentArgs
parameter.
-The agent options are passed as a single string,
-any additional parsing should be performed by the agent itself.
-
-
-If the agent cannot be resolved
-(for example, because the agent class cannot be loaded,
-or because the agent class does not have an appropriate premain
method), the JVM will abort.
-If a premain
method throws an uncaught exception, the JVM will abort.
-
-
-
Starting Agents After VM Startup
-
-
-An implementation may provide a mechanism to start agents sometime after the
-the VM has started. The details as to how this is initiated are implementation
-specific but typically the application has already started and its
-main
method has already been invoked. In cases where an implementation
-supports the starting of agents after the VM has started the following applies:
-
-
- The manifest of the agent JAR must contain the attribute Agent-Class
.
- The value of this attribute is the name of the agent class.
-
- The agent class must implement a public static agentmain
method.
-
- The system class loader (
- {@link java.lang.ClassLoader#getSystemClassLoader ClassLoader.getSystemClassLoader}) must
- support a mechanism to add an agent JAR file to the system class path.
- If it is a custom system class loader then it must define the
- appendToClassPathForInstrumentation
method as specified in
- {@link Instrumentation#appendToSystemClassLoaderSearch appendToSystemClassLoaderSearch}.
-
-
-
-The agent JAR is appended to the system class path. This is the class loader that typically loads
-the class containing the application main
method. The agent class is loaded and the
-JVM attempts to invoke the agentmain
method. The JVM first attempts to invoke
-the following method on the agent class:
-
-
-public static void
-agentmain(String agentArgs, Instrumentation inst);
-
-
-
-
-If the agent class does not implement this method then the JVM will attempt to invoke:
-
-
-public static void
-agentmain(String agentArgs);
-
-
-
-
-The agent class may also have an premain
method for use when the agent is started
-using a command-line option. When the agent is started after VM startup the premain
-method is not invoked.
-
-
-
-The agent is passed its agent options via the agentArgs
parameter.
-The agent options are passed as a single string,
-any additional parsing should be performed by the agent itself.
-
-
-The agentmain
method should do any necessary initialization
-required to start the agent. When startup is complete the method should
-return. If the agent cannot be started
-(for example, because the agent class cannot be loaded,
-or because the agent class does not have a conformant agentmain
method), the JVM will
-not abort. If the agentmain
method throws an uncaught exception it will be ignored.
-
-
-
Deploying Agents in Executable JAR file
-
-The JAR File Specification defines manifest attributes for standalone applications that are
-bundled as executable JAR files. If an implementation supports a mechanism to start
-an application as an executable JAR then the main manifest may include the
-Launcher-Agent-Class
attribute to specify the class name
-of an agent to start before the application main
method is invoked. The Java
-virtual machine attempts to invoke the following method on the agent class:
-
-
- public static void
- agentmain(String agentArgs, Instrumentation inst);
-
-
-
-
-If the agent class does not implement this method then the JVM will attempt to invoke:
-
-
- public static void
- agentmain(String agentArgs);
-
-
-
-
-The value of the agentArgs
parameter is always the empty string.
-
-
-The agentmain
method should do any necessary initialization
-required to start the agent and return. If the agent cannot be started, for
-example the agent class cannot be loaded, the agent class does not define a
-conformant agentmain
method, or the agentmain
method
-throws an uncaught exception or error, the JVM will abort.
-
-
-
Visibility
-
-The types visible to the agent class are the types visible to the system class
-loader. They minimally include the types in packages exported by
-java.base and
-java.instrument.
-Whether all {@linkplain ClassLoader#getPlatformClassLoader() platform classes}
-are visible or not will depend on the initial module or application.
-
-
-Supporting classes that the agent makes visible to the bootstrap class loader
-(by means of {@link Instrumentation#appendToBootstrapClassLoaderSearch
-appendToBootstrapClassLoaderSearch} or the Boot-Class-Path
attribute
-specified below) can only link to types defined to the bootstrap class loader.
-There is no guarantee that all platform classes are visible to the boot class
-loader.
-
-
-
Manifest Attributes
-
-The following manifest attributes are defined for an agent JAR file:
-
-
-Premain-Class
--
- When an agent is specified at JVM launch time this attribute
- specifies the agent class.
- That is, the class containing the
premain
method.
- When an agent is specified at JVM launch time this attribute
- is required. If the attribute is not present the JVM will abort.
- Note: this is a class name, not a file name or path.
-
-Agent-Class
--
- If an implementation supports a mechanism to start agents
- sometime after the VM has started then this attribute specifies
- the agent class.
- That is, the class containing the
agentmain
method.
- This attribute is required, if it is not present the agent
- will not be started.
- Note: this is a class name, not a file name or path.
-
-Launcher-Agent-Class
--
- If an implementation supports a mechanism to start an application
- as an executable JAR then the main manifest may include this
- attribute to specify the class name of an agent to start before the
- application
main
method is invoked.
-
-Boot-Class-Path
--
- A list of paths to be searched by the bootstrap class
- loader. Paths represent directories or libraries
- (commonly referred to as JAR or zip libraries on
- many platforms).
- These paths are searched by the
- bootstrap class loader after the platform specific
- mechanisms of locating a class have failed.
- Paths are searched in the order listed.
- Paths in the list are separated by one or more spaces.
- A path takes the syntax of the path component of a
- hierarchical URI. The path is
- absolute if it begins with a slash character ('/'),
- otherwise it is relative. A relative path is resolved
- against the absolute path of the agent JAR file.
- Malformed and non-existent paths are ignored.
- When an agent is started sometime after the VM has
- started then paths that do not represent a JAR file
- are ignored.
- This attribute is optional.
-
-Can-Redefine-Classes
--
- Boolean (
true
or false
, case irrelevant).
- Is the ability to redefine classes
- needed by this agent.
- Values other than true
are considered false
.
- This attribute is optional, the default is false
.
-
-Can-Retransform-Classes
--
- Boolean (
true
or false
, case irrelevant).
- Is the ability to retransform classes
- needed by this agent.
- Values other than true
are considered false
.
- This attribute is optional, the default is false
.
-
-Can-Set-Native-Method-Prefix
--
- Boolean (
true
or false
, case irrelevant).
- Is the ability to set native method prefix needed by this agent.
- Values other than true
are considered false
.
- This attribute is optional, the default is false
.
-
-
-
-
-
-An agent JAR file may have both the Premain-Class
and Agent-Class
-attributes present in the manifest. When the agent is started on the command-line using
-the -javaagent
option then the Premain-Class
attribute
-specifies the name of the agent class and the Agent-Class
attribute is
-ignored. Similarly, if the agent is started sometime after the VM has started, then
-the Agent-Class
attribute specifies the name of the agent class
-(the value of Premain-Class
attribute is ignored).
-
-
-
Instrumenting code in modules
-
-As an aid to agents that deploy supporting classes on the search path of the
-bootstrap class loader, or the search path of the class loader that loads
-the main agent class, the Java virtual machine arranges for the module of
-transformed classes to read the unnamed module of both class loaders.
-
-
-Related Documentation
-
-For tool documentation, please see:
-
-
-@since 1.5
-@revised 1.6
-
-
-
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java
index bdd8b42db8c..5e1e64e3939 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java
@@ -34,6 +34,10 @@ import java.lang.module.ModuleDescriptor.Opens;
import java.lang.module.ModuleDescriptor.Provides;
import java.lang.module.ModuleDescriptor.Requires;
import java.lang.module.ModuleDescriptor.Version;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReader;
+import java.lang.module.ModuleReference;
+import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
@@ -41,13 +45,17 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.IntSupplier;
+import java.util.stream.Collectors;
import jdk.internal.module.Checks;
import jdk.internal.module.ClassFileAttributes;
import jdk.internal.module.ClassFileConstants;
+import jdk.internal.module.IllegalAccessMaps;
import jdk.internal.module.ModuleHashes;
import jdk.internal.module.ModuleInfo.Attributes;
import jdk.internal.module.ModuleInfoExtender;
@@ -601,6 +609,10 @@ public final class SystemModulesPlugin implements Plugin {
// generate SystemModules::moduleResolutions
genModuleResolutionsMethod();
+ // generate SystemModules::concealedPackagesToOpen and
+ // SystemModules::exportedPackagesToOpen
+ genXXXPackagesToOpenMethods();
+
return cw;
}
@@ -733,6 +745,96 @@ public final class SystemModulesPlugin implements Plugin {
mresmv.visitEnd();
}
+ /**
+ * Generate SystemModules::concealedPackagesToOpen and
+ * SystemModules::exportedPackagesToOpen methods.
+ */
+ private void genXXXPackagesToOpenMethods() {
+ List descriptors = moduleInfos.stream()
+ .map(ModuleInfo::descriptor)
+ .collect(Collectors.toList());
+ ModuleFinder finder = finderOf(descriptors);
+ IllegalAccessMaps maps = IllegalAccessMaps.generate(finder);
+ generate("concealedPackagesToOpen", maps.concealedPackagesToOpen());
+ generate("exportedPackagesToOpen", maps.exportedPackagesToOpen());
+ }
+
+ /**
+ * Generate SystemModules:XXXPackagesToOpen
+ */
+ private void generate(String methodName, Map> map) {
+ // Map> XXXPackagesToOpen()
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC+ACC_STATIC,
+ methodName,
+ "()Ljava/util/Map;",
+ "()Ljava/util/Map;",
+ null);
+ mv.visitCode();
+
+ // new Map$Entry[moduleCount]
+ pushInt(mv, map.size());
+ mv.visitTypeInsn(ANEWARRAY, "java/util/Map$Entry");
+
+ int index = 0;
+ for (Map.Entry> e : map.entrySet()) {
+ String moduleName = e.getKey();
+ Set packages = e.getValue();
+ int packageCount = packages.size();
+
+ mv.visitInsn(DUP);
+ pushInt(mv, index);
+ mv.visitLdcInsn(moduleName);
+
+ // use Set.of(Object[]) when there are more than 2 packages
+ // use Set.of(Object) or Set.of(Object, Object) when fewer packages
+ if (packageCount > 2) {
+ pushInt(mv, packageCount);
+ mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
+ int i = 0;
+ for (String pn : packages) {
+ mv.visitInsn(DUP);
+ pushInt(mv, i);
+ mv.visitLdcInsn(pn);
+ mv.visitInsn(AASTORE);
+ i++;
+ }
+ mv.visitMethodInsn(INVOKESTATIC,
+ "java/util/Set",
+ "of",
+ "([Ljava/lang/Object;)Ljava/util/Set;",
+ true);
+ } else {
+ StringBuilder sb = new StringBuilder("(");
+ for (String pn : packages) {
+ mv.visitLdcInsn(pn);
+ sb.append("Ljava/lang/Object;");
+ }
+ sb.append(")Ljava/util/Set;");
+ mv.visitMethodInsn(INVOKESTATIC,
+ "java/util/Set",
+ "of",
+ sb.toString(),
+ true);
+ }
+
+ String desc = "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/util/Map$Entry;";
+ mv.visitMethodInsn(INVOKESTATIC,
+ "java/util/Map",
+ "entry",
+ desc,
+ true);
+ mv.visitInsn(AASTORE);
+ index++;
+ }
+
+ // invoke Map.ofEntries(Map$Entry[])
+ mv.visitMethodInsn(INVOKESTATIC, "java/util/Map", "ofEntries",
+ "([Ljava/util/Map$Entry;)Ljava/util/Map;", true);
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+ }
+
public boolean isOverriddenClass(String path) {
return path.equals("/java.base/" + CLASSNAME + ".class");
}
@@ -1461,4 +1563,31 @@ public final class SystemModulesPlugin implements Plugin {
}
}
}
+
+ static ModuleFinder finderOf(Iterable descriptors) {
+ Map namesToReference = new HashMap<>();
+ for (ModuleDescriptor descriptor : descriptors) {
+ String name = descriptor.name();
+ URI uri = URI.create("module:/" + name);
+ ModuleReference mref = new ModuleReference(descriptor, uri) {
+ @Override
+ public ModuleReader open() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ namesToReference.putIfAbsent(name, mref);
+ }
+
+ return new ModuleFinder() {
+ @Override
+ public Optional find(String name) {
+ Objects.requireNonNull(name);
+ return Optional.ofNullable(namesToReference.get(name));
+ }
+ @Override
+ public Set findAll() {
+ return new HashSet<>(namesToReference.values());
+ }
+ };
+ }
}
diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt
index f045c7205c2..f73299c549e 100644
--- a/jdk/test/ProblemList.txt
+++ b/jdk/test/ProblemList.txt
@@ -295,6 +295,8 @@ sun/tools/jstat/jstatClassloadOutput1.sh 8173942 generic-
sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java 8057732 generic-all
+com/sun/tools/attach/StartManagementAgent.java 8179700 generic-all
+
############################################################################
# jdk_other
diff --git a/jdk/test/java/lang/ModuleLayer/BasicLayerTest.java b/jdk/test/java/lang/ModuleLayer/BasicLayerTest.java
index eb5eeb8a256..c3f4a1337b2 100644
--- a/jdk/test/java/lang/ModuleLayer/BasicLayerTest.java
+++ b/jdk/test/java/lang/ModuleLayer/BasicLayerTest.java
@@ -1054,8 +1054,6 @@ public class BasicLayerTest {
/**
* Attempt to create a layer with a module containing a "java" package.
- * This should only be allowed when the module is defined to the platform
- * class loader.
*/
@Test(dataProvider = "javaPackages")
public void testLayerWithJavaPackage(String mn, String pn) {
@@ -1067,7 +1065,6 @@ public class BasicLayerTest {
.resolve(finder, ModuleFinder.of(), Set.of(mn));
assertTrue(cf.modules().size() == 1);
- ClassLoader pcl = ClassLoader.getPlatformClassLoader();
ClassLoader scl = ClassLoader.getSystemClassLoader();
try {
@@ -1084,15 +1081,6 @@ public class BasicLayerTest {
ModuleLayer.boot().defineModulesWithManyLoaders(cf, scl);
assertTrue(false);
} catch (LayerInstantiationException e) { }
-
- // create layer with module defined to platform class loader
- ModuleLayer layer = ModuleLayer.boot().defineModules(cf, _mn -> pcl);
- Optional om = layer.findModule(mn);
- assertTrue(om.isPresent());
- Module foo = om.get();
- assertTrue(foo.getClassLoader() == pcl);
- assertTrue(foo.getPackages().size() == 1);
- assertTrue(foo.getPackages().iterator().next().equals(pn));
}
@@ -1101,8 +1089,7 @@ public class BasicLayerTest {
*/
@Test(expectedExceptions = { LayerInstantiationException.class })
public void testLayerWithBootLoader() {
- ModuleDescriptor descriptor = newBuilder("m1")
- .build();
+ ModuleDescriptor descriptor = newBuilder("m1").build();
ModuleFinder finder = ModuleUtils.finderOf(descriptor);
@@ -1115,6 +1102,25 @@ public class BasicLayerTest {
}
+ /**
+ * Attempt to create a layer with a module defined to the platform loader
+ */
+ @Test(expectedExceptions = { LayerInstantiationException.class })
+ public void testLayerWithPlatformLoader() {
+ ModuleDescriptor descriptor = newBuilder("m1").build();
+
+ ModuleFinder finder = ModuleUtils.finderOf(descriptor);
+
+ Configuration cf = ModuleLayer.boot()
+ .configuration()
+ .resolve(finder, ModuleFinder.of(), Set.of("m1"));
+ assertTrue(cf.modules().size() == 1);
+
+ ClassLoader cl = ClassLoader.getPlatformClassLoader();
+ ModuleLayer.boot().defineModules(cf, mn -> cl );
+ }
+
+
/**
* Parent of configuration != configuration of parent layer
*/
diff --git a/jdk/test/java/lang/ModuleLayer/LayerAndLoadersTest.java b/jdk/test/java/lang/ModuleLayer/LayerAndLoadersTest.java
index a67555a47b1..312defa7416 100644
--- a/jdk/test/java/lang/ModuleLayer/LayerAndLoadersTest.java
+++ b/jdk/test/java/lang/ModuleLayer/LayerAndLoadersTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -32,17 +32,21 @@
import java.io.IOException;
import java.io.InputStream;
+import java.io.UncheckedIOException;
import java.lang.module.Configuration;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
+import java.lang.module.ResolvedModule;
import java.lang.reflect.Method;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.ServiceLoader;
@@ -63,7 +67,6 @@ public class LayerAndLoadersTest {
@BeforeTest
public void setup() throws Exception {
-
// javac -d mods --module-source-path src src/**
assertTrue(CompilerUtils.compile(SRC_DIR, MODS_DIR,
"--module-source-path", SRC_DIR.toString()));
@@ -77,7 +80,6 @@ public class LayerAndLoadersTest {
* m1 requires m2 and m3
*/
public void testWithOneLoader() throws Exception {
-
Configuration cf = resolve("m1");
ClassLoader scl = ClassLoader.getSystemClassLoader();
@@ -95,7 +97,6 @@ public class LayerAndLoadersTest {
assertTrue(cl3 == cl1);
invoke(layer, "m1", "p.Main");
-
}
@@ -106,7 +107,6 @@ public class LayerAndLoadersTest {
* m1 requires m2 and m3
*/
public void testWithManyLoaders() throws Exception {
-
Configuration cf = resolve("m1");
ClassLoader scl = ClassLoader.getSystemClassLoader();
@@ -127,7 +127,6 @@ public class LayerAndLoadersTest {
assertTrue(cl3 != cl2);
invoke(layer, "m1", "p.Main");
-
}
@@ -141,7 +140,6 @@ public class LayerAndLoadersTest {
* m4 provides S with ...
*/
public void testServicesWithOneLoader() throws Exception {
-
Configuration cf = resolveAndBind("m1");
ClassLoader scl = ClassLoader.getSystemClassLoader();
@@ -168,7 +166,6 @@ public class LayerAndLoadersTest {
assertTrue(serviceType.isInstance(provider));
assertTrue(provider.getClass().getClassLoader() == cl1);
assertFalse(iter.hasNext());
-
}
@@ -182,7 +179,6 @@ public class LayerAndLoadersTest {
* m4 provides S with ...
*/
public void testServicesWithManyLoaders() throws Exception {
-
Configuration cf = resolveAndBind("m1");
ClassLoader scl = ClassLoader.getSystemClassLoader();
@@ -220,7 +216,6 @@ public class LayerAndLoadersTest {
assertTrue(provider.getClass().getClassLoader() == cl4);
assertFalse(iter.hasNext());
}
-
}
@@ -229,7 +224,6 @@ public class LayerAndLoadersTest {
* to the given parent class loader.
*/
public void testDelegationToParent() throws Exception {
-
Configuration cf = resolve("m1");
ClassLoader parent = this.getClass().getClassLoader();
@@ -250,7 +244,6 @@ public class LayerAndLoadersTest {
// many loader with boot loader as parent
layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, null);
testLoadFail(layer, cn);
-
}
@@ -262,7 +255,6 @@ public class LayerAndLoadersTest {
* m2 exports p
*/
public void testOverlappingPackages() {
-
ModuleDescriptor descriptor1
= ModuleDescriptor.newModule("m1").exports("p").build();
@@ -284,7 +276,6 @@ public class LayerAndLoadersTest {
// should be okay to have one module per class loader
ModuleLayer layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, null);
checkLayer(layer, "m1", "m2");
-
}
@@ -296,7 +287,6 @@ public class LayerAndLoadersTest {
* layer2: m3 reads m1, m4 reads m2
*/
public void testSplitDelegation() {
-
ModuleDescriptor descriptor1
= ModuleDescriptor.newModule("m1").exports("p").build();
@@ -332,7 +322,6 @@ public class LayerAndLoadersTest {
// no split delegation when modules have their own class loader
ModuleLayer layer2 = layer1.defineModulesWithManyLoaders(cf2, null);
checkLayer(layer2, "m3", "m4");
-
}
@@ -345,7 +334,6 @@ public class LayerAndLoadersTest {
* layer2: m1, m2, m4 => same loader
*/
public void testOverriding1() throws Exception {
-
Configuration cf1 = resolve("m1");
ModuleLayer layer1 = ModuleLayer.boot().defineModulesWithOneLoader(cf1, null);
@@ -381,7 +369,6 @@ public class LayerAndLoadersTest {
assertTrue(loader4.loadClass("p.Main").getClassLoader() == loader4);
assertTrue(loader4.loadClass("q.Hello").getClassLoader() == loader4);
assertTrue(loader4.loadClass("w.Hello").getClassLoader() == loader4);
-
}
@@ -394,7 +381,6 @@ public class LayerAndLoadersTest {
* layer2: m1, m2, m3 => loader pool
*/
public void testOverriding2() throws Exception {
-
Configuration cf1 = resolve("m1");
ModuleLayer layer1 = ModuleLayer.boot().defineModulesWithManyLoaders(cf1, null);
@@ -476,7 +462,6 @@ public class LayerAndLoadersTest {
loader6.loadClass("q.Hello");
assertTrue(false);
} catch (ClassNotFoundException expected) { }
-
}
@@ -488,7 +473,6 @@ public class LayerAndLoadersTest {
* layer2: m1, m3 => same loader
*/
public void testOverriding3() throws Exception {
-
Configuration cf1 = resolve("m1");
ModuleLayer layer1 = ModuleLayer.boot().defineModulesWithOneLoader(cf1, null);
@@ -513,7 +497,6 @@ public class LayerAndLoadersTest {
assertTrue(loader2.loadClass("p.Main").getClassLoader() == loader2);
assertTrue(loader2.loadClass("q.Hello").getClassLoader() == loader1);
assertTrue(loader2.loadClass("w.Hello").getClassLoader() == loader2);
-
}
@@ -525,7 +508,6 @@ public class LayerAndLoadersTest {
* layer2: m1, m3 => loader pool
*/
public void testOverriding4() throws Exception {
-
Configuration cf1 = resolve("m1");
ModuleLayer layer1 = ModuleLayer.boot().defineModulesWithManyLoaders(cf1, null);
@@ -565,49 +547,133 @@ public class LayerAndLoadersTest {
assertTrue(loader4.loadClass("w.Hello").getClassLoader() == loader6);
assertTrue(loader6.loadClass("w.Hello").getClassLoader() == loader6);
-
}
/**
- * Basic test of resource loading with a class loader created by
- * Layer.defineModulesWithOneLoader.
+ * Basic test for locating resources with a class loader created by
+ * defineModulesWithOneLoader.
*/
- public void testResourcesOneLoader() throws Exception {
+ public void testResourcesWithOneLoader() throws Exception {
Configuration cf = resolve("m1");
ClassLoader scl = ClassLoader.getSystemClassLoader();
ModuleLayer layer = ModuleLayer.boot().defineModulesWithOneLoader(cf, scl);
+
ClassLoader loader = layer.findLoader("m1");
- testResourceLoading(loader, "p/Main.class");
+ assertNotNull(loader);
+
+ // check that getResource and getResources are consistent
+ URL url1 = loader.getResource("module-info.class");
+ URL url2 = loader.getResources("module-info.class").nextElement();
+ assertEquals(url1.toURI(), url2.toURI());
+
+ // use getResources to find module-info.class resources
+ Enumeration urls = loader.getResources("module-info.class");
+ List list = readModuleNames(urls);
+
+ // m1, m2, ... should be first (order not specified)
+ int count = cf.modules().size();
+ cf.modules().stream()
+ .map(ResolvedModule::name)
+ .forEach(mn -> assertTrue(list.indexOf(mn) < count));
+
+ // java.base should be after m1, m2, ...
+ assertTrue(list.indexOf("java.base") >= count);
+
+ // check resources(String)
+ List list2 = loader.resources("module-info.class")
+ .map(this::readModuleName)
+ .collect(Collectors.toList());
+ assertEquals(list2, list);
+
+ // check nulls
+ try {
+ loader.getResource(null);
+ assertTrue(false);
+ } catch (NullPointerException e) { }
+ try {
+ loader.getResources(null);
+ assertTrue(false);
+ } catch (NullPointerException e) { }
+ try {
+ loader.resources(null);
+ assertTrue(false);
+ } catch (NullPointerException e) { }
}
/**
- * Basic test of resource loading with a class loader created by
- * Layer.defineModulesWithOneLoader.
+ * Basic test for locating resources with class loaders created by
+ * defineModulesWithManyLoaders.
*/
- public void testResourcesManyLoaders() throws Exception {
+ public void testResourcesWithManyLoaders() throws Exception {
Configuration cf = resolve("m1");
ClassLoader scl = ClassLoader.getSystemClassLoader();
ModuleLayer layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, scl);
- ClassLoader loader = layer.findLoader("m1");
- testResourceLoading(loader, "p/Main.class");
+
+ for (Module m : layer.modules()) {
+ String name = m.getName();
+ ClassLoader loader = m.getClassLoader();
+ assertNotNull(loader);
+
+ // getResource should find the module-info.class for the module
+ URL url = loader.getResource("module-info.class");
+ assertEquals(readModuleName(url), name);
+
+ // list of modules names read from module-info.class
+ Enumeration urls = loader.getResources("module-info.class");
+ List list = readModuleNames(urls);
+
+ // module should be the first element
+ assertTrue(list.indexOf(name) == 0);
+
+ // the module-info.class for the other modules in the layer
+ // should not be found
+ layer.modules().stream()
+ .map(Module::getName)
+ .filter(mn -> !mn.equals(name))
+ .forEach(mn -> assertTrue(list.indexOf(mn) < 0));
+
+ // java.base cannot be the first element
+ assertTrue(list.indexOf("java.base") > 0);
+
+ // check resources(String)
+ List list2 = loader.resources("module-info.class")
+ .map(this::readModuleName)
+ .collect(Collectors.toList());
+ assertEquals(list2, list);
+
+ // check nulls
+ try {
+ loader.getResource(null);
+ assertTrue(false);
+ } catch (NullPointerException e) { }
+ try {
+ loader.getResources(null);
+ assertTrue(false);
+ } catch (NullPointerException e) { }
+ try {
+ loader.resources(null);
+ assertTrue(false);
+ } catch (NullPointerException e) { }
+ }
}
- /**
- * Test that a resource is located by a class loader.
- */
- private void testResourceLoading(ClassLoader loader, String name)
- throws IOException
- {
- URL url = loader.getResource(name);
- assertNotNull(url);
-
- try (InputStream in = loader.getResourceAsStream(name)) {
- assertNotNull(in);
+ private List readModuleNames(Enumeration e) {
+ List list = new ArrayList<>();
+ while (e.hasMoreElements()) {
+ URL url = e.nextElement();
+ list.add(readModuleName(url));
}
+ return list;
+ }
- Enumeration urls = loader.getResources(name);
- assertTrue(urls.hasMoreElements());
+ private String readModuleName(URL url) {
+ try (InputStream in = url.openStream()) {
+ ModuleDescriptor descriptor = ModuleDescriptor.read(in);
+ return descriptor.name();
+ } catch (IOException ioe) {
+ throw new UncheckedIOException(ioe);
+ }
}
diff --git a/jdk/test/java/lang/ModuleLayer/LayerControllerTest.java b/jdk/test/java/lang/ModuleLayer/LayerControllerTest.java
index 28246cf9b66..68e9106226b 100644
--- a/jdk/test/java/lang/ModuleLayer/LayerControllerTest.java
+++ b/jdk/test/java/lang/ModuleLayer/LayerControllerTest.java
@@ -59,11 +59,17 @@ public class LayerControllerTest {
.packages(Set.of("p2"))
.build();
- ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
+ ModuleDescriptor descriptor3
+ = ModuleDescriptor.newModule("m3")
+ .requires("java.base")
+ .packages(Set.of("p3"))
+ .build();
+
+ ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3);
ModuleLayer bootLayer = ModuleLayer.boot();
Configuration cf = bootLayer.configuration()
- .resolve(finder, ModuleFinder.of(), Set.of("m1", "m2"));
+ .resolve(finder, ModuleFinder.of(), Set.of("m1", "m2", "m3"));
ClassLoader scl = ClassLoader.getSystemClassLoader();
@@ -72,9 +78,10 @@ public class LayerControllerTest {
ModuleLayer layer = controller.layer();
- assertTrue(layer.modules().size() == 2);
+ assertTrue(layer.modules().size() == 3);
assertTrue(layer.findModule("m1").isPresent());
assertTrue(layer.findModule("m2").isPresent());
+ assertTrue(layer.findModule("m3").isPresent());
return controller;
}
@@ -88,18 +95,34 @@ public class LayerControllerTest {
ModuleLayer layer = controller.layer();
Module m1 = layer.findModule("m1").orElseThrow(RuntimeException::new);
Module m2 = layer.findModule("m2").orElseThrow(RuntimeException::new);
+ Module m3 = layer.findModule("m3").orElseThrow(RuntimeException::new);
assertFalse(m1.canRead(m2));
+ assertFalse(m1.canRead(m3));
assertFalse(m1.isExported("p1"));
assertFalse(m1.isOpen("p1"));
assertFalse(m1.isExported("p1", m2));
+ assertFalse(m1.isExported("p1", m3));
assertFalse(m1.isOpen("p1", m2));
+ assertFalse(m1.isOpen("p1", m3));
assertFalse(m2.canRead(m1));
+ assertFalse(m2.canRead(m3));
assertFalse(m2.isExported("p2"));
assertFalse(m2.isOpen("p2"));
assertFalse(m2.isExported("p2", m1));
+ assertFalse(m2.isExported("p2", m3));
assertFalse(m2.isOpen("p2", m1));
+ assertFalse(m2.isOpen("p2", m3));
+
+ assertFalse(m3.canRead(m1));
+ assertFalse(m3.canRead(m2));
+ assertFalse(m3.isExported("p3"));
+ assertFalse(m3.isOpen("p3"));
+ assertFalse(m3.isExported("p3", m1));
+ assertFalse(m3.isExported("p3", m2));
+ assertFalse(m3.isOpen("p3", m1));
+ assertFalse(m3.isOpen("p3", m2));
// update m1 to read m2
assertTrue(controller.addReads(m1, m2) == controller);
@@ -111,19 +134,33 @@ public class LayerControllerTest {
assertTrue(m1.canRead(m2));
assertTrue(m1.canRead(m1));
- // update m1 to open p1 to m2
- assertTrue(controller.addOpens(m1, "p1", m2) == controller);
+ // update m1 to export p1 to m2
+ assertTrue(controller.addExports(m1, "p1", m2) == controller);
assertTrue(m1.isExported("p1", m2));
- assertTrue(m1.isOpen("p1", m2));
+ assertFalse(m1.isOpen("p1", m2));
assertFalse(m1.isExported("p1"));
assertFalse(m1.isOpen("p1"));
- // update m2 to open p2 to m1
- assertTrue(controller.addOpens(m2, "p2", m1) == controller);
- assertTrue(m2.isExported("p2", m1));
- assertTrue(m2.isOpen("p2", m1));
- assertFalse(m2.isExported("p2"));
- assertFalse(m2.isOpen("p2"));
+ // update m3 to open p3 to m1
+ assertTrue(controller.addExports(m3, "p3", m1) == controller);
+ assertTrue(m3.isExported("p3", m1));
+ assertFalse(m3.isOpen("p3", m1));
+ assertFalse(m3.isExported("p3"));
+ assertFalse(m3.isOpen("p3"));
+
+ // update m1 to open p1 to m3
+ assertTrue(controller.addOpens(m1, "p1", m3) == controller);
+ assertTrue(m1.isExported("p1", m3));
+ assertTrue(m1.isOpen("p1", m3));
+ assertFalse(m1.isExported("p1"));
+ assertFalse(m1.isOpen("p1"));
+
+ // update m3 to open p3 to m1
+ assertTrue(controller.addOpens(m3, "p3", m1) == controller);
+ assertTrue(m3.isExported("p3", m1));
+ assertTrue(m3.isOpen("p3", m1));
+ assertFalse(m3.isExported("p3"));
+ assertFalse(m3.isOpen("p3"));
}
/**
@@ -142,6 +179,18 @@ public class LayerControllerTest {
assertTrue(false);
} catch (IllegalArgumentException expected) { }
+ // java.base is not in layer
+ try {
+ controller.addExports(base, "java.lang", m2);
+ assertTrue(false);
+ } catch (IllegalArgumentException expected) { }
+
+ // m1 does not contain java.lang
+ try {
+ controller.addExports(m1, "java.lang", m2);
+ assertTrue(false);
+ } catch (IllegalArgumentException expected) { }
+
// java.base is not in layer
try {
controller.addOpens(base, "java.lang", m2);
@@ -176,6 +225,21 @@ public class LayerControllerTest {
assertTrue(false);
} catch (NullPointerException expected) { }
+ try {
+ controller.addExports(null, "p1", m2);
+ assertTrue(false);
+ } catch (NullPointerException expected) { }
+
+ try {
+ controller.addExports(m1, null, m2);
+ assertTrue(false);
+ } catch (NullPointerException expected) { }
+
+ try {
+ controller.addExports(m1, "p1", null);
+ assertTrue(false);
+ } catch (NullPointerException expected) { }
+
try {
controller.addOpens(null, "p1", m2);
assertTrue(false);
diff --git a/jdk/test/java/lang/ModuleTests/AnnotationsTest.java b/jdk/test/java/lang/ModuleTests/AnnotationsTest.java
index b4319a7bb11..9b3fe4c9839 100644
--- a/jdk/test/java/lang/ModuleTests/AnnotationsTest.java
+++ b/jdk/test/java/lang/ModuleTests/AnnotationsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -62,6 +62,7 @@ public class AnnotationsTest {
public void testUnnamedModule() {
Module module = this.getClass().getModule();
assertTrue(module.getAnnotations().length == 0);
+ assertTrue(module.getDeclaredAnnotations().length == 0);
}
/**
@@ -88,6 +89,7 @@ public class AnnotationsTest {
Annotation[] a = module.getAnnotations();
assertTrue(a.length == 1);
assertTrue(a[0] instanceof Deprecated);
+ assertEquals(module.getDeclaredAnnotations(), a);
}
diff --git a/jdk/test/java/lang/ModuleTests/BasicModuleTest.java b/jdk/test/java/lang/ModuleTests/BasicModuleTest.java
index b2f5eaa3a14..3f12734efd1 100644
--- a/jdk/test/java/lang/ModuleTests/BasicModuleTest.java
+++ b/jdk/test/java/lang/ModuleTests/BasicModuleTest.java
@@ -35,7 +35,7 @@ import static org.testng.Assert.*;
* @test
* @summary Basic test of java.lang.Module
* @modules java.desktop java.xml
- * @run testng BasicModuleTest
+ * @run testng/othervm --illegal-access=deny BasicModuleTest
*/
public class BasicModuleTest {
diff --git a/jdk/test/java/lang/ModuleTests/annotation/Basic.java b/jdk/test/java/lang/ModuleTests/annotation/Basic.java
index dc17cbb5e4f..7d18434b053 100644
--- a/jdk/test/java/lang/ModuleTests/annotation/Basic.java
+++ b/jdk/test/java/lang/ModuleTests/annotation/Basic.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -29,7 +29,7 @@
* @summary Basic test for annotations on modules
*/
-import java.util.Arrays;
+import java.lang.annotation.Annotation;
import p.annotation.Foo;
import p.annotation.Bar;
@@ -71,6 +71,28 @@ public class Basic {
Baz baz = module.getAnnotation(Baz.class);
assertNotNull(baz);
String[] expected = { "one", "two", "three" };
- assertTrue(Arrays.equals(baz.value(), expected));
+ assertEquals(baz.value(), expected);
+ }
+
+ /**
+ * Test annotations with RUNTIME retention policy
+ */
+ @Test
+ public void testRuntimeAnnotations() {
+ Annotation[] a = module.getAnnotations();
+ assertEquals(a, module.getDeclaredAnnotations());
+ assertTrue(a.length == 2);
+ Bar bar;
+ Baz baz;
+ if (a[0] instanceof Bar) {
+ bar = (Bar)a[0];
+ baz = (Baz)a[1];
+ } else {
+ bar = (Bar)a[1];
+ baz = (Baz)a[0];
+ }
+ assertEquals(bar.value(), "bar");
+ String[] expected = { "one", "two", "three"};
+ assertEquals(baz.value(), expected);
}
}
diff --git a/jdk/test/java/lang/instrument/RedefineModuleTest.java b/jdk/test/java/lang/instrument/RedefineModuleTest.java
index 60ae18f7d09..f78266ea543 100644
--- a/jdk/test/java/lang/instrument/RedefineModuleTest.java
+++ b/jdk/test/java/lang/instrument/RedefineModuleTest.java
@@ -29,7 +29,7 @@
* java.base/jdk.internal.test.TestProviderImpl1
* java.base/jdk.internal.test.TestProviderImpl2
* @run shell MakeJAR3.sh RedefineModuleAgent
- * @run testng/othervm -javaagent:RedefineModuleAgent.jar RedefineModuleTest
+ * @run testng/othervm --illegal-access=deny -javaagent:RedefineModuleAgent.jar RedefineModuleTest
*/
import java.lang.TestProvider;
diff --git a/jdk/test/java/lang/module/AutomaticModulesTest.java b/jdk/test/java/lang/module/AutomaticModulesTest.java
index d3b049e94b4..f4668737e06 100644
--- a/jdk/test/java/lang/module/AutomaticModulesTest.java
+++ b/jdk/test/java/lang/module/AutomaticModulesTest.java
@@ -58,8 +58,8 @@ public class AutomaticModulesTest {
private static final Path USER_DIR
= Paths.get(System.getProperty("user.dir"));
- @DataProvider(name = "names")
- public Object[][] createNames() {
+ @DataProvider(name = "jarnames")
+ public Object[][] createJarNames() {
return new Object[][] {
// JAR file name module-name[/version]
@@ -100,7 +100,7 @@ public class AutomaticModulesTest {
}
// JAR file names that do not map to a legal module name
- @DataProvider(name = "badnames")
+ @DataProvider(name = "badjarnames")
public Object[][] createBadNames() {
return new Object[][]{
@@ -117,7 +117,7 @@ public class AutomaticModulesTest {
/**
* Test mapping of JAR file names to module names
*/
- @Test(dataProvider = "names")
+ @Test(dataProvider = "jarnames")
public void testNames(String fn, String mid) throws IOException {
String[] s = mid.split("/");
String mn = s[0];
@@ -146,11 +146,10 @@ public class AutomaticModulesTest {
}
}
-
/**
* Test impossible mapping of JAR files to modules names
*/
- @Test(dataProvider = "badnames", expectedExceptions = FindException.class)
+ @Test(dataProvider = "badjarnames", expectedExceptions = FindException.class)
public void testBadNames(String fn, String ignore) throws IOException {
Path dir = Files.createTempDirectory(USER_DIR, "mods");
Path jf = dir.resolve(fn);
@@ -163,6 +162,76 @@ public class AutomaticModulesTest {
}
+ @DataProvider(name = "modulenames")
+ public Object[][] createModuleNames() {
+ return new Object[][] {
+ { "foo", null },
+ { "foo", "1.0" },
+ { "foo.bar", null },
+ { "foo.bar", "1.0" },
+ { "class_", null },
+ { "class_", "1.0" },
+ };
+ }
+
+ @DataProvider(name = "badmodulenames")
+ public Object[][] createBadModuleNames() {
+ return new Object[][] {
+ { "", null },
+ { "", "1.0" },
+ { "666", null },
+ { "666", "1.0" },
+ { "foo.class", null },
+ { "foo.class", "1.0" },
+ };
+ }
+
+ /**
+ * Test JAR files with the Automatic-Module-Name attribute
+ */
+ @Test(dataProvider = "modulenames")
+ public void testAutomaticModuleNameAttribute(String name, String vs)
+ throws IOException
+ {
+ Manifest man = new Manifest();
+ Attributes attrs = man.getMainAttributes();
+ attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
+ attrs.put(new Attributes.Name("Automatic-Module-Name"), name);
+
+ Path dir = Files.createTempDirectory(USER_DIR, "mods");
+ String jar;
+ if (vs == null) {
+ jar = "m.jar";
+ } else {
+ jar = "m-" + vs + ".jar";
+ }
+ createDummyJarFile(dir.resolve(jar), man);
+
+ ModuleFinder finder = ModuleFinder.of(dir);
+
+ assertTrue(finder.findAll().size() == 1);
+ assertTrue(finder.find(name).isPresent());
+
+ ModuleReference mref = finder.find(name).get();
+ ModuleDescriptor descriptor = mref.descriptor();
+ assertEquals(descriptor.name(), name);
+ assertEquals(descriptor.version()
+ .map(ModuleDescriptor.Version::toString)
+ .orElse(null), vs);
+ }
+
+ /**
+ * Test JAR files with the Automatic-Module-Name attribute with a value
+ * that is not a legal module name.
+ */
+ @Test(dataProvider = "badmodulenames", expectedExceptions = FindException.class)
+ public void testBadAutomaticModuleNameAttribute(String name, String ignore)
+ throws IOException
+ {
+ // should throw FindException
+ testAutomaticModuleNameAttribute(name, null);
+ }
+
/**
* Test all packages are exported
*/
@@ -277,7 +346,6 @@ public class AutomaticModulesTest {
assertTrue(provides.providers().contains((provider)));
}
-
// META-INF/services files that don't map to legal service names
@DataProvider(name = "badservices")
public Object[][] createBadServices() {
@@ -310,7 +378,6 @@ public class AutomaticModulesTest {
assertTrue(descriptor.provides().isEmpty());
}
-
// META-INF/services configuration file entries that are not legal
@DataProvider(name = "badproviders")
public Object[][] createBadProviders() {
@@ -370,7 +437,6 @@ public class AutomaticModulesTest {
ModuleFinder.of(dir).findAll();
}
-
/**
* Test that a JAR file with a Main-Class attribute results
* in a module with a main class.
@@ -398,7 +464,6 @@ public class AutomaticModulesTest {
assertEquals(descriptor.mainClass().get(), mainClass);
}
-
// Main-Class files that do not map to a legal qualified type name
@DataProvider(name = "badmainclass")
public Object[][] createBadMainClass() {
@@ -450,7 +515,6 @@ public class AutomaticModulesTest {
assertFalse(descriptor.mainClass().isPresent());
}
-
/**
* Basic test of a configuration created with automatic modules.
* a requires b*
@@ -583,7 +647,6 @@ public class AutomaticModulesTest {
testReadAllBootModules(cf, "d"); // d reads all modules in boot layer
}
-
/**
* Basic test of a configuration created with automatic modules
* a requires b
@@ -662,7 +725,6 @@ public class AutomaticModulesTest {
testReadAllBootModules(cf, "d"); // d reads all modules in boot layer
}
-
/**
* Basic test to ensure that no automatic modules are resolved when
* an automatic module is not a root or required by other modules.
@@ -692,7 +754,6 @@ public class AutomaticModulesTest {
assertTrue(cf.findModule("m1").isPresent());
}
-
/**
* Basic test to ensure that if an automatic module is resolved then
* all observable automatic modules are resolved.
@@ -770,7 +831,6 @@ public class AutomaticModulesTest {
assertTrue(auto3.reads().contains(base));
}
-
/**
* Basic test of automatic modules in a child configuration. All automatic
* modules that are found with the before finder should be resolved. The
@@ -845,7 +905,6 @@ public class AutomaticModulesTest {
assertTrue(auto3.reads().contains(base));
}
-
/**
* Basic test of a configuration created with automatic modules
* a requires b* and c*
@@ -874,7 +933,6 @@ public class AutomaticModulesTest {
resolve(parent, finder, "a");
}
-
/**
* Basic test of a configuration created with automatic modules
* a contains p, requires b*
@@ -901,7 +959,6 @@ public class AutomaticModulesTest {
resolve(parent, finder, "a");
}
-
/**
* Basic test of layer containing automatic modules
*/
@@ -943,7 +1000,6 @@ public class AutomaticModulesTest {
testsReadsAll(c, layer);
}
-
/**
* Test miscellaneous methods.
*/
@@ -961,7 +1017,6 @@ public class AutomaticModulesTest {
assertFalse(m.modifiers().contains(ModuleDescriptor.Modifier.SYNTHETIC));
}
-
/**
* Invokes parent.resolve to resolve the given root modules.
*/
@@ -1055,7 +1110,7 @@ public class AutomaticModulesTest {
* in the resulting JAR file.
*/
static Path createDummyJarFile(Path jarfile, String... entries)
- throws IOException
+ throws IOException
{
return createDummyJarFile(jarfile, null, entries);
}
diff --git a/jdk/test/java/lang/reflect/AccessibleObject/CanAccessTest.java b/jdk/test/java/lang/reflect/AccessibleObject/CanAccessTest.java
index c73eb795b26..ba641215b05 100644
--- a/jdk/test/java/lang/reflect/AccessibleObject/CanAccessTest.java
+++ b/jdk/test/java/lang/reflect/AccessibleObject/CanAccessTest.java
@@ -25,7 +25,7 @@
* @test
* @build CanAccessTest
* @modules java.base/jdk.internal.misc:+open
- * @run testng CanAccessTest
+ * @run testng/othervm --illegal-access=deny CanAccessTest
* @summary Test AccessibleObject::canAccess method
*/
diff --git a/jdk/test/java/lang/reflect/AccessibleObject/ModuleSetAccessibleTest.java b/jdk/test/java/lang/reflect/AccessibleObject/ModuleSetAccessibleTest.java
index a287e6f6807..18a05a2600a 100644
--- a/jdk/test/java/lang/reflect/AccessibleObject/ModuleSetAccessibleTest.java
+++ b/jdk/test/java/lang/reflect/AccessibleObject/ModuleSetAccessibleTest.java
@@ -26,7 +26,7 @@
* @build ModuleSetAccessibleTest
* @modules java.base/java.lang:open
* java.base/jdk.internal.misc:+open
- * @run testng ModuleSetAccessibleTest
+ * @run testng/othervm --illegal-access=deny ModuleSetAccessibleTest
* @summary Test java.lang.reflect.AccessibleObject with modules
*/
diff --git a/jdk/test/java/lang/reflect/AccessibleObject/TrySetAccessibleTest.java b/jdk/test/java/lang/reflect/AccessibleObject/TrySetAccessibleTest.java
index 340e7d00613..923ca0b69da 100644
--- a/jdk/test/java/lang/reflect/AccessibleObject/TrySetAccessibleTest.java
+++ b/jdk/test/java/lang/reflect/AccessibleObject/TrySetAccessibleTest.java
@@ -27,7 +27,7 @@
* @modules java.base/java.lang:open
* java.base/jdk.internal.perf
* java.base/jdk.internal.misc:+open
- * @run testng TrySetAccessibleTest
+ * @run testng/othervm --illegal-access=deny TrySetAccessibleTest
* @summary Test AccessibleObject::trySetAccessible method
*/
diff --git a/jdk/test/java/util/ResourceBundle/modules/cache/CacheTest.java b/jdk/test/java/util/ResourceBundle/modules/cache/CacheTest.java
index 15d75aec5e4..7952ec59d2c 100644
--- a/jdk/test/java/util/ResourceBundle/modules/cache/CacheTest.java
+++ b/jdk/test/java/util/ResourceBundle/modules/cache/CacheTest.java
@@ -89,6 +89,7 @@ public class CacheTest {
assertTrue(executeTestJava("--class-path", MODS_DIR.resolve(TEST_MODULE).toString(),
"--module-path", MODS_DIR.resolve(MAIN_BUNDLES_MODULE).toString(),
"--add-modules", MAIN_BUNDLES_MODULE,
+ "--illegal-access=deny",
MAIN_CLASS, "cache")
.outputTo(System.out)
.errorTo(System.out)
@@ -111,6 +112,7 @@ public class CacheTest {
assertTrue(executeTestJava("--class-path", MODS_DIR.resolve(TEST_MODULE).toString(),
"--module-path", MODS_DIR.resolve(MAIN_BUNDLES_MODULE).toString(),
"--add-modules", MAIN_BUNDLES_MODULE,
+ "--illegal-access=deny",
MAIN_CLASS)
.outputTo(System.out)
.errorTo(System.out)
diff --git a/jdk/test/java/util/ServiceLoader/modules/BadProvidersTest.java b/jdk/test/java/util/ServiceLoader/BadProvidersTest.java
similarity index 74%
rename from jdk/test/java/util/ServiceLoader/modules/BadProvidersTest.java
rename to jdk/test/java/util/ServiceLoader/BadProvidersTest.java
index a1bf4abf099..fbe406e8146 100644
--- a/jdk/test/java/util/ServiceLoader/modules/BadProvidersTest.java
+++ b/jdk/test/java/util/ServiceLoader/BadProvidersTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -24,7 +24,8 @@
/**
* @test
* @library /lib/testlibrary
- * @modules jdk.compiler
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * jdk.compiler
* @build CompilerUtils
* @run testng/othervm BadProvidersTest
* @summary Basic test of ServiceLoader with bad provider and bad provider
@@ -44,6 +45,10 @@ import java.util.ServiceLoader.Provider;
import java.util.Set;
import java.util.stream.Collectors;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+
import org.testng.annotations.Test;
import org.testng.annotations.DataProvider;
import static org.testng.Assert.*;
@@ -191,5 +196,68 @@ public class BadProvidersTest {
loadProviders(mods, TEST2_MODULE).forEach(Provider::get);
}
+
+ /**
+ * Test a service provider that defines more than one no-args
+ * public static "provider" method.
+ */
+ @Test(expectedExceptions = ServiceConfigurationError.class)
+ public void testWithTwoFactoryMethods() throws Exception {
+ Path mods = compileTest(TEST1_MODULE);
+
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
+ + ClassWriter.COMPUTE_FRAMES);
+ cw.visit(V1_9,
+ ACC_PUBLIC + ACC_SUPER,
+ "p/ProviderFactory",
+ null,
+ "java/lang/Object",
+ null);
+
+ // public static p.Service provider()
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC,
+ "provider",
+ "()Lp/Service;",
+ null,
+ null);
+ mv.visitTypeInsn(NEW, "p/ProviderFactory$1");
+ mv.visitInsn(DUP);
+ mv.visitMethodInsn(INVOKESPECIAL,
+ "p/ProviderFactory$1",
+ "", "()V",
+ false);
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+
+ // public static p.ProviderFactory$1 provider()
+ mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC,
+ "provider",
+ "()Lp/ProviderFactory$1;",
+ null,
+ null);
+ mv.visitTypeInsn(NEW, "p/ProviderFactory$1");
+ mv.visitInsn(DUP);
+ mv.visitMethodInsn(INVOKESPECIAL,
+ "p/ProviderFactory$1",
+ "",
+ "()V",
+ false);
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+
+ cw.visitEnd();
+
+ // write the class bytes into the compiled module directory
+ Path classFile = mods.resolve(TEST1_MODULE)
+ .resolve("p")
+ .resolve("ProviderFactory.class");
+ Files.write(classFile, cw.toByteArray());
+
+ // load providers and instantiate each one
+ loadProviders(mods, TEST1_MODULE).forEach(Provider::get);
+ }
+
}
diff --git a/jdk/test/java/util/ServiceLoader/modules/Basic.java b/jdk/test/java/util/ServiceLoader/ModulesTest.java
similarity index 87%
rename from jdk/test/java/util/ServiceLoader/modules/Basic.java
rename to jdk/test/java/util/ServiceLoader/ModulesTest.java
index 75e30bc4413..622eea0d1fd 100644
--- a/jdk/test/java/util/ServiceLoader/modules/Basic.java
+++ b/jdk/test/java/util/ServiceLoader/ModulesTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -23,12 +23,13 @@
/**
* @test
- * @library modules
* @modules java.scripting
+ * @library modules /lib/testlibrary
* @build bananascript/*
- * @compile src/pearscript/org/pear/PearScriptEngineFactory.java
- * src/pearscript/org/pear/PearScript.java
- * @run testng/othervm Basic
+ * @build JarUtils
+ * @compile classpath/pearscript/org/pear/PearScriptEngineFactory.java
+ * classpath/pearscript/org/pear/PearScript.java
+ * @run testng/othervm ModulesTest
* @summary Basic test for ServiceLoader with a provider deployed as a module.
*/
@@ -38,8 +39,15 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Optional;
+import java.util.ServiceLoader;
import java.util.ServiceLoader.Provider;
+import java.util.Set;
import java.util.stream.Collectors;
import javax.script.ScriptEngineFactory;
@@ -56,16 +64,16 @@ import static org.testng.Assert.*;
* with a service configuration file.
*/
-public class Basic {
+public class ModulesTest {
// Copy the services configuration file for "pearscript" into place.
@BeforeTest
public void setup() throws Exception {
- Path src = Paths.get(System.getProperty("test.src", ""));
- Path classes = Paths.get(System.getProperty("test.classes", ""));
+ Path src = Paths.get(System.getProperty("test.src"));
+ Path classes = Paths.get(System.getProperty("test.classes"));
String st = ScriptEngineFactory.class.getName();
Path config = Paths.get("META-INF", "services", st);
- Path source = src.resolve("src").resolve("pearscript").resolve(config);
+ Path source = src.resolve("classpath").resolve("pearscript").resolve(config);
Path target = classes.resolve(config);
Files.createDirectories(target.getParent());
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
@@ -204,7 +212,7 @@ public class Basic {
// iterator
ServiceLoader loader
- = ServiceLoader.load(ScriptEngineFactory.class, pcl);
+ = ServiceLoader.load(ScriptEngineFactory.class, pcl);
Set names = collectAll(loader)
.stream()
.map(ScriptEngineFactory::getEngineName)
@@ -222,6 +230,44 @@ public class Basic {
assertFalse(names.contains("PearScriptEngine"));
}
+ /**
+ * Basic test of ServiceLoader.load where the service provider module is an
+ * automatic module.
+ */
+ @Test
+ public void testWithAutomaticModule() throws Exception {
+ Path classes = Paths.get(System.getProperty("test.classes"));
+ Path jar = Files.createTempDirectory("lib").resolve("pearscript.jar");
+ JarUtils.createJarFile(jar, classes, "META-INF", "org");
+
+ ModuleFinder finder = ModuleFinder.of(jar);
+ ModuleLayer bootLayer = ModuleLayer.boot();
+ Configuration parent = bootLayer.configuration();
+ Configuration cf = parent.resolveAndBind(finder, ModuleFinder.of(), Set.of());
+ assertTrue(cf.modules().size() == 1);
+
+ ClassLoader scl = ClassLoader.getSystemClassLoader();
+ ModuleLayer layer = bootLayer.defineModulesWithOneLoader(cf, scl);
+ assertTrue(layer.modules().size() == 1);
+
+ ClassLoader loader = layer.findLoader("pearscript");
+ ScriptEngineFactory factory;
+
+ // load using the class loader as context
+ factory = ServiceLoader.load(ScriptEngineFactory.class, loader)
+ .findFirst()
+ .orElse(null);
+ assertNotNull(factory);
+ assertTrue(factory.getClass().getClassLoader() == loader);
+
+ // load using the layer as context
+ factory = ServiceLoader.load(layer, ScriptEngineFactory.class)
+ .findFirst()
+ .orElse(null);
+ assertNotNull(factory);
+ assertTrue(factory.getClass().getClassLoader() == loader);
+ }
+
/**
* Basic test of ServiceLoader.load, using the class loader for
* a module in a custom layer as the context.
diff --git a/jdk/test/java/util/ServiceLoader/NoInterferenceTest.java b/jdk/test/java/util/ServiceLoader/NoInterferenceTest.java
new file mode 100644
index 00000000000..05f08f83210
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/NoInterferenceTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @library /lib/testlibrary
+ * @modules jdk.compiler
+ * @build CompilerUtils
+ * @run testng NoInterferenceTest
+ * @summary Basic test of ServiceLoader that ensures there is no interference
+ * when there are two service interfaces of the same name in a layer
+ * or overridden in a child layer.
+ */
+
+import java.lang.module.Configuration;
+import java.lang.module.ModuleFinder;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+public class NoInterferenceTest {
+
+ private static final String TEST_SRC = System.getProperty("test.src");
+ private static final Path SRC_DIR = Paths.get(TEST_SRC, "modules");
+ private static final Path MODS_DIR = Paths.get("mods");
+ private static final List MODULES = Arrays.asList("s1", "p1", "s2", "p2");
+
+ @BeforeTest
+ void compile() throws Exception {
+ Files.createDirectory(MODS_DIR);
+ for (String name : MODULES) {
+ Path src = SRC_DIR.resolve(name);
+ Path output = Files.createDirectory(MODS_DIR.resolve(name));
+ assertTrue(CompilerUtils.compile(src, output, "-p", MODS_DIR.toString()));
+ }
+ }
+
+ @Test
+ public void test() throws Exception {
+ ModuleFinder empty = ModuleFinder.of();
+ ModuleFinder finder = ModuleFinder.of(MODS_DIR);
+
+ ModuleLayer bootLayer = ModuleLayer.boot();
+
+ Configuration cf0 = bootLayer.configuration();
+ Configuration cf1 = cf0.resolveAndBind(finder, empty, Set.of("s1", "s2"));
+ Configuration cf2 = cf1.resolveAndBind(finder, empty, Set.of("s1", "s2"));
+
+ // cf1 contains s1, p1, s2, p2
+ assertTrue(cf1.modules().size() == 4);
+
+ // cf1 contains s1, p1, s2, p2
+ assertTrue(cf2.modules().size() == 4);
+
+ ClassLoader scl = ClassLoader.getSystemClassLoader();
+
+ ModuleLayer layer1 = bootLayer.defineModulesWithManyLoaders(cf1, scl);
+ testLayer(layer1);
+
+ ModuleLayer layer2 = layer1.defineModulesWithManyLoaders(cf2, scl);
+ testLayer(layer2);
+ }
+
+ /**
+ * Tests that the layer contains s1, p1, s2, and p2.
+ *
+ * Tests loading instances of s1/p.S and s2/p.S.
+ */
+ private void testLayer(ModuleLayer layer) throws Exception {
+ assertTrue(layer.modules().size() == 4);
+ Module s1 = layer.findModule("s1").get();
+ Module p1 = layer.findModule("p1").get();
+ Module s2 = layer.findModule("s2").get();
+ Module p2 = layer.findModule("p2").get();
+
+ // p1 reads s1
+ assertTrue(p1.canRead(s1));
+ assertFalse(p1.canRead(s2));
+
+ // p2 reads s2
+ assertTrue(p2.canRead(s2));
+ assertFalse(p2.canRead(s1));
+
+ // iterate over implementations of s1/p.S
+ {
+ ClassLoader loader = layer.findLoader("s1");
+ Class> service = loader.loadClass("p.S");
+
+ List> list = collectAll(ServiceLoader.load(service, loader));
+ assertTrue(list.size() == 1);
+ assertTrue(list.get(0).getClass().getModule() == p1);
+
+ list = collectAll(ServiceLoader.load(layer, service));
+ assertTrue(list.size() == 1);
+ assertTrue(list.get(0).getClass().getModule() == p1);
+ }
+
+ // iterate over implementations of s2/p.S
+ {
+ ClassLoader loader = layer.findLoader("s2");
+ Class> service = loader.loadClass("p.S");
+
+ List> list = collectAll(ServiceLoader.load(service, loader));
+ assertTrue(list.size() == 1);
+ assertTrue(list.get(0).getClass().getModule() == p2);
+
+ list = collectAll(ServiceLoader.load(layer, service));
+ assertTrue(list.size() == 1);
+ assertTrue(list.get(0).getClass().getModule() == p2);
+ }
+ }
+
+ private List collectAll(ServiceLoader loader) {
+ List list = new ArrayList<>();
+ Iterator iterator = loader.iterator();
+ while (iterator.hasNext()) {
+ list.add(iterator.next());
+ }
+ return list;
+ }
+}
\ No newline at end of file
diff --git a/jdk/test/java/util/ServiceLoader/ReloadTest.java b/jdk/test/java/util/ServiceLoader/ReloadTest.java
new file mode 100644
index 00000000000..e6b7ae7652f
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/ReloadTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @library modules
+ * @modules java.scripting
+ * @run testng/othervm ReloadTest
+ * @summary Basic test of ServiceLoader.reload
+ */
+
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.ServiceLoader.Provider;
+import java.util.Spliterator;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import static java.util.ServiceLoader.*;
+import javax.script.ScriptEngineFactory;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class ReloadTest {
+
+ public void testReload() {
+ ServiceLoader sl = load(ScriptEngineFactory.class);
+ List names1 = sl.stream()
+ .map(Provider::get)
+ .map(ScriptEngineFactory::getEngineName)
+ .collect(Collectors.toList());
+ assertFalse(names1.isEmpty());
+ sl.reload();
+ List names2 = sl.stream()
+ .map(Provider::get)
+ .map(ScriptEngineFactory::getEngineName)
+ .collect(Collectors.toList());
+ assertEquals(names1, names2);
+ }
+
+ @Test(expectedExceptions = { ConcurrentModificationException.class })
+ public void testIteratorHasNext() {
+ ServiceLoader sl = load(ScriptEngineFactory.class);
+ Iterator iterator = sl.iterator();
+ sl.reload();
+ iterator.hasNext();
+ }
+
+ @Test(expectedExceptions = { ConcurrentModificationException.class })
+ public void testIteratorNext() {
+ ServiceLoader sl = load(ScriptEngineFactory.class);
+ Iterator iterator = sl.iterator();
+ assertTrue(iterator.hasNext());
+ sl.reload();
+ iterator.next();
+ }
+
+ @Test(expectedExceptions = { ConcurrentModificationException.class })
+ public void testStreamFindAny() {
+ ServiceLoader sl = load(ScriptEngineFactory.class);
+ Stream> stream = sl.stream();
+ sl.reload();
+ stream.findAny();
+ }
+
+ @Test(expectedExceptions = { ConcurrentModificationException.class })
+ public void testSpliteratorTryAdvance() {
+ ServiceLoader sl = load(ScriptEngineFactory.class);
+ Stream> stream = sl.stream();
+ Spliterator> spliterator = stream.spliterator();
+ sl.reload();
+ spliterator.tryAdvance(System.out::println);
+ }
+
+}
diff --git a/jdk/test/java/util/ServiceLoader/modules/badfactories/badreturntype/ProviderFactory.java b/jdk/test/java/util/ServiceLoader/badfactories/badreturntype/ProviderFactory.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/badfactories/badreturntype/ProviderFactory.java
rename to jdk/test/java/util/ServiceLoader/badfactories/badreturntype/ProviderFactory.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/badfactories/classnotpublic/ProviderFactory.java b/jdk/test/java/util/ServiceLoader/badfactories/classnotpublic/ProviderFactory.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/badfactories/classnotpublic/ProviderFactory.java
rename to jdk/test/java/util/ServiceLoader/badfactories/classnotpublic/ProviderFactory.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/badfactories/classnotpublic/Service.java b/jdk/test/java/util/ServiceLoader/badfactories/classnotpublic/Service.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/badfactories/classnotpublic/Service.java
rename to jdk/test/java/util/ServiceLoader/badfactories/classnotpublic/Service.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/badfactories/methodnotpublic/ProviderFactory.java b/jdk/test/java/util/ServiceLoader/badfactories/methodnotpublic/ProviderFactory.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/badfactories/methodnotpublic/ProviderFactory.java
rename to jdk/test/java/util/ServiceLoader/badfactories/methodnotpublic/ProviderFactory.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/badfactories/methodnotpublic/Service.java b/jdk/test/java/util/ServiceLoader/badfactories/methodnotpublic/Service.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/badfactories/methodnotpublic/Service.java
rename to jdk/test/java/util/ServiceLoader/badfactories/methodnotpublic/Service.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/badfactories/returnsnull/ProviderFactory.java b/jdk/test/java/util/ServiceLoader/badfactories/returnsnull/ProviderFactory.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/badfactories/returnsnull/ProviderFactory.java
rename to jdk/test/java/util/ServiceLoader/badfactories/returnsnull/ProviderFactory.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/badfactories/returnsnull/Service.java b/jdk/test/java/util/ServiceLoader/badfactories/returnsnull/Service.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/badfactories/returnsnull/Service.java
rename to jdk/test/java/util/ServiceLoader/badfactories/returnsnull/Service.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/badfactories/throwsexception/ProviderFactory.java b/jdk/test/java/util/ServiceLoader/badfactories/throwsexception/ProviderFactory.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/badfactories/throwsexception/ProviderFactory.java
rename to jdk/test/java/util/ServiceLoader/badfactories/throwsexception/ProviderFactory.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/badfactories/throwsexception/Service.java b/jdk/test/java/util/ServiceLoader/badfactories/throwsexception/Service.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/badfactories/throwsexception/Service.java
rename to jdk/test/java/util/ServiceLoader/badfactories/throwsexception/Service.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/badproviders/ctornotpublic/Provider.java b/jdk/test/java/util/ServiceLoader/badproviders/ctornotpublic/Provider.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/badproviders/ctornotpublic/Provider.java
rename to jdk/test/java/util/ServiceLoader/badproviders/ctornotpublic/Provider.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/badproviders/ctornotpublic/Service.java b/jdk/test/java/util/ServiceLoader/badproviders/ctornotpublic/Service.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/badproviders/ctornotpublic/Service.java
rename to jdk/test/java/util/ServiceLoader/badproviders/ctornotpublic/Service.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/badproviders/notasubtype/Provider.java b/jdk/test/java/util/ServiceLoader/badproviders/notasubtype/Provider.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/badproviders/notasubtype/Provider.java
rename to jdk/test/java/util/ServiceLoader/badproviders/notasubtype/Provider.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/badproviders/notpublic/Provider.java b/jdk/test/java/util/ServiceLoader/badproviders/notpublic/Provider.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/badproviders/notpublic/Provider.java
rename to jdk/test/java/util/ServiceLoader/badproviders/notpublic/Provider.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/badproviders/notpublic/Service.java b/jdk/test/java/util/ServiceLoader/badproviders/notpublic/Service.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/badproviders/notpublic/Service.java
rename to jdk/test/java/util/ServiceLoader/badproviders/notpublic/Service.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/badproviders/throwsexception/Provider.java b/jdk/test/java/util/ServiceLoader/badproviders/throwsexception/Provider.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/badproviders/throwsexception/Provider.java
rename to jdk/test/java/util/ServiceLoader/badproviders/throwsexception/Provider.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/badproviders/throwsexception/Service.java b/jdk/test/java/util/ServiceLoader/badproviders/throwsexception/Service.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/badproviders/throwsexception/Service.java
rename to jdk/test/java/util/ServiceLoader/badproviders/throwsexception/Service.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/src/pearscript/META-INF/services/javax.script.ScriptEngineFactory b/jdk/test/java/util/ServiceLoader/classpath/pearscript/META-INF/services/javax.script.ScriptEngineFactory
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/src/pearscript/META-INF/services/javax.script.ScriptEngineFactory
rename to jdk/test/java/util/ServiceLoader/classpath/pearscript/META-INF/services/javax.script.ScriptEngineFactory
diff --git a/jdk/test/java/util/ServiceLoader/modules/src/pearscript/org/pear/PearScript.java b/jdk/test/java/util/ServiceLoader/classpath/pearscript/org/pear/PearScript.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/src/pearscript/org/pear/PearScript.java
rename to jdk/test/java/util/ServiceLoader/classpath/pearscript/org/pear/PearScript.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/src/pearscript/org/pear/PearScriptEngineFactory.java b/jdk/test/java/util/ServiceLoader/classpath/pearscript/org/pear/PearScriptEngineFactory.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/src/pearscript/org/pear/PearScriptEngineFactory.java
rename to jdk/test/java/util/ServiceLoader/classpath/pearscript/org/pear/PearScriptEngineFactory.java
diff --git a/jdk/test/java/util/ServiceLoader/inheritance/NoInheritanceTest.java b/jdk/test/java/util/ServiceLoader/inheritance/NoInheritanceTest.java
new file mode 100644
index 00000000000..a7834a99847
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/inheritance/NoInheritanceTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @build test/*
+ * @run main/othervm test/p.Main
+ * @summary Basic test of ServiceLoader to ensure that static provider methods
+ * are explicitly declared and not inherited from super classes
+ */
diff --git a/jdk/test/java/util/ServiceLoader/inheritance/test/module-info.java b/jdk/test/java/util/ServiceLoader/inheritance/test/module-info.java
new file mode 100644
index 00000000000..668a2290ad4
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/inheritance/test/module-info.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import p.Main.*;
+
+module test {
+ exports p;
+ uses S;
+ provides S with P1, P2, P3;
+}
diff --git a/jdk/test/java/util/ServiceLoader/inheritance/test/p/Main.java b/jdk/test/java/util/ServiceLoader/inheritance/test/p/Main.java
new file mode 100644
index 00000000000..d11f0bae35e
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/inheritance/test/p/Main.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p;
+
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.stream.Collectors;
+
+/**
+ * Basic test of ServiceLoader with a provider interface and 3 provider
+ * implementations.
+ *
+ * The provider interface (test.Main.Provider) defines a static factory method
+ * name "provider" that locates a provider implementation. At least one of the
+ * provider implementations does not define a static "provider" method.
+ */
+
+public class Main {
+ public static void main(String[] args) {
+ List providers = ServiceLoader.load(S.class).stream()
+ .map(ServiceLoader.Provider::get)
+ .collect(Collectors.toList());
+ if (providers.size() != 3)
+ throw new RuntimeException("Expected 3 providers");
+ }
+
+ /**
+ * Service type
+ */
+ public static interface S {
+ }
+
+ /**
+ * Base implementation, its static provider method should never be called
+ */
+ public static class BaseProvider implements S {
+ protected BaseProvider() { }
+ public static S provider() {
+ throw new RuntimeException("Should not get here");
+ }
+ }
+
+ /**
+ * Provider implementation with public constructor.
+ */
+ public static class P1 extends BaseProvider {
+ public P1() { }
+ }
+
+ /**
+ * Provider implementation with static factory method.
+ */
+ public static class P2 extends BaseProvider {
+ private P2() { }
+ public static P2 provider() {
+ return new P2();
+ }
+ }
+
+ /**
+ * Provider implementation with static factory method and public
+ * constructor.
+ */
+ public static class P3 extends BaseProvider {
+ public P3() {
+ throw new RuntimeException("Should not get here");
+ }
+ private P3(int x) { }
+ public static S provider() {
+ return new P3(0);
+ }
+ }
+}
diff --git a/jdk/test/java/util/ServiceLoader/modules/modules/bananascript/module-info.java b/jdk/test/java/util/ServiceLoader/modules/bananascript/module-info.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/modules/bananascript/module-info.java
rename to jdk/test/java/util/ServiceLoader/modules/bananascript/module-info.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/modules/bananascript/org/banana/BananaScript.java b/jdk/test/java/util/ServiceLoader/modules/bananascript/org/banana/BananaScript.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/modules/bananascript/org/banana/BananaScript.java
rename to jdk/test/java/util/ServiceLoader/modules/bananascript/org/banana/BananaScript.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/modules/bananascript/org/banana/BananaScriptEngineFactory.java b/jdk/test/java/util/ServiceLoader/modules/bananascript/org/banana/BananaScriptEngineFactory.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/modules/bananascript/org/banana/BananaScriptEngineFactory.java
rename to jdk/test/java/util/ServiceLoader/modules/bananascript/org/banana/BananaScriptEngineFactory.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/p1/module-info.java b/jdk/test/java/util/ServiceLoader/modules/p1/module-info.java
new file mode 100644
index 00000000000..e3ed70f88e3
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/p1/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+module p1 {
+ requires s1;
+ provides p.S with q.P;
+}
diff --git a/jdk/test/java/util/ServiceLoader/modules/p1/q/P.java b/jdk/test/java/util/ServiceLoader/modules/p1/q/P.java
new file mode 100644
index 00000000000..26a0186ac25
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/p1/q/P.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package q;
+
+import p.S;
+
+public class P implements S { }
diff --git a/jdk/test/java/util/ServiceLoader/modules/p2/module-info.java b/jdk/test/java/util/ServiceLoader/modules/p2/module-info.java
new file mode 100644
index 00000000000..aeb81471512
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/p2/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+module p2 {
+ requires s2;
+ provides p.S with q.P;
+}
diff --git a/jdk/test/java/util/ServiceLoader/modules/p2/q/P.java b/jdk/test/java/util/ServiceLoader/modules/p2/q/P.java
new file mode 100644
index 00000000000..26a0186ac25
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/p2/q/P.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package q;
+
+import p.S;
+
+public class P implements S { }
diff --git a/jdk/test/java/util/ServiceLoader/modules/s1/module-info.java b/jdk/test/java/util/ServiceLoader/modules/s1/module-info.java
new file mode 100644
index 00000000000..784ad40a8df
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/s1/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+module s1 {
+ exports p;
+ uses p.S;
+}
diff --git a/jdk/test/java/util/ServiceLoader/modules/s1/p/S.java b/jdk/test/java/util/ServiceLoader/modules/s1/p/S.java
new file mode 100644
index 00000000000..e9ecc6f9949
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/s1/p/S.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package p;
+
+public interface S { }
diff --git a/jdk/test/java/util/ServiceLoader/modules/s2/module-info.java b/jdk/test/java/util/ServiceLoader/modules/s2/module-info.java
new file mode 100644
index 00000000000..b1d8f3ed462
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/s2/module-info.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+module s2 {
+ exports p;
+}
diff --git a/jdk/test/java/util/ServiceLoader/modules/s2/p/S.java b/jdk/test/java/util/ServiceLoader/modules/s2/p/S.java
new file mode 100644
index 00000000000..e9ecc6f9949
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/s2/p/S.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package p;
+
+public interface S { }
diff --git a/jdk/test/java/util/ServiceLoader/modules/modules/test1/module-info.java b/jdk/test/java/util/ServiceLoader/modules/test1/module-info.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/modules/test1/module-info.java
rename to jdk/test/java/util/ServiceLoader/modules/test1/module-info.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/modules/test1/p/ProviderFactory.java b/jdk/test/java/util/ServiceLoader/modules/test1/p/ProviderFactory.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/modules/test1/p/ProviderFactory.java
rename to jdk/test/java/util/ServiceLoader/modules/test1/p/ProviderFactory.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/modules/test1/p/Service.java b/jdk/test/java/util/ServiceLoader/modules/test1/p/Service.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/modules/test1/p/Service.java
rename to jdk/test/java/util/ServiceLoader/modules/test1/p/Service.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/modules/test2/module-info.java b/jdk/test/java/util/ServiceLoader/modules/test2/module-info.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/modules/test2/module-info.java
rename to jdk/test/java/util/ServiceLoader/modules/test2/module-info.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/modules/test2/p/Provider.java b/jdk/test/java/util/ServiceLoader/modules/test2/p/Provider.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/modules/test2/p/Provider.java
rename to jdk/test/java/util/ServiceLoader/modules/test2/p/Provider.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/modules/test2/p/Service.java b/jdk/test/java/util/ServiceLoader/modules/test2/p/Service.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/modules/test2/p/Service.java
rename to jdk/test/java/util/ServiceLoader/modules/test2/p/Service.java
diff --git a/jdk/test/java/util/ServiceLoader/nouses/NoUsesTest.java b/jdk/test/java/util/ServiceLoader/nouses/NoUsesTest.java
new file mode 100644
index 00000000000..641574b77d1
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/nouses/NoUsesTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @modules java.scripting
+ * @build test/*
+ * @run main/othervm test/p.Main
+ * @summary Basic test of ServiceLoader.load from named modules that does
+ * does delcare the use
+ */
diff --git a/jdk/test/java/util/ServiceLoader/nouses/test/module-info.java b/jdk/test/java/util/ServiceLoader/nouses/test/module-info.java
new file mode 100644
index 00000000000..1bcf5944728
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/nouses/test/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module test {
+ exports p;
+ requires java.scripting;
+}
diff --git a/jdk/test/java/util/ServiceLoader/nouses/test/p/Main.java b/jdk/test/java/util/ServiceLoader/nouses/test/p/Main.java
new file mode 100644
index 00000000000..ce8ee0fcbb6
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/nouses/test/p/Main.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p;
+
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
+import javax.script.ScriptEngineFactory;
+
+public class Main {
+
+ public static void main(String[] args) {
+ Module thisModule = Main.class.getModule();
+ assertTrue(thisModule.isNamed());
+
+ // this module does not declare that it uses ScriptEngineFactory
+ assertFalse(thisModule.canUse(ScriptEngineFactory.class));
+ try {
+ ServiceLoader.load(ScriptEngineFactory.class);
+ assertTrue(false);
+ } catch (ServiceConfigurationError expected) { }
+
+ // invoke addUses and retry
+ thisModule.addUses(ScriptEngineFactory.class);
+ ServiceLoader.load(ScriptEngineFactory.class).findFirst();
+ }
+
+ static void assertFalse(boolean value) {
+ if (value) throw new RuntimeException();
+ }
+
+ static void assertTrue(boolean value) {
+ if (!value) throw new RuntimeException();
+ }
+}
diff --git a/jdk/test/java/util/ServiceLoader/security/SecurityTest.java b/jdk/test/java/util/ServiceLoader/security/SecurityTest.java
new file mode 100644
index 00000000000..5a680355277
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/security/SecurityTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @build test/*
+ * @run testng/othervm test/p.Tests
+ * @summary Tests to exercise ServiceLoader with a security manager
+ */
diff --git a/jdk/test/java/util/ServiceLoader/security/test/module-info.java b/jdk/test/java/util/ServiceLoader/security/test/module-info.java
new file mode 100644
index 00000000000..f9d02cfb345
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/security/test/module-info.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import p.Tests.*;
+
+module test {
+ uses S1;
+ uses S2;
+ provides S1 with P1;
+ provides S2 with P2;
+ requires testng;
+ exports p to testng;
+}
diff --git a/jdk/test/java/util/ServiceLoader/security/test/p/Tests.java b/jdk/test/java/util/ServiceLoader/security/test/p/Tests.java
new file mode 100644
index 00000000000..bccc14cc9bd
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/security/test/p/Tests.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2017, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p;
+
+import java.security.AccessControlContext;
+import java.security.AccessControlException;
+import java.security.AccessController;
+import java.security.AllPermission;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
+import java.util.ServiceLoader.Provider;
+import static java.security.AccessController.doPrivileged;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeTest;
+import static org.testng.Assert.*;
+
+/**
+ * Basic tests with a security manager to ensure that the provider code
+ * is run with permissions restricted by whatever created the ServiceLoader
+ * object.
+ */
+
+public class Tests {
+
+ static final Permission PERM = new RuntimePermission("eatMuffin");
+
+ static PrivilegedAction> loadAction(Class