--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/data/docs-resources/specs/resources/jdk-default.css Thu May 04 17:54:50 2017 +0000
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+body {
+ margin: 2em 2em;
+ font-family: DejaVu Sans, Bitstream Vera Sans, Luxi Sans, Verdana, Arial, Helvetica;
+ font-size: 10pt;
+ line-height: 1.4;
+}
+
+pre, code, tt {
+ font-family: DejaVu Sans Mono, Bitstream Vera Sans Mono, Luxi Mono,
+ Courier New, monospace;
+}
+
+blockquote {
+ margin: 1.5ex 0em 1.5ex 2em;
+}
+
+p {
+ padding: 0pt;
+ margin: 1ex 0em;
+}
+
+p:first-child, pre:first-child { margin-top: 0pt; }
+
+h1 {
+ font-weight: bold;
+ padding: 0pt;
+ margin: 2ex .5ex 1ex 0pt;
+}
+
+h1:first-child, h2:first-child {
+ margin-top: 0ex;
+}
+
+h2 {
+ font-weight: bold;
+ padding: 0pt;
+ margin: 2ex 0pt 1ex 0pt;
+}
+
+h3 {
+ font-weight: bold;
+ padding: 0pt;
+ margin: 1.5ex 0pt 1ex 0pt;
+}
+
+h4 {
+ font-weight: bold;
+ padding: 0pt;
+ margin: 1.5ex 0pt 1ex 0pt;
+}
+
+a:link {
+ color: #437291;
+}
+
+a:visited {
+ color: #666666;
+}
+
+a[href]:hover {
+ color: #e76f00;
+}
+
+a img {
+ border-width: 0px;
+}
+
+img {
+ background: white;
+}
+
+table {
+ border-collapse: collapse;
+ margin-left: 15px;
+ margin-right: 15px;
+}
+
+th, td {
+ padding: 3px;
+ vertical-align: top;
+}
+
+table, th, td {
+ border: 1px solid black;
+}
+
+caption {
+ text-align: left;
+ font-style: italic;
+ text-indent: 15px;
+ margin-bottom:10px;
+}
+
+tr:nth-child(even) {
+ background: #DDD;
+}
+
+tr:nth-child(odd) {
+ background: #FFF;
+}
+
+th {
+ background: #DDF;
+}
--- a/jdk/make/mapfiles/libinstrument/mapfile-vers Thu May 04 16:38:09 2017 +0000
+++ b/jdk/make/mapfiles/libinstrument/mapfile-vers Thu May 04 17:54:50 2017 +0000
@@ -39,6 +39,7 @@
Java_sun_instrument_InstrumentationImpl_getObjectSize0;
Java_sun_instrument_InstrumentationImpl_appendToClassLoaderSearch0;
Java_sun_instrument_InstrumentationImpl_setNativeMethodPrefixes;
+ Java_sun_instrument_InstrumentationImpl_loadAgent0;
local:
*;
};
--- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Thu May 04 17:54:50 2017 +0000
@@ -119,18 +119,24 @@
* The Java run-time has the following built-in class loaders:
*
* <ul>
- * <li>Bootstrap class loader.
+ * <li><p>Bootstrap class loader.
* It is the virtual machine's built-in class loader, typically represented
* as {@code null}, and does not have a parent.</li>
- * <li>{@linkplain #getPlatformClassLoader() Platform class loader}.
+ * <li><p>{@linkplain #getPlatformClassLoader() Platform class loader}.
* All <em>platform classes</em> are visible to the platform class loader
* that can be used as the parent of a {@code ClassLoader} instance.
* Platform classes include Java SE platform APIs, their implementation
* classes and JDK-specific run-time classes that are defined by the
- * platform class loader or its ancestors.</li>
- * <li>{@linkplain #getSystemClassLoader() System class loader}.
- * It is also known as <em>application class
- * loader</em> and is distinct from the platform class loader.
+ * platform class loader or its ancestors.
+ * <p> To allow for upgrading/overriding of modules defined to the platform
+ * class loader, and where classes in the upgraded version link to
+ * classes in modules defined to the application class loader, the
+ * platform class loader may delegate to the application class loader.
+ * In other words, classes in named modules defined to the application
+ * class loader may be visible to the platform class loader. </li>
+ * <li><p>{@linkplain #getSystemClassLoader() System class loader}.
+ * It is also known as <em>application class loader</em> and is distinct
+ * from the platform class loader.
* The system class loader is typically used to define classes on the
* application class path, module path, and JDK-specific tools.
* The platform class loader is a parent or an ancestor of the system class
@@ -368,6 +374,10 @@
* Creates a new class loader of the specified name and using the
* specified parent class loader for delegation.
*
+ * @apiNote If the parent is specified as {@code null} (for the
+ * bootstrap class loader) then there is no guarantee that all platform
+ * classes are visible.
+ *
* @param name class loader name; or {@code null} if not named
* @param parent the parent class loader
*
@@ -390,9 +400,12 @@
* delegation.
*
* <p> If there is a security manager, its {@link
- * SecurityManager#checkCreateClassLoader()
- * checkCreateClassLoader} method is invoked. This may result in
- * a security exception. </p>
+ * SecurityManager#checkCreateClassLoader() checkCreateClassLoader} method
+ * is invoked. This may result in a security exception. </p>
+ *
+ * @apiNote If the parent is specified as {@code null} (for the
+ * bootstrap class loader) then there is no guarantee that all platform
+ * classes are visible.
*
* @param parent
* The parent class loader
@@ -2206,6 +2219,12 @@
* this class loader are searched recursively (parent by parent)
* for a {@code Package} of the given name.
*
+ * @apiNote The {@link #getPlatformClassLoader() platform class loader}
+ * may delegate to the application class loader but the application class
+ * loader is not its ancestor. When invoked on the platform class loader,
+ * this method will not find packages defined to the application
+ * class loader.
+ *
* @param name
* The <a href="#name">package name</a>
*
@@ -2251,6 +2270,14 @@
* {@code Package} object of the same package name, each defined by
* a different class loader in the class loader hierarchy.
*
+ * @apiNote The {@link #getPlatformClassLoader() platform class loader}
+ * may delegate to the application class loader. In other words,
+ * packages in modules defined to the application class loader may be
+ * visible to the platform class loader. On the other hand,
+ * the application class loader is not its ancestor and hence
+ * when invoked on the platform class loader, this method will not
+ * return any packages defined to the application class loader.
+ *
* @return The array of {@code Package} objects defined by this
* class loader and its ancestors
*
--- a/jdk/src/java.base/share/classes/java/lang/Module.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/Module.java Thu May 04 17:54:50 2017 +0000
@@ -57,6 +57,7 @@
import jdk.internal.loader.BootLoader;
import jdk.internal.misc.JavaLangAccess;
import jdk.internal.misc.SharedSecrets;
+import jdk.internal.module.ModuleLoaderMap;
import jdk.internal.module.ServicesCatalog;
import jdk.internal.module.Resources;
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
@@ -215,8 +216,8 @@
}
/**
- * Returns the layer that contains this module or {@code null} if this
- * module is not in a layer.
+ * Returns the module layer that contains this module or {@code null} if
+ * this module is not in a module layer.
*
* A module layer contains named modules and therefore this method always
* returns {@code null} when invoked on an unnamed module.
@@ -691,6 +692,13 @@
* <p> This method has no effect if the package is already <em>open</em>
* to the given module. </p>
*
+ * @apiNote This method can be used for cases where a <em>consumer
+ * module</em> uses a qualified opens to open a package to an <em>API
+ * module</em> but where the reflective access to the members of classes in
+ * the consumer module is delegated to code in another module. Code in the
+ * API module can use this method to open the package in the consumer module
+ * to the other module.
+ *
* @param pn
* The package name
* @param other
@@ -1077,7 +1085,7 @@
if (loader != null) {
moduleToLoader.put(name, loader);
loaders.add(loader);
- } else if (!isBootLayer) {
+ } else if (!(clf instanceof ModuleLoaderMap.Mapper)) {
throw new IllegalArgumentException("loader can't be 'null'");
}
}
@@ -1458,11 +1466,11 @@
* encapsulated. </li>
*
* <li> A <em>package name</em> is derived from the resource name. If
- * the package name is a {@link #getPackages() package} in the module
- * then the resource can only be located by the caller of this method
- * when the package is {@link #isOpen(String,Module) open} to at least
- * the caller's module. If the resource is not in a package in the module
- * then the resource is not encapsulated. </li>
+ * the package name is a {@linkplain #getPackages() package} in the
+ * module then the resource can only be located by the caller of this
+ * method when the package is {@linkplain #isOpen(String,Module) open}
+ * to at least the caller's module. If the resource is not in a
+ * package in the module then the resource is not encapsulated. </li>
* </ul>
*
* <p> In the above, the <em>package name</em> for a resource is derived
@@ -1521,8 +1529,7 @@
}
// locate resource in module
- JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
- URL url = jla.findResource(loader, mn, name);
+ URL url = loader.findResource(mn, name);
if (url != null) {
try {
return url.openStream();
--- a/jdk/src/java.base/share/classes/java/lang/SecurityManager.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/SecurityManager.java Thu May 04 17:54:50 2017 +0000
@@ -25,10 +25,10 @@
package java.lang;
-import java.lang.RuntimePermission;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Exports;
import java.lang.module.ModuleDescriptor.Opens;
+import java.lang.module.ModuleReference;
import java.lang.reflect.Member;
import java.io.FileDescriptor;
import java.io.File;
@@ -42,12 +42,15 @@
import java.security.Security;
import java.security.SecurityPermission;
import java.util.HashSet;
+import java.util.Map;
import java.util.Objects;
import java.util.PropertyPermission;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
-import java.util.stream.Stream;
+import jdk.internal.module.ModuleBootstrap;
+import jdk.internal.module.ModuleLoaderMap;
import jdk.internal.reflect.CallerSensitive;
import sun.security.util.SecurityConstants;
@@ -1431,29 +1434,29 @@
return packages;
}
- // The non-exported packages of the modules in the boot layer that are
- // loaded by the platform class loader or its ancestors. A non-exported
- // package is a package that either is not exported at all by its containing
- // module or is exported in a qualified fashion by its containing module.
- private static final Set<String> nonExportedPkgs;
-
+ // The non-exported packages in modules defined to the boot or platform
+ // class loaders. A non-exported package is a package that is not exported
+ // or is only exported to specific modules.
+ private static final Map<String, Boolean> nonExportedPkgs = new ConcurrentHashMap<>();
static {
- // Get the modules in the boot layer
- Stream<Module> bootLayerModules = ModuleLayer.boot().modules().stream();
+ addNonExportedPackages(ModuleLayer.boot());
+ }
- // Filter out the modules loaded by the boot or platform loader
- PrivilegedAction<Set<Module>> pa = () ->
- bootLayerModules.filter(SecurityManager::isBootOrPlatformModule)
- .collect(Collectors.toSet());
- Set<Module> modules = AccessController.doPrivileged(pa);
+ /**
+ * Record the non-exported packages of the modules in the given layer
+ */
+ static void addNonExportedPackages(ModuleLayer layer) {
+ Set<String> bootModules = ModuleLoaderMap.bootModules();
+ Set<String> platformModules = ModuleLoaderMap.platformModules();
+ layer.modules().stream()
+ .map(Module::getDescriptor)
+ .filter(md -> bootModules.contains(md.name())
+ || platformModules.contains(md.name()))
+ .map(SecurityManager::nonExportedPkgs)
+ .flatMap(Set::stream)
+ .forEach(pn -> nonExportedPkgs.put(pn, Boolean.TRUE));
+ }
- // Filter out the non-exported packages
- nonExportedPkgs = modules.stream()
- .map(Module::getDescriptor)
- .map(SecurityManager::nonExportedPkgs)
- .flatMap(Set::stream)
- .collect(Collectors.toSet());
- }
/**
* Called by java.security.Security
@@ -1468,14 +1471,6 @@
}
/**
- * Returns true if the module's loader is the boot or platform loader.
- */
- private static boolean isBootOrPlatformModule(Module m) {
- return m.getClassLoader() == null ||
- m.getClassLoader() == ClassLoader.getPlatformClassLoader();
- }
-
- /**
* Returns the non-exported packages of the specified module.
*/
private static Set<String> nonExportedPkgs(ModuleDescriptor md) {
@@ -1535,7 +1530,7 @@
Objects.requireNonNull(pkg, "package name can't be null");
// check if pkg is not exported to all modules
- if (nonExportedPkgs.contains(pkg)) {
+ if (nonExportedPkgs.containsKey(pkg)) {
checkPermission(
new RuntimePermission("accessClassInPackage." + pkg));
return;
@@ -1634,7 +1629,7 @@
Objects.requireNonNull(pkg, "package name can't be null");
// check if pkg is not exported to all modules
- if (nonExportedPkgs.contains(pkg)) {
+ if (nonExportedPkgs.containsKey(pkg)) {
checkPermission(
new RuntimePermission("defineClassInPackage." + pkg));
return;
--- a/jdk/src/java.base/share/classes/java/lang/System.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/System.java Thu May 04 17:54:50 2017 +0000
@@ -41,7 +41,6 @@
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URI;
-import java.net.URL;
import java.security.AccessControlContext;
import java.security.ProtectionDomain;
import java.security.AccessController;
@@ -2111,9 +2110,6 @@
public Class<?> findBootstrapClassOrNull(ClassLoader cl, String name) {
return cl.findBootstrapClassOrNull(name);
}
- public URL findResource(ClassLoader cl, String mn, String name) throws IOException {
- return cl.findResource(mn, name);
- }
public Stream<Package> packages(ClassLoader cl) {
return cl.packages();
}
@@ -2123,6 +2119,9 @@
public String fastUUID(long lsb, long msb) {
return Long.fastUUID(lsb, msb);
}
+ public void addNonExportedPackages(ModuleLayer layer) {
+ SecurityManager.addNonExportedPackages(layer);
+ }
public void invalidatePackageAccessCache() {
SecurityManager.invalidatePackageAccessCache();
}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Thu May 04 17:54:50 2017 +0000
@@ -876,9 +876,7 @@
* accessible to the class. The {@code PACKAGE} lookup mode serves to authenticate
* that the lookup object was created by a caller in the runtime package (or derived
* from a lookup originally created by suitably privileged code to a target class in
- * the runtime package). The lookup modes cannot include {@link #PRIVATE PRIVATE}
- * access. A lookup with {@code PRIVATE} access can be downgraded to drop this lookup
- * mode with the {@linkplain #dropLookupMode(int) dropLookupMode} method. </p>
+ * the runtime package). </p>
*
* <p> The {@code bytes} parameter is the class bytes of a valid class file (as defined
* by the <em>The Java Virtual Machine Specification</em>) with a class name in the
@@ -896,7 +894,6 @@
* @throws IllegalArgumentException the bytes are for a class in a different package
* to the lookup class
* @throws IllegalAccessException if this lookup does not have {@code PACKAGE} access
- * @throws UnsupportedOperationException if the lookup class has {@code PRIVATE} access
* @throws LinkageError if the class is malformed ({@code ClassFormatError}), cannot be
* verified ({@code VerifyError}), is already defined, or another linkage error occurs
* @throws SecurityException if denied by the security manager
@@ -911,8 +908,6 @@
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkPermission(new RuntimePermission("defineClass"));
- if (hasPrivateAccess())
- throw new UnsupportedOperationException("PRIVATE access not supported");
if ((lookupModes() & PACKAGE) == 0)
throw new IllegalAccessException("Lookup does not have PACKAGE access");
assert (lookupModes() & (MODULE|PUBLIC)) != 0;
--- a/jdk/src/java.base/share/classes/java/lang/module/Configuration.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/module/Configuration.java Thu May 04 17:54:50 2017 +0000
@@ -109,20 +109,17 @@
private final Set<ResolvedModule> modules;
private final Map<String, ResolvedModule> nameToModule;
- // module constraints on target
- private final String osName;
- private final String osArch;
+ // constraint on target platform
+ private final String targetPlatform;
- String osName() { return osName; }
- String osArch() { return osArch; }
+ String targetPlatform() { return targetPlatform; }
private Configuration() {
this.parents = Collections.emptyList();
this.graph = Collections.emptyMap();
this.modules = Collections.emptySet();
this.nameToModule = Collections.emptyMap();
- this.osName = null;
- this.osArch = null;
+ this.targetPlatform = null;
}
private Configuration(List<Configuration> parents,
@@ -147,8 +144,7 @@
this.modules = Set.of(moduleArray);
this.nameToModule = Map.ofEntries(nameEntries);
- this.osName = resolver.osName();
- this.osArch = resolver.osArch();
+ this.targetPlatform = resolver.targetPlatform();
}
/**
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java Thu May 04 17:54:50 2017 +0000
@@ -99,6 +99,7 @@
*
* @see ModuleDescriptor#modifiers()
* @since 9
+ * @spec JPMS
*/
public static enum Modifier {
/**
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java Thu May 04 17:54:50 2017 +0000
@@ -286,8 +286,9 @@
* class names of provider classes. </p></li>
*
* <li><p> If the JAR file has a {@code Main-Class} attribute in its
- * main manifest then its value is the module {@link
- * ModuleDescriptor#mainClass() main class}. </p></li>
+ * main manifest, its value is a legal class name, and its package is
+ * in the set of packages derived for the module, then the value is the
+ * module {@linkplain ModuleDescriptor#mainClass() main class}. </p></li>
*
* </ul>
*
@@ -298,8 +299,7 @@
* 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, or where the module main class is not
- * a legal class name or its package is not in the module. </p>
+ * packages derived for the module. </p>
*
* <p> In addition to JAR files, an implementation may also support modules
* that are packaged in other implementation specific module formats. If
--- a/jdk/src/java.base/share/classes/java/lang/module/Resolver.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/module/Resolver.java Thu May 04 17:54:50 2017 +0000
@@ -28,6 +28,7 @@
import java.io.PrintStream;
import java.lang.module.ModuleDescriptor.Provides;
import java.lang.module.ModuleDescriptor.Requires.Modifier;
+import java.net.URI;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
@@ -38,10 +39,8 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.Optional;
import java.util.Set;
-import java.util.StringJoiner;
import java.util.stream.Collectors;
import jdk.internal.module.ModuleHashes;
@@ -69,12 +68,10 @@
// true if all automatic modules have been found
private boolean haveAllAutomaticModules;
- // module constraints on target platform
- private String osName;
- private String osArch;
+ // constraint on target platform
+ private String targetPlatform;
- String osName() { return osName; }
- String osArch() { return osArch; }
+ String targetPlatform() { return targetPlatform; }
/**
* @throws IllegalArgumentException if there are more than one parent and
@@ -89,37 +86,23 @@
this.afterFinder = afterFinder;
this.traceOutput = traceOutput;
- // record constraints on target platform, checking that they don't conflict
+ // record constraint on target platform, checking for conflicts
for (Configuration parent : parents) {
- String value = parent.osName();
+ String value = parent.targetPlatform();
if (value != null) {
- if (osName == null) {
- osName = value;
+ if (targetPlatform == null) {
+ targetPlatform = value;
} else {
- if (!value.equals(osName)) {
- failParentConflict("Operating System", osName, value);
- }
- }
- }
- value = parent.osArch();
- if (value != null) {
- if (osArch == null) {
- osArch = value;
- } else {
- if (!value.equals(osArch)) {
- failParentConflict("OS architecture", osArch, value);
+ if (!value.equals(targetPlatform)) {
+ String msg = "Parents have conflicting constraints on target" +
+ " platform: " + targetPlatform + ", " + value;
+ throw new IllegalArgumentException(msg);
}
}
}
}
}
- private void failParentConflict(String constraint, String s1, String s2) {
- String msg = "Parents have conflicting constraints on target "
- + constraint + ": " + s1 + ", " + s2;
- throw new IllegalArgumentException(msg);
- }
-
/**
* Resolves the given named modules.
*
@@ -147,8 +130,7 @@
}
if (isTracing()) {
- trace("Root module %s located", root);
- mref.location().ifPresent(uri -> trace(" (%s)", uri));
+ trace("root %s", nameAndInfo(mref));
}
addFoundModule(mref);
@@ -180,9 +162,7 @@
ModuleDescriptor other = mref.descriptor();
q.offer(other);
if (isTracing()) {
- trace("Automatic module %s located, required by %s",
- other.name(), descriptor.name());
- mref.location().ifPresent(uri -> trace(" (%s)", uri));
+ trace("%s requires %s", descriptor.name(), nameAndInfo(mref));
}
});
haveAllAutomaticModules = true;
@@ -213,21 +193,13 @@
}
}
+ if (isTracing() && !dn.equals("java.base")) {
+ trace("%s requires %s", descriptor.name(), nameAndInfo(mref));
+ }
+
if (!nameToReference.containsKey(dn)) {
addFoundModule(mref);
q.offer(mref.descriptor());
-
- if (isTracing()) {
- String prefix;
- if (mref.descriptor().isAutomatic()) {
- prefix = "Automatic module";
- } else {
- prefix = "Module";
- }
- trace(prefix + " %s located, required by %s",
- dn, descriptor.name());
- mref.location().ifPresent(uri -> trace(" (%s)", uri));
- }
}
}
@@ -291,6 +263,13 @@
do {
for (ModuleDescriptor descriptor : candidateConsumers) {
if (!descriptor.uses().isEmpty()) {
+
+ // the modules that provide at least one service
+ Set<ModuleDescriptor> modulesToBind = null;
+ if (isTracing()) {
+ modulesToBind = new HashSet<>();
+ }
+
for (String service : descriptor.uses()) {
Set<ModuleReference> mrefs = availableProviders.get(service);
if (mrefs != null) {
@@ -298,15 +277,13 @@
ModuleDescriptor provider = mref.descriptor();
if (!provider.equals(descriptor)) {
- trace("Module %s provides %s, used by %s",
- provider.name(), service, descriptor.name());
+ if (isTracing() && modulesToBind.add(provider)) {
+ trace("%s binds %s", descriptor.name(),
+ nameAndInfo(mref));
+ }
String pn = provider.name();
if (!nameToReference.containsKey(pn)) {
- if (isTracing()) {
- mref.location()
- .ifPresent(uri -> trace(" (%s)", uri));
- }
addFoundModule(mref);
q.push(provider);
}
@@ -349,59 +326,31 @@
if (mref instanceof ModuleReferenceImpl) {
ModuleTarget target = ((ModuleReferenceImpl)mref).moduleTarget();
if (target != null)
- checkTargetConstraints(mn, target);
+ checkTargetPlatform(mn, target);
}
nameToReference.put(mn, mref);
}
/**
- * Check that the module's constraints on the target platform do not
- * conflict with the constraints of other modules resolved so far or
- * modules in parent configurations.
+ * Check that the module's constraints on the target platform does
+ * conflict with the constraint of other modules resolved so far.
*/
- private void checkTargetConstraints(String mn, ModuleTarget target) {
- String value = target.osName();
+ private void checkTargetPlatform(String mn, ModuleTarget target) {
+ String value = target.targetPlatform();
if (value != null) {
- if (osName == null) {
- osName = value;
+ if (targetPlatform == null) {
+ targetPlatform = value;
} else {
- if (!value.equals(osName)) {
- failTargetConstraint(mn, target);
- }
- }
- }
- value = target.osArch();
- if (value != null) {
- if (osArch == null) {
- osArch = value;
- } else {
- if (!value.equals(osArch)) {
- failTargetConstraint(mn, target);
+ if (!value.equals(targetPlatform)) {
+ findFail("Module %s has constraints on target platform (%s)"
+ + " that conflict with other modules: %s", mn,
+ value, targetPlatform);
}
}
}
}
- private void failTargetConstraint(String mn, ModuleTarget target) {
- String s1 = targetAsString(osName, osArch);
- String s2 = targetAsString(target.osName(), target.osArch());
- findFail("Module %s has constraints on target platform (%s) that"
- + " conflict with other modules: %s", mn, s1, s2);
- }
-
- private String targetAsString(ModuleTarget target) {
- return targetAsString(target.osName(), target.osArch());
- }
-
- private String targetAsString(String osName, String osArch) {
- return new StringJoiner("-")
- .add(Objects.toString(osName, "*"))
- .add(Objects.toString(osArch, "*"))
- .toString();
- }
-
-
/**
* Execute post-resolution checks and returns the module graph of resolved
* modules as {@code Map}. The resolved modules will be in the given
@@ -412,12 +361,6 @@
Map<ResolvedModule, Set<ResolvedModule>> finish(Configuration cf,
boolean check)
{
- if (isTracing()) {
- trace("Result:");
- Set<String> names = nameToReference.keySet();
- names.stream().sorted().forEach(name -> trace(" %s", name));
- }
-
if (check) {
detectCycles();
checkHashes();
@@ -520,9 +463,8 @@
findFail("Unable to compute the hash of module %s", dn);
}
- // skip checking the hash if the module has been patched
ModuleReferenceImpl other = (ModuleReferenceImpl)mref2;
- if (other != null && !other.isPatched()) {
+ if (other != null) {
byte[] recordedHash = hashes.hashFor(dn);
byte[] actualHash = other.computeHash(algorithm);
if (actualHash == null)
@@ -965,9 +907,17 @@
private void trace(String fmt, Object ... args) {
if (traceOutput != null) {
- traceOutput.format("[Resolver] " + fmt, args);
+ traceOutput.format(fmt, args);
traceOutput.println();
}
}
+ private String nameAndInfo(ModuleReference mref) {
+ ModuleDescriptor descriptor = mref.descriptor();
+ StringBuilder sb = new StringBuilder(descriptor.name());
+ mref.location().ifPresent(uri -> sb.append(" " + uri));
+ if (descriptor.isAutomatic())
+ sb.append(" automatic");
+ return sb.toString();
+ }
}
--- a/jdk/src/java.base/share/classes/java/nio/file/FileSystems.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/java/nio/file/FileSystems.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -36,6 +36,8 @@
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
+import jdk.internal.misc.VM;
+
/**
* Factory methods for file systems. This class defines the {@link #getDefault
* getDefault} method to get the default file system and factory methods to
@@ -120,8 +122,8 @@
// if the property java.nio.file.spi.DefaultFileSystemProvider is
// set then its value is the name of the default provider (or a list)
- String propValue = System
- .getProperty("java.nio.file.spi.DefaultFileSystemProvider");
+ String prop = "java.nio.file.spi.DefaultFileSystemProvider";
+ String propValue = System.getProperty(prop);
if (propValue != null) {
for (String cn: propValue.split(",")) {
try {
@@ -184,7 +186,7 @@
* @return the default file system
*/
public static FileSystem getDefault() {
- if (jdk.internal.misc.VM.isBooted()) {
+ if (VM.isModuleSystemInited()) {
return DefaultFileSystemHolder.defaultFileSystem;
} else {
return BuiltinFileSystemHolder.builtinFileSystem;
--- a/jdk/src/java.base/share/classes/javax/crypto/CipherInputStream.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/javax/crypto/CipherInputStream.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, 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
@@ -93,7 +93,7 @@
// stream status
private boolean closed = false;
- /**
+ /*
* private convenience function.
*
* Entry condition: ostart = ofinish
--- a/jdk/src/java.base/share/classes/javax/crypto/CryptoPermission.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/javax/crypto/CryptoPermission.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -196,19 +196,19 @@
* Checks if the specified permission is "implied" by
* this object.
* <p>
- * More specifically, this method returns true if:<p>
+ * More specifically, this method returns true if:
* <ul>
- * <li> <i>p</i> is an instance of CryptoPermission, and<p>
+ * <li> <i>p</i> is an instance of CryptoPermission, and</li>
* <li> <i>p</i>'s algorithm name equals or (in the case of wildcards)
- * is implied by this permission's algorithm name, and<p>
+ * is implied by this permission's algorithm name, and</li>
* <li> <i>p</i>'s maximum allowable key size is less or
- * equal to this permission's maximum allowable key size, and<p>
+ * equal to this permission's maximum allowable key size, and</li>
* <li> <i>p</i>'s algorithm parameter spec equals or is
- * implied by this permission's algorithm parameter spec, and<p>
+ * implied by this permission's algorithm parameter spec, and</li>
* <li> <i>p</i>'s exemptionMechanism equals or
* is implied by this permission's
* exemptionMechanism (a <code>null</code> exemption mechanism
- * implies any other exemption mechanism).
+ * implies any other exemption mechanism).</li>
* </ul>
*
* @param p the permission to check against.
--- a/jdk/src/java.base/share/classes/javax/crypto/CryptoPolicyParser.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/javax/crypto/CryptoPolicyParser.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -46,10 +46,12 @@
*
* The format of a permission entry in the jurisdiction policy file is:
*
+ * <pre>{@code
* permission <crypto permission class name>[, <algorithm name>
* [[, <exemption mechanism name>][, <maxKeySize>
* [, <AlgrithomParameterSpec class name>, <parameters
* for constructing an AlgrithomParameterSpec object>]]]];
+ * }</pre>
*
* @author Sharon Liu
*
@@ -526,8 +528,7 @@
/**
* Each grant entry in the policy configuration file is represented by a
- * GrantEntry object. <p>
- *
+ * GrantEntry object.
* <p>
* For example, the entry
* <pre>
@@ -587,8 +588,7 @@
/**
* Each crypto permission entry in the policy configuration file is
- * represented by a CryptoPermissionEntry object. <p>
- *
+ * represented by a CryptoPermissionEntry object.
* <p>
* For example, the entry
* <pre>
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java Thu May 04 17:54:50 2017 +0000
@@ -172,12 +172,10 @@
}
/**
- * Register a module this this class loader. This has the effect of making
- * the types in the module visible.
+ * Register a module this class loader. This has the effect of making the
+ * types in the module visible.
*/
public void loadModule(ModuleReference mref) {
- assert !VM.isModuleSystemInited();
-
String mn = mref.descriptor().name();
if (nameToModule.putIfAbsent(mn, mref) != null) {
throw new InternalError(mn + " already defined to this loader");
@@ -191,6 +189,11 @@
+ other.mref().descriptor().name());
}
}
+
+ // clear resources cache if VM is already initialized
+ if (VM.isModuleSystemInited() && resourceCache != null) {
+ resourceCache = null;
+ }
}
/**
@@ -355,7 +358,10 @@
private List<URL> findMiscResource(String name) throws IOException {
SoftReference<Map<String, List<URL>>> ref = this.resourceCache;
Map<String, List<URL>> map = (ref != null) ? ref.get() : null;
- if (map != null) {
+ if (map == null) {
+ map = new ConcurrentHashMap<>();
+ this.resourceCache = new SoftReference<>(map);
+ } else {
List<URL> urls = map.get(name);
if (urls != null)
return urls;
@@ -381,23 +387,18 @@
}
}
}
- return result;
+ return (result != null) ? result : Collections.emptyList();
}
});
} catch (PrivilegedActionException pae) {
throw (IOException) pae.getCause();
}
- // only cache resources after all modules have been defined
+ // only cache resources after VM is fully initialized
if (VM.isModuleSystemInited()) {
- if (map == null) {
- map = new ConcurrentHashMap<>();
- this.resourceCache = new SoftReference<>(map);
- }
- if (urls == null)
- urls = Collections.emptyList();
map.putIfAbsent(name, urls);
}
+
return urls;
}
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java Thu May 04 17:54:50 2017 +0000
@@ -25,13 +25,11 @@
package jdk.internal.misc;
-import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.module.ModuleDescriptor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.net.URI;
-import java.net.URL;
import java.security.AccessControlContext;
import java.security.ProtectionDomain;
import java.util.Map;
@@ -157,12 +155,6 @@
Class<?> findBootstrapClassOrNull(ClassLoader cl, String name);
/**
- * Returns a URL to a resource with the given name in a module that is
- * defined to the given class loader.
- */
- URL findResource(ClassLoader cl, String moduleName, String name) throws IOException;
-
- /**
* Returns the Packages for the given class loader.
*/
Stream<Package> packages(ClassLoader cl);
@@ -178,6 +170,11 @@
String fastUUID(long lsb, long msb);
/**
+ * Record the non-exported packages of the modules in the given layer
+ */
+ void addNonExportedPackages(ModuleLayer layer);
+
+ /**
* Invalidate package access cache
*/
void invalidatePackageAccessCache();
--- a/jdk/src/java.base/share/classes/jdk/internal/module/Checks.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/Checks.java Thu May 04 17:54:50 2017 +0000
@@ -25,6 +25,8 @@
package jdk.internal.module;
+import java.util.Set;
+
/**
* Utility class for checking module, package, and class names.
*/
@@ -45,18 +47,17 @@
int next;
int off = 0;
while ((next = name.indexOf('.', off)) != -1) {
- if (isJavaIdentifier(name, off, (next - off)) == -1) {
- String id = name.substring(off, next);
+ String id = name.substring(off, next);
+ if (!isJavaIdentifier(id)) {
throw new IllegalArgumentException(name + ": Invalid module name"
+ ": '" + id + "' is not a Java identifier");
}
off = next+1;
}
- int last = isJavaIdentifier(name, off, name.length() - off);
- if (last == -1) {
- String id = name.substring(off);
+ String last = name.substring(off);
+ if (!isJavaIdentifier(last)) {
throw new IllegalArgumentException(name + ": Invalid module name"
- + ": '" + id + "' is not a Java identifier");
+ + ": '" + last + "' is not a Java identifier");
}
return name;
}
@@ -68,14 +69,13 @@
int next;
int off = 0;
while ((next = name.indexOf('.', off)) != -1) {
- if (isJavaIdentifier(name, off, (next - off)) == -1)
+ String id = name.substring(off, next);
+ if (!isJavaIdentifier(id))
return false;
off = next+1;
}
- int last = isJavaIdentifier(name, off, name.length() - off);
- if (last == -1)
- return false;
- return true;
+ String last = name.substring(off);
+ return isJavaIdentifier(last);
}
/**
@@ -144,12 +144,13 @@
int next;
int off = 0;
while ((next = name.indexOf('.', off)) != -1) {
- if (isJavaIdentifier(name, off, (next - off)) == -1)
+ String id = name.substring(off, next);
+ if (!isJavaIdentifier(id))
return false;
off = next+1;
}
- int count = name.length() - off;
- return (isJavaIdentifier(name, off, count) != -1);
+ String last = name.substring(off);
+ return isJavaIdentifier(last);
}
/**
@@ -164,76 +165,99 @@
int next;
int off = 0;
while ((next = name.indexOf('.', off)) != -1) {
- if (isJavaIdentifier(name, off, (next - off)) == -1) {
- String id = name.substring(off, next);
+ String id = name.substring(off, next);
+ if (!isJavaIdentifier(id)) {
throw new IllegalArgumentException(name + ": Invalid " + what
+ ": '" + id + "' is not a Java identifier");
}
off = next + 1;
}
- if (isJavaIdentifier(name, off, name.length() - off) == -1) {
- String id = name.substring(off, name.length());
+ String last = name.substring(off);
+ if (!isJavaIdentifier(last)) {
throw new IllegalArgumentException(name + ": Invalid " + what
- + ": '" + id + "' is not a Java identifier");
+ + ": '" + last + "' is not a Java identifier");
}
return name;
}
/**
- * Returns {@code true} if a given legal module name contains an identifier
- * that doesn't end with a Java letter.
+ * Returns true if the given char sequence is a legal Java identifier,
+ * otherwise false.
*/
- public static boolean hasJavaIdentifierWithTrailingDigit(String name) {
- // quick scan to allow names that are just ASCII without digits
- boolean needToParse = false;
- int i = 0;
- while (i < name.length()) {
- int c = name.charAt(i);
- if (c > 0x7F || (c >= '0' && c <= '9')) {
- needToParse = true;
- break;
- }
- i++;
- }
- if (!needToParse)
+ private static boolean isJavaIdentifier(CharSequence cs) {
+ if (cs.length() == 0 || RESERVED.contains(cs))
return false;
- // slow path
- int next;
- int off = 0;
- while ((next = name.indexOf('.', off)) != -1) {
- int last = isJavaIdentifier(name, off, (next - off));
- if (!Character.isJavaIdentifierStart(last))
- return true;
- off = next+1;
- }
- int last = isJavaIdentifier(name, off, name.length() - off);
- if (!Character.isJavaIdentifierStart(last))
- return true;
- return false;
-
- }
+ int first = Character.codePointAt(cs, 0);
+ if (!Character.isJavaIdentifierStart(first))
+ return false;
- /**
- * Checks if a char sequence is a legal Java identifier, returning the code
- * point of the last character if legal or {@code -1} if not legal.
- */
- private static int isJavaIdentifier(CharSequence cs, int offset, int count) {
- if (count == 0)
- return -1;
- int first = Character.codePointAt(cs, offset);
- if (!Character.isJavaIdentifierStart(first))
- return -1;
-
- int cp = first;
int i = Character.charCount(first);
- while (i < count) {
- cp = Character.codePointAt(cs, offset+i);
+ while (i < cs.length()) {
+ int cp = Character.codePointAt(cs, i);
if (!Character.isJavaIdentifierPart(cp))
- return -1;
+ return false;
i += Character.charCount(cp);
}
- return cp;
+ return true;
}
+
+ // keywords, boolean and null literals, not allowed in identifiers
+ private static final Set<String> RESERVED = Set.of(
+ "abstract",
+ "assert",
+ "boolean",
+ "break",
+ "byte",
+ "case",
+ "catch",
+ "char",
+ "class",
+ "const",
+ "continue",
+ "default",
+ "do",
+ "double",
+ "else",
+ "enum",
+ "extends",
+ "final",
+ "finally",
+ "float",
+ "for",
+ "goto",
+ "if",
+ "implements",
+ "import",
+ "instanceof",
+ "int",
+ "interface",
+ "long",
+ "native",
+ "new",
+ "package",
+ "private",
+ "protected",
+ "public",
+ "return",
+ "short",
+ "static",
+ "strictfp",
+ "super",
+ "switch",
+ "synchronized",
+ "this",
+ "throw",
+ "throws",
+ "transient",
+ "try",
+ "void",
+ "volatile",
+ "while",
+ "true",
+ "false",
+ "null",
+ "_"
+ );
}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java Thu May 04 17:54:50 2017 +0000
@@ -549,34 +549,26 @@
* u2 attribute_name_index;
* u4 attribute_length;
*
- * // index to CONSTANT_utf8_info structure with the OS name
- * u2 os_name_index;
- * // index to CONSTANT_utf8_info structure with the OS arch
- * u2 os_arch_index
+ * // index to CONSTANT_utf8_info structure with the target platform
+ * u2 target_platform_index;
* }
*
* } </pre>
*/
public static class ModuleTargetAttribute extends Attribute {
- private final String osName;
- private final String osArch;
+ private final String targetPlatform;
- public ModuleTargetAttribute(String osName, String osArch) {
+ public ModuleTargetAttribute(String targetPlatform) {
super(MODULE_TARGET);
- this.osName = osName;
- this.osArch = osArch;
+ this.targetPlatform = targetPlatform;
}
public ModuleTargetAttribute() {
- this(null, null);
+ this(null);
}
- public String osName() {
- return osName;
- }
-
- public String osArch() {
- return osArch;
+ public String targetPlatform() {
+ return targetPlatform;
}
@Override
@@ -588,20 +580,14 @@
Label[] labels)
{
- String osName = null;
- String osArch = null;
+ String targetPlatform = null;
- int name_index = cr.readUnsignedShort(off);
- if (name_index != 0)
- osName = cr.readUTF8(off, buf);
+ int target_platform_index = cr.readUnsignedShort(off);
+ if (target_platform_index != 0)
+ targetPlatform = cr.readUTF8(off, buf);
off += 2;
- int arch_index = cr.readUnsignedShort(off);
- if (arch_index != 0)
- osArch = cr.readUTF8(off, buf);
- off += 2;
-
- return new ModuleTargetAttribute(osName, osArch);
+ return new ModuleTargetAttribute(targetPlatform);
}
@Override
@@ -613,15 +599,10 @@
{
ByteVector attr = new ByteVector();
- int name_index = 0;
- if (osName != null && osName.length() > 0)
- name_index = cw.newUTF8(osName);
- attr.putShort(name_index);
-
- int arch_index = 0;
- if (osArch != null && osArch.length() > 0)
- arch_index = cw.newUTF8(osArch);
- attr.putShort(arch_index);
+ int target_platform_index = 0;
+ if (targetPlatform != null && targetPlatform.length() > 0)
+ target_platform_index = cw.newUTF8(targetPlatform);
+ attr.putShort(target_platform_index);
return attr;
}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java Thu May 04 17:54:50 2017 +0000
@@ -84,8 +84,9 @@
// The ModulePatcher for the initial configuration
private static final ModulePatcher patcher = initModulePatcher();
- // ModuleFinder for the initial configuration
- private static ModuleFinder initialFinder;
+ // ModuleFinders for the initial configuration
+ private static ModuleFinder unlimitedFinder;
+ private static ModuleFinder limitedFinder;
/**
* Returns the ModulePatcher for the initial configuration.
@@ -95,11 +96,20 @@
}
/**
- * Returns the ModuleFinder for the initial configuration
+ * Returns the ModuleFinder for the initial configuration before observability
+ * is limited by the --limit-modules command line option.
*/
- public static ModuleFinder finder() {
- assert initialFinder != null;
- return initialFinder;
+ public static ModuleFinder unlimitedFinder() {
+ assert unlimitedFinder != null;
+ return unlimitedFinder;
+ }
+
+ /**
+ * Returns the ModuleFinder for the initial configuration.
+ */
+ public static ModuleFinder limitedFinder() {
+ assert limitedFinder != null;
+ return limitedFinder;
}
/**
@@ -134,6 +144,11 @@
PerfCounters.defineBaseTime.addElapsedTimeFrom(t1);
+ // 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();
@@ -180,7 +195,8 @@
}
// --limit-modules
- String propValue = getAndRemoveProperty("jdk.module.limitmods");
+ unlimitedFinder = finder;
+ propValue = getAndRemoveProperty("jdk.module.limitmods");
if (propValue != null) {
Set<String> mods = new HashSet<>();
for (String mod: propValue.split(",")) {
@@ -188,6 +204,7 @@
}
finder = limitFinder(finder, mods, roots);
}
+ limitedFinder = finder;
// If there is no initial module specified then assume that the initial
// module is the unnamed module of the application class loader. This
@@ -267,7 +284,8 @@
}
PrintStream traceOutput = null;
- if (Boolean.getBoolean("jdk.launcher.traceResolver"))
+ propValue = getAndRemoveProperty("jdk.module.showModuleResolution");
+ if (propValue != null && Boolean.parseBoolean(propValue))
traceOutput = System.out;
// run the resolver to create the configuration
@@ -362,10 +380,21 @@
// total time to initialize
PerfCounters.bootstrapTime.addElapsedTimeFrom(t0);
- // remember the ModuleFinder
- initialFinder = finder;
+ return bootLayer;
+ }
- return bootLayer;
+ /**
+ * Create a "minimal" boot module layer that only contains java.base.
+ */
+ private static ModuleLayer createMinimalBootLayer() {
+ Configuration cf = SharedSecrets.getJavaLangModuleAccess()
+ .resolveAndBind(ModuleFinder.ofSystem(),
+ Set.of(JAVA_BASE),
+ false,
+ null);
+
+ Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
+ return ModuleLayer.empty().defineModules(cf, clf);
}
/**
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java Thu May 04 17:54:50 2017 +0000
@@ -138,7 +138,7 @@
}
/*
- * Utilty class
+ * Utility class
*/
static class Graph<T> {
private final Set<T> nodes;
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java Thu May 04 17:54:50 2017 +0000
@@ -546,21 +546,15 @@
private ModuleTarget readModuleTargetAttribute(DataInput in, ConstantPool cpool)
throws IOException
{
- String osName = null;
- String osArch = null;
-
- int name_index = in.readUnsignedShort();
- if (name_index != 0)
- osName = cpool.getUtf8(name_index);
+ String targetPlatform = null;
- int arch_index = in.readUnsignedShort();
- if (arch_index != 0)
- osArch = cpool.getUtf8(arch_index);
+ int index = in.readUnsignedShort();
+ if (index != 0)
+ targetPlatform = cpool.getUtf8(index);
- return new ModuleTarget(osName, osArch);
+ return new ModuleTarget(targetPlatform);
}
-
/**
* Reads the ModuleHashes attribute
*/
@@ -612,7 +606,6 @@
return new ModuleResolution(flags);
}
-
/**
* Returns true if the given attribute can be present at most once
* in the class file. Returns false otherwise.
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java Thu May 04 17:54:50 2017 +0000
@@ -62,9 +62,8 @@
// the value of the ModuleMainClass attribute
private String mainClass;
- // the values for the ModuleTarget attribute
- private String osName;
- private String osArch;
+ // the value for the ModuleTarget attribute
+ private String targetPlatform;
// the hashes for the ModuleHashes attribute
private ModuleHashes hashes;
@@ -108,11 +107,10 @@
}
/**
- * Sets the values for the ModuleTarget attribute.
+ * Sets the value for the ModuleTarget attribute.
*/
- public ModuleInfoExtender targetPlatform(String osName, String osArch) {
- this.osName = osName;
- this.osArch = osArch;
+ public ModuleInfoExtender targetPlatform(String targetPlatform) {
+ this.targetPlatform = targetPlatform;
return this;
}
@@ -199,8 +197,8 @@
cv.addAttribute(new ModulePackagesAttribute(packages));
if (mainClass != null)
cv.addAttribute(new ModuleMainClassAttribute(mainClass));
- if (osName != null || osArch != null)
- cv.addAttribute(new ModuleTargetAttribute(osName, osArch));
+ if (targetPlatform != null)
+ cv.addAttribute(new ModuleTargetAttribute(targetPlatform));
if (hashes != null)
cv.addAttribute(new ModuleHashesAttribute(hashes));
if (moduleResolution != null)
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java Thu May 04 17:54:50 2017 +0000
@@ -66,10 +66,9 @@
// write ModuleMainClass if the module has a main class
md.mainClass().ifPresent(mc -> cw.visitAttribute(new ModuleMainClassAttribute(mc)));
- // write ModuleTarget if there is a platform OS/arch
+ // write ModuleTarget if there is a target platform
if (target != null) {
- cw.visitAttribute(new ModuleTargetAttribute(target.osName(),
- target.osArch()));
+ cw.visitAttribute(new ModuleTargetAttribute(target.targetPlatform()));
}
cw.visitEnd();
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleLoaderMap.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleLoaderMap.java Thu May 04 17:54:50 2017 +0000
@@ -37,36 +37,66 @@
/**
- * The module to class loader map. The list of boot modules and platform modules
- * are generated at build time.
+ * Supports the mapping of modules to class loaders. The set of modules mapped
+ * to the boot and platform class loaders is generated at build time from
+ * this source file.
*/
-final class ModuleLoaderMap {
+public final class ModuleLoaderMap {
+
+ /**
+ * Maps the system modules to the built-in class loaders.
+ */
+ public static final class Mapper implements Function<String, ClassLoader> {
+ private final Map<String, ClassLoader> map;
+
+ Mapper(Map<String, ClassLoader> map) {
+ this.map = map; // defensive copy not needed
+ }
+
+ @Override
+ public ClassLoader apply(String name) {
+ return map.get(name);
+ }
+ }
+
+ /**
+ * Returns the names of the modules defined to the boot loader.
+ */
+ public static Set<String> bootModules() {
+ // The list of boot modules generated at build time.
+ String[] BOOT_MODULES = new String[] { "@@BOOT_MODULE_NAMES@@" };
+ Set<String> bootModules = new HashSet<>(BOOT_MODULES.length);
+ for (String mn : BOOT_MODULES) {
+ bootModules.add(mn);
+ }
+ return bootModules;
+ }
+
+ /**
+ * Returns the names of the modules defined to the platform loader.
+ */
+ public static Set<String> platformModules() {
+ // The list of platform modules generated at build time.
+ String[] PLATFORM_MODULES = new String[] { "@@PLATFORM_MODULE_NAMES@@" };
+ Set<String> platformModules = new HashSet<>(PLATFORM_MODULES.length);
+ for (String mn : PLATFORM_MODULES) {
+ platformModules.add(mn);
+ }
+ return platformModules;
+ }
/**
* Returns the function to map modules in the given configuration to the
* built-in class loaders.
*/
static Function<String, ClassLoader> mappingFunction(Configuration cf) {
-
- // The list of boot modules and platform modules are generated at build time.
- final String[] BOOT_MODULES = new String[] { "@@BOOT_MODULE_NAMES@@" };
- final String[] PLATFORM_MODULES = new String[] { "@@PLATFORM_MODULE_NAMES@@" };
-
- Set<String> bootModules = new HashSet<>(BOOT_MODULES.length);
- for (String mn : BOOT_MODULES) {
- bootModules.add(mn);
- }
-
- Set<String> platformModules = new HashSet<>(PLATFORM_MODULES.length);
- for (String mn : PLATFORM_MODULES) {
- platformModules.add(mn);
- }
+ Set<String> bootModules = bootModules();
+ Set<String> platformModules = platformModules();
ClassLoader platformClassLoader = ClassLoaders.platformClassLoader();
ClassLoader appClassLoader = ClassLoaders.appClassLoader();
Map<String, ClassLoader> map = new HashMap<>();
-
for (ResolvedModule resolvedModule : cf.modules()) {
String mn = resolvedModule.name();
if (!bootModules.contains(mn)) {
@@ -77,12 +107,6 @@
}
}
}
-
- return new Function<String, ClassLoader> () {
- @Override
- public ClassLoader apply(String mn) {
- return map.get(mn);
- }
- };
+ return new Mapper(map);
}
}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java Thu May 04 17:54:50 2017 +0000
@@ -120,7 +120,7 @@
// JAR file - do not open as a multi-release JAR as this
// is not supported by the boot class loader
- try (JarFile jf = new JarFile(file.toFile())) {
+ try (JarFile jf = new JarFile(file.toString())) {
jf.stream()
.filter(e -> !e.isDirectory()
&& (!isAutomatic || e.getName().endsWith(".class")))
@@ -431,7 +431,7 @@
private final URL csURL;
JarResourceFinder(Path path) throws IOException {
- this.jf = new JarFile(path.toFile());
+ this.jf = new JarFile(path.toString());
this.csURL = path.toUri().toURL();
}
@@ -505,7 +505,7 @@
public Resource find(String name) throws IOException {
Path file = Resources.toFilePath(dir, name);
if (file != null) {
- return newResource(name, dir, file);
+ return newResource(name, dir, file);
} else {
return null;
}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModulePath.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModulePath.java Thu May 04 17:54:50 2017 +0000
@@ -59,6 +59,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
+import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import jdk.internal.jmod.JmodFile;
@@ -315,26 +316,42 @@
{
try {
+ // exploded module
if (attrs.isDirectory()) {
return readExplodedModule(entry); // may return null
- } else {
+ }
+
+ // JAR or JMOD file
+ if (attrs.isRegularFile()) {
String fn = entry.getFileName().toString();
- if (attrs.isRegularFile()) {
- if (fn.endsWith(".jar")) {
+ boolean isDefaultFileSystem = isDefaultFileSystem(entry);
+
+ // JAR file
+ if (fn.endsWith(".jar")) {
+ if (isDefaultFileSystem) {
return readJar(entry);
- } else if (isLinkPhase && fn.endsWith(".jmod")) {
- return readJMod(entry);
+ } else {
+ // the JAR file is in a custom file system so
+ // need to copy it to the local file system
+ Path tmpdir = Files.createTempDirectory("mlib");
+ Path target = Files.copy(entry, tmpdir.resolve(fn));
+ return readJar(target);
}
}
- return null;
+
+ // JMOD file
+ if (isDefaultFileSystem && isLinkPhase && fn.endsWith(".jmod")) {
+ return readJMod(entry);
+ }
}
+ return null;
+
} catch (InvalidModuleDescriptorException e) {
throw new FindException("Error reading module: " + entry, e);
}
}
-
/**
* Returns a string with the file name of the module if possible.
* If the module location is not a file URI then return the URI
@@ -434,7 +451,7 @@
* 3. 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
- * is mapped to the module descriptor mainClass
+ * is mapped to the module descriptor mainClass if possible
*/
private ModuleDescriptor deriveModuleDescriptor(JarFile jf)
throws IOException
@@ -530,12 +547,12 @@
String mainClass = attrs.getValue(Attributes.Name.MAIN_CLASS);
if (mainClass != null) {
mainClass = mainClass.replace("/", ".");
- String pn = packageName(mainClass);
- if (!packages.contains(pn)) {
- String msg = "Main-Class " + mainClass + " not in module";
- throw new InvalidModuleDescriptorException(msg);
+ if (Checks.isClassName(mainClass)) {
+ String pn = packageName(mainClass);
+ if (packages.contains(pn)) {
+ builder.mainClass(mainClass);
+ }
}
- builder.mainClass(mainClass);
}
}
@@ -617,6 +634,8 @@
}
return ModuleReferences.newJarModule(attrs, patcher, file);
+ } catch (ZipException e) {
+ throw new FindException("Error reading " + file, e);
}
}
@@ -733,6 +752,16 @@
}
}
+
+ /**
+ * Return true if a path locates a path in the default file system
+ */
+ private boolean isDefaultFileSystem(Path path) {
+ return path.getFileSystem().provider()
+ .getScheme().equalsIgnoreCase("file");
+ }
+
+
private static final PerfCounter scanTime
= PerfCounter.newPerfCounter("jdk.module.finder.modulepath.scanTime");
private static final PerfCounter moduleCount
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java Thu May 04 17:54:50 2017 +0000
@@ -25,6 +25,7 @@
package jdk.internal.module;
+import java.io.File;
import java.io.IOError;
import java.io.IOException;
import java.io.InputStream;
@@ -226,8 +227,8 @@
static JarFile newJarFile(Path path) {
try {
- return new JarFile(path.toFile(),
- true, // verify
+ return new JarFile(new File(path.toString()),
+ true, // verify
ZipFile.OPEN_READ,
JarFile.runtimeVersion());
} catch (IOException ioe) {
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleResolution.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleResolution.java Thu May 04 17:54:50 2017 +0000
@@ -39,6 +39,10 @@
this.value = value;
}
+ public int value() {
+ return value;
+ }
+
public static ModuleResolution empty() {
return new ModuleResolution(0);
}
@@ -74,35 +78,30 @@
throw new InternalError("cannot add deprecated for removal to " + value);
return new ModuleResolution(value | WARN_DEPRECATED_FOR_REMOVAL);
}
+
public ModuleResolution withIncubating() {
if ((value & (WARN_DEPRECATED | WARN_DEPRECATED_FOR_REMOVAL)) != 0)
throw new InternalError("cannot add incubating to " + value);
return new ModuleResolution(value | WARN_INCUBATING);
}
- public int value() {
- return value;
- }
-
public static boolean doNotResolveByDefault(ModuleReference mref) {
// get the DO_NOT_RESOLVE_BY_DEFAULT flag, if any
- if (!(mref instanceof ModuleReferenceImpl))
- return false;
-
- ModuleResolution mres = ((ModuleReferenceImpl)mref).moduleResolution();
- if (mres != null)
- return mres.doNotResolveByDefault();
+ if (mref instanceof ModuleReferenceImpl) {
+ ModuleResolution mres = ((ModuleReferenceImpl) mref).moduleResolution();
+ if (mres != null)
+ return mres.doNotResolveByDefault();
+ }
return false;
}
public static boolean hasIncubatingWarning(ModuleReference mref) {
- if (!(mref instanceof ModuleReferenceImpl))
- return false;
-
- ModuleResolution mres = ((ModuleReferenceImpl)mref).moduleResolution();
- if (mres != null)
- return mres.hasIncubatingWarning();
+ if (mref instanceof ModuleReferenceImpl) {
+ ModuleResolution mres = ((ModuleReferenceImpl) mref).moduleResolution();
+ if (mres != null)
+ return mres.hasIncubatingWarning();
+ }
return false;
}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleTarget.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleTarget.java Thu May 04 17:54:50 2017 +0000
@@ -25,22 +25,21 @@
package jdk.internal.module;
+/**
+ * Represents the module target.
+ *
+ * For now, this is a single value for the target platform, e.g. "linux-x64".
+ */
public final class ModuleTarget {
- private final String osName;
- private final String osArch;
+ private final String targetPlatform;
- public ModuleTarget(String osName, String osArch) {
- this.osName = osName;
- this.osArch = osArch;
+ public ModuleTarget(String targetPlatform) {
+ this.targetPlatform = targetPlatform;
}
- public String osName() {
- return osName;
- }
-
- public String osArch() {
- return osArch;
+ public String targetPlatform() {
+ return targetPlatform;
}
}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/Modules.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/Modules.java Thu May 04 17:54:50 2017 +0000
@@ -25,12 +25,22 @@
package jdk.internal.module;
+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.net.URI;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
import jdk.internal.loader.BootLoader;
+import jdk.internal.loader.BuiltinClassLoader;
import jdk.internal.loader.ClassLoaders;
import jdk.internal.misc.JavaLangAccess;
import jdk.internal.misc.SharedSecrets;
@@ -38,8 +48,8 @@
/**
* A helper class for creating and updating modules. This class is intended to
* support command-line options, tests, and the instrumentation API. It is also
- * used by the VM to add read edges when agents are instrumenting code that
- * need to link to supporting classes.
+ * used by the VM to load modules or add read edges when agents are instrumenting
+ * code that need to link to supporting classes.
*
* The parameters that are package names in this API are the fully-qualified
* names of the packages as defined in section 6.5.3 of <cite>The Java™
@@ -154,4 +164,90 @@
addReads(m, BootLoader.getUnnamedModule());
addReads(m, ClassLoaders.appClassLoader().getUnnamedModule());
}
+
+ /**
+ * Called by the VM to load a system module, typically "java.instrument" or
+ * "jdk.management.agent". If the module is not loaded then it is resolved
+ * and loaded (along with any dependences that weren't previously loaded)
+ * into a child layer.
+ */
+ public static synchronized Module loadModule(String name) {
+ ModuleLayer top = topLayer;
+ if (top == null)
+ top = ModuleLayer.boot();
+
+ Module module = top.findModule(name).orElse(null);
+ if (module != null) {
+ // module already loaded
+ return module;
+ }
+
+ // resolve the module with the top-most layer as the parent
+ ModuleFinder empty = ModuleFinder.of();
+ ModuleFinder finder = ModuleBootstrap.unlimitedFinder();
+ Set<String> roots = Set.of(name);
+ Configuration cf = top.configuration().resolveAndBind(empty, finder, roots);
+
+ // create the child layer
+ Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
+ ModuleLayer newLayer = top.defineModules(cf, clf);
+
+ // add qualified exports/opens to give access to modules in child layer
+ Map<String, Module> map = newLayer.modules().stream()
+ .collect(Collectors.toMap(Module::getName,
+ Function.identity()));
+ ModuleLayer layer = top;
+ while (layer != null) {
+ for (Module m : layer.modules()) {
+ // qualified exports
+ m.getDescriptor().exports().stream()
+ .filter(ModuleDescriptor.Exports::isQualified)
+ .forEach(e -> e.targets().forEach(target -> {
+ Module other = map.get(target);
+ if (other != null) {
+ addExports(m, e.source(), other);
+ }}));
+
+ // qualified opens
+ m.getDescriptor().opens().stream()
+ .filter(ModuleDescriptor.Opens::isQualified)
+ .forEach(o -> o.targets().forEach(target -> {
+ Module other = map.get(target);
+ if (other != null) {
+ addOpens(m, o.source(), other);
+ }}));
+ }
+
+ List<ModuleLayer> parents = layer.parents();
+ assert parents.size() <= 1;
+ layer = parents.isEmpty() ? null : parents.get(0);
+ }
+
+ // update security manager before making types visible
+ JLA.addNonExportedPackages(newLayer);
+
+ // update the built-in class loaders to make the types visible
+ for (ResolvedModule resolvedModule : cf.modules()) {
+ ModuleReference mref = resolvedModule.reference();
+ String mn = mref.descriptor().name();
+ ClassLoader cl = clf.apply(mn);
+ if (cl == null) {
+ BootLoader.loadModule(mref);
+ } else {
+ ((BuiltinClassLoader) cl).loadModule(mref);
+ }
+ }
+
+ // new top layer
+ topLayer = newLayer;
+
+ // return module
+ return newLayer.findModule(name)
+ .orElseThrow(() -> new InternalError("module not loaded"));
+
+ }
+
+ // the top-most system layer
+ private static ModuleLayer topLayer;
+
}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/Resources.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/Resources.java Thu May 04 17:54:50 2017 +0000
@@ -26,10 +26,10 @@
import java.io.File;
import java.io.IOException;
+import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
/**
@@ -94,7 +94,7 @@
if (expectDirectory) {
name = name.substring(0, name.length() - 1); // drop trailing "/"
}
- Path path = toSafeFilePath(name);
+ Path path = toSafeFilePath(dir.getFileSystem(), name);
if (path != null) {
Path file = dir.resolve(path);
try {
@@ -116,7 +116,7 @@
* are rejected, as are resource names that translates to a file path
* with a root component.
*/
- private static Path toSafeFilePath(String name) {
+ private static Path toSafeFilePath(FileSystem fs, String name) {
// scan elements of resource name
int next;
int off = 0;
@@ -135,12 +135,12 @@
// convert to file path
Path path;
if (File.separatorChar == '/') {
- path = Paths.get(name);
+ path = fs.getPath(name);
} else {
// not allowed to embed file separators
if (name.contains(File.separator))
return null;
- path = Paths.get(name.replace('/', File.separatorChar));
+ path = fs.getPath(name.replace('/', File.separatorChar));
}
// file path not allowed to have root component
--- a/jdk/src/java.base/share/classes/module-info.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/module-info.java Thu May 04 17:54:50 2017 +0000
@@ -161,6 +161,7 @@
java.security.jgss,
java.sql,
java.xml,
+ jdk.attach,
jdk.charsets,
jdk.compiler, // reflective dependency
jdk.incubator.httpclient,
--- a/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java Thu May 04 17:54:50 2017 +0000
@@ -43,13 +43,17 @@
import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
-import java.lang.module.ModuleFinder;
-import java.lang.module.ModuleReference;
+import java.lang.module.Configuration;
+import java.lang.module.FindException;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Requires;
import java.lang.module.ModuleDescriptor.Exports;
import java.lang.module.ModuleDescriptor.Opens;
import java.lang.module.ModuleDescriptor.Provides;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.lang.module.ResolvedModule;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
@@ -58,14 +62,16 @@
import java.nio.charset.Charset;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
import java.text.Normalizer;
import java.text.MessageFormat;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
-import java.util.HashSet;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
@@ -83,6 +89,7 @@
import java.util.stream.Stream;
import jdk.internal.misc.VM;
+import jdk.internal.module.ModuleBootstrap;
import jdk.internal.module.Modules;
@@ -98,6 +105,7 @@
"javafx.application.Application";
private static final String JAVAFX_FXHELPER_CLASS_NAME_SUFFIX =
"sun.launcher.LauncherHelper$FXHelper";
+ private static final String LAUNCHER_AGENT_CLASS = "Launcher-Agent-Class";
private static final String MAIN_CLASS = "Main-Class";
private static final String ADD_EXPORTS = "Add-Exports";
private static final String ADD_OPENS = "Add-Opens";
@@ -408,8 +416,12 @@
ostream = (printToStderr) ? System.err : System.out;
}
+ static void initOutput(PrintStream ps) {
+ ostream = ps;
+ }
+
static String getMainClassFromJar(String jarname) {
- String mainValue = null;
+ String mainValue;
try (JarFile jarFile = new JarFile(jarname)) {
Manifest manifest = jarFile.getManifest();
if (manifest == null) {
@@ -426,6 +438,22 @@
abort(null, "java.launcher.jar.error3", jarname);
}
+ // Launcher-Agent-Class (only check for this when Main-Class present)
+ String agentClass = mainAttrs.getValue(LAUNCHER_AGENT_CLASS);
+ if (agentClass != null) {
+ ModuleLayer.boot().findModule("java.instrument").ifPresent(m -> {
+ try {
+ String cn = "sun.instrument.InstrumentationImpl";
+ Class<?> clazz = Class.forName(cn, false, null);
+ Method loadAgent = clazz.getMethod("loadAgent", String.class);
+ loadAgent.invoke(null, jarname);
+ } catch (Throwable e) {
+ if (e instanceof InvocationTargetException) e = e.getCause();
+ abort(e, "java.launcher.jar.error4", jarname);
+ }
+ });
+ }
+
// Add-Exports and Add-Opens
String exports = mainAttrs.getValue(ADD_EXPORTS);
if (exports != null) {
@@ -913,141 +941,350 @@
}
}
- private static void formatCommaList(PrintStream out,
- String prefix,
- Collection<?> list)
- {
- if (list.isEmpty())
- return;
- out.format("%s", prefix);
- boolean first = true;
- for (Object ob : list) {
- if (first) {
- out.format(" %s", ob);
- first = false;
- } else {
- out.format(", %s", ob);
- }
- }
- out.format("%n");
+ /**
+ * Called by the launcher to list the observable modules.
+ */
+ static void listModules() {
+ initOutput(System.out);
+
+ ModuleBootstrap.limitedFinder().findAll().stream()
+ .sorted(new JrtFirstComparator())
+ .forEach(LauncherHelper::showModule);
+ }
+
+ /**
+ * Called by the launcher to show the resolved modules
+ */
+ static void showResolvedModules() {
+ initOutput(System.out);
+
+ ModuleLayer bootLayer = ModuleLayer.boot();
+ Configuration cf = bootLayer.configuration();
+
+ cf.modules().stream()
+ .map(ResolvedModule::reference)
+ .sorted(new JrtFirstComparator())
+ .forEach(LauncherHelper::showModule);
}
/**
- * Called by the launcher to list the observable modules.
- * If called without any sub-options then the output is a simple list of
- * the modules. If called with sub-options then the sub-options are the
- * names of the modules to list (e.g. --list-modules java.base,java.desktop)
+ * Called by the launcher to describe a module
*/
- static void listModules(boolean printToStderr, String optionFlag)
- throws IOException, ClassNotFoundException
- {
- initOutput(printToStderr);
+ static void describeModule(String moduleName) {
+ initOutput(System.out);
- ModuleFinder finder = jdk.internal.module.ModuleBootstrap.finder();
- int colon = optionFlag.indexOf('=');
- if (colon == -1) {
- finder.findAll().stream()
- .sorted(Comparator.comparing(ModuleReference::descriptor))
- .forEach(mref -> describeModule(finder, mref, false));
- } else {
- String[] names = optionFlag.substring(colon+1).split(",");
- for (String name: names) {
- ModuleReference mref = finder.find(name).orElse(null);
- if (mref == null) {
- System.err.format("%s not found%n", name);
- continue;
- }
- describeModule(finder, mref, true);
- }
+ ModuleFinder finder = ModuleBootstrap.limitedFinder();
+ ModuleReference mref = finder.find(moduleName).orElse(null);
+ if (mref == null) {
+ abort(null, "java.launcher.module.error4", moduleName);
}
- }
+ ModuleDescriptor md = mref.descriptor();
- /**
- * Describes the given module.
- */
- static void describeModule(ModuleFinder finder,
- ModuleReference mref,
- boolean verbose)
- {
- ModuleDescriptor md = mref.descriptor();
- ostream.print("module " + midAndLocation(md, mref.location()));
- if (md.isAutomatic())
- ostream.print(" automatic");
- ostream.println();
-
- if (!verbose)
- return;
+ // one-line summary
+ showModule(mref);
// unqualified exports (sorted by package)
- Set<Exports> exports = new TreeSet<>(Comparator.comparing(Exports::source));
- md.exports().stream().filter(e -> !e.isQualified()).forEach(exports::add);
- for (Exports e : exports) {
- String modsAndSource = Stream.concat(toStringStream(e.modifiers()),
- Stream.of(e.source()))
+ md.exports().stream()
+ .filter(e -> !e.isQualified())
+ .sorted(Comparator.comparing(Exports::source))
+ .map(e -> Stream.concat(Stream.of(e.source()),
+ toStringStream(e.modifiers()))
+ .collect(Collectors.joining(" ")))
+ .forEach(sourceAndMods -> ostream.format("exports %s%n", sourceAndMods));
+
+ // dependences
+ for (Requires r : md.requires()) {
+ String nameAndMods = Stream.concat(Stream.of(r.name()),
+ toStringStream(r.modifiers()))
.collect(Collectors.joining(" "));
- ostream.format(" exports %s%n", modsAndSource);
+ ostream.format("requires %s", nameAndMods);
+ finder.find(r.name())
+ .map(ModuleReference::descriptor)
+ .filter(ModuleDescriptor::isAutomatic)
+ .ifPresent(any -> ostream.print(" automatic"));
+ ostream.println();
}
- for (Requires d : md.requires()) {
- ostream.format(" requires %s", d);
- String suffix = finder.find(d.name())
- .map(ModuleReference::descriptor)
- .map(any -> any.isAutomatic() ? " automatic" : "")
- .orElse(" not found");
- ostream.println(suffix);
+ // service use and provides
+ for (String s : md.uses()) {
+ ostream.format("uses %s%n", s);
}
- for (String s : md.uses()) {
- ostream.format(" uses %s%n", s);
- }
+ for (Provides ps : md.provides()) {
+ String names = ps.providers().stream().collect(Collectors.joining(" "));
+ ostream.format("provides %s with %s%n", ps.service(), names);
- for (Provides ps : md.provides()) {
- ostream.format(" provides %s with %s%n", ps.service(),
- ps.providers().stream().collect(Collectors.joining(", ")));
}
// qualified exports
for (Exports e : md.exports()) {
if (e.isQualified()) {
- String modsAndSource = Stream.concat(toStringStream(e.modifiers()),
- Stream.of(e.source()))
- .collect(Collectors.joining(" "));
- ostream.format(" exports %s", modsAndSource);
- formatCommaList(ostream, " to", e.targets());
+ String who = e.targets().stream().collect(Collectors.joining(" "));
+ ostream.format("qualified exports %s to %s%n", e.source(), who);
}
}
// open packages
- for (Opens obj: md.opens()) {
- String modsAndSource = Stream.concat(toStringStream(obj.modifiers()),
- Stream.of(obj.source()))
+ for (Opens opens: md.opens()) {
+ if (opens.isQualified())
+ ostream.print("qualified ");
+ String sourceAndMods = Stream.concat(Stream.of(opens.source()),
+ toStringStream(opens.modifiers()))
.collect(Collectors.joining(" "));
- ostream.format(" opens %s", modsAndSource);
- if (obj.isQualified())
- formatCommaList(ostream, " to", obj.targets());
- else
- ostream.println();
+ ostream.format("opens %s", sourceAndMods);
+ if (opens.isQualified()) {
+ String who = opens.targets().stream().collect(Collectors.joining(" "));
+ ostream.format(" to %s", who);
+ }
+ ostream.println();
}
// non-exported/non-open packages
Set<String> concealed = new TreeSet<>(md.packages());
md.exports().stream().map(Exports::source).forEach(concealed::remove);
md.opens().stream().map(Opens::source).forEach(concealed::remove);
- concealed.forEach(p -> ostream.format(" contains %s%n", p));
+ concealed.forEach(p -> ostream.format("contains %s%n", p));
+ }
+
+ /**
+ * Prints a single line with the module name, version and modifiers
+ */
+ private static void showModule(ModuleReference mref) {
+ ModuleDescriptor md = mref.descriptor();
+ ostream.print(md.toNameAndVersion());
+ mref.location()
+ .filter(uri -> !isJrt(uri))
+ .ifPresent(uri -> ostream.format(" %s", uri));
+ if (md.isOpen())
+ ostream.print(" open");
+ if (md.isAutomatic())
+ ostream.print(" automatic");
+ ostream.println();
}
- static <T> String toString(Set<T> s) {
- return toStringStream(s).collect(Collectors.joining(" "));
+ /**
+ * A ModuleReference comparator that considers modules in the run-time
+ * image to be less than modules than not in the run-time image.
+ */
+ private static class JrtFirstComparator implements Comparator<ModuleReference> {
+ private final Comparator<ModuleReference> real;
+
+ JrtFirstComparator() {
+ this.real = Comparator.comparing(ModuleReference::descriptor);
+ }
+
+ @Override
+ public int compare(ModuleReference a, ModuleReference b) {
+ if (isJrt(a)) {
+ return isJrt(b) ? real.compare(a, b) : -1;
+ } else {
+ return isJrt(b) ? 1 : real.compare(a, b);
+ }
+ }
}
- static <T> Stream<String> toStringStream(Set<T> s) {
+ private static <T> Stream<String> toStringStream(Set<T> s) {
return s.stream().map(e -> e.toString().toLowerCase());
}
- static String midAndLocation(ModuleDescriptor md, Optional<URI> location ) {
- URI loc = location.orElse(null);
- if (loc == null || loc.getScheme().equalsIgnoreCase("jrt"))
- return md.toNameAndVersion();
- else
- return md.toNameAndVersion() + " (" + loc + ")";
+ private static boolean isJrt(ModuleReference mref) {
+ return isJrt(mref.location().orElse(null));
+ }
+
+ private static boolean isJrt(URI uri) {
+ return (uri != null && uri.getScheme().equalsIgnoreCase("jrt"));
+ }
+
+ /**
+ * Called by the launcher to validate the modules on the upgrade and
+ * application module paths.
+ *
+ * @return {@code true} if no errors are found
+ */
+ private static boolean validateModules() {
+ initOutput(System.out);
+
+ ModuleValidator validator = new ModuleValidator();
+
+ // upgrade module path
+ String value = System.getProperty("jdk.module.upgrade.path");
+ if (value != null) {
+ Stream.of(value.split(File.pathSeparator))
+ .map(Paths::get)
+ .forEach(validator::scan);
+ }
+
+ // system modules
+ ModuleFinder.ofSystem().findAll().stream()
+ .sorted(Comparator.comparing(ModuleReference::descriptor))
+ .forEach(validator::process);
+
+ // application module path
+ value = System.getProperty("jdk.module.path");
+ if (value != null) {
+ Stream.of(value.split(File.pathSeparator))
+ .map(Paths::get)
+ .forEach(validator::scan);
+ }
+
+ return !validator.foundErrors();
+ }
+
+ /**
+ * A simple validator to check for errors and conflicts between modules.
+ */
+ static class ModuleValidator {
+ private static final String MODULE_INFO = "module-info.class";
+
+ private Map<String, ModuleReference> nameToModule = new HashMap<>();
+ private Map<String, ModuleReference> packageToModule = new HashMap<>();
+ private boolean errorFound;
+
+ /**
+ * Returns true if at least one error was found
+ */
+ boolean foundErrors() {
+ return errorFound;
+ }
+
+ /**
+ * Prints the module location and name.
+ */
+ private void printModule(ModuleReference mref) {
+ mref.location()
+ .filter(uri -> !isJrt(uri))
+ .ifPresent(uri -> ostream.print(uri + " "));
+ ModuleDescriptor descriptor = mref.descriptor();
+ ostream.print(descriptor.name());
+ if (descriptor.isAutomatic())
+ ostream.print(" automatic");
+ ostream.println();
+ }
+
+ /**
+ * Prints the module location and name, checks if the module is
+ * shadowed by a previously seen module, and finally checks for
+ * package conflicts with previously seen modules.
+ */
+ void process(ModuleReference mref) {
+ printModule(mref);
+
+ String name = mref.descriptor().name();
+ ModuleReference previous = nameToModule.putIfAbsent(name, mref);
+ if (previous != null) {
+ ostream.print(INDENT + "shadowed by ");
+ printModule(previous);
+ } else {
+ // check for package conflicts when not shadowed
+ for (String pkg : mref.descriptor().packages()) {
+ previous = packageToModule.putIfAbsent(pkg, mref);
+ if (previous != null) {
+ String mn = previous.descriptor().name();
+ ostream.println(INDENT + "contains " + pkg
+ + " conflicts with module " + mn);
+ errorFound = true;
+ }
+ }
+ }
+ }
+
+ /**
+ * Scan an element on a module path. The element is a directory
+ * of modules, an exploded module, or a JAR file.
+ */
+ void scan(Path entry) {
+ BasicFileAttributes attrs;
+ try {
+ attrs = Files.readAttributes(entry, BasicFileAttributes.class);
+ } catch (NoSuchFileException ignore) {
+ return;
+ } catch (IOException ioe) {
+ ostream.println(entry + " " + ioe);
+ errorFound = true;
+ return;
+ }
+
+ String fn = entry.getFileName().toString();
+ if (attrs.isRegularFile() && fn.endsWith(".jar")) {
+ // JAR file, explicit or automatic module
+ scanModule(entry).ifPresent(this::process);
+ } else if (attrs.isDirectory()) {
+ Path mi = entry.resolve(MODULE_INFO);
+ if (Files.exists(mi)) {
+ // exploded module
+ scanModule(entry).ifPresent(this::process);
+ } else {
+ // directory of modules
+ scanDirectory(entry);
+ }
+ }
+ }
+
+ /**
+ * Scan the JAR files and exploded modules in a directory.
+ */
+ private void scanDirectory(Path dir) {
+ try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
+ Map<String, Path> moduleToEntry = new HashMap<>();
+
+ for (Path entry : stream) {
+ BasicFileAttributes attrs;
+ try {
+ attrs = Files.readAttributes(entry, BasicFileAttributes.class);
+ } catch (IOException ioe) {
+ ostream.println(entry + " " + ioe);
+ errorFound = true;
+ continue;
+ }
+
+ ModuleReference mref = null;
+
+ String fn = entry.getFileName().toString();
+ if (attrs.isRegularFile() && fn.endsWith(".jar")) {
+ mref = scanModule(entry).orElse(null);
+ } else if (attrs.isDirectory()) {
+ Path mi = entry.resolve(MODULE_INFO);
+ if (Files.exists(mi)) {
+ mref = scanModule(entry).orElse(null);
+ }
+ }
+
+ if (mref != null) {
+ String name = mref.descriptor().name();
+ Path previous = moduleToEntry.putIfAbsent(name, entry);
+ if (previous != null) {
+ // same name as other module in the directory
+ printModule(mref);
+ ostream.println(INDENT + "contains same module as "
+ + previous.getFileName());
+ errorFound = true;
+ } else {
+ process(mref);
+ }
+ }
+ }
+ } catch (IOException ioe) {
+ ostream.println(dir + " " + ioe);
+ errorFound = true;
+ }
+ }
+
+ /**
+ * Scan a JAR file or exploded module.
+ */
+ private Optional<ModuleReference> scanModule(Path entry) {
+ ModuleFinder finder = ModuleFinder.of(entry);
+ try {
+ return finder.findAll().stream().findFirst();
+ } catch (FindException e) {
+ ostream.println(entry);
+ ostream.println(INDENT + e.getMessage());
+ Throwable cause = e.getCause();
+ if (cause != null) {
+ ostream.println(INDENT + cause);
+ }
+ errorFound = true;
+ return Optional.empty();
+ }
+ }
}
}
--- a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties Thu May 04 17:54:50 2017 +0000
@@ -53,26 +53,33 @@
\ A {0} separated list of directories, each directory\n\
\ is a directory of modules that replace upgradeable\n\
\ modules in the runtime image\n\
-\ --add-modules <modulename>[,<modulename>...]\n\
+\ --add-modules <module name>[,<module name>...]\n\
\ root modules to resolve in addition to the initial module.\n\
-\ <modulename> can also be ALL-DEFAULT, ALL-SYSTEM,\n\
+\ <module name> can also be ALL-DEFAULT, ALL-SYSTEM,\n\
\ ALL-MODULE-PATH.\n\
-\ --limit-modules <modulename>[,<modulename>...]\n\
-\ limit the universe of observable modules\n\
-\ --list-modules [<modulename>[,<modulename>...]]\n\
-\ list the observable modules and exit\n\
-\ --dry-run create VM but do not execute main method.\n\
-\ This --dry-run option may be useful for validating the\n\
+\ --list-modules\n\
+\ list observable modules and exit\n\
+\ --d <module name>\n\
+\ --describe-module <module name>\n\
+\ describe a module and exit\n\
+\ --dry-run create VM and load main class but do not execute main method.\n\
+\ The --dry-run option may be useful for validating the\n\
\ command-line options such as the module system configuration.\n\
+\ --validate-modules\n\
+\ validate all modules and exit\n\
+\ The --validate-modules option may be useful for finding\n\
+\ conflicts and other errors with modules on the module path.\n\
\ -D<name>=<value>\n\
\ set a system property\n\
-\ -verbose:[class|gc|jni]\n\
+\ -verbose:[class|module|gc|jni]\n\
\ enable verbose output\n\
\ -version print product version to the error stream and exit\n\
\ --version print product version to the output stream and exit\n\
\ -showversion print product version to the error stream and continue\n\
\ --show-version\n\
\ print product version to the output stream and continue\n\
+\ --show-module-resolution\n\
+\ show module resolution output during startup\n\
\ -? -h -help\n\
\ print this help message to the error stream\n\
\ --help print this help message to the output stream\n\
@@ -119,7 +126,6 @@
\ -Xcomp forces compilation of methods on first invocation\n\
\ -Xdebug provided for backward compatibility\n\
\ -Xdiag show additional diagnostic messages\n\
-\ -Xdiag:resolver show resolver diagnostic messages\n\
\ -Xfuture enable strictest checks, anticipating future default\n\
\ -Xint interpreted mode execution only\n\
\ -Xinternalversion\n\
@@ -164,10 +170,12 @@
\ 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\
-\ --disable-@files disable further argument file expansion\n\
+\ --limit-modules <module name>[,<module name>...]\n\
+\ limit the universe of observable modules\n\
\ --patch-module <module>=<file>({0}<file>)*\n\
-\ Override or augment a module with classes and resources\n\
-\ in JAR files or directories.\n\n\
+\ override or augment a module with classes and resources\n\
+\ in JAR files or directories.\n\
+\ --disable-@files disable further argument file expansion\n\n\
These extra options are subject to change without notice.\n
# Translators please note do not translate the options themselves
@@ -204,6 +212,7 @@
Error: An unexpected error occurred while trying to open file {0}
java.launcher.jar.error2=manifest not found in {0}
java.launcher.jar.error3=no main manifest attribute, in {0}
+java.launcher.jar.error4=error loading java agent in {0}
java.launcher.init.error=initialization error
java.launcher.javafx.error1=\
Error: The JavaFX launchApplication method has the wrong signature, it\n\
@@ -215,4 +224,5 @@
java.launcher.module.error3=\
Error: Unable to load main class {0} from module {1}\n\
\t{2}
-
+java.launcher.module.error4=\
+ {0} not found
--- a/jdk/src/java.base/share/native/libjli/emessages.h Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/native/libjli/emessages.h Thu May 04 17:54:50 2017 +0000
@@ -43,13 +43,14 @@
#define ARG_ERROR2 "Error: %s requires jar file specification"
#define ARG_ERROR3 "Error: The -J option should not be followed by a space."
#define ARG_ERROR4 "Error: %s requires module path specification"
-#define ARG_ERROR5 "Error: %s requires module id"
+#define ARG_ERROR5 "Error: %s requires module name"
#define ARG_ERROR6 "Error: %s requires modules to be specified"
#define ARG_ERROR7 "Error: %s can only be specified once"
#define ARG_ERROR8 "Error: Unmatched quote in environment variable %s"
#define ARG_ERROR9 "Error: Option %s is not allowed in environment variable %s"
#define ARG_ERROR10 "Error: Option %s in %s is not allowed in environment variable %s"
#define ARG_ERROR11 "Error: Cannot specify main class in environment variable %s"
+#define ARG_ERROR12 "Error: %s requires module name"
#define JVM_ERROR1 "Error: Could not create the Java Virtual Machine.\n" GEN_ERROR
#define JVM_ERROR2 "Error: Could not detach main thread.\n" JNI_ERROR
--- a/jdk/src/java.base/share/native/libjli/java.c Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.base/share/native/libjli/java.c Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -71,7 +71,10 @@
static jboolean printXUsage = JNI_FALSE; /* print and exit*/
static jboolean dryRun = JNI_FALSE; /* initialize VM and exit */
static char *showSettings = NULL; /* print but continue */
-static char *listModules = NULL;
+static jboolean showResolvedModules = JNI_FALSE;
+static jboolean listModules = JNI_FALSE;
+static char *describeModule = NULL;
+static jboolean validateModules = JNI_FALSE;
static const char *_program_name;
static const char *_launcher_name;
@@ -118,7 +121,10 @@
static void PrintJavaVersion(JNIEnv *env, jboolean extraLF);
static void PrintUsage(JNIEnv* env, jboolean doXUsage);
static void ShowSettings(JNIEnv* env, char *optString);
-static void ListModules(JNIEnv* env, char *optString);
+static void ShowResolvedModules(JNIEnv* env);
+static void ListModules(JNIEnv* env);
+static void DescribeModule(JNIEnv* env, char* optString);
+static jboolean ValidateModules(JNIEnv* env);
static void SetPaths(int argc, char **argv);
@@ -409,12 +415,34 @@
CHECK_EXCEPTION_LEAVE(1);
}
- if (listModules != NULL) {
- ListModules(env, listModules);
+ // show resolved modules and continue
+ if (showResolvedModules) {
+ ShowResolvedModules(env);
+ CHECK_EXCEPTION_LEAVE(1);
+ }
+
+ // list observable modules, then exit
+ if (listModules) {
+ ListModules(env);
CHECK_EXCEPTION_LEAVE(1);
LEAVE();
}
+ // describe a module, then exit
+ if (describeModule != NULL) {
+ DescribeModule(env, describeModule);
+ CHECK_EXCEPTION_LEAVE(1);
+ LEAVE();
+ }
+
+ // validate modules on the module path, then exit
+ if (validateModules) {
+ jboolean okay = ValidateModules(env);
+ CHECK_EXCEPTION_LEAVE(1);
+ if (!okay) ret = 1;
+ LEAVE();
+ }
+
if (printVersion || showVersion) {
PrintJavaVersion(env, showVersion);
CHECK_EXCEPTION_LEAVE(0);
@@ -552,7 +580,8 @@
IsLauncherOption(const char* name) {
return IsClassPathOption(name) ||
IsLauncherMainOption(name) ||
- JLI_StrCmp(name, "--list-modules") == 0;
+ JLI_StrCmp(name, "--describe-module") == 0 ||
+ JLI_StrCmp(name, "-d") == 0;
}
/*
@@ -1199,7 +1228,7 @@
} else if (JLI_StrCCmp(arg, "--") == 0 && (equals = JLI_StrChr(arg, '=')) != NULL) {
value = equals+1;
- if (JLI_StrCCmp(arg, "--list-modules=") == 0 ||
+ if (JLI_StrCCmp(arg, "--describe-module=") == 0 ||
JLI_StrCCmp(arg, "--module=") == 0 ||
JLI_StrCCmp(arg, "--class-path=") == 0) {
kind = LAUNCHER_OPTION_WITH_ARGUMENT;
@@ -1263,18 +1292,18 @@
REPORT_ERROR (has_arg_any_len, ARG_ERROR1, arg);
SetClassPath(value);
mode = LM_CLASS;
- } else if (JLI_StrCmp(arg, "--list-modules") == 0 ||
- JLI_StrCCmp(arg, "--list-modules=") == 0) {
- listModules = arg;
-
- // set listModules to --list-modules=<module-names> if argument is specified
- if (JLI_StrCmp(arg, "--list-modules") == 0 && has_arg) {
- static const char format[] = "%s=%s";
- size_t buflen = JLI_StrLen(option) + 2 + JLI_StrLen(value);
- listModules = JLI_MemAlloc(buflen);
- JLI_Snprintf(listModules, buflen, format, option, value);
- }
- return JNI_TRUE;
+ } else if (JLI_StrCmp(arg, "--list-modules") == 0) {
+ listModules = JNI_TRUE;
+ } else if (JLI_StrCmp(arg, "--show-resolved-modules") == 0) {
+ showResolvedModules = JNI_TRUE;
+ } else if (JLI_StrCmp(arg, "--validate-modules") == 0) {
+ AddOption("-Djdk.module.minimumBoot=true", NULL);
+ validateModules = JNI_TRUE;
+ } else if (JLI_StrCmp(arg, "--describe-module") == 0 ||
+ JLI_StrCCmp(arg, "--describe-module=") == 0 ||
+ JLI_StrCmp(arg, "-d") == 0) {
+ REPORT_ERROR (has_arg_any_len, ARG_ERROR12, arg);
+ describeModule = value;
/*
* Parse white-space options
*/
@@ -1336,9 +1365,8 @@
showSettings = arg;
} else if (JLI_StrCmp(arg, "-Xdiag") == 0) {
AddOption("-Dsun.java.launcher.diag=true", NULL);
- AddOption("-Djdk.launcher.traceResolver=true", NULL);
- } else if (JLI_StrCmp(arg, "-Xdiag:resolver") == 0) {
- AddOption("-Djdk.launcher.traceResolver=true", NULL);
+ } else if (JLI_StrCmp(arg, "--show-module-resolution") == 0) {
+ AddOption("-Djdk.module.showModuleResolution=true", NULL);
/*
* The following case provide backward compatibility with old-style
* command line options.
@@ -1399,7 +1427,10 @@
}
if (*pwhat == NULL) {
- *pret = 1;
+ /* LM_UNKNOWN okay for options that exit */
+ if (!listModules && !describeModule && !validateModules) {
+ *pret = 1;
+ }
} else if (mode == LM_UNKNOWN) {
/* default to LM_CLASS if -m, -jar and -cp options are
* not specified */
@@ -1828,21 +1859,61 @@
}
/**
- * List modules supported by the runtime
+ * Show resolved modules
+ */
+static void
+ShowResolvedModules(JNIEnv *env)
+{
+ jmethodID showResolvedModulesID;
+ jclass cls = GetLauncherHelperClass(env);
+ NULL_CHECK(cls);
+ NULL_CHECK(showResolvedModulesID = (*env)->GetStaticMethodID(env, cls,
+ "showResolvedModules", "()V"));
+ (*env)->CallStaticVoidMethod(env, cls, showResolvedModulesID);
+}
+
+/**
+ * List observable modules
*/
static void
-ListModules(JNIEnv *env, char *optString)
+ListModules(JNIEnv *env)
{
jmethodID listModulesID;
+ jclass cls = GetLauncherHelperClass(env);
+ NULL_CHECK(cls);
+ NULL_CHECK(listModulesID = (*env)->GetStaticMethodID(env, cls,
+ "listModules", "()V"));
+ (*env)->CallStaticVoidMethod(env, cls, listModulesID);
+}
+
+/**
+ * Describe a module
+ */
+static void
+DescribeModule(JNIEnv *env, char *optString)
+{
+ jmethodID describeModuleID;
jstring joptString = NULL;
jclass cls = GetLauncherHelperClass(env);
NULL_CHECK(cls);
- NULL_CHECK(listModulesID = (*env)->GetStaticMethodID(env, cls,
- "listModules", "(ZLjava/lang/String;)V"));
+ NULL_CHECK(describeModuleID = (*env)->GetStaticMethodID(env, cls,
+ "describeModule", "(Ljava/lang/String;)V"));
NULL_CHECK(joptString = (*env)->NewStringUTF(env, optString));
- (*env)->CallStaticVoidMethod(env, cls, listModulesID,
- USE_STDOUT,
- joptString);
+ (*env)->CallStaticVoidMethod(env, cls, describeModuleID, joptString);
+}
+
+/**
+ * Validate modules
+ */
+static jboolean
+ValidateModules(JNIEnv *env)
+{
+ jmethodID validateModulesID;
+ jclass cls = GetLauncherHelperClass(env);
+ NULL_CHECK_RETURN_VALUE(cls, JNI_FALSE);
+ validateModulesID = (*env)->GetStaticMethodID(env, cls, "validateModules", "()Z");
+ NULL_CHECK_RETURN_VALUE(cls, JNI_FALSE);
+ return (*env)->CallStaticBooleanMethod(env, cls, validateModulesID);
}
/*
--- a/jdk/src/java.instrument/share/classes/java/lang/instrument/Instrumentation.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.instrument/share/classes/java/lang/instrument/Instrumentation.java Thu May 04 17:54:50 2017 +0000
@@ -729,7 +729,8 @@
* Tests whether a module can be modified with {@link #redefineModule
* redefineModule}. If a module is modifiable then this method returns
* {@code true}. If a module is not modifiable then this method returns
- * {@code false}.
+ * {@code false}. This method always returns {@code true} when the module
+ * is an unnamed module (as redefining an unnamed module is a no-op).
*
* @param module the module to test if it can be modified
* @return {@code true} if the module is modifiable, otherwise {@code false}
--- a/jdk/src/java.instrument/share/classes/java/lang/instrument/package.html Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.instrument/share/classes/java/lang/instrument/package.html Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
<!--
- Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ 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
@@ -112,7 +112,9 @@
The <code>premain</code> methods will be run under the same security and classloader
rules as the application <code>main</code> method.
There are no modeling restrictions on what the agent <code>premain</code> method may do.
-Anything application <code>main</code> can do, including creating threads, is legal from <code>premain</code>.
+Anything application <code>main</code> can do, including creating threads, is legal from
+<code>premain</code>.
+
<P>
Each agent is passed its agent options via the <code>agentArgs</code> parameter.
@@ -126,7 +128,6 @@
If a <code>premain</code> method throws an uncaught exception, the JVM will abort.
-
<h3>Starting Agents After VM Startup</h3>
<p>
@@ -191,76 +192,134 @@
not abort. If the <code>agentmain</code> method throws an uncaught exception it will be ignored.
+<h3>Deploying Agents in Executable JAR file</h3>
+
+The JAR File Specification defines manifest attributes for standalone applications that are
+bundled as <em>executable JAR files</em>. 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</code> attribute to specify the class name
+of an agent to start before the application <code>main</code> method is invoked. The Java
+virtual machine attempts to invoke the following method on the agent class:
+
+<blockquote>
+ <code>public static void
+ agentmain(String agentArgs, Instrumentation inst);
+ </code>
+</blockquote>
+
+<P>
+If the agent class does not implement this method then the JVM will attempt to invoke:
+
+<blockquote>
+ <code>public static void
+ agentmain(String agentArgs);
+ </code>
+</blockquote>
+
+<p>
+The value of the <code>agentArgs</code> parameter is always the empty string.
+
+<P>
+The <code>agentmain</code> 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</code> method, or the <code>agentmain</code> method
+throws an uncaught exception or error, the JVM will abort.
+
+
+<h3>Visibility</h3>
+
+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
+<a href="{@docRoot}/java.base-summary.html">java.base</a> and
+<a href="{@docRoot}/java.instrument-summary.html">java.instrument</a>.
+Whether all {@linkplain ClassLoader#getPlatformClassLoader() platform classes}
+are visible or not will depend on the initial module or application.
+
+<p>
+Supporting classes that the agent makes visible to the bootstrap class loader
+(by means of {@link Instrumentation#appendToBootstrapClassLoaderSearch
+appendToBootstrapClassLoaderSearch} or the <code>Boot-Class-Path</code> 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.
+
<h3>Manifest Attributes</h3>
+
The following manifest attributes are defined for an agent JAR file:
<blockquote>
<dl>
<dt><code>Premain-Class</code></dt>
<dd>
- When an agent is specified at JVM launch time this attribute
- specifies the agent class.
- That is, the class containing the <code>premain</code> 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.
+ When an agent is specified at JVM launch time this attribute
+ specifies the agent class.
+ That is, the class containing the <code>premain</code> 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.
</dd>
-
<dt><code>Agent-Class</code></dt>
<dd>
- 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</code> 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.
-</dd>
-
+ 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</code> 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.
+</dd>
+<dt><code>Launcher-Agent-Class</code></dt>
+<dd>
+ 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</code> method is invoked.
+</dd>
<dt><code>Boot-Class-Path</code></dt>
<dd>
- 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.
+ 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.
</dd>
<dt><code>Can-Redefine-Classes</code></dt>
<dd>
- Boolean (<code>true</code> or <code>false</code>, case irrelevant).
- Is the ability to redefine classes
- needed by this agent.
- Values other than <code>true</code> are considered <code>false</code>.
- This attribute is optional, the default is <code>false</code>.
+ Boolean (<code>true</code> or <code>false</code>, case irrelevant).
+ Is the ability to redefine classes
+ needed by this agent.
+ Values other than <code>true</code> are considered <code>false</code>.
+ This attribute is optional, the default is <code>false</code>.
</dd>
<dt><code>Can-Retransform-Classes</code></dt>
<dd>
- Boolean (<code>true</code> or <code>false</code>, case irrelevant).
- Is the ability to retransform classes
- needed by this agent.
- Values other than <code>true</code> are considered <code>false</code>.
- This attribute is optional, the default is <code>false</code>.
+ Boolean (<code>true</code> or <code>false</code>, case irrelevant).
+ Is the ability to retransform classes
+ needed by this agent.
+ Values other than <code>true</code> are considered <code>false</code>.
+ This attribute is optional, the default is <code>false</code>.
</dd>
<dt><code>Can-Set-Native-Method-Prefix</code></dt>
<dd>
- Boolean (<code>true</code> or <code>false</code>, case irrelevant).
- Is the ability to set native method prefix needed by this agent.
- Values other than <code>true</code> are considered <code>false</code>.
- This attribute is optional, the default is <code>false</code>.
+ Boolean (<code>true</code> or <code>false</code>, case irrelevant).
+ Is the ability to set native method prefix needed by this agent.
+ Values other than <code>true</code> are considered <code>false</code>.
+ This attribute is optional, the default is <code>false</code>.
</dd>
</dl>
</blockquote>
--- a/jdk/src/java.instrument/share/classes/module-info.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.instrument/share/classes/module-info.java Thu May 04 17:54:50 2017 +0000
@@ -32,5 +32,8 @@
*/
module java.instrument {
exports java.lang.instrument;
+
+ // allow java launcher to load agents in executable JAR files
+ exports sun.instrument to java.base;
}
--- a/jdk/src/java.instrument/share/classes/sun/instrument/InstrumentationImpl.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.instrument/share/classes/sun/instrument/InstrumentationImpl.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -555,4 +555,15 @@
classfileBuffer);
}
}
+
+
+ /**
+ * Invoked by the java launcher to load a java agent that is packaged with
+ * the main application in an executable JAR file.
+ */
+ public static void loadAgent(String path) {
+ loadAgent0(path);
+ }
+
+ private static native void loadAgent0(String path);
}
--- a/jdk/src/java.instrument/share/native/libinstrument/InstrumentationImplNativeMethods.c Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.instrument/share/native/libinstrument/InstrumentationImplNativeMethods.c Thu May 04 17:54:50 2017 +0000
@@ -159,3 +159,20 @@
(JNIEnv * jnienv, jobject implThis, jlong agent, jobjectArray prefixArray, jboolean isRetransformable) {
setNativeMethodPrefixes(jnienv, (JPLISAgent*)(intptr_t)agent, prefixArray, isRetransformable);
}
+
+
+/*
+ * Class: sun_instrument_InstrumentationImpl
+ * Method: loadAgent0
+ */
+JNIEXPORT void JNICALL Java_sun_instrument_InstrumentationImpl_loadAgent0
+ (JNIEnv* env, jclass clazz, jstring jarfile)
+{
+ extern jint loadAgent(JNIEnv* env, jstring path);
+ if (loadAgent(env, jarfile) != JNI_OK) {
+ if (!(*env)->ExceptionCheck(env)) {
+ createAndThrowInternalError(env);
+ }
+ }
+}
+
--- a/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -106,7 +106,7 @@
* convert them to JVM TI capabilities.
*/
void
-convertCapabilityAtrributes(const jarAttribute* attributes, JPLISAgent* agent) {
+convertCapabilityAttributes(const jarAttribute* attributes, JPLISAgent* agent) {
/* set redefineClasses capability */
if (getBooleanAttribute(attributes, "Can-Redefine-Classes")) {
addRedefineClassesCapability(agent);
@@ -229,7 +229,7 @@
/*
* Convert JAR attributes into agent capabilities
*/
- convertCapabilityAtrributes(attributes, agent);
+ convertCapabilityAttributes(attributes, agent);
/*
* Track (record) the agent class name and options data
@@ -386,7 +386,7 @@
/*
* Convert JAR attributes into agent capabilities
*/
- convertCapabilityAtrributes(attributes, agent);
+ convertCapabilityAttributes(attributes, agent);
/*
* Create the java.lang.instrument.Instrumentation instance
@@ -435,6 +435,109 @@
DEF_Agent_OnUnload(JavaVM *vm) {
}
+/**
+ * Invoked by the java launcher to load an agent in the main executable JAR.
+ * The Launcher-Agent-Class attribute in the main manifest of the JAR file
+ * is the agent class.
+ *
+ * Returns JNI_OK if the agent is loaded and initialized; JNI_ERR if this
+ * function fails, possibly with a pending exception.
+ */
+jint loadAgent(JNIEnv* env, jstring path) {
+ JavaVM* vm;
+ JPLISAgent* agent;
+ const char* jarfile = NULL;
+ jarAttribute* attributes = NULL;
+ char* agentClass = NULL;
+ char* bootClassPath;
+ int oldLen, newLen;
+ jint result = JNI_ERR;
+
+ if ((*env)->GetJavaVM(env, &vm) < 0) {
+ return JNI_ERR;
+ }
+
+ // create JPLISAgent with JVMTI environment
+ if (createNewJPLISAgent(vm, &agent) != JPLIS_INIT_ERROR_NONE) {
+ return JNI_ERR;
+ }
+
+ // get path to JAR file as UTF-8 string
+ jarfile = (*env)->GetStringUTFChars(env, path, NULL);
+ if (jarfile == NULL) {
+ return JNI_ERR;
+ }
+
+ // read the attributes in the main section of JAR manifest
+ attributes = readAttributes(jarfile);
+ if (attributes == NULL) {
+ goto releaseAndReturn;
+ }
+
+ // Launcher-Agent-Class is required
+ agentClass = getAttribute(attributes, "Launcher-Agent-Class");
+ if (agentClass == NULL) {
+ goto releaseAndReturn;
+ }
+
+ // The value of Launcher-Agent-Class is in UTF-8, convert it to modified UTF-8
+ oldLen = (int) strlen(agentClass);
+ newLen = modifiedUtf8LengthOfUtf8(agentClass, oldLen);
+ if (newLen == oldLen) {
+ agentClass = strdup(agentClass);
+ } else {
+ char* str = (char*) malloc(newLen + 1);
+ if (str != NULL) {
+ convertUtf8ToModifiedUtf8(agentClass, oldLen, str, newLen);
+ }
+ agentClass = str;
+ }
+ if (agentClass == NULL) {
+ jthrowable oome = createThrowable(env, "java/lang/OutOfMemoryError", NULL);
+ if (oome != NULL) (*env)->Throw(env, oome);
+ goto releaseAndReturn;
+ }
+
+ // Boot-Class-Path
+ bootClassPath = getAttribute(attributes, "Boot-Class-Path");
+ if (bootClassPath != NULL) {
+ appendBootClassPath(agent, jarfile, bootClassPath);
+ }
+
+ // Can-XXXX capabilities
+ convertCapabilityAttributes(attributes, agent);
+
+ // Create the java.lang.instrument.Instrumentation object
+ if (!createInstrumentationImpl(env, agent)) {
+ goto releaseAndReturn;
+ }
+
+ // Enable the ClassFileLoadHook
+ if (!setLivePhaseEventHandlers(agent)) {
+ goto releaseAndReturn;
+ }
+
+ // invoke the agentmain method
+ if (!startJavaAgent(agent, env, agentClass, "", agent->mAgentmainCaller)) {
+ goto releaseAndReturn;
+ }
+
+ // initialization complete
+ result = JNI_OK;
+
+ releaseAndReturn:
+ if (agentClass != NULL) {
+ free(agentClass);
+ }
+ if (attributes != NULL) {
+ freeAttributes(attributes);
+ }
+ if (jarfile != NULL) {
+ (*env)->ReleaseStringUTFChars(env, path, jarfile);
+ }
+
+ return result;
+}
/*
* JVMTI callback support
--- a/jdk/src/java.management/share/classes/java/lang/management/ThreadInfo.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.management/share/classes/java/lang/management/ThreadInfo.java Thu May 04 17:54:50 2017 +0000
@@ -843,6 +843,9 @@
* @return a {@code ThreadInfo} object represented
* by {@code cd} if {@code cd} is not {@code null};
* {@code null} otherwise.
+ *
+ * @revised 9
+ * @spec JPMS
*/
public static ThreadInfo from(CompositeData cd) {
if (cd == null) {
--- a/jdk/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/XMLSignContext.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/XMLSignContext.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, 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
@@ -41,7 +41,7 @@
* (for example, you should not use the same <code>XMLSignContext</code>
* instance to sign two different {@link XMLSignature} objects).
* <p>
- * <b><a name="SupportedProperties"></a>Supported Properties</b>
+ * <b><a id="SupportedProperties"></a>Supported Properties</b>
* <p>The following properties can be set using the
* {@link #setProperty setProperty} method.
* <ul>
--- a/jdk/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/XMLValidateContext.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/XMLValidateContext.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, 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
@@ -40,7 +40,7 @@
* (for example, you should not use the same <code>XMLValidateContext</code>
* instance to validate two different {@link XMLSignature} objects).
* <p>
- * <b><a name="SupportedProperties"></a>Supported Properties</b>
+ * <b><a id="SupportedProperties"></a>Supported Properties</b>
* <p>The following properties can be set by an application using the
* {@link #setProperty setProperty} method.
* <ul>
--- a/jdk/src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java Thu May 04 17:54:50 2017 +0000
@@ -214,13 +214,14 @@
// Special-case the "load" command so that the right exception is
// thrown.
if (cmd.equals("load")) {
- throw new AgentLoadException("Failed to load agent library");
+ String msg = "Failed to load agent library";
+ if (!message.isEmpty())
+ msg += ": " + message;
+ throw new AgentLoadException(msg);
} else {
- if (message == null) {
- throw new AttachOperationFailedException("Command failed in target VM");
- } else {
- throw new AttachOperationFailedException(message);
- }
+ if (message.isEmpty())
+ message = "Command failed in target VM";
+ throw new AttachOperationFailedException(message);
}
}
--- a/jdk/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java Thu May 04 17:54:50 2017 +0000
@@ -211,13 +211,14 @@
// Special-case the "load" command so that the right exception is
// thrown.
if (cmd.equals("load")) {
- throw new AgentLoadException("Failed to load agent library");
+ String msg = "Failed to load agent library";
+ if (!message.isEmpty())
+ msg += ": " + message;
+ throw new AgentLoadException(msg);
} else {
- if (message == null) {
- throw new AttachOperationFailedException("Command failed in target VM");
- } else {
- throw new AttachOperationFailedException(message);
- }
+ if (message.isEmpty())
+ message = "Command failed in target VM";
+ throw new AttachOperationFailedException(message);
}
}
--- a/jdk/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java Thu May 04 17:54:50 2017 +0000
@@ -213,13 +213,14 @@
// Special-case the "load" command so that the right exception is
// thrown.
if (cmd.equals("load")) {
- throw new AgentLoadException("Failed to load agent library");
+ String msg = "Failed to load agent library";
+ if (!message.isEmpty())
+ msg += ": " + message;
+ throw new AgentLoadException(msg);
} else {
- if (message == null) {
- throw new AttachOperationFailedException("Command failed in target VM");
- } else {
- throw new AttachOperationFailedException(message);
- }
+ if (message.isEmpty())
+ message = "Command failed in target VM";
+ throw new AttachOperationFailedException(message);
}
}
--- a/jdk/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2014, 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
@@ -25,15 +25,19 @@
package sun.tools.attach;
+import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.AgentLoadException;
import com.sun.tools.attach.AgentInitializationException;
import com.sun.tools.attach.spi.AttachProvider;
+import jdk.internal.misc.VM;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.Properties;
import java.util.stream.Collectors;
@@ -43,8 +47,33 @@
public abstract class HotSpotVirtualMachine extends VirtualMachine {
- HotSpotVirtualMachine(AttachProvider provider, String id) {
+ private static final long CURRENT_PID;
+ private static final boolean ALLOW_ATTACH_SELF;
+ static {
+ PrivilegedAction<ProcessHandle> pa = ProcessHandle::current;
+ CURRENT_PID = AccessController.doPrivileged(pa).pid();
+
+ String s = VM.getSavedProperty("jdk.attach.allowAttachSelf");
+ ALLOW_ATTACH_SELF = "".equals(s) || Boolean.parseBoolean(s);
+ }
+
+ HotSpotVirtualMachine(AttachProvider provider, String id)
+ throws AttachNotSupportedException, IOException
+ {
super(provider, id);
+
+ int pid;
+ try {
+ pid = Integer.parseInt(id);
+ } catch (NumberFormatException e) {
+ throw new AttachNotSupportedException("Invalid process identifier");
+ }
+
+ // The tool should be a different VM to the target. This check will
+ // eventually be enforced by the target VM.
+ if (!ALLOW_ATTACH_SELF && (pid == 0 || pid == CURRENT_PID)) {
+ throw new IOException("Can not attach to current VM");
+ }
}
/*
@@ -103,8 +132,6 @@
}
try {
loadAgentLibrary("instrument", args);
- } catch (AgentLoadException x) {
- throw new InternalError("instrument library is missing in target VM", x);
} catch (AgentInitializationException x) {
/*
* Translate interesting errors into the right exception and
@@ -116,13 +143,17 @@
case JNI_ENOMEM:
throw new AgentLoadException("Insuffient memory");
case ATTACH_ERROR_BADJAR:
- throw new AgentLoadException("Agent JAR not found or no Agent-Class attribute");
+ throw new AgentLoadException(
+ "Agent JAR not found or no Agent-Class attribute");
case ATTACH_ERROR_NOTONCP:
- throw new AgentLoadException("Unable to add JAR file to system class path");
+ throw new AgentLoadException(
+ "Unable to add JAR file to system class path");
case ATTACH_ERROR_STARTFAIL:
- throw new AgentInitializationException("Agent JAR loaded but agent failed to initialize");
+ throw new AgentInitializationException(
+ "Agent JAR loaded but agent failed to initialize");
default :
- throw new AgentLoadException("Failed to load agent - unknown reason: " + rc);
+ throw new AgentLoadException("" +
+ "Failed to load agent - unknown reason: " + rc);
}
}
}
@@ -163,20 +194,20 @@
return props;
}
- private static final String MANAGMENT_PREFIX = "com.sun.management.";
+ private static final String MANAGEMENT_PREFIX = "com.sun.management.";
private static boolean checkedKeyName(Object key) {
if (!(key instanceof String)) {
throw new IllegalArgumentException("Invalid option (not a String): "+key);
}
- if (!((String)key).startsWith(MANAGMENT_PREFIX)) {
+ if (!((String)key).startsWith(MANAGEMENT_PREFIX)) {
throw new IllegalArgumentException("Invalid option: "+key);
}
return true;
}
private static String stripKeyName(Object key) {
- return ((String)key).substring(MANAGMENT_PREFIX.length());
+ return ((String)key).substring(MANAGEMENT_PREFIX.length());
}
@Override
@@ -204,9 +235,11 @@
@Override
public String startLocalManagementAgent() throws IOException {
executeJCmd("ManagementAgent.start_local").close();
- return getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress");
+ String prop = MANAGEMENT_PREFIX + "jmxremote.localConnectorAddress";
+ return getAgentProperties().getProperty(prop);
}
+
// --- HotSpot specific methods ---
// same as SIGQUIT
@@ -245,9 +278,9 @@
return executeCommand("jcmd", command);
}
+
// -- Supporting methods
-
/*
* Execute the given command in the target VM - specific platform
* implementation must implement this.
@@ -306,10 +339,10 @@
/*
* Utility method to read data into a String.
*/
- String readErrorMessage(InputStream sis) throws IOException {
+ String readErrorMessage(InputStream in) throws IOException {
String s;
StringBuilder message = new StringBuilder();
- BufferedReader br = new BufferedReader(new InputStreamReader(sis));
+ BufferedReader br = new BufferedReader(new InputStreamReader(in));
while ((s = br.readLine()) != null) {
message.append(s);
}
--- a/jdk/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java Thu May 04 17:54:50 2017 +0000
@@ -160,13 +160,14 @@
String message = readErrorMessage(sis);
sis.close();
if (cmd.equals("load")) {
- throw new AgentLoadException("Failed to load agent library");
+ String msg = "Failed to load agent library";
+ if (!message.isEmpty())
+ msg += ": " + message;
+ throw new AgentLoadException(msg);
} else {
- if (message == null) {
- throw new AttachOperationFailedException("Command failed in target VM");
- } else {
- throw new AttachOperationFailedException(message);
- }
+ if (message.isEmpty())
+ message = "Command failed in target VM";
+ throw new AttachOperationFailedException(message);
}
}
--- a/jdk/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java Thu May 04 17:54:50 2017 +0000
@@ -100,28 +100,29 @@
connectPipe(hPipe);
// create an input stream for the pipe
- PipedInputStream is = new PipedInputStream(hPipe);
+ PipedInputStream in = new PipedInputStream(hPipe);
// read completion status
- int status = readInt(is);
+ int status = readInt(in);
if (status != 0) {
// read from the stream and use that as the error message
- String message = readErrorMessage(is);
- is.close();
+ String message = readErrorMessage(in);
+ in.close();
// special case the load command so that the right exception is thrown
if (cmd.equals("load")) {
- throw new AgentLoadException("Failed to load agent library");
+ String msg = "Failed to load agent library";
+ if (!message.isEmpty())
+ msg += ": " + message;
+ throw new AgentLoadException(msg);
} else {
- if (message == null) {
- throw new AttachOperationFailedException("Command failed in target VM");
- } else {
- throw new AttachOperationFailedException(message);
- }
+ if (message.isEmpty())
+ message = "Command failed in target VM";
+ throw new AttachOperationFailedException(message);
}
}
// return the input stream
- return is;
+ return in;
} catch (IOException ioe) {
closePipe(hPipe);
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java Thu May 04 17:54:50 2017 +0000
@@ -71,6 +71,7 @@
import static java.util.jar.JarFile.MANIFEST_NAME;
import static java.util.stream.Collectors.joining;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+import static sun.tools.jar.Validator.ENTRYNAME_COMPARATOR;
/**
* This class implements a simple utility for creating files in the JAR
@@ -132,6 +133,10 @@
// if --release option found followed by at least file
boolean isMultiRelease;
+ // The last parsed --release value, if any. Used in conjunction with
+ // "-d,--describe-module" to select the operative module descriptor.
+ int releaseValue = -1;
+
/*
* cflag: create
* uflag: update
@@ -413,7 +418,7 @@
}
} else {
try (FileInputStream fin = new FileInputStream(FileDescriptor.in)) {
- found = describeModule(fin);
+ found = describeModuleFromStream(fin);
}
}
if (!found)
@@ -604,11 +609,6 @@
/* parse file arguments */
int n = args.length - count;
if (n > 0) {
- if (dflag) {
- // "--describe-module/-d" does not require file argument(s)
- usageError(formatMsg("error.bad.dflag", args[count]));
- return false;
- }
int version = BASE_VERSION;
int k = 0;
String[] nameBuf = new String[n];
@@ -616,6 +616,12 @@
try {
for (int i = count; i < args.length; i++) {
if (args[i].equals("-C")) {
+ if (dflag) {
+ // "--describe-module/-d" does not require file argument(s),
+ // but does accept --release
+ usageError(getMsg("error.bad.dflag"));
+ return false;
+ }
/* change the directory */
String dir = args[++i];
dir = (dir.endsWith(File.separator) ?
@@ -649,8 +655,15 @@
k = 0;
nameBuf = new String[n];
version = v;
+ releaseValue = version;
pathsMap.put(version, new HashSet<>());
} else {
+ if (dflag) {
+ // "--describe-module/-d" does not require file argument(s),
+ // but does accept --release
+ usageError(getMsg("error.bad.dflag"));
+ return false;
+ }
nameBuf[k++] = args[i];
}
}
@@ -756,7 +769,7 @@
* can be found by recursively descending directories.
*
* @param dir parent directory
- * @param file s list of files to expand
+ * @param files list of files to expand
* @param cpaths set of directories specified by -C option for the files
* @throws IOException if an I/O error occurs
*/
@@ -1721,23 +1734,62 @@
// Modular jar support
- static <T> String toString(Collection<T> c,
- CharSequence prefix,
- CharSequence suffix ) {
- if (c.isEmpty())
- return "";
- return c.stream().map(e -> e.toString())
- .collect(joining(", ", prefix, suffix));
+ /**
+ * Associates a module descriptor's zip entry name along with its
+ * bytes and an optional URI. Used when describing modules.
+ */
+ interface ModuleInfoEntry {
+ String name();
+ Optional<String> uriString();
+ InputStream bytes() throws IOException;
}
+ static class ZipFileModuleInfoEntry implements ModuleInfoEntry {
+ private final ZipFile zipFile;
+ private final ZipEntry entry;
+ ZipFileModuleInfoEntry(ZipFile zipFile, ZipEntry entry) {
+ this.zipFile = zipFile;
+ this.entry = entry;
+ }
+ @Override public String name() { return entry.getName(); }
+ @Override public InputStream bytes() throws IOException {
+ return zipFile.getInputStream(entry);
+ }
+ /** Returns an optional containing the effective URI. */
+ @Override public Optional<String> uriString() {
+ String uri = (Paths.get(zipFile.getName())).toUri().toString();
+ uri = "jar:" + uri + "/!" + entry.getName();
+ return Optional.of(uri);
+ }
+ }
+
+ static class StreamedModuleInfoEntry implements ModuleInfoEntry {
+ private final String name;
+ private final byte[] bytes;
+ StreamedModuleInfoEntry(String name, byte[] bytes) {
+ this.name = name;
+ this.bytes = bytes;
+ }
+ @Override public String name() { return name; }
+ @Override public InputStream bytes() throws IOException {
+ return new ByteArrayInputStream(bytes);
+ }
+ /** Returns an empty optional. */
+ @Override public Optional<String> uriString() {
+ return Optional.empty(); // no URI can be derived
+ }
+ }
+
+ /** Describes a module from a given zip file. */
private boolean describeModule(ZipFile zipFile) throws IOException {
- ZipEntry[] zes = zipFile.stream()
- .filter(e -> isModuleInfoEntry(e.getName()))
- .sorted(Validator.ENTRY_COMPARATOR)
- .toArray(ZipEntry[]::new);
+ ZipFileModuleInfoEntry[] infos = zipFile.stream()
+ .filter(e -> isModuleInfoEntry(e.getName()))
+ .sorted(Validator.ENTRY_COMPARATOR)
+ .map(e -> new ZipFileModuleInfoEntry(zipFile, e))
+ .toArray(ZipFileModuleInfoEntry[]::new);
- if (zes.length == 0) {
- // No module descriptor found, derive the automatic module name
+ if (infos.length == 0) {
+ // No module descriptor found, derive and describe the automatic module
String fn = zipFile.getName();
ModuleFinder mf = ModuleFinder.of(Paths.get(fn));
try {
@@ -1747,8 +1799,8 @@
return true;
}
ModuleDescriptor md = mref.iterator().next().descriptor();
- output(getMsg("out.automodule"));
- describeModule(md, null, null, "automatic");
+ output(getMsg("out.automodule") + "\n");
+ describeModule(md, null, null, "");
} catch (FindException e) {
String msg = formatMsg("error.unable.derive.automodule", fn);
Throwable t = e.getCause();
@@ -1757,46 +1809,117 @@
output(msg);
}
} else {
- for (ZipEntry ze : zes) {
- try (InputStream is = zipFile.getInputStream(ze)) {
- describeModule(is, ze.getName());
- }
- }
+ return describeModuleFromEntries(infos);
}
return true;
}
- private boolean describeModule(FileInputStream fis)
+ private boolean describeModuleFromStream(FileInputStream fis)
throws IOException
{
+ List<ModuleInfoEntry> infos = new LinkedList<>();
+
try (BufferedInputStream bis = new BufferedInputStream(fis);
ZipInputStream zis = new ZipInputStream(bis)) {
ZipEntry e;
while ((e = zis.getNextEntry()) != null) {
String ename = e.getName();
- if (isModuleInfoEntry(ename)){
- moduleInfos.put(ename, zis.readAllBytes());
+ if (isModuleInfoEntry(ename)) {
+ infos.add(new StreamedModuleInfoEntry(ename, zis.readAllBytes()));
}
}
}
- if (moduleInfos.size() == 0)
+
+ if (infos.size() == 0)
return false;
- String[] names = moduleInfos.keySet().stream()
- .sorted(Validator.ENTRYNAME_COMPARATOR)
- .toArray(String[]::new);
- for (String name : names) {
- describeModule(new ByteArrayInputStream(moduleInfos.get(name)), name);
+
+ ModuleInfoEntry[] sorted = infos.stream()
+ .sorted(Comparator.comparing(ModuleInfoEntry::name, ENTRYNAME_COMPARATOR))
+ .toArray(ModuleInfoEntry[]::new);
+
+ return describeModuleFromEntries(sorted);
+ }
+
+ private boolean lessThanEqualReleaseValue(ModuleInfoEntry entry) {
+ return intVersionFromEntry(entry) <= releaseValue ? true : false;
+ }
+
+ private static String versionFromEntryName(String name) {
+ String s = name.substring(VERSIONS_DIR_LENGTH);
+ return s.substring(0, s.indexOf("/"));
+ }
+
+ private static int intVersionFromEntry(ModuleInfoEntry entry) {
+ String name = entry.name();
+ if (!name.startsWith(VERSIONS_DIR))
+ return BASE_VERSION;
+
+ String s = name.substring(VERSIONS_DIR_LENGTH);
+ s = s.substring(0, s.indexOf('/'));
+ return Integer.valueOf(s);
+ }
+
+ /**
+ * Describes a single module descriptor, determined by the specified
+ * --release, if any, from the given ordered entries.
+ * The given infos must be ordered as per ENTRY_COMPARATOR.
+ */
+ private boolean describeModuleFromEntries(ModuleInfoEntry[] infos)
+ throws IOException
+ {
+ assert infos.length > 0;
+
+ // Informative: output all non-root descriptors, if any
+ String releases = Arrays.stream(infos)
+ .filter(e -> !e.name().equals(MODULE_INFO))
+ .map(ModuleInfoEntry::name)
+ .map(Main::versionFromEntryName)
+ .collect(joining(" "));
+ if (!releases.equals(""))
+ output("releases: " + releases + "\n");
+
+ // Describe the operative descriptor for the specified --release, if any
+ if (releaseValue != -1) {
+ ModuleInfoEntry entry = null;
+ int i = 0;
+ while (i < infos.length && lessThanEqualReleaseValue(infos[i])) {
+ entry = infos[i];
+ i++;
+ }
+
+ if (entry == null) {
+ output(formatMsg("error.no.operative.descriptor",
+ String.valueOf(releaseValue)));
+ return false;
+ }
+
+ String uriString = entry.uriString().orElse("");
+ try (InputStream is = entry.bytes()) {
+ describeModule(is, uriString);
+ }
+ } else {
+ // no specific --release specified, output the root, if any
+ if (infos[0].name().equals(MODULE_INFO)) {
+ String uriString = infos[0].uriString().orElse("");
+ try (InputStream is = infos[0].bytes()) {
+ describeModule(is, uriString);
+ }
+ } else {
+ // no root, output message to specify --release
+ output(getMsg("error.no.root.descriptor"));
+ }
}
return true;
}
static <T> String toString(Collection<T> set) {
if (set.isEmpty()) { return ""; }
- return set.stream().map(e -> e.toString().toLowerCase(Locale.ROOT))
- .collect(joining(" "));
+ return " " + set.stream().map(e -> e.toString().toLowerCase(Locale.ROOT))
+ .sorted().collect(joining(" "));
}
- private void describeModule(InputStream entryInputStream, String ename)
+
+ private void describeModule(InputStream entryInputStream, String uriString)
throws IOException
{
ModuleInfo.Attributes attrs = ModuleInfo.read(entryInputStream, null);
@@ -1804,71 +1927,94 @@
ModuleTarget target = attrs.target();
ModuleHashes hashes = attrs.recordedHashes();
- describeModule(md, target, hashes, ename);
+ describeModule(md, target, hashes, uriString);
}
private void describeModule(ModuleDescriptor md,
ModuleTarget target,
ModuleHashes hashes,
- String ename)
+ String uriString)
throws IOException
{
StringBuilder sb = new StringBuilder();
- sb.append("\nmodule ")
- .append(md.toNameAndVersion())
- .append(" (").append(ename).append(")");
+
+ sb.append(md.toNameAndVersion());
+
+ if (!uriString.equals(""))
+ sb.append(" ").append(uriString);
+ if (md.isOpen())
+ sb.append(" open");
+ if (md.isAutomatic())
+ sb.append(" automatic");
+ sb.append("\n");
- if (md.isOpen())
- sb.append("\n open ");
+ // unqualified exports (sorted by package)
+ md.exports().stream()
+ .sorted(Comparator.comparing(Exports::source))
+ .filter(e -> !e.isQualified())
+ .forEach(e -> sb.append("exports ").append(e.source())
+ .append(toString(e.modifiers())).append("\n"));
+
+ // dependences
+ md.requires().stream().sorted()
+ .forEach(r -> sb.append("requires ").append(r.name())
+ .append(toString(r.modifiers())).append("\n"));
- md.requires().stream()
- .sorted(Comparator.comparing(Requires::name))
- .forEach(r -> {
- sb.append("\n requires ");
- if (!r.modifiers().isEmpty())
- sb.append(toString(r.modifiers())).append(" ");
- sb.append(r.name());
- });
+ // service use and provides
+ md.uses().stream().sorted()
+ .forEach(s -> sb.append("uses ").append(s).append("\n"));
+
+ md.provides().stream()
+ .sorted(Comparator.comparing(Provides::service))
+ .forEach(p -> sb.append("provides ").append(p.service())
+ .append(" with")
+ .append(toString(p.providers()))
+ .append("\n"));
- md.uses().stream().sorted()
- .forEach(p -> sb.append("\n uses ").append(p));
+ // qualified exports
+ md.exports().stream()
+ .sorted(Comparator.comparing(Exports::source))
+ .filter(Exports::isQualified)
+ .forEach(e -> sb.append("qualified exports ").append(e.source())
+ .append(" to").append(toString(e.targets()))
+ .append("\n"));
- md.exports().stream()
- .sorted(Comparator.comparing(Exports::source))
- .forEach(p -> sb.append("\n exports ").append(p));
+ // open packages
+ md.opens().stream()
+ .sorted(Comparator.comparing(Opens::source))
+ .filter(o -> !o.isQualified())
+ .forEach(o -> sb.append("opens ").append(o.source())
+ .append(toString(o.modifiers()))
+ .append("\n"));
md.opens().stream()
- .sorted(Comparator.comparing(Opens::source))
- .forEach(p -> sb.append("\n opens ").append(p));
+ .sorted(Comparator.comparing(Opens::source))
+ .filter(Opens::isQualified)
+ .forEach(o -> sb.append("qualified opens ").append(o.source())
+ .append(toString(o.modifiers()))
+ .append(" to").append(toString(o.targets()))
+ .append("\n"));
- Set<String> concealed = new HashSet<>(md.packages());
+ // non-exported/non-open packages
+ Set<String> concealed = new TreeSet<>(md.packages());
md.exports().stream().map(Exports::source).forEach(concealed::remove);
md.opens().stream().map(Opens::source).forEach(concealed::remove);
- concealed.stream().sorted()
- .forEach(p -> sb.append("\n contains ").append(p));
+ concealed.forEach(p -> sb.append("contains ").append(p).append("\n"));
- md.provides().stream()
- .sorted(Comparator.comparing(Provides::service))
- .forEach(p -> sb.append("\n provides ").append(p.service())
- .append(" with ")
- .append(toString(p.providers())));
-
- md.mainClass().ifPresent(v -> sb.append("\n main-class " + v));
+ md.mainClass().ifPresent(v -> sb.append("main-class ").append(v).append("\n"));
if (target != null) {
- String osName = target.osName();
- if (osName != null)
- sb.append("\n operating-system-name " + osName);
- String osArch = target.osArch();
- if (osArch != null)
- sb.append("\n operating-system-architecture " + osArch);
+ String targetPlatform = target.targetPlatform();
+ if (!targetPlatform.isEmpty())
+ sb.append("platform ").append(targetPlatform).append("\n");
}
if (hashes != null) {
hashes.names().stream().sorted().forEach(
- mod -> sb.append("\n hashes ").append(mod).append(" ")
+ mod -> sb.append("hashes ").append(mod).append(" ")
.append(hashes.algorithm()).append(" ")
- .append(toHex(hashes.hashFor(mod))));
+ .append(toHex(hashes.hashFor(mod)))
+ .append("\n"));
}
output(sb.toString());
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Validator.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Validator.java Thu May 04 17:54:50 2017 +0000
@@ -116,7 +116,7 @@
// version number strings need to be sorted numerically
n = VERSIONS_DIR.length(); // skip the common prefix
int i1 = s1.indexOf('/', n);
- int i2 = s1.indexOf('/', n);
+ int i2 = s2.indexOf('/', n);
if (i1 == -1) throw new InvalidJarException(s1);
if (i2 == -1) throw new InvalidJarException(s2);
// shorter version numbers go first
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties Thu May 04 17:54:50 2017 +0000
@@ -45,7 +45,7 @@
'e' flag and manifest with the 'Main-Class' attribute cannot be specified \n\
together!
error.bad.dflag=\
- '-d, --describe-module' option requires no input file(s) to be specified: {0}
+ '-d, --describe-module' option requires no input file(s) to be specified
error.bad.reason=\
bad reason: {0}, must be one of deprecated, deprecated-for-removal, or incubating
error.nosuch.fileordir=\
@@ -62,6 +62,10 @@
Hashing module {0} dependences, unable to find module {1} on module path
error.module.options.without.info=\
One of --module-version or --hash-modules without module-info.class
+error.no.operative.descriptor=\
+ No operative descriptor for release: {0}
+error.no.root.descriptor=\
+ No root module descriptor, specify --release
error.unable.derive.automodule=\
Unable to derive module descriptor for: {0}
error.unexpected.module-info=\
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/ClassType.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/ClassType.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -217,9 +217,6 @@
* a member of this class or a superclass, if the size of the argument list
* does not match the number of declared arguments for the method, or
* if the method is an initializer, constructor or static intializer.
- * @throws {@link InvalidTypeException} if any argument in the
- * argument list is not assignable to the corresponding method argument
- * type.
* @throws ClassNotLoadedException if any argument type has not yet been loaded
* through the appropriate class loader.
* @throws IncompatibleThreadStateException if the specified thread has not
@@ -322,9 +319,6 @@
* a member of this class, if the size of the argument list
* does not match the number of declared arguments for the constructor,
* or if the method is not a constructor.
- * @throws {@link InvalidTypeException} if any argument in the
- * argument list is not assignable to the corresponding method argument
- * type.
* @throws ClassNotLoadedException if any argument type has not yet been loaded
* through the appropriate class loader.
* @throws IncompatibleThreadStateException if the specified thread has not
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/InterfaceType.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/InterfaceType.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -168,9 +168,6 @@
* a member of this interface, if the size of the argument list
* does not match the number of declared arguments for the method, or
* if the method is not static or is a static initializer.
- * @throws {@link InvalidTypeException} if any argument in the
- * argument list is not assignable to the corresponding method argument
- * type.
* @throws ClassNotLoadedException if any argument type has not yet been loaded
* through the appropriate class loader.
* @throws IncompatibleThreadStateException if the specified thread has not
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/JDIPermission.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/JDIPermission.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -40,8 +40,9 @@
* permission allows, and discusses the risks of granting code the
* permission.
*
- * <table border=1 cellpadding=5 summary="Table shows permission
- * target name, what the permission allows, and associated risks">
+ * <table border="1" cellpadding=5>
+ * <caption style="display:none">Table shows permission target name, what the
+ * permission allows, and associated risks</caption>
* <tr>
* <th>Permission Target Name</th>
* <th>What the Permission Allows</th>
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/Location.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/Location.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -41,7 +41,7 @@
* Several mirror interfaces have locations. Each such mirror
* extends a {@link Locatable} interface.
* <p>
- * <a name="strata"><b>Strata</b></a>
+ * <a id="strata"><b>Strata</b></a>
* <p>
* The source information for a Location is dependent on the
* <i>stratum</i> which is used. A stratum is a source code
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -249,9 +249,6 @@
* if the method is a constructor or static initializer, or
* if {@link #INVOKE_NONVIRTUAL} is specified and the method is
* abstract.
- * @throws {@link InvalidTypeException} if any argument in the
- * argument list is not assignable to the corresponding method argument
- * type.
* @throws ClassNotLoadedException if any argument type has not yet been loaded
* through the appropriate class loader.
* @throws IncompatibleThreadStateException if the specified thread has not
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/Type.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/Type.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -45,13 +45,14 @@
* <P>
* The following table illustrates which subinterfaces of Type
* are used to mirror types in the target VM --
- * <TABLE BORDER=1 SUMMARY="Maps each type declared in target to a mirrored
- * instance of a subinterface of PrimitiveType or ReferenceType">
- * <TR BGCOLOR="#EEEEFF">
+ * <TABLE BORDER="1">
+ * <CAPTION style="display:none">Maps each type declared in target to a mirrored
+ * instance of a subinterface of PrimitiveType or ReferenceType"</CAPTION>
+ * <TR style="background-color:#EEEEFF">
* <TH id="primtype" colspan=3>Subinterfaces of {@link PrimitiveType}</TH>
- * <TR BGCOLOR="#EEEEFF">
- * <TH id="declared" align="left" colspan=2>Type declared in target as</TH>
- * <TH id="mirrored" align="left">Is mirrored as an instance of</TH>
+ * <TR style="background-color:#EEEEFF">
+ * <TH id="declared" style="text-align:left" colspan=2>Type declared in target as</TH>
+ * <TH id="mirrored" style="text-align:left">Is mirrored as an instance of</TH>
* <TR>
* <TD headers="primtype declared" colspan=2><CODE>boolean</CODE></TD>
* <TD headers="primtype mirrored"> {@link BooleanType}</TD>
@@ -79,12 +80,12 @@
* <TR>
* <TD headers="primtype declared" colspan=2><CODE>void</CODE></TD>
* <TD headers="primtype mirrored">{@link VoidType}</TD>
- * <TR BGCOLOR="#EEEEFF">
+ * <TR style="background-color:#EEEEFF">
* <TH id="reftype" colspan=3>Subinterfaces of {@link ReferenceType}</TH>
- * <TR BGCOLOR="#EEEEFF">
- * <TH id="declared2" align="left">Type declared in target as</TH>
- * <TH id="example2" align="left">For example</TH>
- * <TH id="mirrored2" align="left">Is mirrored as an instance of</TH>
+ * <TR style="background-color:#EEEEFF">
+ * <TH id="declared2"style="text-align:left">Type declared in target as</TH>
+ * <TH id="example2" style="text-align:left">For example</TH>
+ * <TH id="mirrored2" style="text-align:left">Is mirrored as an instance of</TH>
* <TR>
* <TD headers="reftype declared2"><I>a class</I></TD>
* <TD headers="reftype example2"><CODE>Date</CODE></TD>
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/Value.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/Value.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -31,7 +31,7 @@
* value hierarchy encompassing primitive values and object values.
* <P>
* Some examples of where values may be accessed:
- * <BLOCKQUOTE><TABLE SUMMARY="layout">
+ * <BLOCKQUOTE><TABLE><CAPTION style="display:none">layout</CAPTION>
* <TR>
* <TD>{@link ObjectReference#getValue(com.sun.jdi.Field)
* ObjectReference.getValue(Field)}
@@ -52,15 +52,16 @@
* <P>
* The following table illustrates which subinterfaces of Value
* are used to mirror values in the target VM --
- * <TABLE BORDER=1 SUMMARY="Maps each kind of value to a mirrored
- * instance of a subinterface of Value">
- * <TR BGCOLOR="#EEEEFF">
+ * <TABLE BORDER="1">
+ * <CAPTION style="display:none">Maps each kind of value to a mirrored
+ * instance of a subinterface of Value</CAPTION>
+ * <TR style="background-color:#EEEEFF">
* <TH id="primval" colspan=4>Subinterfaces of {@link PrimitiveValue}</TH>
- * <TR BGCOLOR="#EEEEFF">
- * <TH id="kind" align="left">Kind of value</TH>
- * <TH id="example" align="left">For example -<br>expression in target</TH>
- * <TH id="mirrored" align="left">Is mirrored as an<br>instance of</TH>
- * <TH id="type" align="left">{@link Type} of value<br>{@link #type() Value.type()}</TH>
+ * <TR style="background-color:#EEEEFF">
+ * <TH id="kind" style="text-align:left">Kind of value</TH>
+ * <TH id="example" style="text-align:left">For example -<br>expression in target</TH>
+ * <TH id="mirrored" style="text-align:left">Is mirrored as an<br>instance of</TH>
+ * <TH id="type" style="text-align:left">{@link Type} of value<br>{@link #type() Value.type()}</TH>
* <TR>
* <TD headers="primval kind"> a boolean</TD>
* <TD headers="primval example"> {@code true}</TD>
@@ -106,13 +107,13 @@
* <TD headers="primval example"> </TD>
* <TD headers="primval mirrored"> {@link VoidValue}</TD>
* <TD headers="primval type"> {@link VoidType}</TD>
- * <TR BGCOLOR="#EEEEFF">
+ * <TR style="background-color:#EEEEFF">
* <TH id="objref" colspan=4>Subinterfaces of {@link ObjectReference}</TH>
- * <TR BGCOLOR="#EEEEFF">
- * <TH id="kind2" align="left">Kind of value</TH>
- * <TH id="example2" align="left">For example -<br>expression in target</TH>
- * <TH id="mirrored2" align="left">Is mirrored as an<br>instance of</TH>
- * <TH id="type2" align="left">{@link Type} of value<br>{@link #type() Value.type()}</TH>
+ * <TR style="background-color:#EEEEFF">
+ * <TH id="kind2" style="text-align:left">Kind of value</TH>
+ * <TH id="example2" style="text-align:left">For example -<br>expression in target</TH>
+ * <TH id="mirrored2" style="text-align:left">Is mirrored as an<br>instance of</TH>
+ * <TH id="type2" style="text-align:left">{@link Type} of value<br>{@link #type() Value.type()}</TH>
* <TR>
* <TD headers="objref kind2"> a class instance</TD>
* <TD headers="objref example2"> {@code this}</TD>
@@ -148,13 +149,13 @@
* <TD headers="objref example2"> {@code this.getClass()}<br> {@code .getClassLoader()}</TD>
* <TD headers="objref mirrored2"> {@link ClassLoaderReference}</TD>
* <TD headers="objref type2"> {@link ClassType}</TD>
- * <TR BGCOLOR="#EEEEFF">
+ * <TR style="background-color:#EEEEFF">
* <TH id="other" colspan=4>Other</TH>
- * <TR BGCOLOR="#EEEEFF">
- * <TD id="kind3" align="left">Kind of value</TD>
- * <TD id="example3" align="left">For example -<br>expression in target</TD>
- * <TD id="mirrored3" align="left">Is mirrored as</TD>
- * <TD id="type3" align="left">{@link Type} of value</TD>
+ * <TR style="background-color:#EEEEFF">
+ * <TD id="kind3" style="text-align:left">Kind of value</TD>
+ * <TD id="example3" style="text-align:left">For example -<br>expression in target</TD>
+ * <TD id="mirrored3" style="text-align:left">Is mirrored as</TD>
+ * <TD id="type3" style="text-align:left">{@link Type} of value</TD>
* <TR>
* <TD headers="other kind3"> null</TD>
* <TD headers="other example3"> {@code null}</TD>
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -51,8 +51,8 @@
* Some {@link com.sun.jdi.connect.Connector} implementations may require slightly
* different handling than presented below.
*
- * <TABLE BORDER WIDTH="75%" SUMMARY="Four scenarios for connecting a debugger
- * to a virtual machine">
+ * <TABLE BORDER="1" style="width:75%">
+ * <CAPTION style="display:none">Four scenarios for connecting a debugger to a virtual machine"</CAPTION>
* <TR>
* <TH scope=col>Scenario</TH>
* <TH scope=col>Description</TH>
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/doc-files/signature.html Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/doc-files/signature.html Thu May 04 17:54:50 2017 +0000
@@ -4,7 +4,7 @@
JDI Type Signatures
</TITLE>
</HEAD>
-<BODY BGCOLOR="white">
+<BODY style="background-color:white">
<dl><dd>
<Table Border="0">
<caption><font size=5><b>JDI Type Signatures</b></font></caption>
--- a/jdk/src/jdk.jdi/share/classes/module-info.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jdi/share/classes/module-info.java Thu May 04 17:54:50 2017 +0000
@@ -45,8 +45,8 @@
* Platform Debugger Architecture documentation</a> for this release and the <a
* href="http://java.sun.com/products/jpda">Java Platform Debugger Architecture
* website</a>.
- * <p>
- * <font size="+1"><b>Global Exceptions:</b></font>
+ * <p style="font-size:larger">
+ * <b>Global Exceptions:</b>
* <p>
* This section documents exceptions which apply to the entire API and are thus
* not documented on individual methods.
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java Thu May 04 17:54:50 2017 +0000
@@ -152,14 +152,14 @@
@Override
public void storeFiles(ResourcePool files) {
try {
- String targetOsName = files.moduleView()
- .findModule("java.base")
- .map(ResourcePoolModule::osName)
- .orElse(null);
- if (targetOsName == null) {
+ String value = files.moduleView()
+ .findModule("java.base")
+ .map(ResourcePoolModule::targetPlatform)
+ .orElse(null);
+ if (value == null) {
throw new PluginException("ModuleTarget attribute is missing for java.base module");
}
- this.targetPlatform = Platform.toPlatform(targetOsName);
+ this.targetPlatform = Platform.toPlatform(value);
checkResourcePool(files);
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java Thu May 04 17:54:50 2017 +0000
@@ -324,15 +324,9 @@
}
@Override
- public String osName() {
+ public String targetPlatform() {
initModuleAttributes();
- return target != null? target.osName() : null;
- }
-
- @Override
- public String osArch() {
- initModuleAttributes();
- return target != null? target.osArch() : null;
+ return target != null? target.targetPlatform() : null;
}
private void initModuleAttributes() {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Platform.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Platform.java Thu May 04 17:54:50 2017 +0000
@@ -40,12 +40,17 @@
UNKNOWN;
/**
- * Returns the {@code Platform} of the given OS name specified
+ * Returns the {@code Platform} derived from the target platform
* in the {@code ModuleTarget} attribute.
- *
- * @param osName OS name in ModuleTarget attribute
*/
- public static Platform toPlatform(String osName) {
+ public static Platform toPlatform(String targetPlatform) {
+ String osName;
+ int index = targetPlatform.indexOf("-");
+ if (index < 0) {
+ osName = targetPlatform;
+ } else {
+ osName = targetPlatform.substring(0, index);
+ }
try {
return Platform.valueOf(osName.toUpperCase(Locale.ENGLISH));
} catch (IllegalArgumentException e) {
@@ -57,9 +62,9 @@
* Returns the {@code Platform} to which the given module is target to.
*/
public static Platform getTargetPlatform(ResourcePoolModule module) {
- String osName = module.osName();
- if (osName != null) {
- return toPlatform(osName);
+ String targetPlatform = module.targetPlatform();
+ if (targetPlatform != null) {
+ return toPlatform(targetPlatform);
} else {
return Platform.UNKNOWN;
}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolManager.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolManager.java Thu May 04 17:54:50 2017 +0000
@@ -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
@@ -110,15 +110,9 @@
}
@Override
- public String osName() {
+ public String targetPlatform() {
initModuleAttributes();
- return target != null? target.osName() : null;
- }
-
- @Override
- public String osArch() {
- initModuleAttributes();
- return target != null? target.osArch() : null;
+ return target != null? target.targetPlatform() : null;
}
private void initModuleAttributes() {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin.java Thu May 04 17:54:50 2017 +0000
@@ -33,13 +33,13 @@
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
-import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import jdk.tools.jlink.internal.ModuleSorter;
import jdk.tools.jlink.internal.Utils;
+import jdk.tools.jlink.plugin.PluginException;
import jdk.tools.jlink.plugin.ResourcePool;
import jdk.tools.jlink.plugin.ResourcePoolBuilder;
import jdk.tools.jlink.plugin.ResourcePoolEntry;
@@ -132,18 +132,16 @@
public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
in.transformAndCopy(Function.identity(), out);
- Optional<ResourcePoolModule> javaBase = in.moduleView().findModule("java.base");
- javaBase.ifPresent(mod -> {
- // fill release information available from transformed "java.base" module!
- ModuleDescriptor desc = mod.descriptor();
- desc.version().ifPresent(s -> release.put("JAVA_VERSION",
- quote(parseVersion(s.toString()))));
- desc.version().ifPresent(s -> release.put("JAVA_FULL_VERSION",
- quote(s.toString())));
+ ResourcePoolModule javaBase = in.moduleView().findModule("java.base")
+ .orElse(null);
+ if (javaBase == null || javaBase.targetPlatform() == null) {
+ throw new PluginException("ModuleTarget attribute is missing for java.base module");
+ }
- release.put("OS_NAME", quote(mod.osName()));
- release.put("OS_ARCH", quote(mod.osArch()));
- });
+ // fill release information available from transformed "java.base" module!
+ ModuleDescriptor desc = javaBase.descriptor();
+ desc.version().ifPresent(v -> release.put("JAVA_VERSION",
+ quote(parseVersion(v))));
// put topological sorted module names separated by space
release.put("MODULES", new ModuleSorter(in.moduleView())
@@ -152,14 +150,15 @@
// create a TOP level ResourcePoolEntry for "release" file.
out.add(ResourcePoolEntry.create("/java.base/release",
- ResourcePoolEntry.Type.TOP, releaseFileContent()));
+ ResourcePoolEntry.Type.TOP,
+ releaseFileContent()));
return out.build();
}
// Parse version string and return a string that includes only version part
// leaving "pre", "build" information. See also: java.lang.Runtime.Version.
- private static String parseVersion(String str) {
- return Runtime.Version.parse(str)
+ private static String parseVersion(ModuleDescriptor.Version v) {
+ return Runtime.Version.parse(v.toString())
.version()
.stream()
.map(Object::toString)
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java Thu May 04 17:54:50 2017 +0000
@@ -211,8 +211,7 @@
// drop target attribute only if any OS property is present
ModuleTarget target = attrs.target();
if (dropModuleTarget && target != null) {
- this.dropModuleTarget = (target.osName() != null)
- || (target.osArch() != null);
+ this.dropModuleTarget = (target.targetPlatform() != null);
} else {
this.dropModuleTarget = false;
}
@@ -377,7 +376,7 @@
}
void dropModuleTarget() {
- extender.targetPlatform("", "");
+ extender.targetPlatform("");
}
byte[] getBytes() throws IOException {
@@ -527,8 +526,7 @@
ModuleDescriptor md = moduleInfo.descriptor;
// drop ModuleTarget attribute if java.base has all OS properties
ModuleTarget target = moduleInfo.target();
- if (dropModuleTarget
- && (target.osName() != null) && (target.osArch() != null)) {
+ if (dropModuleTarget && target.targetPlatform() != null) {
dropModuleTarget = true;
} else {
dropModuleTarget = false;
@@ -543,7 +541,7 @@
moduleInfo.validatePackages();
// module-info.class may be overridden for optimization
- // 1. update ModuleTarget attribute to drop osName, osArch, osVersion
+ // 1. update ModuleTarget attribute to drop targetPlartform
// 2. add/update ModulePackages attribute
if (moduleInfo.shouldRewrite()) {
entry = entry.copyWithContent(moduleInfo.getBytes());
@@ -655,10 +653,9 @@
// new ModuleTarget(String, String)
mv.visitTypeInsn(NEW, MODULE_TARGET_CLASSNAME);
mv.visitInsn(DUP);
- mv.visitLdcInsn(minfo.target().osName());
- mv.visitLdcInsn(minfo.target().osArch());
+ mv.visitLdcInsn(minfo.target().targetPlatform());
mv.visitMethodInsn(INVOKESPECIAL, MODULE_TARGET_CLASSNAME,
- "<init>", "(Ljava/lang/String;Ljava/lang/String;)V", false);
+ "<init>", "(Ljava/lang/String;)V", false);
mv.visitInsn(AASTORE);
}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolModule.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ResourcePoolModule.java Thu May 04 17:54:50 2017 +0000
@@ -58,18 +58,11 @@
public ModuleDescriptor descriptor();
/**
- * The module target OS name for this module.
+ * The target platform
*
- * @return The module target OS name
+ * @return The target platform
*/
- public String osName();
-
- /**
- * The module target OS arch for this module.
- *
- * @return The module target OS arch
- */
- public String osArch();
+ public String targetPlatform();
/**
* Retrieves all the packages located in this module.
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java Thu May 04 17:54:50 2017 +0000
@@ -177,8 +177,7 @@
ModuleFinder moduleFinder;
Version moduleVersion;
String mainClass;
- String osName;
- String osArch;
+ String targetPlatform;
Pattern modulesToHash;
ModuleResolution moduleResolution;
boolean dryrun;
@@ -311,9 +310,9 @@
try (JmodFile jf = new JmodFile(options.jmodFile)) {
try (InputStream in = jf.getInputStream(Section.CLASSES, MODULE_INFO)) {
ModuleInfo.Attributes attrs = ModuleInfo.read(in, null);
- printModuleDescriptor(attrs.descriptor(),
- attrs.target(),
- attrs.recordedHashes());
+ describeModule(attrs.descriptor(),
+ attrs.target(),
+ attrs.recordedHashes());
return true;
} catch (IOException e) {
throw new CommandException("err.module.descriptor.not.found");
@@ -323,66 +322,92 @@
static <T> String toString(Collection<T> c) {
if (c.isEmpty()) { return ""; }
- return c.stream().map(e -> e.toString().toLowerCase(Locale.ROOT))
- .collect(joining(" "));
+ return " " + c.stream().map(e -> e.toString().toLowerCase(Locale.ROOT))
+ .sorted().collect(joining(" "));
}
- private void printModuleDescriptor(ModuleDescriptor md,
- ModuleTarget target,
- ModuleHashes hashes)
+ private void describeModule(ModuleDescriptor md,
+ ModuleTarget target,
+ ModuleHashes hashes)
throws IOException
{
StringBuilder sb = new StringBuilder();
- sb.append("\n").append(md.toNameAndVersion());
+
+ sb.append(md.toNameAndVersion());
+
+ if (md.isOpen())
+ sb.append(" open");
+ if (md.isAutomatic())
+ sb.append(" automatic");
+ sb.append("\n");
+
+ // unqualified exports (sorted by package)
+ md.exports().stream()
+ .sorted(Comparator.comparing(Exports::source))
+ .filter(e -> !e.isQualified())
+ .forEach(e -> sb.append("exports ").append(e.source())
+ .append(toString(e.modifiers())).append("\n"));
+
+ // dependences
+ md.requires().stream().sorted()
+ .forEach(r -> sb.append("requires ").append(r.name())
+ .append(toString(r.modifiers())).append("\n"));
- md.requires().stream()
- .sorted(Comparator.comparing(Requires::name))
- .forEach(r -> {
- sb.append("\n requires ");
- if (!r.modifiers().isEmpty())
- sb.append(toString(r.modifiers())).append(" ");
- sb.append(r.name());
- });
+ // service use and provides
+ md.uses().stream().sorted()
+ .forEach(s -> sb.append("uses ").append(s).append("\n"));
+
+ md.provides().stream()
+ .sorted(Comparator.comparing(Provides::service))
+ .forEach(p -> sb.append("provides ").append(p.service())
+ .append(" with")
+ .append(toString(p.providers()))
+ .append("\n"));
- md.uses().stream().sorted()
- .forEach(s -> sb.append("\n uses ").append(s));
+ // qualified exports
+ md.exports().stream()
+ .sorted(Comparator.comparing(Exports::source))
+ .filter(Exports::isQualified)
+ .forEach(e -> sb.append("qualified exports ").append(e.source())
+ .append(" to").append(toString(e.targets()))
+ .append("\n"));
- md.exports().stream()
- .sorted(Comparator.comparing(Exports::source))
- .forEach(p -> sb.append("\n exports ").append(p));
+ // open packages
+ md.opens().stream()
+ .sorted(Comparator.comparing(Opens::source))
+ .filter(o -> !o.isQualified())
+ .forEach(o -> sb.append("opens ").append(o.source())
+ .append(toString(o.modifiers()))
+ .append("\n"));
md.opens().stream()
- .sorted(Comparator.comparing(Opens::source))
- .forEach(p -> sb.append("\n opens ").append(p));
+ .sorted(Comparator.comparing(Opens::source))
+ .filter(Opens::isQualified)
+ .forEach(o -> sb.append("qualified opens ").append(o.source())
+ .append(toString(o.modifiers()))
+ .append(" to").append(toString(o.targets()))
+ .append("\n"));
- Set<String> concealed = new HashSet<>(md.packages());
+ // non-exported/non-open packages
+ Set<String> concealed = new TreeSet<>(md.packages());
md.exports().stream().map(Exports::source).forEach(concealed::remove);
md.opens().stream().map(Opens::source).forEach(concealed::remove);
- concealed.stream().sorted()
- .forEach(p -> sb.append("\n contains ").append(p));
+ concealed.forEach(p -> sb.append("contains ").append(p).append("\n"));
- md.provides().stream()
- .sorted(Comparator.comparing(Provides::service))
- .forEach(p -> sb.append("\n provides ").append(p.service())
- .append(" with ")
- .append(toString(p.providers())));
-
- md.mainClass().ifPresent(v -> sb.append("\n main-class " + v));
+ md.mainClass().ifPresent(v -> sb.append("main-class ").append(v).append("\n"));
if (target != null) {
- String osName = target.osName();
- if (osName != null)
- sb.append("\n operating-system-name " + osName);
- String osArch = target.osArch();
- if (osArch != null)
- sb.append("\n operating-system-architecture " + osArch);
- }
+ String targetPlatform = target.targetPlatform();
+ if (!targetPlatform.isEmpty())
+ sb.append("platform ").append(targetPlatform).append("\n");
+ }
- if (hashes != null) {
- hashes.names().stream().sorted().forEach(
- mod -> sb.append("\n hashes ").append(mod).append(" ")
- .append(hashes.algorithm()).append(" ")
- .append(toHex(hashes.hashFor(mod))));
+ if (hashes != null) {
+ hashes.names().stream().sorted().forEach(
+ mod -> sb.append("hashes ").append(mod).append(" ")
+ .append(hashes.algorithm()).append(" ")
+ .append(toHex(hashes.hashFor(mod)))
+ .append("\n"));
}
out.println(sb.toString());
@@ -437,8 +462,7 @@
final Version moduleVersion = options.moduleVersion;
final String mainClass = options.mainClass;
- final String osName = options.osName;
- final String osArch = options.osArch;
+ final String targetPlatform = options.targetPlatform;
final List<PathMatcher> excludes = options.excludes;
final ModuleResolution moduleResolution = options.moduleResolution;
@@ -534,9 +558,10 @@
if (mainClass != null)
extender.mainClass(mainClass);
- // --os-name, --os-arch
- if (osName != null || osArch != null)
- extender.targetPlatform(osName, osArch);
+ // --target-platform
+ if (targetPlatform != null) {
+ extender.targetPlatform(targetPlatform);
+ }
// --module-version
if (moduleVersion != null)
@@ -1327,15 +1352,10 @@
.withRequiredArg()
.withValuesConvertedBy(new ModuleVersionConverter());
- OptionSpec<String> osName
- = parser.accepts("os-name", getMessage("main.opt.os-name"))
+ OptionSpec<String> targetPlatform
+ = parser.accepts("target-platform", getMessage("main.opt.target-platform"))
.withRequiredArg()
- .describedAs(getMessage("main.opt.os-name.arg"));
-
- OptionSpec<String> osArch
- = parser.accepts("os-arch", getMessage("main.opt.os-arch"))
- .withRequiredArg()
- .describedAs(getMessage("main.opt.os-arch.arg"));
+ .describedAs(getMessage("main.opt.target-platform.arg"));
OptionSpec<Void> doNotResolveByDefault
= parser.accepts("do-not-resolve-by-default",
@@ -1400,10 +1420,8 @@
options.moduleVersion = getLastElement(opts.valuesOf(moduleVersion));
if (opts.has(mainClass))
options.mainClass = getLastElement(opts.valuesOf(mainClass));
- if (opts.has(osName))
- options.osName = getLastElement(opts.valuesOf(osName));
- if (opts.has(osArch))
- options.osArch = getLastElement(opts.valuesOf(osArch));
+ if (opts.has(targetPlatform))
+ options.targetPlatform = getLastElement(opts.valuesOf(targetPlatform));
if (opts.has(warnIfResolved))
options.moduleResolution = getLastElement(opts.valuesOf(warnIfResolved));
if (opts.has(doNotResolveByDefault)) {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties Thu May 04 16:38:09 2017 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties Thu May 04 17:54:50 2017 +0000
@@ -64,10 +64,8 @@
main.opt.main-class=Main class
main.opt.main-class.arg=class-name
main.opt.man-pages=Location of man pages
-main.opt.os-name=Operating system name
-main.opt.os-name.arg=os-name
-main.opt.os-arch=Operating system architecture
-main.opt.os-arch.arg=os-arch
+main.opt.target-platform=Target platform
+main.opt.target-platform.arg=target-platform
main.opt.module-path=Module path
main.opt.hash-modules=Compute and record hashes to tie a packaged module\
\ with modules matching the given <regex-pattern> and depending upon it directly\
--- a/jdk/test/com/sun/management/HotSpotDiagnosticMXBean/CheckOrigin.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/com/sun/management/HotSpotDiagnosticMXBean/CheckOrigin.java Thu May 04 17:54:50 2017 +0000
@@ -66,6 +66,7 @@
"-XX:+UseCodeAging",
"-XX:+UseCerealGC", // Should be ignored.
"-XX:Flags=" + flagsFile.getAbsolutePath(),
+ "-Djdk.attach.allowAttachSelf",
"-cp", System.getProperty("test.class.path"),
"CheckOrigin",
"-runtests");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/tools/attach/AttachSelf.java Thu May 04 17:54:50 2017 +0000
@@ -0,0 +1,61 @@
+/*
+ * 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 com.sun.tools.attach.VirtualMachine;
+
+import java.io.IOException;
+
+/**
+ * @test
+ * @modules jdk.attach
+ * @run main AttachSelf
+ * @run main/othervm -Djdk.attach.allowAttachSelf AttachSelf
+ * @run main/othervm -Djdk.attach.allowAttachSelf=true AttachSelf
+ * @run main/othervm -Djdk.attach.allowAttachSelf=false AttachSelf
+ */
+
+public class AttachSelf {
+
+ public static void main(String[] args) throws Exception {
+
+ String value = System.getProperty("jdk.attach.allowAttachSelf");
+ boolean canAttachSelf = (value != null) && !value.equals("false");
+
+ String vmid = "" + ProcessHandle.current().pid();
+
+ VirtualMachine vm = null;
+ try {
+ vm = VirtualMachine.attach(vmid);
+ if (!canAttachSelf)
+ throw new RuntimeException("Attached to self not expected");
+ } catch (IOException ioe) {
+ if (canAttachSelf)
+ throw ioe;
+ } finally {
+ if (vm != null) vm.detach();
+ }
+
+ }
+
+}
+
--- a/jdk/test/com/sun/tools/attach/RunnerUtil.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/com/sun/tools/attach/RunnerUtil.java Thu May 04 17:54:50 2017 +0000
@@ -48,7 +48,10 @@
*/
public static ProcessThread startApplication(String... additionalOpts) throws Throwable {
String classpath = System.getProperty("test.class.path", ".");
- String[] myArgs = concat(additionalOpts, new String [] { "-XX:+UsePerfData", "-Dattach.test=true", "-classpath", classpath, "Application" });
+ String[] myArgs = concat(additionalOpts, new String [] {
+ "-XX:+UsePerfData", "-XX:+EnableDynamicAgentLoading",
+ "-Dattach.test=true", "-classpath", classpath, "Application"
+ });
String[] args = Utils.addTestJavaOpts(myArgs);
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args);
ProcessThread pt = new ProcessThread("runApplication", (line) -> line.equals(Application.READY_MSG), pb);
--- a/jdk/test/com/sun/tools/attach/java.policy.allow Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/com/sun/tools/attach/java.policy.allow Thu May 04 17:54:50 2017 +0000
@@ -8,7 +8,8 @@
permission com.sun.tools.attach.AttachPermission "createAttachProvider";
/* implementation specific */
- permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
+ permission java.lang.RuntimePermission "manageProcess";
+ permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
permission java.lang.RuntimePermission "accessClassInPackage.sun.tools.attach";
permission java.lang.RuntimePermission "accessClassInPackage.sun.jvmstat.monitor";
permission java.lang.RuntimePermission "loadLibrary.attach";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/tools/attach/modules/Agent.java Thu May 04 17:54:50 2017 +0000
@@ -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 java.lang.instrument.Instrumentation;
+
+public class Agent {
+
+ public static void agentmain(String agentArgs, Instrumentation inst) {
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/tools/attach/modules/Driver.java Thu May 04 17:54:50 2017 +0000
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.attach
+ * @build m/* Agent
+ * @run main/othervm -Djdk.attach.allowAttachSelf m/p.Main jmx javaagent
+ * @run main/othervm -Djdk.attach.allowAttachSelf m/p.Main javaagent jmx
+ * @run main/othervm --limit-modules=jdk.attach -Djdk.attach.allowAttachSelf m/p.Main jmx javaagent
+ * @run main/othervm --limit-modules=jdk.attach -Djdk.attach.allowAttachSelf m/p.Main javaagent jmx
+ * @summary Basic test to ensure that a JMX agent or a tool agent can be loaded/started in
+ * a modular application.
+ */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/tools/attach/modules/m/module-info.java Thu May 04 17:54:50 2017 +0000
@@ -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 m {
+ exports p;
+ requires jdk.attach;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/tools/attach/modules/m/p/Main.java Thu May 04 17:54:50 2017 +0000
@@ -0,0 +1,164 @@
+/*
+ * 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.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import com.sun.tools.attach.VirtualMachine;
+
+public class Main {
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("#modules loaded: " + moduleInfoCont());
+
+ String vmid = "" + ProcessHandle.current().pid();
+ VirtualMachine vm = VirtualMachine.attach(vmid);
+
+ for (String test : args) {
+ switch (test) {
+ case "jmx" :
+ startJMXAgent(vm);
+ break;
+ case "javaagent" :
+ startJavaAgent(vm, createAgentJar());
+ break;
+ }
+
+ System.out.println("#modules loaded: " + moduleInfoCont());
+ }
+ }
+
+ /**
+ * Locates module-info.class resources to get a count of the module of system
+ * modules.
+ */
+ static long moduleInfoCont() {
+ ClassLoader scl = ClassLoader.getSystemClassLoader();
+ return scl.resources("module-info.class").count();
+ }
+
+ /**
+ * Starts a JMX agent and checks that java.management is loaded.
+ */
+ static void startJMXAgent(VirtualMachine vm) throws Exception {
+ System.out.println("Start JMX agent");
+ vm.startLocalManagementAgent();
+
+ // types in java.management should be visible
+ Class.forName("javax.management.MXBean");
+ }
+
+ /**
+ * Loads a java agent into the VM and checks that java.instrument is loaded.
+ */
+ static void startJavaAgent(VirtualMachine vm, Path agent) throws Exception {
+ System.out.println("Load java agent ...");
+ vm.loadAgent(agent.toString());
+
+ // the Agent class should be visible
+ Class.forName("Agent");
+
+ // types in java.instrument should be visible
+ Class.forName("java.lang.instrument.Instrumentation");
+ }
+
+ /**
+ * Creates a java agent, return the file path to the agent JAR file.
+ */
+ static Path createAgentJar() throws IOException {
+ Manifest man = new Manifest();
+ Attributes attrs = man.getMainAttributes();
+ attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
+ attrs.put(new Attributes.Name("Agent-Class"), "Agent");
+ Path agent = Paths.get("agent.jar");
+ Path dir = Paths.get(System.getProperty("test.classes"));
+ createJarFile(agent, man, dir, "Agent.class");
+ return agent;
+ }
+
+ /**
+ * Creates a JAR file.
+ *
+ * Equivalent to {@code jar cfm <jarfile> <manifest> -C <dir> file...}
+ *
+ * The input files are resolved against the given directory. Any input
+ * files that are directories are processed recursively.
+ */
+ static void createJarFile(Path jarfile, Manifest man, Path dir, String... files)
+ throws IOException
+ {
+ // create the target directory
+ Path parent = jarfile.getParent();
+ if (parent != null)
+ Files.createDirectories(parent);
+
+ List<Path> entries = new ArrayList<>();
+ for (String file : files) {
+ Files.find(dir.resolve(file), Integer.MAX_VALUE,
+ (p, attrs) -> attrs.isRegularFile())
+ .map(e -> dir.relativize(e))
+ .forEach(entries::add);
+ }
+
+ try (OutputStream out = Files.newOutputStream(jarfile);
+ JarOutputStream jos = new JarOutputStream(out))
+ {
+ if (man != null) {
+ JarEntry je = new JarEntry(JarFile.MANIFEST_NAME);
+ jos.putNextEntry(je);
+ man.write(jos);
+ jos.closeEntry();
+ }
+
+ for (Path entry : entries) {
+ String name = toJarEntryName(entry);
+ jos.putNextEntry(new JarEntry(name));
+ Files.copy(dir.resolve(entry), jos);
+ jos.closeEntry();
+ }
+ }
+ }
+
+ /**
+ * Map a file path to the equivalent name in a JAR file
+ */
+ static String toJarEntryName(Path file) {
+ Path normalized = file.normalize();
+ return normalized.subpath(0, normalized.getNameCount())
+ .toString()
+ .replace(File.separatorChar, '/');
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/instrument/executableJAR/Agent.java Thu May 04 17:54:50 2017 +0000
@@ -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 java.lang.instrument.Instrumentation;
+
+public class Agent {
+
+ public static Instrumentation inst;
+
+ public static void agentmain(String agentArgs, Instrumentation inst) {
+ Agent.inst = inst;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/instrument/executableJAR/AgentHelper.java Thu May 04 17:54:50 2017 +0000
@@ -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.
+ */
+
+public class AgentHelper {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/instrument/executableJAR/ExecJarWithAgent.java Thu May 04 17:54:50 2017 +0000
@@ -0,0 +1,138 @@
+/*
+ * 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
+ * @build ExecJarWithAgent Main Agent AgentHelper JarUtils jdk.testlibrary.*
+ * @run testng ExecJarWithAgent
+ * @summary Test starting agents in executable JAR files
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+import java.util.stream.Stream;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.OutputAnalyzer;
+
+@Test
+public class ExecJarWithAgent {
+
+ /**
+ * Basic test of java -jar with agent in the executable JAR
+ */
+ public void testBasic() throws Exception {
+ Manifest man = new Manifest();
+ Attributes attrs = man.getMainAttributes();
+ attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
+ attrs.put(Attributes.Name.MAIN_CLASS, "Main");
+ attrs.put(new Attributes.Name("Launcher-Agent-Class"), "Agent");
+
+ // require all capabilities
+ attrs.put(new Attributes.Name("Can-Redefine-Classes"), "true");
+ attrs.put(new Attributes.Name("Can-Retransform-Classes"), "true");
+ attrs.put(new Attributes.Name("Can-Set-Native-Method-Prefix"), "true");
+ attrs.put(new Attributes.Name("Boot-Class-Path"), "helper.jar");
+
+ Path app = Paths.get("app.jar");
+ Path dir = Paths.get(System.getProperty("test.classes"));
+
+ Path[] paths = Stream.of("Main.class", "Agent.class")
+ .map(Paths::get)
+ .toArray(Path[]::new);
+
+ JarUtils.createJarFile(app, man, dir, paths);
+
+ // helper API to test that the BCP has been extended
+ Path helper = Paths.get("helper.jar");
+ JarUtils.createJarFile(helper, dir, "AgentHelper.class");
+
+ // java -jar app.jar
+ assertEquals(exec(app).getExitValue(), 0);
+ }
+
+ /**
+ * Test that java -jar fails when the executable JAR has the
+ * Launcher-Agent-Class attribute but the class cannot be loaded.
+ */
+ public void testBadAgentClass() throws Exception {
+ Manifest man = new Manifest();
+ Attributes attrs = man.getMainAttributes();
+ attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
+ attrs.put(Attributes.Name.MAIN_CLASS, "Main");
+
+ // agent class does not exist
+ attrs.put(new Attributes.Name("Launcher-Agent-Class"), "BadAgent");
+
+ Path app = Paths.get("app.jar");
+ Path dir = Paths.get(System.getProperty("test.classes"));
+
+ JarUtils.createJarFile(app, man, dir, Paths.get("Main.class"));
+
+ // java -jar app.jar
+ int exitCode = exec(app).shouldContain("ClassNotFoundException").getExitValue();
+ assertNotEquals(exitCode, 0);
+ }
+
+ /**
+ * Test that java -jar fails when the executable JAR has the
+ * Launcher-Agent-Class attribute and the class does not define an
+ * agentmain method.
+ */
+ public void testNoAgentMain() throws Exception {
+ // manifest for the executable JAR
+ Manifest man = new Manifest();
+ Attributes attrs = man.getMainAttributes();
+ attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
+ attrs.put(Attributes.Name.MAIN_CLASS, "Main");
+
+ // the main class does not define the agentmain method
+ attrs.put(new Attributes.Name("Launcher-Agent-Class"), "Main");
+
+ Path app = Paths.get("app.jar");
+ Path dir = Paths.get(System.getProperty("test.classes"));
+
+ JarUtils.createJarFile(app, man, dir, Paths.get("Main.class"));
+
+ // java -jar app.jar
+ int exitCode = exec(app).shouldContain("NoSuchMethodException").getExitValue();
+ assertNotEquals(exitCode, 0);
+ }
+
+ /**
+ * java -jar app.jar, returning the OutputAnalyzer to analyze the output
+ */
+ private OutputAnalyzer exec(Path appJar) throws Exception {
+ return ProcessTools.executeTestJava("-jar", appJar.toString())
+ .outputTo(System.out)
+ .errorTo(System.out);
+ }
+
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/instrument/executableJAR/Main.java Thu May 04 17:54:50 2017 +0000
@@ -0,0 +1,41 @@
+/*
+ * 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 java.lang.instrument.Instrumentation;
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ Instrumentation inst = Agent.inst;
+ if (inst == null)
+ throw new RuntimeException("Agent not loaded");
+
+ // check boot class path has been extended
+ Class<?> helper = Class.forName("AgentHelper");
+ if (helper.getClassLoader() != null)
+ throw new RuntimeException("AgentHelper not loaded by boot loader");
+
+ // check Instrumentation object can be used
+ Class<?>[] classes = inst.getAllLoadedClasses();
+ System.out.println(classes.length + " classes loaded");
+ }
+}
--- a/jdk/test/java/lang/invoke/DefineClassTest.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/java/lang/invoke/DefineClassTest.java Thu May 04 17:54:50 2017 +0000
@@ -75,7 +75,7 @@
@Test
public void testDefineClass() throws Exception {
final String CLASS_NAME = THIS_PACKAGE + ".Foo";
- Lookup lookup = lookup().dropLookupMode(PRIVATE);
+ Lookup lookup = lookup();
Class<?> clazz = lookup.defineClass(generateClass(CLASS_NAME));
// test name
@@ -101,7 +101,7 @@
public void testAccess() throws Exception {
final String THIS_CLASS = this.getClass().getName();
final String CLASS_NAME = THIS_PACKAGE + ".Runner";
- Lookup lookup = lookup().dropLookupMode(PRIVATE);
+ Lookup lookup = lookup();
// public
byte[] classBytes = generateRunner(CLASS_NAME + nextNumber(), THIS_CLASS, "method1");
@@ -144,9 +144,8 @@
final String CLASS_NAME = THIS_PACKAGE + ".ClassWithClinit";
byte[] classBytes = generateClassWithInitializer(CLASS_NAME, THIS_CLASS, "fail");
- Lookup lookup = lookup().dropLookupMode(PRIVATE);
+ Class<?> clazz = lookup().defineClass(classBytes);
- Class<?> clazz = lookup.defineClass(classBytes);
// trigger initializer to run
try {
clazz.newInstance();
@@ -186,14 +185,14 @@
assertNotEquals(target1.getProtectionDomain(), target2.getProtectionDomain());
// protection domain 1
- Lookup lookup1 = privateLookupIn(target1, lookup()).dropLookupMode(PRIVATE);
+ Lookup lookup1 = privateLookupIn(target1, lookup());
Class<?> clazz = lookup1.defineClass(generateClass("p.Foo"));
testSameAbode(clazz, lookup1.lookupClass());
testDiscoverable(clazz, lookup1);
// protection domain 2
- Lookup lookup2 = privateLookupIn(target2, lookup()).dropLookupMode(PRIVATE);
+ Lookup lookup2 = privateLookupIn(target2, lookup());
clazz = lookup2.defineClass(generateClass("p.Bar"));
testSameAbode(clazz, lookup2.lookupClass());
@@ -205,7 +204,7 @@
*/
@Test
public void testBootLoader() throws Exception {
- Lookup lookup = privateLookupIn(Thread.class, lookup()).dropLookupMode(PRIVATE);
+ Lookup lookup = privateLookupIn(Thread.class, lookup());
assertTrue(lookup.getClass().getClassLoader() == null);
Class<?> clazz = lookup.defineClass(generateClass("java.lang.Foo"));
@@ -216,8 +215,7 @@
@Test(expectedExceptions = { IllegalArgumentException.class })
public void testWrongPackage() throws Exception {
- Lookup lookup = lookup().dropLookupMode(PRIVATE);
- lookup.defineClass(generateClass("other.C"));
+ lookup().defineClass(generateClass("other.C"));
}
@Test(expectedExceptions = { IllegalAccessException.class })
@@ -226,23 +224,14 @@
lookup.defineClass(generateClass(THIS_PACKAGE + ".C"));
}
- @Test(expectedExceptions = { UnsupportedOperationException.class })
- public void testHasPrivateAccess() throws Exception {
- Lookup lookup = lookup();
- assertTrue(lookup.hasPrivateAccess());
- lookup.defineClass(generateClass(THIS_PACKAGE + ".C"));
- }
-
@Test(expectedExceptions = { ClassFormatError.class })
public void testTruncatedClassFile() throws Exception {
- Lookup lookup = lookup().dropLookupMode(PRIVATE);
- lookup.defineClass(new byte[0]);
+ lookup().defineClass(new byte[0]);
}
@Test(expectedExceptions = { NullPointerException.class })
public void testNull() throws Exception {
- Lookup lookup = lookup().dropLookupMode(PRIVATE);
- lookup.defineClass(null);
+ lookup().defineClass(null);
}
/**
--- a/jdk/test/java/lang/module/AutomaticModulesTest.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/java/lang/module/AutomaticModulesTest.java Thu May 04 17:54:50 2017 +0000
@@ -402,9 +402,7 @@
// Main-Class files that do not map to a legal qualified type name
@DataProvider(name = "badmainclass")
public Object[][] createBadMainClass() {
- return new Object[][]{
-
- { "Main", null },
+ return new Object[][] {
{ "p..Main", null },
{ "p-.Main", null },
@@ -415,7 +413,7 @@
* Test that a JAR file with a Main-Class attribute that is not a qualified
* type name.
*/
- @Test(dataProvider = "badmainclass", expectedExceptions = FindException.class)
+ @Test(dataProvider = "badmainclass")
public void testBadMainClass(String mainClass, String ignore) throws IOException {
Manifest man = new Manifest();
Attributes attrs = man.getMainAttributes();
@@ -426,14 +424,16 @@
String entry = mainClass.replace('.', '/') + ".class";
createDummyJarFile(dir.resolve("m.jar"), man, entry);
- // should throw FindException
- ModuleFinder.of(dir).findAll();
+ // bad Main-Class value should be ignored
+ Optional<ModuleReference> omref = ModuleFinder.of(dir).find("m");
+ assertTrue(omref.isPresent());
+ ModuleDescriptor descriptor = omref.get().descriptor();
+ assertFalse(descriptor.mainClass().isPresent());
}
/**
* Test that a JAR file with a Main-Class attribute that is not in the module
*/
- @Test(expectedExceptions = FindException.class)
public void testMissingMainClassPackage() throws IOException {
Manifest man = new Manifest();
Attributes attrs = man.getMainAttributes();
@@ -443,8 +443,11 @@
Path dir = Files.createTempDirectory(USER_DIR, "mods");
createDummyJarFile(dir.resolve("m.jar"), man);
- // should throw FindException
- ModuleFinder.of(dir).findAll();
+ // Main-Class should be ignored because package p is not in module
+ Optional<ModuleReference> omref = ModuleFinder.of(dir).find("m");
+ assertTrue(omref.isPresent());
+ ModuleDescriptor descriptor = omref.get().descriptor();
+ assertFalse(descriptor.mainClass().isPresent());
}
--- a/jdk/test/java/lang/module/ConfigurationTest.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/java/lang/module/ConfigurationTest.java Thu May 04 17:54:50 2017 +0000
@@ -1843,17 +1843,9 @@
public Object[][] createPlatformMatches() {
return new Object[][]{
- { "linux-arm", "*-*" },
- { "linux-*", "*-*" },
- { "*-arm", "*-*" },
-
- { "linux-*", "linux-*" },
- { "linux-arm", "linux-*" },
-
- { "*-arm", "*-arm" },
- { "linux-arm", "*-arm" },
-
- { "linux-arm", "linux-arm" },
+ { "", "" },
+ { "linux-arm", "" },
+ { "linux-arm", "linux-arm" },
};
@@ -1863,9 +1855,8 @@
public Object[][] createBad() {
return new Object[][] {
- { "linux-*", "solaris-*" },
- { "*-arm", "*-sparc" },
- { "linux-x86", "solaris-sparc" },
+ { "linux-x64", "linux-arm" },
+ { "linux-x64", "windows-x64" },
};
}
@@ -1877,7 +1868,7 @@
public void testPlatformMatch(String s1, String s2) throws IOException {
ModuleDescriptor base = ModuleDescriptor.newModule("java.base").build();
- Path system = writeModule(base, "*-*");
+ Path system = writeModule(base, null);
ModuleDescriptor descriptor1 = ModuleDescriptor.newModule("m1")
.requires("m2")
@@ -1928,7 +1919,7 @@
throws IOException
{
ModuleDescriptor base = ModuleDescriptor.newModule("java.base").build();
- Path system = writeModule(base, "*-*");
+ Path system = writeModule(base, null);
ModuleDescriptor descriptor1 = ModuleDescriptor.newModule("m1").build();
Path dir1 = writeModule(descriptor1, s1);
@@ -2113,17 +2104,18 @@
/**
- * Decodes the platform string and calls the builder osName/osArch/osVersion
- * methods to set the platform constraints.
+ * Writes a module-info.class. If {@code targetPlatform} is not null then
+ * it includes the ModuleTarget class file attribute with the target platform.
*/
- static Path writeModule(ModuleDescriptor descriptor, String platformString)
+ static Path writeModule(ModuleDescriptor descriptor, String targetPlatform)
throws IOException
{
- String[] s = platformString.split("-");
- String osName = !s[0].equals("*") ? s[0] : null;
- String osArch = !s[1].equals("*") ? s[1] : null;
- ModuleTarget target = new ModuleTarget(osName, osArch);
-
+ ModuleTarget target;
+ if (targetPlatform != null) {
+ target = new ModuleTarget(targetPlatform);
+ } else {
+ target = null;
+ }
String name = descriptor.name();
Path dir = Files.createTempDirectory(name);
Path mi = dir.resolve("module-info.class");
--- a/jdk/test/java/lang/module/ModuleDescriptorTest.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/java/lang/module/ModuleDescriptorTest.java Thu May 04 17:54:50 2017 +0000
@@ -65,8 +65,8 @@
@Test
public class ModuleDescriptorTest {
- @DataProvider(name = "invalidjavaidentifiers")
- public Object[][] invalidJavaIdentifiers() {
+ @DataProvider(name = "invalidNames")
+ public Object[][] invalidNames() {
return new Object[][]{
{ null, null },
@@ -84,6 +84,32 @@
{ "foo.bar.1gus", null },
{ "foo.bar.[gus]", null },
+ { "class", null },
+ { "interface", null },
+ { "true", null },
+ { "false", null },
+ { "null", null },
+
+ { "x.class", null },
+ { "x.interface", null },
+ { "x.true", null },
+ { "x.false", null },
+ { "x.null", null },
+
+ { "class.x", null },
+ { "interface.x", null },
+ { "true.x", null },
+ { "false.x", null },
+ { "null.x", null },
+
+ { "x.class.x", null },
+ { "x.interface.x", null },
+ { "x.true.x", null },
+ { "x.false.x", null },
+ { "x.null.x", null },
+
+ { "_", null },
+
};
}
@@ -199,7 +225,7 @@
ModuleDescriptor.newModule("m").requires(EnumSet.allOf(Modifier.class), "m");
}
- @Test(dataProvider = "invalidjavaidentifiers",
+ @Test(dataProvider = "invalidNames",
expectedExceptions = IllegalArgumentException.class )
public void testRequiresWithBadModuleName(String mn, String ignore) {
requires(EnumSet.noneOf(Modifier.class), mn);
@@ -406,7 +432,7 @@
ModuleDescriptor.newModule("foo").exports("p", Collections.emptySet());
}
- @Test(dataProvider = "invalidjavaidentifiers",
+ @Test(dataProvider = "invalidNames",
expectedExceptions = IllegalArgumentException.class )
public void testExportsWithBadName(String pn, String ignore) {
ModuleDescriptor.newModule("foo").exports(pn);
@@ -568,7 +594,7 @@
ModuleDescriptor.newModule("foo").opens("p", Collections.emptySet());
}
- @Test(dataProvider = "invalidjavaidentifiers",
+ @Test(dataProvider = "invalidNames",
expectedExceptions = IllegalArgumentException.class )
public void testOpensWithBadName(String pn, String ignore) {
ModuleDescriptor.newModule("foo").opens(pn);
@@ -664,7 +690,7 @@
ModuleDescriptor.newModule("foo").uses("S");
}
- @Test(dataProvider = "invalidjavaidentifiers",
+ @Test(dataProvider = "invalidNames",
expectedExceptions = IllegalArgumentException.class )
public void testUsesWithBadName(String service, String ignore) {
ModuleDescriptor.newModule("foo").uses(service);
@@ -737,13 +763,13 @@
ModuleDescriptor.newModule("foo").provides("p.S", List.of("P"));
}
- @Test(dataProvider = "invalidjavaidentifiers",
+ @Test(dataProvider = "invalidNames",
expectedExceptions = IllegalArgumentException.class )
public void testProvidesWithBadService(String service, String ignore) {
ModuleDescriptor.newModule("foo").provides(service, List.of("p.Provider"));
}
- @Test(dataProvider = "invalidjavaidentifiers",
+ @Test(dataProvider = "invalidNames",
expectedExceptions = IllegalArgumentException.class )
public void testProvidesWithBadProvider(String provider, String ignore) {
List<String> names = new ArrayList<>(); // allows nulls
@@ -928,7 +954,7 @@
assertTrue(Objects.equals(packages, Set.of("p1", "p2", "p3", "p4", "p5")));
}
- @Test(dataProvider = "invalidjavaidentifiers",
+ @Test(dataProvider = "invalidNames",
expectedExceptions = IllegalArgumentException.class )
public void testPackagesWithBadName(String pn, String ignore) {
Set<String> pkgs = new HashSet<>(); // allows nulls
@@ -943,7 +969,7 @@
assertEquals(mn, "foo");
}
- @Test(dataProvider = "invalidjavaidentifiers",
+ @Test(dataProvider = "invalidNames",
expectedExceptions = IllegalArgumentException.class )
public void testBadModuleName(String mn, String ignore) {
ModuleDescriptor.newModule(mn);
@@ -1264,7 +1290,7 @@
ModuleDescriptor.newModule("foo").mainClass("Main");
}
- @Test(dataProvider = "invalidjavaidentifiers",
+ @Test(dataProvider = "invalidNames",
expectedExceptions = IllegalArgumentException.class )
public void testMainClassWithBadName(String mainClass, String ignore) {
Builder builder = ModuleDescriptor.newModule("foo");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/module/customfs/ModulesInCustomFileSystem.java Thu May 04 17:54:50 2017 +0000
@@ -0,0 +1,142 @@
+/*
+ * 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 jdk.zipfs
+ * @library /lib/testlibrary
+ * @build ModulesInCustomFileSystem JarUtils m1/* m2/*
+ * @run testng/othervm ModulesInCustomFileSystem
+ * @summary Test ModuleFinder to find modules in a custom file system
+ */
+
+import java.io.File;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReader;
+import java.lang.module.ModuleReference;
+import java.lang.reflect.Method;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Set;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class ModulesInCustomFileSystem {
+
+ /**
+ * Test exploded modules in a JAR file system.
+ */
+ public void testExplodedModulesInJarFileSystem() throws Exception {
+ Path m1 = findModuleDirectory("m1");
+ Path m2 = findModuleDirectory("m2");
+ Path mlib = m1.getParent();
+ assertEquals(mlib, m2.getParent());
+
+ // create JAR file containing m1/** and m2/**
+ Path jar = Files.createTempDirectory("mlib").resolve("modules.jar");
+ JarUtils.createJarFile(jar, mlib);
+ testJarFileSystem(jar);
+ }
+
+ /**
+ * Test modular JARs in a JAR file system
+ */
+ public void testModularJARsInJarFileSystem() throws Exception {
+ Path m1 = findModuleDirectory("m1");
+ Path m2 = findModuleDirectory("m2");
+ Path contents = Files.createTempDirectory("contents");
+ JarUtils.createJarFile(contents.resolve("m1.jar"), m1);
+ JarUtils.createJarFile(contents.resolve("m2.jar"), m2);
+
+ // create JAR file containing m1.jar and m2.jar
+ Path jar = Files.createTempDirectory("mlib").resolve("modules.jar");
+ JarUtils.createJarFile(jar, contents);
+ testJarFileSystem(jar);
+ }
+
+ /**
+ * Opens a JAR file as a file system
+ */
+ private void testJarFileSystem(Path jar) throws Exception {
+ ClassLoader scl = ClassLoader.getSystemClassLoader();
+ try (FileSystem fs = FileSystems.newFileSystem(jar, scl)) {
+ // ModuleFinder to find modules in top-level directory
+ Path top = fs.getPath("/");
+ ModuleFinder finder = ModuleFinder.of(top);
+
+ // list the modules
+ listAllModules(finder);
+
+ // load modules into child layer, invoking m1/p.Main
+ loadAndRunModule(finder);
+ }
+ }
+
+ /**
+ * List all modules that the finder finds and the resources in the module.
+ */
+ private void listAllModules(ModuleFinder finder) throws Exception {
+ for (ModuleReference mref : finder.findAll()) {
+ System.out.println(mref.descriptor());
+ try (ModuleReader reader = mref.open()) {
+ reader.list().forEach(name -> System.out.format(" %s%n", name));
+ }
+ }
+ }
+
+ /**
+ * Creates a child layer with m1 and m2, invokes m1/p.Main to ensure that
+ * classes can be loaded.
+ */
+ private void loadAndRunModule(ModuleFinder finder) throws Exception {
+ ModuleLayer bootLayer = ModuleLayer.boot();
+ Configuration cf = bootLayer.configuration()
+ .resolve(finder, ModuleFinder.of(), Set.of("m1"));
+ ClassLoader scl = ClassLoader.getSystemClassLoader();
+ ModuleLayer layer = bootLayer.defineModulesWithOneLoader(cf, scl);
+ Class<?> c = layer.findLoader("m1").loadClass("p.Main");
+ Method m = c.getMethod("main", String[].class);
+ m.invoke(null, (Object)new String[0]);
+ }
+
+ /**
+ * Find the directory for a module on the module path
+ */
+ private Path findModuleDirectory(String name) {
+ String mp = System.getProperty("jdk.module.path");
+ for (String element : mp.split(File.pathSeparator)) {
+ Path dir = Paths.get(element).resolve(name);
+ if (Files.exists(dir)) {
+ return dir;
+ }
+ }
+ assertFalse(true);
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/module/customfs/m1/module-info.java Thu May 04 17:54:50 2017 +0000
@@ -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 m1 {
+ exports p;
+ requires m2;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/module/customfs/m1/p/Main.java Thu May 04 17:54:50 2017 +0000
@@ -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.
+ */
+
+package p;
+
+public class Main {
+ public static void main(String[] args) {
+ q.Hello.hello();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/module/customfs/m2/module-info.java Thu May 04 17:54:50 2017 +0000
@@ -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 m2 {
+ exports q;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/module/customfs/m2/q/Hello.java Thu May 04 17:54:50 2017 +0000
@@ -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.
+ */
+
+package q;
+
+public class Hello {
+ public static void hello() {
+ System.out.println("hello");
+ }
+}
--- a/jdk/test/java/nio/file/spi/SetDefaultProvider.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/java/nio/file/spi/SetDefaultProvider.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -21,23 +21,141 @@
* questions.
*/
-/* @test
- * @bug 4313887 7006126
- * @summary Unit test for java.nio.file.spi.FileSystemProvider
- * @build TestProvider SetDefaultProvider
- * @run main/othervm -Djava.nio.file.spi.DefaultFileSystemProvider=TestProvider SetDefaultProvider
+/**
+ * @test
+ * @modules jdk.jartool
+ * @library /lib/testlibrary
+ * @build SetDefaultProvider TestProvider m/* jdk.testlibrary.ProcessTools
+ * @run testng/othervm SetDefaultProvider
+ * @summary Runs tests with -Djava.nio.file.spi.DefaultFileSystemProvider set on
+ * the command line to override the default file system provider
*/
-import java.nio.file.*;
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.spi.ToolProvider;
+import jdk.testlibrary.ProcessTools;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
public class SetDefaultProvider {
- public static void main(String[] args) throws Exception {
- Class<?> c = FileSystems.getDefault().provider().getClass();
+
+ private static String SET_DEFAULT_FSP =
+ "-Djava.nio.file.spi.DefaultFileSystemProvider=TestProvider";
+
+ private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar")
+ .orElseThrow(() ->
+ new RuntimeException("jar tool not found")
+ );
+
+ /**
+ * Test override of default FileSystemProvider with the main application
+ * on the class path.
+ */
+ public void testClassPath() throws Exception {
+ String moduleClasses = moduleClasses();
+ String testClasses = System.getProperty("test.classes");
+ String classpath = moduleClasses + File.pathSeparator + testClasses;
+ int exitValue = exec(SET_DEFAULT_FSP, "-cp", classpath, "p.Main");
+ assertTrue(exitValue == 0);
+ }
+
+ /**
+ * Test override of default FileSystemProvider with the main application
+ * on the module path as an exploded module.
+ */
+ public void testExplodedModule() throws Exception {
+ String modulePath = System.getProperty("jdk.module.path");
+ int exitValue = exec(SET_DEFAULT_FSP, "-p", modulePath, "-m", "m/p.Main");
+ assertTrue(exitValue == 0);
+ }
+
+ /**
+ * Test override of default FileSystemProvider with the main application
+ * on the module path as a modular JAR.
+ */
+ public void testModularJar() throws Exception {
+ String jarFile = createModularJar();
+ int exitValue = exec(SET_DEFAULT_FSP, "-p", jarFile, "-m", "m/p.Main");
+ assertTrue(exitValue == 0);
+ }
- Class<?> expected = Class.forName("TestProvider", false,
- ClassLoader.getSystemClassLoader());
+ /**
+ * Test override of default FileSystemProvider where the main application
+ * is a module that is patched by an exploded patch.
+ */
+ public void testExplodedModuleWithExplodedPatch() throws Exception {
+ Path patchdir = Files.createTempDirectory("patch");
+ String modulePath = System.getProperty("jdk.module.path");
+ int exitValue = exec(SET_DEFAULT_FSP,
+ "--patch-module", "m=" + patchdir,
+ "-p", modulePath,
+ "-m", "m/p.Main");
+ assertTrue(exitValue == 0);
+ }
+
+ /**
+ * Test override of default FileSystemProvider where the main application
+ * is a module that is patched by an exploded patch.
+ */
+ public void testExplodedModuleWithJarPatch() throws Exception {
+ Path patchdir = Files.createTempDirectory("patch");
+ Files.createDirectory(patchdir.resolve("m.properties"));
+ Path patch = createJarFile(patchdir);
+ String modulePath = System.getProperty("jdk.module.path");
+ int exitValue = exec(SET_DEFAULT_FSP,
+ "--patch-module", "m=" + patch,
+ "-p", modulePath,
+ "-m", "m/p.Main");
+ assertTrue(exitValue == 0);
+ }
- if (c != expected)
- throw new RuntimeException();
+ /**
+ * Returns the directory containing the classes for module "m".
+ */
+ private String moduleClasses() {
+ String mp = System.getProperty("jdk.module.path");
+ for (String dir : mp.split(File.pathSeparator)) {
+ Path m = Paths.get(dir, "m");
+ if (Files.exists(m)) return m.toString();
+ }
+ assertFalse(true);
+ return null;
+ }
+
+ /**
+ * Creates a modular JAR containing module "m".
+ */
+ private String createModularJar() throws Exception {
+ Path dir = Paths.get(moduleClasses());
+ Path jar = createJarFile(dir);
+ return jar.toString();
+ }
+
+ /**
+ * Creates a JAR file containing the entries in the given file tree.
+ */
+ private Path createJarFile(Path dir) throws Exception {
+ Path jar = Files.createTempDirectory("tmp").resolve("m.jar");
+ String[] args = { "--create", "--file=" + jar, "-C", dir.toString(), "." };
+ int ret = JAR_TOOL.run(System.out, System.out, args);
+ assertTrue(ret == 0);
+ return jar;
+ }
+
+ /**
+ * Invokes the java launcher with the given arguments, returning the exit code.
+ */
+ private int exec(String... args) throws Exception {
+ return ProcessTools.executeTestJava(args)
+ .outputTo(System.out)
+ .errorTo(System.out)
+ .getExitValue();
}
}
--- a/jdk/test/java/nio/file/spi/TestProvider.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/java/nio/file/spi/TestProvider.java Thu May 04 17:54:50 2017 +0000
@@ -77,7 +77,7 @@
LinkOption... options)
throws IOException
{
- throw new ReadOnlyFileSystemException();
+ throw new RuntimeException("not implemented");
}
@Override
@@ -110,19 +110,20 @@
@Override
public void delete(Path file) throws IOException {
- throw new ReadOnlyFileSystemException();
+ Path delegate = theFileSystem.unwrap(file);
+ defaultProvider.delete(delegate);
}
@Override
public void createSymbolicLink(Path link, Path target, FileAttribute<?>... attrs)
throws IOException
{
- throw new ReadOnlyFileSystemException();
+ throw new RuntimeException("not implemented");
}
@Override
public void createLink(Path link, Path existing) throws IOException {
- throw new ReadOnlyFileSystemException();
+ throw new RuntimeException("not implemented");
}
@Override
@@ -136,14 +137,14 @@
public void copy(Path source, Path target, CopyOption... options)
throws IOException
{
- throw new ReadOnlyFileSystemException();
+ throw new RuntimeException("not implemented");
}
@Override
public void move(Path source, Path target, CopyOption... options)
throws IOException
{
- throw new ReadOnlyFileSystemException();
+ throw new RuntimeException("not implemented");
}
@Override
@@ -158,7 +159,8 @@
public void createDirectory(Path dir, FileAttribute<?>... attrs)
throws IOException
{
- throw new ReadOnlyFileSystemException();
+ Path delegate = theFileSystem.unwrap(dir);
+ defaultProvider.createDirectory(delegate, attrs);
}
@Override
@@ -167,13 +169,8 @@
FileAttribute<?>... attrs)
throws IOException
{
- if (options.contains(StandardOpenOption.READ) && options.size() == 1) {
- Path delegate = theFileSystem.unwrap(file);
- options = Collections.singleton(StandardOpenOption.READ);
- return defaultProvider.newByteChannel(delegate, options, attrs);
- }
-
- throw new RuntimeException("not implemented");
+ Path delegate = theFileSystem.unwrap(file);
+ return defaultProvider.newByteChannel(delegate, options, attrs);
}
@Override
@@ -236,7 +233,7 @@
@Override
public boolean isReadOnly() {
- return true;
+ return false;
}
@Override
@@ -419,7 +416,7 @@
@Override
public File toFile() {
- return delegate.toFile();
+ return new File(toString());
}
@Override
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/spi/m/module-info.java Thu May 04 17:54:50 2017 +0000
@@ -0,0 +1,24 @@
+/*
+ * 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 m {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/spi/m/p/Main.java Thu May 04 17:54:50 2017 +0000
@@ -0,0 +1,62 @@
+/*
+ * 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.io.File;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+/**
+ * Launched by SetDefaultProvider to test startup with the default file system
+ * provider overridden.
+ */
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ FileSystem fs = FileSystems.getDefault();
+ if (fs.getClass().getModule() == Object.class.getModule())
+ throw new RuntimeException("FileSystemProvider not overridden");
+
+ // exercise the file system
+ Path dir = Files.createTempDirectory("tmp");
+ if (dir.getFileSystem() != fs)
+ throw new RuntimeException("'dir' not in default file system");
+ System.out.println("created: " + dir);
+
+ Path foo = Files.createFile(dir.resolve("foo"));
+ if (foo.getFileSystem() != fs)
+ throw new RuntimeException("'foo' not in default file system");
+ System.out.println("created: " + foo);
+
+ // exercise interop with java.io.File
+ File file = foo.toFile();
+ Path path = file.toPath();
+ if (path.getFileSystem() != fs)
+ throw new RuntimeException("'path' not in default file system");
+ if (!path.equals(foo))
+ throw new RuntimeException(path + " not equal to " + foo);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/sql/driverModuleTests/DriverManagerModuleTests.java Thu May 04 17:54:50 2017 +0000
@@ -0,0 +1,146 @@
+/*
+ * 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 java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import static org.testng.Assert.*;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @library /java/sql/modules
+ * @build luckydogdriver/* mystubdriver/*
+ * @run testng/othervm DriverManagerModuleTests
+ * @summary Tests that a JDBC Driver that is a module can be loaded
+ * via the service-provider loading mechanism.
+ */
+public class DriverManagerModuleTests {
+
+ private final String LUCKYDOGDRIVER_URL = "jdbc:tennis:myDB";
+ private static final String STUBDRIVERURL = "jdbc:stub:myDB";
+ private static final String CONNECTION_CLASS_NAME = "com.luckydogtennis.StubConnection";
+
+ @BeforeClass
+ public static void setUpClass() throws Exception {
+ }
+
+ @AfterClass
+ public static void tearDownClass() throws Exception {
+ }
+
+ @BeforeMethod
+ public void setUpMethod() throws Exception {
+ }
+
+ @AfterMethod
+ public void tearDownMethod() throws Exception {
+ }
+
+ /**
+ * Validate JDBC drivers as modules will be accessible. One driver will be
+ * loaded and registered via the service-provider loading mechanism. The
+ * other driver will need to be explictly loaded
+ *
+ * @throws java.lang.Exception
+ */
+ @Test
+ public void test() throws Exception {
+ System.out.println("\n$$$ runing Test()\n");
+ dumpRegisteredDrivers();
+ Driver d = DriverManager.getDriver(STUBDRIVERURL);
+ assertNotNull(d, "StubDriver should not be null");
+ assertTrue(isDriverRegistered(d));
+ Driver d2 = null;
+
+ // This driver should not be found until it is explictly loaded
+ try {
+ d2 = DriverManager.getDriver(LUCKYDOGDRIVER_URL);
+ } catch (SQLException e) {
+ // ignore expected Exception
+ }
+ assertNull(d2, "LuckyDogDriver should be null");
+ loadDriver();
+ d2 = DriverManager.getDriver(LUCKYDOGDRIVER_URL);
+ assertNotNull(d2, "LuckyDogDriver should not be null");
+ assertTrue(isDriverRegistered(d2), "Driver was NOT registered");
+
+ dumpRegisteredDrivers();
+ DriverManager.deregisterDriver(d2);
+ assertFalse(isDriverRegistered(d2), "Driver IS STILL registered");
+ dumpRegisteredDrivers();
+
+ }
+
+ /**
+ * Validate that a Connection can be obtained from a JDBC driver which is a
+ * module and loaded via the service-provider loading mechanism.
+ *
+ * @throws java.lang.Exception
+ */
+ @Test
+ public void test00() throws Exception {
+ System.out.println("\n$$$ runing Test00()\n");
+ Connection con = DriverManager.getConnection(STUBDRIVERURL);
+ assertNotNull(con, "Returned Connection should not be NULL");
+ System.out.println("con=" + con.getClass().getName());
+ assertTrue(con.getClass().getName().equals(CONNECTION_CLASS_NAME));
+
+ }
+
+ /**
+ * Utility method to see if a driver is registered
+ */
+ private static void dumpRegisteredDrivers() {
+ System.out.println("\n+++ Loaded Drivers +++");
+
+ DriverManager.drivers().forEach(d -> System.out.println("\t\t### Driver:" + d));
+
+ System.out.println("++++++++++++++++++++++++");
+ }
+
+ /**
+ * Utility method to load the LuckyDogDriver
+ */
+ private static void loadDriver() {
+ try {
+ Class.forName("luckydogtennis.LuckyDogDriver");
+ } catch (ClassNotFoundException ex) {
+ System.out.println("**** Error: luckydogtennis.LuckyDogDriver not found");
+ }
+ System.out.println("Driver Loaded");
+ }
+
+ /**
+ * Utility method to see if a driver is registered
+ */
+ private static boolean isDriverRegistered(Driver d) {
+ return DriverManager.drivers().filter(driver-> driver == d).findFirst().isPresent();
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/sql/modules/luckydogdriver/luckydogtennis/LuckyDogDriver.java Thu May 04 17:54:50 2017 +0000
@@ -0,0 +1,91 @@
+/*
+ * 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 luckydogtennis;
+
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class LuckyDogDriver implements Driver {
+
+ static {
+ registerDriver();
+ System.out.println("*****in static block LuckyDogDriver");
+ }
+
+ private static void registerDriver() {
+ try {
+ DriverManager.registerDriver(new LuckyDogDriver());
+ } catch (SQLException ex) {
+ Logger.getLogger(LuckyDogDriver.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ public LuckyDogDriver() {
+ System.out.println("*****in LuckyDogDriver Constructor");
+ }
+
+ @Override
+ public Connection connect(String url, Properties info) throws SQLException {
+ if (acceptsURL(url)) {
+ return new StubConnection();
+ }
+ return null;
+ }
+
+ @Override
+ public boolean acceptsURL(String url) throws SQLException {
+ return url.matches("^jdbc:tennis:.*");
+ }
+
+ @Override
+ public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public int getMajorVersion() {
+ return 1;
+ }
+
+ @Override
+ public int getMinorVersion() {
+ return 0;
+ }
+
+ @Override
+ public boolean jdbcCompliant() {
+ return true;
+ }
+
+ @Override
+ public Logger getParentLogger() throws SQLFeatureNotSupportedException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/sql/modules/luckydogdriver/luckydogtennis/StubConnection.java Thu May 04 17:54:50 2017 +0000
@@ -0,0 +1,315 @@
+/*
+ * 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 luckydogtennis;
+
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.CallableStatement;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.NClob;
+import java.sql.PreparedStatement;
+import java.sql.SQLClientInfoException;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Savepoint;
+import java.sql.Statement;
+import java.sql.Struct;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Executor;
+
+public class StubConnection implements Connection{
+
+ @Override
+ public Statement createStatement() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public CallableStatement prepareCall(String sql) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public String nativeSQL(String sql) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setAutoCommit(boolean autoCommit) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public boolean getAutoCommit() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void commit() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void rollback() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void close() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public boolean isClosed() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public DatabaseMetaData getMetaData() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setReadOnly(boolean readOnly) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public boolean isReadOnly() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setCatalog(String catalog) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public String getCatalog() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setTransactionIsolation(int level) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public int getTransactionIsolation() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public SQLWarning getWarnings() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void clearWarnings() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Map<String, Class<?>> getTypeMap() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setHoldability(int holdability) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public int getHoldability() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Savepoint setSavepoint() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Savepoint setSavepoint(String name) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void rollback(Savepoint savepoint) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void releaseSavepoint(Savepoint savepoint) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Clob createClob() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Blob createBlob() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public NClob createNClob() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public SQLXML createSQLXML() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public boolean isValid(int timeout) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setClientInfo(String name, String value) throws SQLClientInfoException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setClientInfo(Properties properties) throws SQLClientInfoException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public String getClientInfo(String name) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Properties getClientInfo() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setSchema(String schema) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public String getSchema() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void abort(Executor executor) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public int getNetworkTimeout() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/sql/modules/luckydogdriver/module-info.java Thu May 04 17:54:50 2017 +0000
@@ -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 luckydogdriver {
+ requires transitive java.logging;
+ requires transitive java.sql;
+ exports luckydogtennis;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/sql/modules/mystubdriver/com/luckydogtennis/StubConnection.java Thu May 04 17:54:50 2017 +0000
@@ -0,0 +1,315 @@
+/*
+ * 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 com.luckydogtennis;
+
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.CallableStatement;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.NClob;
+import java.sql.PreparedStatement;
+import java.sql.SQLClientInfoException;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Savepoint;
+import java.sql.Statement;
+import java.sql.Struct;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Executor;
+
+public class StubConnection implements Connection{
+
+ @Override
+ public Statement createStatement() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public CallableStatement prepareCall(String sql) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public String nativeSQL(String sql) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setAutoCommit(boolean autoCommit) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public boolean getAutoCommit() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void commit() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void rollback() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void close() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public boolean isClosed() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public DatabaseMetaData getMetaData() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setReadOnly(boolean readOnly) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public boolean isReadOnly() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setCatalog(String catalog) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public String getCatalog() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setTransactionIsolation(int level) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public int getTransactionIsolation() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public SQLWarning getWarnings() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void clearWarnings() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Map<String, Class<?>> getTypeMap() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setHoldability(int holdability) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public int getHoldability() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Savepoint setSavepoint() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Savepoint setSavepoint(String name) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void rollback(Savepoint savepoint) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void releaseSavepoint(Savepoint savepoint) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Clob createClob() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Blob createBlob() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public NClob createNClob() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public SQLXML createSQLXML() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public boolean isValid(int timeout) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setClientInfo(String name, String value) throws SQLClientInfoException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setClientInfo(Properties properties) throws SQLClientInfoException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public String getClientInfo(String name) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Properties getClientInfo() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setSchema(String schema) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public String getSchema() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void abort(Executor executor) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public int getNetworkTimeout() throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/sql/modules/mystubdriver/com/luckydogtennis/StubDriver.java Thu May 04 17:54:50 2017 +0000
@@ -0,0 +1,97 @@
+/*
+ * 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 com.luckydogtennis;
+
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class StubDriver implements Driver {
+
+ static {
+ System.out.println("*****in static block StubDriver");
+ registerDriver();
+ }
+
+ private static void registerDriver() {
+ try {
+ DriverManager.registerDriver(new StubDriver());
+ } catch (SQLException ex) {
+ Logger.getLogger(StubDriver.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ public StubDriver() {
+ System.out.println("*****in StubDriver Constructor*************");
+ /*
+ for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
+ System.out.println(ste);
+ }
+ System.out.println("******************");
+ */
+ }
+
+ @Override
+ public Connection connect(String url, Properties info) throws SQLException {
+ if (acceptsURL(url)) {
+ return new StubConnection();
+ }
+ return null;
+ }
+
+ @Override
+ public boolean acceptsURL(String url) throws SQLException {
+ return url.matches("^jdbc:stub:.*");
+ }
+
+ @Override
+ public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public int getMajorVersion() {
+ return 1;
+ }
+
+ @Override
+ public int getMinorVersion() {
+ return 0;
+ }
+
+ @Override
+ public boolean jdbcCompliant() {
+ return true;
+ }
+
+ @Override
+ public Logger getParentLogger() throws SQLFeatureNotSupportedException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/sql/modules/mystubdriver/module-info.java Thu May 04 17:54:50 2017 +0000
@@ -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.
+ */
+module mystubdriver {
+ requires transitive java.logging;
+ requires transitive java.sql;
+ exports com.luckydogtennis;
+ provides java.sql.Driver with
+ com.luckydogtennis.StubDriver;
+}
--- a/jdk/test/java/util/Arrays/ParallelPrefix.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/java/util/Arrays/ParallelPrefix.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -179,119 +179,65 @@
@Test
public void testNPEs() {
// null array
- assertThrows( () -> Arrays.parallelPrefix((int[]) null, Integer::max),
- NullPointerException.class, "should throw NPE");
- assertThrows( () -> Arrays.parallelPrefix((long []) null, Long::max),
- NullPointerException.class, "should throw NPE");
- assertThrows( () -> Arrays.parallelPrefix((double []) null, Double::max),
- NullPointerException.class, "should throw NPE");
- assertThrows( () -> Arrays.parallelPrefix((String []) null, String::concat),
- NullPointerException.class, "should throw NPE");
+ assertThrowsNPE(() -> Arrays.parallelPrefix((int[]) null, Integer::max));
+ assertThrowsNPE(() -> Arrays.parallelPrefix((long []) null, Long::max));
+ assertThrowsNPE(() -> Arrays.parallelPrefix((double []) null, Double::max));
+ assertThrowsNPE(() -> Arrays.parallelPrefix((String []) null, String::concat));
// null array w/ range
- assertThrows( () -> Arrays.parallelPrefix((int[]) null, 0, 0, Integer::max),
- NullPointerException.class, "should throw NPE");
- assertThrows( () -> Arrays.parallelPrefix((long []) null, 0, 0, Long::max),
- NullPointerException.class, "should throw NPE");
- assertThrows( () -> Arrays.parallelPrefix((double []) null, 0, 0, Double::max),
- NullPointerException.class, "should throw NPE");
- assertThrows( () -> Arrays.parallelPrefix((String []) null, 0, 0, String::concat),
- NullPointerException.class, "should throw NPE");
+ assertThrowsNPE(() -> Arrays.parallelPrefix((int[]) null, 0, 0, Integer::max));
+ assertThrowsNPE(() -> Arrays.parallelPrefix((long []) null, 0, 0, Long::max));
+ assertThrowsNPE(() -> Arrays.parallelPrefix((double []) null, 0, 0, Double::max));
+ assertThrowsNPE(() -> Arrays.parallelPrefix((String []) null, 0, 0, String::concat));
// null op
- assertThrows( () -> Arrays.parallelPrefix(new int[] {}, null),
- NullPointerException.class, "should throw NPE");
- assertThrows( () -> Arrays.parallelPrefix(new long[] {}, null),
- NullPointerException.class, "should throw NPE");
- assertThrows( () -> Arrays.parallelPrefix(new double[] {}, null),
- NullPointerException.class, "should throw NPE");
- assertThrows( () -> Arrays.parallelPrefix(new String[] {}, null),
- NullPointerException.class, "should throw NPE");
+ assertThrowsNPE(() -> Arrays.parallelPrefix(new int[] {}, null));
+ assertThrowsNPE(() -> Arrays.parallelPrefix(new long[] {}, null));
+ assertThrowsNPE(() -> Arrays.parallelPrefix(new double[] {}, null));
+ assertThrowsNPE(() -> Arrays.parallelPrefix(new String[] {}, null));
// null op w/ range
- assertThrows( () -> Arrays.parallelPrefix(new int[] {}, 0, 0, null),
- NullPointerException.class, "should throw NPE");
- assertThrows( () -> Arrays.parallelPrefix(new long[] {}, 0, 0, null),
- NullPointerException.class, "should throw NPE");
- assertThrows( () -> Arrays.parallelPrefix(new double[] {}, 0, 0, null),
- NullPointerException.class, "should throw NPE");
- assertThrows( () -> Arrays.parallelPrefix(new String[] {}, 0, 0, null),
- NullPointerException.class, "should throw NPE");
+ assertThrowsNPE(() -> Arrays.parallelPrefix(new int[] {}, 0, 0, null));
+ assertThrowsNPE(() -> Arrays.parallelPrefix(new long[] {}, 0, 0, null));
+ assertThrowsNPE(() -> Arrays.parallelPrefix(new double[] {}, 0, 0, null));
+ assertThrowsNPE(() -> Arrays.parallelPrefix(new String[] {}, 0, 0, null));
}
@Test
public void testIAEs() {
- assertThrows( () -> Arrays.parallelPrefix(new int[] {}, 1, 0, Integer::max),
- IllegalArgumentException.class, "should throw IAE");
- assertThrows( () -> Arrays.parallelPrefix(new long[] {}, 1, 0, Long::max),
- IllegalArgumentException.class, "should throw IAE");
- assertThrows( () -> Arrays.parallelPrefix(new double[] {}, 1, 0, Double::max),
- IllegalArgumentException.class, "should throw IAE");
- assertThrows( () -> Arrays.parallelPrefix(new String[] {}, 1, 0, String::concat),
- IllegalArgumentException.class, "should throw IAE");
+ assertThrowsIAE(() -> Arrays.parallelPrefix(new int[] {}, 1, 0, Integer::max));
+ assertThrowsIAE(() -> Arrays.parallelPrefix(new long[] {}, 1, 0, Long::max));
+ assertThrowsIAE(() -> Arrays.parallelPrefix(new double[] {}, 1, 0, Double::max));
+ assertThrowsIAE(() -> Arrays.parallelPrefix(new String[] {}, 1, 0, String::concat));
}
@Test
- public void testAIOBEs() {
+ public void testAIOOBEs() {
// bad "fromIndex"
- assertThrows( () -> Arrays.parallelPrefix(new int[] {}, -1, 0, Integer::max),
- ArrayIndexOutOfBoundsException.class, "should throw AIOBE");
- assertThrows( () -> Arrays.parallelPrefix(new long[] {}, -1, 0, Long::max),
- ArrayIndexOutOfBoundsException.class, "should throw AIOBE");
- assertThrows( () -> Arrays.parallelPrefix(new double[] {}, -1, 0, Double::max),
- ArrayIndexOutOfBoundsException.class, "should throw AIOBE");
- assertThrows( () -> Arrays.parallelPrefix(new String[] {}, -1, 0, String::concat),
- ArrayIndexOutOfBoundsException.class, "should throw AIOBE");
+ assertThrowsAIOOB(() -> Arrays.parallelPrefix(new int[] {}, -1, 0, Integer::max));
+ assertThrowsAIOOB(() -> Arrays.parallelPrefix(new long[] {}, -1, 0, Long::max));
+ assertThrowsAIOOB(() -> Arrays.parallelPrefix(new double[] {}, -1, 0, Double::max));
+ assertThrowsAIOOB(() -> Arrays.parallelPrefix(new String[] {}, -1, 0, String::concat));
// bad "toIndex"
- assertThrows( () -> Arrays.parallelPrefix(new int[] {}, 0, 1, Integer::max),
- ArrayIndexOutOfBoundsException.class, "should throw AIOBE");
- assertThrows( () -> Arrays.parallelPrefix(new long[] {}, 0, 1, Long::max),
- ArrayIndexOutOfBoundsException.class, "should throw AIOBE");
- assertThrows( () -> Arrays.parallelPrefix(new double[] {}, 0, 1, Double::max),
- ArrayIndexOutOfBoundsException.class, "should throw AIOBE");
- assertThrows( () -> Arrays.parallelPrefix(new String[] {}, 0, 1, String::concat),
- ArrayIndexOutOfBoundsException.class, "should throw AIOBE");
+ assertThrowsAIOOB(() -> Arrays.parallelPrefix(new int[] {}, 0, 1, Integer::max));
+ assertThrowsAIOOB(() -> Arrays.parallelPrefix(new long[] {}, 0, 1, Long::max));
+ assertThrowsAIOOB(() -> Arrays.parallelPrefix(new double[] {}, 0, 1, Double::max));
+ assertThrowsAIOOB(() -> Arrays.parallelPrefix(new String[] {}, 0, 1, String::concat));
}
// "library" code
- public interface Thrower<T extends Throwable> {
-
- public void run() throws T;
- }
-
-
- public static <T extends Throwable> void assertThrows(Thrower<T> thrower, Class<T> throwable) {
- assertThrows(thrower, throwable, null);
+ private void assertThrowsNPE(ThrowingRunnable r) {
+ assertThrows(NullPointerException.class, r);
}
- public static <T extends Throwable> void assertThrows(Thrower<T> thrower, Class<T> throwable, String message) {
- Throwable thrown;
- try {
- thrower.run();
- thrown = null;
- } catch (Throwable caught) {
- thrown = caught;
- }
-
- assertInstance(thrown, throwable,
- ((null != message) ? message : "") +
- " Failed to throw " + throwable.getCanonicalName());
+ private void assertThrowsIAE(ThrowingRunnable r) {
+ assertThrows(IllegalArgumentException.class, r);
}
- public static <T extends Throwable> void assertThrows(Class<T> throwable, String message, Thrower<T>... throwers) {
- for(Thrower<T> thrower : throwers) {
- assertThrows(thrower, throwable, message);
- }
- }
-
- public static void assertInstance(Object actual, Class<?> expected) {
- assertInstance(expected.isInstance(actual), null);
- }
-
- public static void assertInstance(Object actual, Class<?> expected, String message) {
- assertTrue(expected.isInstance(actual), message);
+ private void assertThrowsAIOOB(ThrowingRunnable r) {
+ assertThrows(ArrayIndexOutOfBoundsException.class, r);
}
static void assertArraysEqual(int[] actual, int[] expected) {
--- a/jdk/test/java/util/Arrays/StreamAndSpliterator.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/java/util/Arrays/StreamAndSpliterator.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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,7 +32,9 @@
import java.util.Arrays;
import java.util.Spliterators;
-import static org.testng.Assert.assertNotNull;
+import org.testng.Assert.ThrowingRunnable;
+
+import static org.testng.Assert.assertThrows;
public class StreamAndSpliterator {
@Test
@@ -124,25 +126,11 @@
assertThrowsAIOOB(() -> Spliterators.spliterator(new String[]{}, 0, 1, 0));
}
- void assertThrowsNPE(Runnable r) {
- NullPointerException caught = null;
- try {
- r.run();
- }
- catch (NullPointerException e) {
- caught = e;
- }
- assertNotNull(caught, "NullPointerException not thrown");
+ void assertThrowsNPE(ThrowingRunnable r) {
+ assertThrows(NullPointerException.class, r);
}
- void assertThrowsAIOOB(Runnable r) {
- ArrayIndexOutOfBoundsException caught = null;
- try {
- r.run();
- }
- catch (ArrayIndexOutOfBoundsException e) {
- caught = e;
- }
- assertNotNull(caught, "ArrayIndexOutOfBoundsException not thrown");
+ void assertThrowsAIOOB(ThrowingRunnable r) {
+ assertThrows(ArrayIndexOutOfBoundsException.class, r);
}
}
--- a/jdk/test/java/util/BitSet/stream/BitSetStreamTest.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/java/util/BitSet/stream/BitSetStreamTest.java Thu May 04 17:54:50 2017 +0000
@@ -42,6 +42,7 @@
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertThrows;
import static org.testng.Assert.assertTrue;
/**
@@ -167,8 +168,8 @@
@Test(dataProvider = "BitSet.stream.spliterator")
public void testIntNullPointerException(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) {
- executeAndCatch(NullPointerException.class, () -> s.get().forEachRemaining((IntConsumer) null));
- executeAndCatch(NullPointerException.class, () -> s.get().tryAdvance((IntConsumer) null));
+ assertThrows(NullPointerException.class, () -> s.get().forEachRemaining((IntConsumer) null));
+ assertThrows(NullPointerException.class, () -> s.get().tryAdvance((IntConsumer) null));
}
@Test(dataProvider = "BitSet.stream.spliterator")
--- a/jdk/test/java/util/Collections/EmptyNavigableMap.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/java/util/Collections/EmptyNavigableMap.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -36,10 +36,12 @@
import java.util.NavigableMap;
import java.util.SortedMap;
import java.util.TreeMap;
+
+import org.testng.Assert;
+import org.testng.Assert.ThrowingRunnable;
import org.testng.annotations.Test;
import org.testng.annotations.DataProvider;
-import static org.testng.Assert.fail;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.assertFalse;
@@ -65,26 +67,27 @@
((null != message) ? message : "") + " Not empty. ");
}
- public interface Thrower<T extends Throwable> {
-
- public void run() throws T;
- }
-
- public static <T extends Throwable> void assertThrows(Thrower<T> thrower, Class<T> throwable) {
- assertThrows(thrower, throwable, null);
+ private <T extends Throwable> void assertThrows(Class<T> throwableClass,
+ ThrowingRunnable runnable,
+ String message) {
+ try {
+ Assert.assertThrows(throwableClass, runnable);
+ } catch (AssertionError e) {
+ throw new AssertionError(String.format("%s%n%s",
+ ((null != message) ? message : ""), e.getMessage()), e);
+ }
}
- public static <T extends Throwable> void assertThrows(Thrower<T> thrower, Class<T> throwable, String message) {
- Throwable result;
- try {
- thrower.run();
- fail(((null != message) ? message : "") + "Failed to throw " + throwable.getCanonicalName() + ". ");
- return;
- } catch (Throwable caught) {
- result = caught;
- }
+ private void assertThrowsCCE(ThrowingRunnable r, String s) {
+ assertThrows(ClassCastException.class, r, s);
+ }
- assertInstance(result, throwable, ((null != message) ? message : "") + "Failed to throw " + throwable.getCanonicalName() + ". ");
+ private void assertThrowsNPE(ThrowingRunnable r, String s) {
+ assertThrows(NullPointerException.class, r, s);
+ }
+
+ private void assertThrowsIAE(ThrowingRunnable r, String s) {
+ assertThrows(IllegalArgumentException.class, r, s);
}
public static final boolean isDescending(SortedMap<?,?> set) {
@@ -121,10 +124,9 @@
*/
@Test(dataProvider = "NavigableMap<?,?>", dataProviderClass = EmptyNavigableMap.class)
public void testContainsRequiresComparable(String description, NavigableMap<?,?> navigableMap) {
- assertThrows(() -> {
+ assertThrowsCCE(() -> {
navigableMap.containsKey(new Object());
},
- ClassCastException.class,
description + ": Compareable should be required");
}
@@ -175,14 +177,12 @@
*/
@Test(dataProvider = "NavigableMap<?,?>", dataProviderClass = EmptyNavigableMap.class)
public void testHeadMap(String description, NavigableMap navigableMap) {
- assertThrows(
+ assertThrowsNPE(
() -> { NavigableMap ss = navigableMap.headMap(null, false); },
- NullPointerException.class,
description + ": Must throw NullPointerException for null element");
- assertThrows(
+ assertThrowsCCE(
() -> { NavigableMap ss = navigableMap.headMap(new Object(), true); },
- ClassCastException.class,
description + ": Must throw ClassCastException for non-Comparable element");
NavigableMap ss = navigableMap.headMap("1", false);
@@ -203,50 +203,44 @@
*/
@Test(dataProvider = "NavigableMap<?,?>", dataProviderClass = EmptyNavigableMap.class)
public void testSubMap(String description, NavigableMap navigableMap) {
- assertThrows(
+ assertThrowsNPE(
() -> {
SortedMap ss = navigableMap.subMap(null, BigInteger.TEN);
},
- NullPointerException.class,
description + ": Must throw NullPointerException for null element");
- assertThrows(
+ assertThrowsNPE(
() -> {
SortedMap ss = navigableMap.subMap(BigInteger.ZERO, null);
},
- NullPointerException.class,
description + ": Must throw NullPointerException for null element");
- assertThrows(
+ assertThrowsNPE(
() -> {
SortedMap ss = navigableMap.subMap(null, null);
},
- NullPointerException.class,
description + ": Must throw NullPointerException for null element");
Object obj1 = new Object();
Object obj2 = new Object();
- assertThrows(
+ assertThrowsCCE(
() -> {
SortedMap ss = navigableMap.subMap(obj1, BigInteger.TEN);
},
- ClassCastException.class, description
- + ": Must throw ClassCastException for parameter which is not Comparable.");
+ description + ": Must throw ClassCastException for parameter which is not Comparable.");
- assertThrows(
+ assertThrowsCCE(
() -> {
SortedMap ss = navigableMap.subMap(BigInteger.ZERO, obj2);
},
- ClassCastException.class, description
- + ": Must throw ClassCastException for parameter which is not Comparable.");
+ description + ": Must throw ClassCastException for parameter which is not Comparable.");
- assertThrows(
+ assertThrowsCCE(
() -> {
SortedMap ss = navigableMap.subMap(obj1, obj2);
},
- ClassCastException.class, description
- + ": Must throw ClassCastException for parameter which is not Comparable.");
+ description + ": Must throw ClassCastException for parameter which is not Comparable.");
// minimal range
navigableMap.subMap(BigInteger.ZERO, false, BigInteger.ZERO, false);
@@ -257,12 +251,11 @@
Object first = isDescending(navigableMap) ? BigInteger.TEN : BigInteger.ZERO;
Object last = (BigInteger.ZERO == first) ? BigInteger.TEN : BigInteger.ZERO;
- assertThrows(
+ assertThrowsIAE(
() -> {
navigableMap.subMap(last, true, first, false);
},
- IllegalArgumentException.class, description
- + ": Must throw IllegalArgumentException when fromElement is not less than toElement.");
+ description + ": Must throw IllegalArgumentException when fromElement is not less than toElement.");
navigableMap.subMap(first, true, last, false);
}
@@ -280,10 +273,9 @@
// slightly smaller
NavigableMap ns = subMap.subMap(first, false, last, false);
// slight expansion
- assertThrows(() -> {
+ assertThrowsIAE(() -> {
ns.subMap(first, true, last, true);
},
- IllegalArgumentException.class,
description + ": Expansion should not be allowed");
// much smaller
@@ -301,10 +293,9 @@
NavigableMap ns = subMap.headMap(BigInteger.ONE, false);
// slight expansion
- assertThrows(() -> {
+ assertThrowsIAE(() -> {
ns.headMap(BigInteger.ONE, true);
},
- IllegalArgumentException.class,
description + ": Expansion should not be allowed");
// much smaller
@@ -322,10 +313,9 @@
NavigableMap ns = subMap.tailMap(BigInteger.ONE, false);
// slight expansion
- assertThrows(() -> {
+ assertThrowsIAE(() -> {
ns.tailMap(BigInteger.ONE, true);
},
- IllegalArgumentException.class,
description + ": Expansion should not be allowed");
// much smaller
@@ -337,15 +327,15 @@
*/
@Test(dataProvider = "NavigableMap<?,?>", dataProviderClass = EmptyNavigableMap.class)
public void testTailMap(String description, NavigableMap navigableMap) {
- assertThrows(() -> {
+ assertThrowsNPE(() -> {
navigableMap.tailMap(null);
},
- NullPointerException.class,
description + ": Must throw NullPointerException for null element");
- assertThrows(() -> {
+ assertThrowsCCE(() -> {
navigableMap.tailMap(new Object());
- }, ClassCastException.class);
+ },
+ description);
NavigableMap ss = navigableMap.tailMap("1", true);
--- a/jdk/test/java/util/Collections/EmptyNavigableSet.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/java/util/Collections/EmptyNavigableSet.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -37,10 +37,12 @@
import java.util.NavigableSet;
import java.util.SortedSet;
import java.util.TreeSet;
+
+import org.testng.Assert;
+import org.testng.Assert.ThrowingRunnable;
import org.testng.annotations.Test;
import org.testng.annotations.DataProvider;
-import static org.testng.Assert.fail;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;
@@ -67,26 +69,31 @@
((null != message) ? message : "") + " Not empty. ");
}
- public interface Thrower<T extends Throwable> {
-
- public void run() throws T;
- }
-
- public static <T extends Throwable> void assertThrows(Thrower<T> thrower, Class<T> throwable) {
- assertThrows(thrower, throwable, null);
+ private <T extends Throwable> void assertThrows(Class<T> throwableClass,
+ ThrowingRunnable runnable,
+ String message) {
+ try {
+ Assert.assertThrows(throwableClass, runnable);
+ } catch (AssertionError e) {
+ throw new AssertionError(String.format("%s%n%s",
+ ((null != message) ? message : ""), e.getMessage()), e);
+ }
}
- public static <T extends Throwable> void assertThrows(Thrower<T> thrower, Class<T> throwable, String message) {
- Throwable result;
- try {
- thrower.run();
- fail(((null != message) ? message : "") + "Failed to throw " + throwable.getCanonicalName() + ". ");
- return;
- } catch (Throwable caught) {
- result = caught;
- }
+ private void assertThrowsCCE(ThrowingRunnable r, String s) {
+ assertThrows(ClassCastException.class, r, s);
+ }
- assertInstance(result, throwable, ((null != message) ? message : "") + "Failed to throw " + throwable.getCanonicalName() + ". ");
+ private void assertThrowsNPE(ThrowingRunnable r, String s) {
+ assertThrows(NullPointerException.class, r, s);
+ }
+
+ private void assertThrowsIAE(ThrowingRunnable r, String s) {
+ assertThrows(IllegalArgumentException.class, r, s);
+ }
+
+ private void assertThrowsNSEE(ThrowingRunnable r, String s) {
+ assertThrows(NoSuchElementException.class, r, s);
}
public static final boolean isDescending(SortedSet<?> set) {
@@ -123,10 +130,9 @@
*/
@Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
public void testContainsRequiresComparable(String description, NavigableSet<?> navigableSet) {
- assertThrows(() -> {
+ assertThrowsCCE(() -> {
navigableSet.contains(new Object());
},
- ClassCastException.class,
description + ": Compareable should be required");
}
@@ -176,9 +182,9 @@
*/
@Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
public void testFirst(String description, NavigableSet<?> navigableSet) {
- assertThrows(() -> {
+ assertThrowsNSEE(() -> {
navigableSet.first();
- }, NoSuchElementException.class, description);
+ }, description);
}
/**
@@ -186,14 +192,12 @@
*/
@Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
public void testHeadSet(String description, NavigableSet navigableSet) {
- assertThrows(
+ assertThrowsNPE(
() -> { NavigableSet ns = navigableSet.headSet(null, false); },
- NullPointerException.class,
description + ": Must throw NullPointerException for null element");
- assertThrows(
+ assertThrowsCCE(
() -> { NavigableSet ns = navigableSet.headSet(new Object(), true); },
- ClassCastException.class,
description + ": Must throw ClassCastException for non-Comparable element");
NavigableSet ns = navigableSet.headSet("1", false);
@@ -206,9 +210,9 @@
*/
@Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
public void testLast(String description, NavigableSet<?> navigableSet) {
- assertThrows(() -> {
+ assertThrowsNSEE(() -> {
navigableSet.last();
- }, NoSuchElementException.class, description);
+ }, description);
}
/**
@@ -224,50 +228,44 @@
*/
@Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
public void testSubSet(String description, NavigableSet navigableSet) {
- assertThrows(
+ assertThrowsNPE(
() -> {
SortedSet ss = navigableSet.subSet(null, BigInteger.TEN);
},
- NullPointerException.class,
description + ": Must throw NullPointerException for null element");
- assertThrows(
+ assertThrowsNPE(
() -> {
SortedSet ss = navigableSet.subSet(BigInteger.ZERO, null);
},
- NullPointerException.class,
description + ": Must throw NullPointerException for null element");
- assertThrows(
+ assertThrowsNPE(
() -> {
SortedSet ss = navigableSet.subSet(null, null);
},
- NullPointerException.class,
description + ": Must throw NullPointerException for null element");
Object obj1 = new Object();
Object obj2 = new Object();
- assertThrows(
+ assertThrowsCCE(
() -> {
SortedSet ss = navigableSet.subSet(obj1, BigInteger.TEN);
},
- ClassCastException.class, description
- + ": Must throw ClassCastException for parameter which is not Comparable.");
+ description + ": Must throw ClassCastException for parameter which is not Comparable.");
- assertThrows(
+ assertThrowsCCE(
() -> {
SortedSet ss = navigableSet.subSet(BigInteger.ZERO, obj2);
},
- ClassCastException.class, description
- + ": Must throw ClassCastException for parameter which is not Comparable.");
+ description + ": Must throw ClassCastException for parameter which is not Comparable.");
- assertThrows(
+ assertThrowsCCE(
() -> {
SortedSet ss = navigableSet.subSet(obj1, obj2);
},
- ClassCastException.class, description
- + ": Must throw ClassCastException for parameter which is not Comparable.");
+ description + ": Must throw ClassCastException for parameter which is not Comparable.");
// minimal range
navigableSet.subSet(BigInteger.ZERO, false, BigInteger.ZERO, false);
@@ -278,11 +276,11 @@
Object first = isDescending(navigableSet) ? BigInteger.TEN : BigInteger.ZERO;
Object last = (BigInteger.ZERO == first) ? BigInteger.TEN : BigInteger.ZERO;
- assertThrows(
+ assertThrowsIAE(
() -> {
navigableSet.subSet(last, true, first, false);
},
- IllegalArgumentException.class, description
+ description
+ ": Must throw IllegalArgumentException when fromElement is not less than toElement.");
navigableSet.subSet(first, true, last, false);
@@ -301,10 +299,9 @@
// slightly smaller
NavigableSet ns = subSet.subSet(first, false, last, false);
// slight expansion
- assertThrows(() -> {
+ assertThrowsIAE(() -> {
ns.subSet(first, true, last, true);
},
- IllegalArgumentException.class,
description + ": Expansion should not be allowed");
// much smaller
@@ -322,10 +319,9 @@
NavigableSet ns = subSet.headSet(BigInteger.ONE, false);
// slight expansion
- assertThrows(() -> {
+ assertThrowsIAE(() -> {
ns.headSet(BigInteger.ONE, true);
},
- IllegalArgumentException.class,
description + ": Expansion should not be allowed");
// much smaller
@@ -343,10 +339,9 @@
NavigableSet ns = subSet.tailSet(BigInteger.ONE, false);
// slight expansion
- assertThrows(() -> {
+ assertThrowsIAE(() -> {
ns.tailSet(BigInteger.ONE, true);
},
- IllegalArgumentException.class,
description + ": Expansion should not be allowed");
// much smaller
@@ -358,15 +353,14 @@
*/
@Test(dataProvider = "NavigableSet<?>", dataProviderClass = EmptyNavigableSet.class)
public void testTailSet(String description, NavigableSet navigableSet) {
- assertThrows(() -> {
+ assertThrowsNPE(() -> {
navigableSet.tailSet(null);
},
- NullPointerException.class,
description + ": Must throw NullPointerException for null element");
- assertThrows(() -> {
+ assertThrowsCCE(() -> {
navigableSet.tailSet(new Object());
- }, ClassCastException.class);
+ }, description);
NavigableSet ss = navigableSet.tailSet("1", true);
--- a/jdk/test/java/util/Iterator/PrimitiveIteratorDefaults.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/java/util/Iterator/PrimitiveIteratorDefaults.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -21,16 +21,16 @@
* questions.
*/
-import org.testng.annotations.Test;
-
import java.util.PrimitiveIterator;
import java.util.function.Consumer;
import java.util.function.DoubleConsumer;
import java.util.function.IntConsumer;
import java.util.function.LongConsumer;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
+import org.testng.Assert.ThrowingRunnable;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertThrows;
/**
* @test
@@ -53,8 +53,8 @@
}
};
- executeAndCatch(() -> i.forEachRemaining((IntConsumer) null));
- executeAndCatch(() -> i.forEachRemaining((Consumer<Integer>) null));
+ assertThrowsNPE(() -> i.forEachRemaining((IntConsumer) null));
+ assertThrowsNPE(() -> i.forEachRemaining((Consumer<Integer>) null));
}
public void testLongForEachRemainingWithNull() {
@@ -70,8 +70,8 @@
}
};
- executeAndCatch(() -> i.forEachRemaining((LongConsumer) null));
- executeAndCatch(() -> i.forEachRemaining((Consumer<Long>) null));
+ assertThrowsNPE(() -> i.forEachRemaining((LongConsumer) null));
+ assertThrowsNPE(() -> i.forEachRemaining((Consumer<Long>) null));
}
public void testDoubleForEachRemainingWithNull() {
@@ -87,29 +87,12 @@
}
};
- executeAndCatch(() -> i.forEachRemaining((DoubleConsumer) null));
- executeAndCatch(() -> i.forEachRemaining((Consumer<Double>) null));
- }
-
- private void executeAndCatch(Runnable r) {
- executeAndCatch(NullPointerException.class, r);
+ assertThrowsNPE(() -> i.forEachRemaining((DoubleConsumer) null));
+ assertThrowsNPE(() -> i.forEachRemaining((Consumer<Double>) null));
}
- private void executeAndCatch(Class<? extends Exception> expected, Runnable r) {
- Exception caught = null;
- try {
- r.run();
- }
- catch (Exception e) {
- caught = e;
- }
-
- assertNotNull(caught,
- String.format("No Exception was thrown, expected an Exception of %s to be thrown",
- expected.getName()));
- assertTrue(expected.isInstance(caught),
- String.format("Exception thrown %s not an instance of %s",
- caught.getClass().getName(), expected.getName()));
+ private void assertThrowsNPE(ThrowingRunnable r) {
+ assertThrows(NullPointerException.class, r);
}
}
--- a/jdk/test/java/util/Map/Defaults.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/java/util/Map/Defaults.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -53,15 +53,19 @@
import java.util.function.Function;
import java.util.function.Supplier;
+import org.testng.Assert.ThrowingRunnable;
import org.testng.annotations.Test;
import org.testng.annotations.DataProvider;
+
import static java.util.Objects.requireNonNull;
+
import static org.testng.Assert.fail;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertThrows;
public class Defaults {
@@ -159,14 +163,8 @@
@Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=nonNull values=nonNull")
public static void testReplaceAllNoNullReplacement(String description, Map<IntegerEnum, String> map) {
- assertThrows(
- () -> { map.replaceAll(null); },
- NullPointerException.class,
- description);
- assertThrows(
- () -> { map.replaceAll((k,v) -> null); },
- NullPointerException.class,
- description + " should not allow replacement with null value");
+ assertThrowsNPE(() -> map.replaceAll(null));
+ assertThrowsNPE(() -> map.replaceAll((k,v) -> null)); //should not allow replacement with null value
}
@Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
@@ -209,7 +207,7 @@
public void testReplaceKVNoNulls(String description, Map<IntegerEnum, String> map) {
assertTrue(map.containsKey(FIRST_KEY), "expected key missing");
assertSame(map.get(FIRST_KEY), FIRST_VALUE, "found wrong value");
- assertThrows( () -> {map.replace(FIRST_KEY, null);}, NullPointerException.class, description + ": should throw NPE");
+ assertThrowsNPE(() -> map.replace(FIRST_KEY, null));
assertSame(map.replace(FIRST_KEY, EXTRA_VALUE), FIRST_VALUE, description + ": replaced wrong value");
assertSame(map.get(FIRST_KEY), EXTRA_VALUE, "found wrong value");
}
@@ -248,8 +246,13 @@
public void testReplaceKVVNoNulls(String description, Map<IntegerEnum, String> map) {
assertTrue(map.containsKey(FIRST_KEY), "expected key missing");
assertSame(map.get(FIRST_KEY), FIRST_VALUE, "found wrong value");
- assertThrows( () -> {map.replace(FIRST_KEY, FIRST_VALUE, null);}, NullPointerException.class, description + ": should throw NPE");
- assertThrows( () -> {if (!map.replace(FIRST_KEY, null, EXTRA_VALUE)) throw new NullPointerException("default returns false rather than throwing");}, NullPointerException.class, description + ": should throw NPE");
+ assertThrowsNPE(() -> map.replace(FIRST_KEY, FIRST_VALUE, null));
+ assertThrowsNPE(
+ () -> {
+ if (!map.replace(FIRST_KEY, null, EXTRA_VALUE)) {
+ throw new NullPointerException("default returns false rather than throwing");
+ }
+ });
assertTrue(map.replace(FIRST_KEY, FIRST_VALUE, EXTRA_VALUE), description + ": replaced wrong value");
assertSame(map.get(FIRST_KEY), EXTRA_VALUE, "found wrong value");
}
@@ -319,9 +322,7 @@
@Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
public void testComputeIfAbsentNullFunction(String description, Map<IntegerEnum, String> map) {
- assertThrows( () -> { map.computeIfAbsent(KEYS[1], null);},
- NullPointerException.class,
- "Should throw NPE");
+ assertThrowsNPE(() -> map.computeIfAbsent(KEYS[1], null));
}
@Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
@@ -366,9 +367,7 @@
@Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
public void testComputeIfPresentNullFunction(String description, Map<IntegerEnum, String> map) {
- assertThrows( () -> { map.computeIfPresent(KEYS[1], null);},
- NullPointerException.class,
- "Should throw NPE");
+ assertThrowsNPE(() -> map.computeIfPresent(KEYS[1], null));
}
@Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
@@ -459,9 +458,7 @@
@Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
public void testComputeNullFunction(String description, Map<IntegerEnum, String> map) {
- assertThrows( () -> { map.compute(KEYS[1], null);},
- NullPointerException.class,
- "Should throw NPE");
+ assertThrowsNPE(() -> map.compute(KEYS[1], null));
}
@Test(dataProvider = "MergeCases")
@@ -531,9 +528,7 @@
@Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
public void testMergeNullMerger(String description, Map<IntegerEnum, String> map) {
- assertThrows( () -> { map.merge(KEYS[1], VALUES[1], null);},
- NullPointerException.class,
- "Should throw NPE");
+ assertThrowsNPE(() -> map.merge(KEYS[1], VALUES[1], null));
}
/** A function that flipflops between running two other functions. */
@@ -973,41 +968,8 @@
return cases;
}
- public interface Thrower<T extends Throwable> {
-
- public void run() throws T;
- }
-
- public static <T extends Throwable> void assertThrows(Thrower<T> thrower, Class<T> throwable) {
- assertThrows(thrower, throwable, null);
- }
-
- public static <T extends Throwable> void assertThrows(Thrower<T> thrower, Class<T> throwable, String message) {
- Throwable thrown;
- try {
- thrower.run();
- thrown = null;
- } catch (Throwable caught) {
- thrown = caught;
- }
-
- assertInstance(thrown, throwable,
- ((null != message) ? message : "") +
- " Failed to throw " + throwable.getCanonicalName());
- }
-
- public static <T extends Throwable> void assertThrows(Class<T> throwable, String message, Thrower<T>... throwers) {
- for (Thrower<T> thrower : throwers) {
- assertThrows(thrower, throwable, message);
- }
- }
-
- public static void assertInstance(Object actual, Class<?> expected) {
- assertInstance(expected.isInstance(actual), null);
- }
-
- public static void assertInstance(Object actual, Class<?> expected, String message) {
- assertTrue(expected.isInstance(actual), message);
+ public static void assertThrowsNPE(ThrowingRunnable r) {
+ assertThrows(NullPointerException.class, r);
}
/**
--- a/jdk/test/java/util/Random/RandomTest.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/java/util/Random/RandomTest.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -21,14 +21,13 @@
* questions.
*/
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.BiConsumer;
+import org.testng.annotations.Test;
+
import static org.testng.Assert.*;
/**
@@ -172,12 +171,12 @@
*/
public void testBadStreamSize() {
Random r = new Random();
- executeAndCatchIAE(() -> r.ints(-1L));
- executeAndCatchIAE(() -> r.ints(-1L, 2, 3));
- executeAndCatchIAE(() -> r.longs(-1L));
- executeAndCatchIAE(() -> r.longs(-1L, -1L, 1L));
- executeAndCatchIAE(() -> r.doubles(-1L));
- executeAndCatchIAE(() -> r.doubles(-1L, .5, .6));
+ assertThrowsIAE(() -> r.ints(-1L));
+ assertThrowsIAE(() -> r.ints(-1L, 2, 3));
+ assertThrowsIAE(() -> r.longs(-1L));
+ assertThrowsIAE(() -> r.longs(-1L, -1L, 1L));
+ assertThrowsIAE(() -> r.doubles(-1L));
+ assertThrowsIAE(() -> r.doubles(-1L, .5, .6));
}
/**
@@ -186,10 +185,10 @@
*/
public void testBadStreamBounds() {
Random r = new Random();
- executeAndCatchIAE(() -> r.ints(2, 1));
- executeAndCatchIAE(() -> r.ints(10, 42, 42));
- executeAndCatchIAE(() -> r.longs(-1L, -1L));
- executeAndCatchIAE(() -> r.longs(10, 1L, -2L));
+ assertThrowsIAE(() -> r.ints(2, 1));
+ assertThrowsIAE(() -> r.ints(10, 42, 42));
+ assertThrowsIAE(() -> r.longs(-1L, -1L));
+ assertThrowsIAE(() -> r.longs(10, 1L, -2L));
testDoubleBadOriginBound((o, b) -> r.doubles(10, o, b));
}
@@ -198,45 +197,28 @@
static final double FINITE = Math.PI;
void testDoubleBadOriginBound(BiConsumer<Double, Double> bi) {
- executeAndCatchIAE(() -> bi.accept(17.0, 2.0));
- executeAndCatchIAE(() -> bi.accept(0.0, 0.0));
- executeAndCatchIAE(() -> bi.accept(Double.NaN, FINITE));
- executeAndCatchIAE(() -> bi.accept(FINITE, Double.NaN));
- executeAndCatchIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY));
+ assertThrowsIAE(() -> bi.accept(17.0, 2.0));
+ assertThrowsIAE(() -> bi.accept(0.0, 0.0));
+ assertThrowsIAE(() -> bi.accept(Double.NaN, FINITE));
+ assertThrowsIAE(() -> bi.accept(FINITE, Double.NaN));
+ assertThrowsIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY));
// Returns NaN
-// executeAndCatchIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, FINITE));
-// executeAndCatchIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
+// assertThrowsIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, FINITE));
+// assertThrowsIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
- executeAndCatchIAE(() -> bi.accept(FINITE, Double.NEGATIVE_INFINITY));
+ assertThrowsIAE(() -> bi.accept(FINITE, Double.NEGATIVE_INFINITY));
// Returns Double.MAX_VALUE
-// executeAndCatchIAE(() -> bi.accept(FINITE, Double.POSITIVE_INFINITY));
+// assertThrowsIAE(() -> bi.accept(FINITE, Double.POSITIVE_INFINITY));
- executeAndCatchIAE(() -> bi.accept(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY));
- executeAndCatchIAE(() -> bi.accept(Double.POSITIVE_INFINITY, FINITE));
- executeAndCatchIAE(() -> bi.accept(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY));
+ assertThrowsIAE(() -> bi.accept(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY));
+ assertThrowsIAE(() -> bi.accept(Double.POSITIVE_INFINITY, FINITE));
+ assertThrowsIAE(() -> bi.accept(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY));
}
- private void executeAndCatchIAE(Runnable r) {
- executeAndCatch(IllegalArgumentException.class, r);
- }
-
- private void executeAndCatch(Class<? extends Exception> expected, Runnable r) {
- Exception caught = null;
- try {
- r.run();
- }
- catch (Exception e) {
- caught = e;
- }
-
- assertNotNull(caught,
- String.format("No Exception was thrown, expected an Exception of %s to be thrown",
- expected.getName()));
- Assert.assertTrue(expected.isInstance(caught),
- String.format("Exception thrown %s not an instance of %s",
- caught.getClass().getName(), expected.getName()));
+ private void assertThrowsIAE(ThrowingRunnable r) {
+ assertThrows(IllegalArgumentException.class, r);
}
/**
--- a/jdk/test/java/util/Spliterator/SpliteratorCollisions.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/java/util/Spliterator/SpliteratorCollisions.java Thu May 04 17:54:50 2017 +0000
@@ -212,16 +212,16 @@
void testNullPointerException(String description,
Collection<HashableInteger> exp,
Supplier<Spliterator<HashableInteger>> s) {
- executeAndCatch(NullPointerException.class, () -> s.get().forEachRemaining(null));
- executeAndCatch(NullPointerException.class, () -> s.get().tryAdvance(null));
+ assertThrowsNPE(() -> s.get().forEachRemaining(null));
+ assertThrowsNPE(() -> s.get().tryAdvance(null));
}
@Test(dataProvider = "HashableIntSpliteratorWithNull")
void testNullPointerExceptionWithNull(String description,
Collection<HashableInteger> exp,
Supplier<Spliterator<HashableInteger>> s) {
- executeAndCatch(NullPointerException.class, () -> s.get().forEachRemaining(null));
- executeAndCatch(NullPointerException.class, () -> s.get().tryAdvance(null));
+ assertThrowsNPE(() -> s.get().forEachRemaining(null));
+ assertThrowsNPE(() -> s.get().tryAdvance(null));
}
--- a/jdk/test/java/util/Spliterator/SpliteratorFailFastTest.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/java/util/Spliterator/SpliteratorFailFastTest.java Thu May 04 17:54:50 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -21,9 +21,6 @@
* questions.
*/
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.ConcurrentModificationException;
@@ -42,8 +39,11 @@
import java.util.WeakHashMap;
import java.util.function.Supplier;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
+import org.testng.Assert.ThrowingRunnable;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertThrows;
/**
* @test
@@ -125,7 +125,7 @@
});
source.update();
- executeAndCatch(() -> s.tryAdvance(e -> {
+ assertThrowsCME(() -> s.tryAdvance(e -> {
}));
}
@@ -137,7 +137,7 @@
});
source.update();
- executeAndCatch(() -> s.forEachRemaining(e -> {
+ assertThrowsCME(() -> s.forEachRemaining(e -> {
}));
}
}
@@ -147,7 +147,7 @@
Source<T> source = ss.get();
Spliterator<T> s = source.spliterator();
- executeAndCatch(() -> s.forEachRemaining(e -> {
+ assertThrowsCME(() -> s.forEachRemaining(e -> {
source.update();
}));
}
@@ -161,7 +161,7 @@
s.estimateSize();
source.update();
- executeAndCatch(() -> s.tryAdvance(e -> {
+ assertThrowsCME(() -> s.tryAdvance(e -> {
}));
}
@@ -172,30 +172,13 @@
s.estimateSize();
source.update();
- executeAndCatch(() -> s.forEachRemaining(e -> {
+ assertThrowsCME(() -> s.forEachRemaining(e -> {
}));
}
}
- private void executeAndCatch(Runnable r) {
- executeAndCatch(ConcurrentModificationException.class, r);
- }
-
- private void executeAndCatch(Class<? extends Exception> expected, Runnable r) {
- Exception caught = null;
- try {
- r.run();
- }
- catch (Exception e) {
- caught = e;
- }
-
- assertNotNull(caught,
- String.format("No Exception was thrown, expected an Exception of %s to be thrown",
- expected.getName()));
- assertTrue(expected.isInstance(caught),
- String.format("Exception thrown %s not an instance of %s",
- caught.getClass().getName(), expected.getName()));
+ private void assertThrowsCME(ThrowingRunnable r) {
+ assertThrows(ConcurrentModificationException.class, r);
}
}
--- a/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java Thu May 04 17:54:50 2017 +0000
@@ -666,8 +666,8 @@
@Test(dataProvider = "Spliterator<Integer>")
public void testNullPointerException(String description, Collection<Integer> exp, Supplier<Spliterator<Integer>> s) {
- executeAndCatch(NullPointerException.class, () -> s.get().forEachRemaining(null));
- executeAndCatch(NullPointerException.class, () -> s.get().tryAdvance(null));
+ assertThrowsNPE(() -> s.get().forEachRemaining(null));
+ assertThrowsNPE(() -> s.get().tryAdvance(null));
}
@Test(dataProvider = "Spliterator<Integer>")
@@ -866,8 +866,8 @@
@Test(dataProvider = "Spliterator.OfInt")
public void testIntNullPointerException(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) {
- executeAndCatch(NullPointerException.class, () -> s.get().forEachRemaining((IntConsumer) null));
- executeAndCatch(NullPointerException.class, () -> s.get().tryAdvance((IntConsumer) null));
+ assertThrowsNPE(() -> s.get().forEachRemaining((IntConsumer) null));
+ assertThrowsNPE(() -> s.get().tryAdvance((IntConsumer) null));
}
@Test(dataProvider = "Spliterator.OfInt")
@@ -1009,8 +1009,8 @@
@Test(dataProvider = "Spliterator.OfLong")
public void testLongNullPointerException(String description, Collection<Long> exp, Supplier<Spliterator.OfLong> s) {
- executeAndCatch(NullPointerException.class, () -> s.get().forEachRemaining((LongConsumer) null));
- executeAndCatch(NullPointerException.class, () -> s.get().tryAdvance((LongConsumer) null));
+ assertThrowsNPE(() -> s.get().forEachRemaining((LongConsumer) null));
+ assertThrowsNPE(() -> s.get().tryAdvance((LongConsumer) null));
}
@Test(dataProvider = "Spliterator.OfLong")
@@ -1152,8 +1152,8 @@
@Test(dataProvider = "Spliterator.OfDouble")
public void testDoubleNullPointerException(String description, Collection<Double> exp, Supplier<Spliterator.OfDouble> s) {
- executeAndCatch(NullPointerException.class, () -> s.get().forEachRemaining((DoubleConsumer) null));
- executeAndCatch(NullPointerException.class, () -> s.get().tryAdvance((DoubleConsumer) null));
+ assertThrowsNPE(() -> s.get().forEachRemaining((DoubleConsumer) null));
+ assertThrowsNPE(() -> s.get().tryAdvance((DoubleConsumer) null));
}
@Test(dataProvider = "Spliterator.OfDouble")
--- a/jdk/test/java/util/logging/TestLoggerWeakRefLeak.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/java/util/logging/TestLoggerWeakRefLeak.java Thu May 04 17:54:50 2017 +0000
@@ -41,8 +41,8 @@
* @modules jdk.attach/sun.tools.attach
* java.logging
* @build jdk.testlibrary.ProcessTools
- * @run main/othervm TestLoggerWeakRefLeak Logger
- * @run main/othervm TestLoggerWeakRefLeak AnonymousLogger
+ * @run main/othervm -Djdk.attach.allowAttachSelf TestLoggerWeakRefLeak Logger
+ * @run main/othervm -Djdk.attach.allowAttachSelf TestLoggerWeakRefLeak AnonymousLogger
*/
public class TestLoggerWeakRefLeak {
--- a/jdk/test/java/util/stream/bootlib/java.base/java/util/SpliteratorTestHelper.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/SpliteratorTestHelper.java Thu May 04 17:54:50 2017 +0000
@@ -26,8 +26,6 @@
import java.util.stream.LambdaTestHelpers;
import static org.testng.Assert.*;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.fail;
/**
* Assertion methods for spliterators, to be called from other tests
@@ -224,22 +222,22 @@
// directly test the primitive methods
if (sp instanceof Spliterator.OfInt) {
Spliterator.OfInt psp = (Spliterator.OfInt) sp;
- executeAndCatch(NullPointerException.class, () -> psp.forEachRemaining((IntConsumer) null));
- executeAndCatch(NullPointerException.class, () -> psp.tryAdvance((IntConsumer) null));
+ assertThrowsNPE(() -> psp.forEachRemaining((IntConsumer) null));
+ assertThrowsNPE(() -> psp.tryAdvance((IntConsumer) null));
}
else if (sp instanceof Spliterator.OfLong) {
Spliterator.OfLong psp = (Spliterator.OfLong) sp;
- executeAndCatch(NullPointerException.class, () -> psp.forEachRemaining((LongConsumer) null));
- executeAndCatch(NullPointerException.class, () -> psp.tryAdvance((LongConsumer) null));
+ assertThrowsNPE(() -> psp.forEachRemaining((LongConsumer) null));
+ assertThrowsNPE(() -> psp.tryAdvance((LongConsumer) null));
}
else if (sp instanceof Spliterator.OfDouble) {
Spliterator.OfDouble psp = (Spliterator.OfDouble) sp;
- executeAndCatch(NullPointerException.class, () -> psp.forEachRemaining((DoubleConsumer) null));
- executeAndCatch(NullPointerException.class, () -> psp.tryAdvance((DoubleConsumer) null));
+ assertThrowsNPE(() -> psp.forEachRemaining((DoubleConsumer) null));
+ assertThrowsNPE(() -> psp.tryAdvance((DoubleConsumer) null));
}
else {
- executeAndCatch(NullPointerException.class, () -> sp.forEachRemaining(null));
- executeAndCatch(NullPointerException.class, () -> sp.tryAdvance(null));
+ assertThrowsNPE(() -> sp.forEachRemaining(null));
+ assertThrowsNPE(() -> sp.tryAdvance(null));
}
}
@@ -653,21 +651,8 @@
}
}
- public static void executeAndCatch(Class<? extends Exception> expected, Runnable r) {
- Exception caught = null;
- try {
- r.run();
- }
- catch (Exception e) {
- caught = e;
- }
-
- assertNotNull(caught,
- String.format("No Exception was thrown, expected an Exception of %s to be thrown",
- expected.getName()));
- assertTrue(expected.isInstance(caught),
- String.format("Exception thrown %s not an instance of %s",
- caught.getClass().getName(), expected.getName()));
+ public static void assertThrowsNPE(ThrowingRunnable r) {
+ assertThrows(NullPointerException.class, r);
}
public static<U> void mixedTraverseAndSplit(Consumer<U> b, Spliterator<U> splTop) {
--- a/jdk/test/lib/testlibrary/ModuleTargetHelper.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/lib/testlibrary/ModuleTargetHelper.java Thu May 04 17:54:50 2017 +0000
@@ -41,19 +41,14 @@
private ModuleTargetHelper() {}
public static final class ModuleTarget {
- private String osName, osArch;
+ private String targetPlatform;
- public ModuleTarget(String osName, String osArch) {
- this.osName = osName;
- this.osArch = osArch;
+ public ModuleTarget(String targetPlatform) {
+ this.targetPlatform = targetPlatform;
}
- public String osName() {
- return osName;
- }
-
- public String osArch() {
- return osArch;
+ public String targetPlatform() {
+ return targetPlatform;
}
}
@@ -84,7 +79,7 @@
ClassReader cr = new ClassReader(in);
cr.accept(cv, attrs, 0);
if (modTargets[0] != null) {
- return new ModuleTarget(modTargets[0].osName(), modTargets[0].osArch());
+ return new ModuleTarget(modTargets[0].targetPlatform());
}
return null;
--- a/jdk/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java Thu May 04 17:54:50 2017 +0000
@@ -37,7 +37,7 @@
* @run main/othervm/timeout=600 -XX:+UsePerfData JvmstatCountersTest 1
* @run main/othervm/timeout=600 -XX:+UsePerfData -Dcom.sun.management.jmxremote JvmstatCountersTest 2
* @run main/othervm/timeout=600 -XX:+UsePerfData -Dcom.sun.management.jmxremote.port=0 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false JvmstatCountersTest 3
- * @run main/othervm/timeout=600 -XX:+UsePerfData JvmstatCountersTest 4
+ * @run main/othervm/timeout=600 -XX:+UsePerfData -Djdk.attach.allowAttachSelf JvmstatCountersTest 4
*/
import java.io.*;
--- a/jdk/test/sun/security/ssl/CertPathRestrictions/JSSEClient.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/sun/security/ssl/CertPathRestrictions/JSSEClient.java Thu May 04 17:54:50 2017 +0000
@@ -1,6 +1,24 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
- * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ * 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 java.io.InputStream;
--- a/jdk/test/sun/security/ssl/CertPathRestrictions/JSSEServer.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/sun/security/ssl/CertPathRestrictions/JSSEServer.java Thu May 04 17:54:50 2017 +0000
@@ -1,6 +1,24 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
- * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ * 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 java.io.InputStream;
--- a/jdk/test/sun/security/ssl/CertPathRestrictions/TLSRestrictions.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/sun/security/ssl/CertPathRestrictions/TLSRestrictions.java Thu May 04 17:54:50 2017 +0000
@@ -4,9 +4,7 @@
*
* 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.
+ * 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
--- a/jdk/test/tools/jar/mmrjar/Basic.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/tools/jar/mmrjar/Basic.java Thu May 04 17:54:50 2017 +0000
@@ -221,7 +221,8 @@
Assert.assertEquals(actual, expected);
}
- // jar tool does two updates, no exported packages, all concealed
+ // jar tool does two updates, no exported packages, all concealed.
+ // Along with various --describe-module variants
@Test
public void test5() throws IOException {
// compile the mr10 directory
@@ -266,10 +267,13 @@
jar("-d --file mr.jar");
+ String uri = (Paths.get("mr.jar")).toUri().toString();
+ uri = "jar:" + uri + "/!module-info.class";
+
actual = lines(outbytes);
expected = Set.of(
- "module hi (module-info.class)",
- "requires mandated java.base",
+ "hi " + uri,
+ "requires java.base mandated",
"contains p",
"contains p.internal"
);
@@ -304,13 +308,19 @@
actual = lines(outbytes);
expected = Set.of(
- "module hi (module-info.class)",
- "requires mandated java.base",
+ "hi " + uri,
+ "requires java.base mandated",
"contains p",
"contains p.internal",
"contains p.internal.bar"
);
Assert.assertEquals(actual, expected);
+
+ for (String release : new String[] {"9" , "10", "100", "1000"}) {
+ jar("-d --file mr.jar --release " + release);
+ actual = lines(outbytes);
+ Assert.assertEquals(actual, expected);
+ }
}
// root and versioned module-info entries have different main-class, version
@@ -399,15 +409,42 @@
Assert.assertEquals(rc, 0);
jar("-d --file=mmr.jar");
- System.out.println("-----------------------");
- System.out.println( new String(outbytes.toByteArray()));
- Assert.assertEquals(lines(outbytes),
- Set.of(
- "module m1 (META-INF/versions/9/module-info.class)",
- "module m1 (META-INF/versions/10/module-info.class)",
- "requires mandated java.base",
- "exports p",
- "main-class p.Main"));
+ Set<String> actual = lines(outbytes);
+ Set<String> expected = Set.of(
+ "releases: 9 10",
+ "No root module descriptor, specify --release"
+ );
+ Assert.assertEquals(actual, expected);
+
+ String uriPrefix = "jar:" + (Paths.get("mmr.jar")).toUri().toString();
+
+ jar("-d --file=mmr.jar --release 9");
+ actual = lines(outbytes);
+ expected = Set.of(
+ "releases: 9 10",
+ "m1 " + uriPrefix + "/!META-INF/versions/9/module-info.class",
+ "requires java.base mandated",
+ "exports p",
+ "main-class p.Main"
+ );
+ Assert.assertEquals(actual, expected);
+
+ jar("-d --file=mmr.jar --release 10");
+ actual = lines(outbytes);
+ expected = Set.of(
+ "releases: 9 10",
+ "m1 " + uriPrefix + "/!META-INF/versions/10/module-info.class",
+ "requires java.base mandated",
+ "exports p",
+ "main-class p.Main"
+ );
+ Assert.assertEquals(actual, expected);
+
+ for (String release : new String[] {"11", "12", "15", "100"}) {
+ jar("-d --file mmr.jar --release " + release);
+ actual = lines(outbytes);
+ Assert.assertEquals(actual, expected);
+ }
Optional<String> exp = Optional.of("p.Main");
try (ZipFile zf = new ZipFile("mmr.jar")) {
--- a/jdk/test/tools/jar/modularJar/Basic.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/tools/jar/modularJar/Basic.java Thu May 04 17:54:50 2017 +0000
@@ -478,13 +478,13 @@
"--file=" + modularJar.toString())
.assertSuccess()
.resultChecker(r -> {
- // Expect similar output: "bar, requires mandated foo, ...
+ // Expect "bar jar:file:/.../!module-info.class"
// conceals jdk.test.foo, conceals jdk.test.foo.internal"
- Pattern p = Pattern.compile("module bar \\(module-info.class\\)\\s+requires\\s++foo");
- assertTrue(p.matcher(r.output).find(),
- "Expecting to find \"bar, requires foo,...\"",
+ String uri = "jar:" + modularJar.toUri().toString() + "/!module-info.class";
+ assertTrue(r.output.contains("bar " + uri),
+ "Expecting to find \"bar " + uri + "\"",
"in output, but did not: [" + r.output + "]");
- p = Pattern.compile(
+ Pattern p = Pattern.compile(
"contains\\s+jdk.test.foo\\s+contains\\s+jdk.test.foo.internal");
assertTrue(p.matcher(r.output).find(),
"Expecting to find \"contains jdk.test.foo,...\"",
@@ -758,14 +758,15 @@
for (String option : new String[] {"--describe-module", "-d" }) {
jar(option,
- "--file=" + modularJar.toString())
+ "--file=" + modularJar.toString(),
+ "--release", "9")
.assertSuccess()
.resultChecker(r ->
assertTrue(r.output.contains("main-class jdk.test.baz.Baz"),
"Expected to find ", "main-class jdk.test.baz.Baz",
" in [", r.output, "]"));
- jarWithStdin(modularJar.toFile(), option)
+ jarWithStdin(modularJar.toFile(), option, "--release", "9")
.assertSuccess()
.resultChecker(r ->
assertTrue(r.output.contains("main-class jdk.test.baz.Baz"),
@@ -773,7 +774,7 @@
" in [", r.output, "]"));
}
- // run module maain class
+ // run module main class
java(mp, "baz/jdk.test.baz.Baz")
.assertSuccess()
.resultChecker(r ->
@@ -900,7 +901,7 @@
.resultChecker(r -> {
assertTrue(r.output.contains("No module descriptor found"));
assertTrue(r.output.contains("Derived automatic module"));
- assertTrue(r.output.contains("module " + mid),
+ assertTrue(r.output.contains(mid + " automatic"),
"Expected [", "module " + mid,"] in [", r.output, "]");
}
);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/whitebox/Driver.java Thu May 04 17:54:50 2017 +0000
@@ -0,0 +1,28 @@
+/*
+ * 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 jdk.jartool/sun.tools.jar
+ * @run testng/othervm jdk.jartool/sun.tools.jar.ValidatorComparatorTest
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/whitebox/jdk.jartool/sun/tools/jar/ValidatorComparatorTest.java Thu May 04 17:54:50 2017 +0000
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+/*
+ * @summary White-box test for Validator.ENTRYNAME_COMPARATOR ( currently just
+ * checks module descriptors ).
+ */
+package sun.tools.jar;
+
+import java.util.List;
+import static java.util.stream.Collectors.toList;
+import static sun.tools.jar.Validator.ENTRYNAME_COMPARATOR;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class ValidatorComparatorTest {
+
+ @Test
+ public void testModuleInfo() throws Throwable {
+ List<String> list =
+ List.of("module-info.class",
+ "META-INF/versions/9/module-info.class",
+ "META-INF/versions/10/module-info.class");
+ List<String> sorted = list.stream()
+ .sorted(ENTRYNAME_COMPARATOR)
+ .collect(toList());
+ List<String> expected = list;
+ Assert.assertEquals(sorted, expected);
+
+
+ list = List.of("META-INF/versions/10/module-info.class",
+ "META-INF/versions/9/module-info.class",
+ "module-info.class");
+ sorted = list.stream().sorted(ENTRYNAME_COMPARATOR).collect(toList());
+ expected =
+ List.of("module-info.class",
+ "META-INF/versions/9/module-info.class",
+ "META-INF/versions/10/module-info.class");
+ Assert.assertEquals(sorted, expected);
+
+
+ list = List.of("META-INF/versions/1001/module-info.class",
+ "META-INF/versions/1000/module-info.class",
+ "META-INF/versions/999/module-info.class",
+ "META-INF/versions/101/module-info.class",
+ "META-INF/versions/100/module-info.class",
+ "META-INF/versions/99/module-info.class",
+ "META-INF/versions/31/module-info.class",
+ "META-INF/versions/30/module-info.class",
+ "META-INF/versions/29/module-info.class",
+ "META-INF/versions/21/module-info.class",
+ "META-INF/versions/20/module-info.class",
+ "META-INF/versions/13/module-info.class",
+ "META-INF/versions/12/module-info.class",
+ "META-INF/versions/11/module-info.class",
+ "META-INF/versions/10/module-info.class",
+ "META-INF/versions/9/module-info.class",
+ "module-info.class");
+ sorted = list.stream().sorted(ENTRYNAME_COMPARATOR).collect(toList());
+ expected =
+ List.of("module-info.class",
+ "META-INF/versions/9/module-info.class",
+ "META-INF/versions/10/module-info.class",
+ "META-INF/versions/11/module-info.class",
+ "META-INF/versions/12/module-info.class",
+ "META-INF/versions/13/module-info.class",
+ "META-INF/versions/20/module-info.class",
+ "META-INF/versions/21/module-info.class",
+ "META-INF/versions/29/module-info.class",
+ "META-INF/versions/30/module-info.class",
+ "META-INF/versions/31/module-info.class",
+ "META-INF/versions/99/module-info.class",
+ "META-INF/versions/100/module-info.class",
+ "META-INF/versions/101/module-info.class",
+ "META-INF/versions/999/module-info.class",
+ "META-INF/versions/1000/module-info.class",
+ "META-INF/versions/1001/module-info.class");
+ Assert.assertEquals(sorted, expected);
+ }
+}
--- a/jdk/test/tools/jlink/IntegrationTest.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/tools/jlink/IntegrationTest.java Thu May 04 17:54:50 2017 +0000
@@ -207,11 +207,6 @@
}
checkReleaseProperty(props, "JAVA_VERSION");
- checkReleaseProperty(props, "JAVA_FULL_VERSION");
- checkReleaseProperty(props, "OS_NAME");
- checkReleaseProperty(props, "OS_ARCH");
- // OS_VERSION is added from makefile. We're testing API-way to create image here!
- // checkReleaseProperty(props, "OS_VERSION");
if (!Files.exists(output.resolve("toto.txt"))) {
throw new AssertionError("Post processing not called");
--- a/jdk/test/tools/jlink/JLinkNegativeTest.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/tools/jlink/JLinkNegativeTest.java Thu May 04 17:54:50 2017 +0000
@@ -178,7 +178,7 @@
.output(imageFile)
.addMods("not_zip")
.modulePath(helper.defaultModulePath())
- .call().assertFailure("Error: java.util.zip.ZipException: zip file is empty");
+ .call().assertFailure("Error: Error reading");
} finally {
deleteDirectory(jar);
}
--- a/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/SystemModulesTest.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/SystemModulesTest.java Thu May 04 17:54:50 2017 +0000
@@ -113,12 +113,13 @@
try {
if (modRef.descriptor().name().equals("java.base")) {
ModuleTargetHelper.ModuleTarget mt = ModuleTargetHelper.read(modRef);
- assertTrue(checkOSName(mt.osName()));
- assertTrue(checkOSArch(mt.osArch()));
+ String[] values = mt.targetPlatform().split("-");
+ assertTrue(checkOSName(values[0]));
+ assertTrue(checkOSArch(values[1]));
} else {
// target platform attribute is dropped by jlink plugin for other modules
ModuleTargetHelper.ModuleTarget mt = ModuleTargetHelper.read(modRef);
- assertTrue(mt == null || (mt.osName() == null && mt.osArch() == null));
+ assertTrue(mt == null || mt.targetPlatform() == null);
}
} catch (IOException exp) {
throw new UncheckedIOException(exp);
--- a/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/UserModuleTest.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/UserModuleTest.java Thu May 04 17:54:50 2017 +0000
@@ -220,16 +220,16 @@
throw new RuntimeException("ModuleTarget is missing for java.base");
}
- String osName = mt.osName();
- String osArch = mt.osArch();
+ String[] values = mt.targetPlatform().split("-");
+ String osName = values[0];
+ String osArch = values[1];
// create JMOD files
Files.createDirectories(JMODS_DIR);
Stream.of(modules).forEach(mn ->
assertTrue(jmod("create",
"--class-path", MODS_DIR.resolve(mn).toString(),
- "--os-name", osName,
- "--os-arch", osArch,
+ "--target-platform", mt.targetPlatform(),
"--main-class", mn.replace('m', 'p') + ".Main",
JMODS_DIR.resolve(mn + ".jmod").toString()) == 0)
);
--- a/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m1/p1/Main.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m1/p1/Main.java Thu May 04 17:54:50 2017 +0000
@@ -62,8 +62,7 @@
// parse module-info.class
ClassReader cr = new ClassReader(in);
cr.accept(cv, attrs, 0);
- return modTargets[0] != null &&
- (modTargets[0].osName() != null || modTargets[0].osArch() != null);
+ return modTargets[0] != null && modTargets[0].targetPlatform() != null;
}
public static void main(String... args) throws Exception {
--- a/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m4/p4/Main.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m4/p4/Main.java Thu May 04 17:54:50 2017 +0000
@@ -63,8 +63,7 @@
// parse module-info.class
ClassReader cr = new ClassReader(in);
cr.accept(cv, attrs, 0);
- return modTargets[0] != null &&
- (modTargets[0].osName() != null || modTargets[0].osArch() != null);
+ return modTargets[0] != null && modTargets[0].targetPlatform() != null;
}
private static boolean hasModuleTarget(String modName) throws IOException {
--- a/jdk/test/tools/jmod/JmodTest.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/tools/jmod/JmodTest.java Thu May 04 17:54:50 2017 +0000
@@ -393,16 +393,17 @@
MODS_DIR.resolve("describeFoo.jmod").toString())
.assertSuccess()
.resultChecker(r -> {
- // Expect similar output: "foo, requires mandated java.base
- // exports jdk.test.foo, contains jdk.test.foo.internal"
- Pattern p = Pattern.compile("\\s+foo\\s+requires\\s+mandated\\s+java.base");
+ // Expect similar output: "foo... exports jdk.test.foo ...
+ // ... requires java.base mandated... contains jdk.test.foo.internal"
+ Pattern p = Pattern.compile("foo\\s+exports\\s+jdk.test.foo");
assertTrue(p.matcher(r.output).find(),
- "Expecting to find \"foo, requires java.base\"" +
+ "Expecting to find \"foo... exports jdk.test.foo\"" +
"in output, but did not: [" + r.output + "]");
p = Pattern.compile(
- "exports\\s+jdk.test.foo\\s+contains\\s+jdk.test.foo.internal");
+ "requires\\s+java.base\\s+mandated\\s+contains\\s+jdk.test.foo.internal");
assertTrue(p.matcher(r.output).find(),
- "Expecting to find \"exports ..., contains ...\"" +
+ "Expecting to find \"requires java.base mandated..., " +
+ "contains jdk.test.foo.internal ...\"" +
"in output, but did not: [" + r.output + "]");
});
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/describe/DescribeModuleTest.java Thu May 04 17:54:50 2017 +0000
@@ -0,0 +1,103 @@
+/*
+ * 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.xml
+ * @library /lib/testlibrary
+ * @build DescribeModuleTest jdk.testlibrary.*
+ * @run testng DescribeModuleTest
+ * @summary Basic test for java --describe-module
+ */
+
+import jdk.testlibrary.ProcessTools;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class DescribeModuleTest {
+
+ /**
+ * Test that the output describes java.base
+ */
+ private void expectJavaBase(String... args) throws Exception {
+ int exitValue = ProcessTools.executeTestJava(args)
+ .outputTo(System.out)
+ .errorTo(System.out)
+ .stdoutShouldContain("java.base")
+ .stdoutShouldContain("exports java.lang")
+ .stdoutShouldContain("uses java.nio.file.spi.FileSystemProvider")
+ .stdoutShouldContain("contains sun.launcher")
+ .stdoutShouldNotContain("requires ")
+ .getExitValue();
+ assertTrue(exitValue == 0);
+ }
+
+ /**
+ * Test that the output describes java.xml
+ */
+ private void expectJavaXml(String... args) throws Exception {
+ int exitValue = ProcessTools.executeTestJava(args)
+ .outputTo(System.out)
+ .errorTo(System.out)
+ .stdoutShouldContain("java.xml")
+ .stdoutShouldContain("exports javax.xml")
+ .stdoutShouldContain("requires java.base")
+ .stdoutShouldContain("uses javax.xml.stream.XMLInputFactory")
+ .getExitValue();
+ assertTrue(exitValue == 0);
+ }
+
+ /**
+ * Test output/exitValue when describing an unknown module
+ */
+ private void expectUnknownModule(String... args) throws Exception {
+ int exitValue = ProcessTools.executeTestJava(args)
+ .outputTo(System.out)
+ .errorTo(System.out)
+ .stdoutShouldNotContain("requires java.base")
+ .getExitValue();
+ assertTrue(exitValue != 0);
+ }
+
+
+ public void testDescribeJavaBase() throws Exception {
+ expectJavaBase("--describe-module", "java.base");
+ expectJavaBase("--describe-module=java.base");
+ expectJavaBase("-d", "java.base");
+ }
+
+ public void testDescribeJavaXml() throws Exception {
+ expectJavaXml("--describe-module", "java.xml");
+ expectJavaXml("--describe-module=java.xml");
+ expectJavaXml("-d", "java.xml");
+ }
+
+ public void testDescribeUnknownModule() throws Exception {
+ expectUnknownModule("--describe-module", "jdk.rhubarb");
+ expectUnknownModule("--describe-module=jdk.rhubarb");
+ expectUnknownModule("-d", "jdk.rhubarb");
+ }
+
+}
--- a/jdk/test/tools/launcher/modules/listmods/ListModsTest.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/tools/launcher/modules/listmods/ListModsTest.java Thu May 04 17:54:50 2017 +0000
@@ -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
@@ -33,7 +33,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
-import static jdk.testlibrary.ProcessTools.*;
+import jdk.testlibrary.ProcessTools;
import jdk.testlibrary.OutputAnalyzer;
import org.testng.annotations.BeforeTest;
@@ -66,138 +66,80 @@
SRC_DIR.resolve("java.transaction"),
UPGRADEMODS_DIR.resolve("java.transaction"));
assertTrue(compiled);
-
}
-
@Test
public void testListAll() throws Exception {
- OutputAnalyzer output
- = executeTestJava("--list-modules")
- .outputTo(System.out)
- .errorTo(System.out);
- output.shouldContain("java.base");
- output.shouldContain("java.xml");
- assertTrue(output.getExitValue() == 0);
- }
-
-
- @Test
- public void testListOneModule() throws Exception {
- OutputAnalyzer output
- = executeTestJava("--list-modules=java.base")
- .outputTo(System.out)
- .errorTo(System.out);
- output.shouldContain("java.base");
- output.shouldContain("exports java.lang");
- assertTrue(output.getExitValue() == 0);
+ exec("--list-modules")
+ .shouldContain("java.base")
+ .shouldContain("java.xml")
+ .shouldHaveExitValue(0);
}
-
- @Test
- public void testListTwoModules() throws Exception {
- OutputAnalyzer output
- = executeTestJava("--list-modules", "java.base,java.xml")
- .outputTo(System.out)
- .errorTo(System.out);
- output.shouldContain("java.base");
- output.shouldContain("exports java.lang");
- output.shouldContain("java.xml");
- output.shouldContain("exports javax.xml");
- assertTrue(output.getExitValue() == 0);
- }
-
-
- @Test
- public void testListUnknownModule() throws Exception {
- OutputAnalyzer output
- = executeTestJava("--list-modules", "java.rhubarb")
- .outputTo(System.out)
- .errorTo(System.out);
- output.shouldNotContain("java.base");
- output.shouldContain("java.rhubarb not found");
- assertTrue(output.getExitValue() == 0);
- }
-
-
@Test
public void testListWithModulePath() throws Exception {
- OutputAnalyzer output
- = executeTestJava("--module-path", MODS_DIR.toString(), "--list-modules")
- .outputTo(System.out)
- .errorTo(System.out);
- output.shouldContain("java.base");
- output.shouldContain("m1");
- assertTrue(output.getExitValue() == 0);
+ exec("--list-modules", "--module-path", MODS_DIR.toString())
+ .shouldContain("java.base")
+ .shouldContain("m1")
+ .shouldHaveExitValue(0);
}
-
@Test
public void testListWithUpgradeModulePath() throws Exception {
- OutputAnalyzer output
- = executeTestJava("--upgrade-module-path", UPGRADEMODS_DIR.toString(),
- "--list-modules", "java.transaction")
- .outputTo(System.out)
- .errorTo(System.out);
- output.shouldContain("exports javax.transaction.atomic");
- assertTrue(output.getExitValue() == 0);
+ String dir = UPGRADEMODS_DIR.toString();
+ exec("--list-modules", "--upgrade-module-path", dir)
+ .shouldContain(UPGRADEMODS_DIR.toString())
+ .shouldHaveExitValue(0);
}
-
@Test
public void testListWithLimitMods1() throws Exception {
- OutputAnalyzer output
- = executeTestJava("--limit-modules", "java.management.rmi", "--list-modules")
- .outputTo(System.out)
- .errorTo(System.out);
- output.shouldContain("java.rmi");
- output.shouldContain("java.base");
- output.shouldNotContain("java.scripting");
- assertTrue(output.getExitValue() == 0);
+ exec("--limit-modules", "java.management.rmi", "--list-modules")
+ .shouldContain("java.rmi")
+ .shouldContain("java.base")
+ .shouldNotContain("java.scripting")
+ .shouldHaveExitValue(0);
}
-
@Test
public void testListWithLimitMods2() throws Exception {
- OutputAnalyzer output
- = executeTestJava("--module-path", MODS_DIR.toString(),
- "--limit-modules", "java.management",
- "--list-modules")
- .outputTo(System.out)
- .errorTo(System.out);
- output.shouldContain("java.base");
- output.shouldNotContain("m1");
- assertTrue(output.getExitValue() == 0);
+ exec("--list-modules",
+ "--module-path", MODS_DIR.toString(),
+ "--limit-modules", "java.management")
+ .shouldContain("java.base")
+ .shouldNotContain("m1")
+ .shouldHaveExitValue(0);
}
-
/**
* java -version --list-modules => should print version and exit
*/
@Test
public void testListWithPrintVersion1() throws Exception {
- OutputAnalyzer output
- = executeTestJava("-version", "--list-modules")
- .outputTo(System.out)
- .errorTo(System.out);
- output.shouldNotContain("java.base");
- output.shouldContain("Runtime Environment");
- assertTrue(output.getExitValue() == 0);
+ exec("-version", "--list-modules")
+ .shouldNotContain("java.base")
+ .shouldContain("Runtime Environment")
+ .shouldHaveExitValue(0);
}
-
/**
* java --list-modules -version => should list modules and exit
*/
@Test
public void testListWithPrintVersion2() throws Exception {
- OutputAnalyzer output
- = executeTestJava("--list-modules", "-version")
+ exec("--list-modules", "-version")
+ .shouldContain("java.base")
+ .shouldNotContain("Runtime Environment")
+ .shouldHaveExitValue(0);
+ }
+
+ /**
+ * java args... returning the OutputAnalyzer to analyzer the output
+ */
+ private OutputAnalyzer exec(String... args) throws Exception {
+ return ProcessTools.executeTestJava(args)
.outputTo(System.out)
.errorTo(System.out);
- output.shouldContain("java.base");
- output.shouldNotContain("Runtime Environment");
- assertTrue(output.getExitValue() == 0);
}
}
--- a/jdk/test/tools/launcher/modules/listmods/src/java.transaction/javax/transaction/atomic/Atomic.java Thu May 04 16:38:09 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2015, 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 javax.transaction.atomic;
-
-public interface Atomic {
-
-}
--- a/jdk/test/tools/launcher/modules/listmods/src/java.transaction/module-info.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/tools/launcher/modules/listmods/src/java.transaction/module-info.java Thu May 04 17:54:50 2017 +0000
@@ -23,5 +23,4 @@
module java.transaction {
exports javax.transaction;
- exports javax.transaction.atomic;
}
--- a/jdk/test/tools/launcher/modules/patch/systemmodules/PatchSystemModules.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/tools/launcher/modules/patch/systemmodules/PatchSystemModules.java Thu May 04 17:54:50 2017 +0000
@@ -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,9 +23,8 @@
/*
* @test
- * @bug 8157068
- * @summary Patch java.base and user module with Hashes attribute tied with
- * other module.
+ * @bug 8157068 8177844
+ * @summary Patch java.base and user module with ModuleHashes attribute
* @library /lib/testlibrary
* @modules jdk.compiler
* @build CompilerUtils
@@ -59,6 +58,7 @@
private static final Path JARS_DIR = Paths.get("jars");
private static final Path PATCH_DIR = Paths.get("patches");
private static final Path IMAGE = Paths.get("image");
+ private static final Path NEW_M1_JAR = JARS_DIR.resolve("new_m1.jar");
private static final String JAVA_BASE = "java.base";
private final String[] modules = new String[] { "m1", "m2" };
@@ -80,13 +80,23 @@
assertTrue(CompilerUtils.compile(PATCH_SRC_DIR.resolve("m2"),
PATCH_DIR.resolve("m2")));
+ createJars();
+
// create an image with only m1 and m2
if (Files.exists(JMODS)) {
// create an image with m1,m2
createImage();
}
+
+ // create new copy of m1.jar
+ jar("--create",
+ "--file=" + NEW_M1_JAR.toString(),
+ "-C", MODS_DIR.resolve("m1").toString(), ".");
}
+ /*
+ * Test patching system module and user module on module path
+ */
@Test
public void test() throws Throwable {
Path patchedJavaBase = PATCH_DIR.resolve(JAVA_BASE);
@@ -107,6 +117,9 @@
"-m", "m1/p1.Main", "2");
}
+ /*
+ * Test --patch-module on a custom image
+ */
@Test
public void testImage() throws Throwable {
if (Files.notExists(JMODS))
@@ -125,27 +138,49 @@
"-m", "m1/p1.Main", "2");
}
+ /*
+ * Test a module linked in a system hashed in ModuleHashes attribute
+ * cannot be upgraded
+ */
@Test
- public void upgradeTiedModule() throws Throwable {
+ public void upgradeHashedModule() throws Throwable {
if (Files.notExists(JMODS))
return;
- Path m1 = MODS_DIR.resolve("m1.jar");
-
- // create another m1.jar
- jar("--create",
- "--file=" + m1.toString(),
- "-C", MODS_DIR.resolve("m1").toString(), ".");
-
// Fail to upgrade m1.jar with mismatched hash
runTestWithExitCode(getJava(IMAGE),
- "--upgrade-module-path", m1.toString(),
- "-m", "m1/p1.Main");
+ "--upgrade-module-path", NEW_M1_JAR.toString(),
+ "-m", "m1/p1.Main", "ShouldNeverRun");
+ // test when SystemModules fast path is not enabled, i.e. exploded image
runTestWithExitCode(getJava(IMAGE),
"--patch-module", "java.base=" + PATCH_DIR.resolve(JAVA_BASE),
- "--upgrade-module-path", m1.toString(),
- "-m", "m1/p1.Main", "1");
+ "--upgrade-module-path", NEW_M1_JAR.toString(),
+ "-m", "m1/p1.Main", "ShouldNeverRun");
+ }
+
+ /*
+ * Test a module linked in a system hashed in ModuleHashes attribute
+ * cannot be upgraded combining with --patch-module and --upgrade-module-path
+ */
+ @Test
+ public void patchHashedModule() throws Throwable {
+ if (Files.notExists(JMODS))
+ return;
+
+ // --patch-module does not disable hash check.
+ // Test that a hashed module cannot be upgraded.
+ runTestWithExitCode(getJava(IMAGE),
+ "--patch-module", "m1=.jar",
+ "--upgrade-module-path", NEW_M1_JAR.toString(),
+ "-m", "m1/p1.Main", "ShouldNeverRun");
+
+ // test when SystemModules fast path is not enabled, i.e. exploded image
+ runTestWithExitCode(getJava(IMAGE),
+ "--patch-module", "java.base=" + PATCH_DIR.resolve(JAVA_BASE),
+ "--patch-module", "m1=.jar",
+ "--upgrade-module-path", NEW_M1_JAR.toString(),
+ "-m", "m1/p1.Main", "ShouldNeverRun");
}
private void runTestWithExitCode(String... options) throws Throwable {
@@ -171,9 +206,8 @@
assertTrue(exitValue == 0);
}
- static void createImage() throws Throwable {
+ static void createJars() throws Throwable {
FileUtils.deleteFileTreeUnchecked(JARS_DIR);
- FileUtils.deleteFileTreeUnchecked(IMAGE);
Files.createDirectories(JARS_DIR);
Path m1 = JARS_DIR.resolve("m1.jar");
@@ -189,7 +223,10 @@
"--module-path", JARS_DIR.toString(),
"--hash-modules", "m1",
"-C", MODS_DIR.resolve("m2").toString(), ".");
+ }
+ static void createImage() throws Throwable {
+ FileUtils.deleteFileTreeUnchecked(IMAGE);
String mpath = JARS_DIR.toString() + File.pathSeparator + JMODS.toString();
execTool("jlink", "--module-path", mpath,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/showmoduleresolution/ShowModuleResolutionTest.java Thu May 04 17:54:50 2017 +0000
@@ -0,0 +1,84 @@
+/*
+ * 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 jdk.jdeps jdk.zipfs
+ * @library /lib/testlibrary
+ * @build ShowModuleResolutionTest jdk.testlibrary.*
+ * @run testng ShowModuleResolutionTest
+ * @summary Basic test for java --show-module-resolution
+ */
+
+import jdk.testlibrary.ProcessTools;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class ShowModuleResolutionTest {
+
+ /**
+ * Test that the resolution does not bind any services
+ */
+ private void expectJavaBase(String... args) throws Exception {
+ int exitValue = ProcessTools.executeTestJava(args)
+ .outputTo(System.out)
+ .errorTo(System.out)
+ .stdoutShouldContain("root java.base")
+ .stdoutShouldNotContain("java.base binds")
+ .getExitValue();
+ assertTrue(exitValue == 0);
+ }
+
+ /**
+ * Test that the resolution binds services that resolves additional
+ * modules
+ */
+ private void expectProviders(String... args) throws Exception {
+ int exitValue = ProcessTools.executeTestJava(args)
+ .outputTo(System.out)
+ .errorTo(System.out)
+ .stdoutShouldContain("root java.base")
+ .stdoutShouldContain("root java.compiler")
+ .stdoutShouldContain("root jdk.compiler")
+ .stdoutShouldContain("root java.compiler")
+ .stdoutShouldContain("jdk.compiler requires java.compiler")
+ .stdoutShouldContain("java.base binds jdk.compiler")
+ .stdoutShouldContain("java.base binds jdk.jdeps")
+ .stdoutShouldContain("java.base binds jdk.zipfs")
+ .stdoutShouldContain("java.compiler binds jdk.compiler")
+ .stdoutShouldContain("jdk.jdeps requires jdk.compiler")
+ .getExitValue();
+ assertTrue(exitValue == 0);
+ }
+
+ public void test() throws Exception {
+ expectJavaBase("--show-module-resolution",
+ "--limit-modules", "java.base",
+ "-version");
+ expectProviders("--show-module-resolution",
+ "--limit-modules", "java.base,jdk.jdeps,jdk.zipfs",
+ "-version");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/validate/ValidateModulesTest.java Thu May 04 17:54:50 2017 +0000
@@ -0,0 +1,135 @@
+/*
+ * 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.xml
+ * @library /lib/testlibrary
+ * @build ValidateModulesTest JarUtils jdk.testlibrary.*
+ * @run testng ValidateModulesTest
+ * @summary Basic test for java --validate-modules
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.OutputAnalyzer;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class ValidateModulesTest {
+
+ /**
+ * Test that the system modules validate.
+ */
+ public void testSystemModules() throws Exception {
+ run("--validate-modules")
+ .stdoutShouldContain("java.base")
+ .stdoutShouldContain("java.xml")
+ .shouldHaveExitValue(0);
+ }
+
+ /**
+ * Test an automatic module on the module path with classes in the same
+ * package as a system module.
+ */
+ public void testPackageConflict() throws Exception {
+ Path tmpdir = Files.createTempDirectory("tmp");
+
+ Path classes = Files.createDirectory(tmpdir.resolve("classes"));
+ touch(classes, "javax/xml/XMLConstants.class");
+ touch(classes, "javax/xml/parsers/SAXParser.class");
+
+ Path lib = Files.createDirectory(tmpdir.resolve("lib"));
+ JarUtils.createJarFile(lib.resolve("xml.jar"), classes);
+
+ int exitValue = run("-p", lib.toString(), "--validate-modules")
+ .shouldContain("xml automatic")
+ .shouldContain("conflicts with module java.xml")
+ .getExitValue();
+ assertTrue(exitValue != 0);
+
+ }
+
+ /**
+ * Test two modules with the same name in a directory.
+ */
+ public void testDuplicateModule() throws Exception {
+ Path tmpdir = Files.createTempDirectory("tmp");
+
+ Path classes = Files.createDirectory(tmpdir.resolve("classes"));
+ touch(classes, "org/foo/Bar.class");
+
+ Path lib = Files.createDirectory(tmpdir.resolve("lib"));
+ JarUtils.createJarFile(lib.resolve("foo-1.0.jar"), classes);
+ JarUtils.createJarFile(lib.resolve("foo-2.0.jar"), classes);
+
+ int exitValue = run("-p", lib.toString(), "--validate-modules")
+ .shouldContain("contains same module")
+ .getExitValue();
+ assertTrue(exitValue != 0);
+ }
+
+ /**
+ * Test two modules with the same name in different directories.
+ */
+ public void testShadowed() throws Exception {
+ Path tmpdir = Files.createTempDirectory("tmp");
+
+ Path classes = Files.createDirectory(tmpdir.resolve("classes"));
+ touch(classes, "org/foo/Bar.class");
+
+ Path lib1 = Files.createDirectory(tmpdir.resolve("lib1"));
+ JarUtils.createJarFile(lib1.resolve("foo-1.0.jar"), classes);
+
+ Path lib2 = Files.createDirectory(tmpdir.resolve("lib2"));
+ JarUtils.createJarFile(lib2.resolve("foo-2.0.jar"), classes);
+
+ run("-p", lib1 + File.pathSeparator + lib2, "--validate-modules")
+ .shouldContain("shadowed by")
+ .shouldHaveExitValue(0);
+ }
+
+ /**
+ * Runs the java launcher with the given arguments.
+ */
+ private OutputAnalyzer run(String... args) throws Exception {
+ return ProcessTools.executeTestJava(args)
+ .outputTo(System.out)
+ .errorTo(System.out);
+ }
+
+ /**
+ * Creates a file relative the given directory.
+ */
+ private void touch(Path dir, String relPath) throws IOException {
+ Path file = dir.resolve(relPath.replace('/', File.separatorChar));
+ Files.createDirectories(file.getParent());
+ Files.createFile(file);
+ }
+}
--- a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java Thu May 04 16:38:09 2017 +0000
+++ b/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java Thu May 04 17:54:50 2017 +0000
@@ -1542,8 +1542,7 @@
@Override
public Element visitModuleTarget(ModuleTarget_attribute attr, Element p) {
Element e = new Element(x.getCpString(attr.attribute_name_index));
- e.add(x.getCpString(attr.os_name_index));
- e.add(x.getCpString(attr.os_arch_index));
+ e.add(x.getCpString(attr.target_platform_index));
e.trimToSize();
p.add(e);
return null;