--- a/jdk/.hgtags Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/.hgtags Thu Mar 30 19:55:04 2017 +0200
@@ -405,3 +405,4 @@
cac788454598b95d8b0153c021a7fae3cd7e6fda jdk-9+160
09b92d3067a38ee07bc14efa336b14790c93f7e7 jdk-9+161
f6bf027e88e9a4dd19f721001a7af00157af42c4 jdk-9+162
+50171f8c47961710cbf87aead6f03fa431d8d240 jdk-9+163
--- a/jdk/make/GenerateModuleSummary.gmk Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/make/GenerateModuleSummary.gmk Thu Mar 30 19:55:04 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2014, 2016, 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
@@ -31,7 +31,7 @@
include ModuleTools.gmk
GENGRAPHS_DIR := $(IMAGES_OUTPUTDIR)/gengraphs
-SPEC_DOTFILES_DIR := $(IMAGES_OUTPUTDIR)/spec-dotfiles
+SPEC_DOTFILES_DIR := $(GENGRAPHS_DIR)/spec-dotfiles
TOOLS_MODULE_SRCDIR := $(JDK_TOPDIR)/make/src/classes/build/tools/jigsaw
$(GENGRAPHS_DIR)/jdk.dot: $(BUILD_JIGSAW_TOOLS)
--- a/jdk/make/ModuleTools.gmk Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/make/ModuleTools.gmk Thu Mar 30 19:55:04 2017 +0200
@@ -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
@@ -23,8 +23,9 @@
# questions.
#
-include $(SPEC)
-include MakeBase.gmk
+ifndef _MODULE_TOOLS_GMK
+_MODULE_TOOLS_GMK := 1
+
include JavaCompilation.gmk
TOOLS_CLASSES_DIR := $(BUILDTOOLS_OUTPUTDIR)/tools_jigsaw_classes
@@ -32,7 +33,7 @@
# To avoid reevaluating the compilation setup for the tools each time this file
# is included, the actual compilation is handled by CompileModuleTools.gmk. The
# following trick is used to be able to declare a dependency on the built tools.
-BUILD_TOOLS_JDK := $(call SetupJavaCompilationCompileTarget, \
+BUILD_JIGSAW_TOOLS := $(call SetupJavaCompilationCompileTarget, \
BUILD_JIGSAW_TOOLS, $(TOOLS_CLASSES_DIR))
TOOL_GENGRAPHS := $(BUILD_JAVA) -esa -ea -cp $(TOOLS_CLASSES_DIR) \
@@ -47,3 +48,5 @@
-cp $(TOOLS_CLASSES_DIR) \
--add-exports java.base/jdk.internal.module=ALL-UNNAMED \
build.tools.jigsaw.AddPackagesAttribute
+
+endif # _MODULE_TOOLS_GMK
--- a/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java Thu Mar 30 19:55:04 2017 +0200
@@ -26,7 +26,6 @@
package build.tools.jigsaw;
import com.sun.tools.jdeps.ModuleDotGraph;
-import com.sun.tools.jdeps.ModuleDotGraph.DotGraphBuilder;
import java.io.IOException;
import java.lang.module.Configuration;
@@ -36,10 +35,15 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
+import java.util.Properties;
import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
/**
* Generate the DOT file for a module graph for each module in the JDK
@@ -50,13 +54,19 @@
public static void main(String[] args) throws Exception {
Path dir = null;
boolean spec = false;
+ Properties props = null;
for (int i=0; i < args.length; i++) {
String arg = args[i];
if (arg.equals("--spec")) {
spec = true;
+ } else if (arg.equals("--dot-attributes")) {
+ if (i++ == args.length) {
+ throw new IllegalArgumentException("Missing argument: --dot-attributes option");
+ }
+ props = new Properties();
+ props.load(Files.newInputStream(Paths.get(args[i])));
} else if (arg.equals("--output")) {
- i++;
- dir = i < args.length ? Paths.get(args[i]) : null;
+ dir = ++i < args.length ? Paths.get(args[i]) : null;
} else if (arg.startsWith("-")) {
throw new IllegalArgumentException("Invalid option: " + arg);
}
@@ -67,11 +77,14 @@
System.exit(1);
}
- // setup and configure the dot graph attributes
- initDotGraphAttributes();
Files.createDirectories(dir);
-
- GenGraphs genGraphs = new GenGraphs(dir, spec);
+ ModuleGraphAttributes attributes;
+ if (props != null) {
+ attributes = new ModuleGraphAttributes(props);
+ } else {
+ attributes = new ModuleGraphAttributes();
+ }
+ GenGraphs genGraphs = new GenGraphs(dir, spec, attributes);
// print dot file for each module
Map<String, Configuration> configurations = new HashMap<>();
@@ -99,49 +112,149 @@
genGraphs.genDotFiles(configurations);
}
- static void initDotGraphAttributes() {
- int h = 1000;
- DotGraphBuilder.weight("java.se", "java.sql.rowset", h * 10);
- DotGraphBuilder.weight("java.sql.rowset", "java.sql", h * 10);
- DotGraphBuilder.weight("java.sql", "java.xml", h * 10);
- DotGraphBuilder.weight("java.xml", "java.base", h * 10);
+ /**
+ * Custom dot file attributes.
+ */
+ static class ModuleGraphAttributes implements ModuleDotGraph.Attributes {
+ static Map<String, String> DEFAULT_ATTRIBUTES = Map.of(
+ "ranksep", "0.6",
+ "fontsize", "12",
+ "fontcolor", BLACK,
+ "fontname", "DejaVuSans",
+ "arrowsize", "1",
+ "arrowwidth", "2",
+ "arrowcolor", DARK_GRAY,
+ // custom
+ "requiresMandatedColor", LIGHT_GRAY,
+ "javaSubgraphColor", ORANGE,
+ "jdkSubgraphColor", BLUE
+ );
+
+ final Map<String, Integer> weights = new HashMap<>();
+ final List<Set<String>> ranks = new ArrayList<>();
+ final Map<String, String> attrs;
+ ModuleGraphAttributes(Map<String, String> attrs) {
+ int h = 1000;
+ weight("java.se", "java.sql.rowset", h * 10);
+ weight("java.sql.rowset", "java.sql", h * 10);
+ weight("java.sql", "java.xml", h * 10);
+ weight("java.xml", "java.base", h * 10);
+
+ ranks.add(Set.of("java.logging", "java.scripting", "java.xml"));
+ ranks.add(Set.of("java.sql"));
+ ranks.add(Set.of("java.compiler", "java.instrument"));
+ ranks.add(Set.of("java.desktop", "java.management"));
+ ranks.add(Set.of("java.corba", "java.xml.ws"));
+ ranks.add(Set.of("java.xml.bind", "java.xml.ws.annotation"));
+
+ this.attrs = attrs;
+ }
+
+ ModuleGraphAttributes() {
+ this(DEFAULT_ATTRIBUTES);
+ }
+ ModuleGraphAttributes(Properties props) {
+ this(toAttributes(props));
+ }
+
+ @Override
+ public double rankSep() {
+ return Double.valueOf(attrs.get("ranksep"));
+ }
+
+ @Override
+ public int fontSize() {
+ return Integer.valueOf(attrs.get("fontsize"));
+ }
+
+ @Override
+ public String fontName() {
+ return attrs.get("fontname");
+ }
- DotGraphBuilder.sameRankNodes(Set.of("java.logging", "java.scripting", "java.xml"));
- DotGraphBuilder.sameRankNodes(Set.of("java.sql"));
- DotGraphBuilder.sameRankNodes(Set.of("java.compiler", "java.instrument"));
- DotGraphBuilder.sameRankNodes(Set.of("java.desktop", "java.management"));
- DotGraphBuilder.sameRankNodes(Set.of("java.corba", "java.xml.ws"));
- DotGraphBuilder.sameRankNodes(Set.of("java.xml.bind", "java.xml.ws.annotation"));
- DotGraphBuilder.setRankSep(0.7);
- DotGraphBuilder.setFontSize(12);
- DotGraphBuilder.setArrowSize(1);
- DotGraphBuilder.setArrowWidth(2);
+ @Override
+ public String fontColor() {
+ return attrs.get("fontcolor");
+ }
+
+ @Override
+ public int arrowSize() {
+ return Integer.valueOf(attrs.get("arrowsize"));
+ }
+
+ @Override
+ public int arrowWidth() {
+ return Integer.valueOf(attrs.get("arrowwidth"));
+ }
+
+ @Override
+ public String arrowColor() {
+ return attrs.get("arrowcolor");
+ }
+
+ @Override
+ public List<Set<String>> ranks() {
+ return ranks;
+ }
+
+ @Override
+ public String requiresMandatedColor() {
+ return attrs.get("requiresMandatedColor");
+ }
+
+ @Override
+ public String javaSubgraphColor() {
+ return attrs.get("javaSubgraphColor");
+ }
+
+ @Override
+ public String jdkSubgraphColor() {
+ return attrs.get("jdkSubgraphColor");
+ }
+
+ @Override
+ public int weightOf(String s, String t) {
+ int w = weights.getOrDefault(s + ":" + t, 1);
+ if (w != 1)
+ return w;
+ if (s.startsWith("java.") && t.startsWith("java."))
+ return 10;
+ return 1;
+ }
+
+ public void weight(String s, String t, int w) {
+ weights.put(s + ":" + t, w);
+ }
+
+ static Map<String, String> toAttributes(Properties props) {
+ return DEFAULT_ATTRIBUTES.keySet().stream()
+ .collect(Collectors.toMap(Function.identity(),
+ k -> props.getProperty(k, DEFAULT_ATTRIBUTES.get(k))));
+ }
}
private final Path dir;
private final boolean spec;
- GenGraphs(Path dir, boolean spec) {
+ private final ModuleGraphAttributes attributes;
+ GenGraphs(Path dir, boolean spec, ModuleGraphAttributes attributes) {
this.dir = dir;
this.spec = spec;
+ this.attributes = attributes;
}
void genDotFiles(Map<String, Configuration> configurations) throws IOException {
ModuleDotGraph dotGraph = new ModuleDotGraph(configurations, spec);
- dotGraph.genDotFiles(dir);
+ dotGraph.genDotFiles(dir, attributes);
}
+ /**
+ * Returns true for any name if generating graph for non-spec;
+ * otherwise, returns true except "jdk" and name with "jdk.internal." prefix
+ */
boolean accept(String name, ModuleDescriptor descriptor) {
- if (!spec) return true;
-
- if (name.equals("jdk"))
- return false;
-
- if (name.equals("java.se") || name.equals("java.se.ee"))
+ if (!spec)
return true;
- // only the module that has exported API
- return descriptor.exports().stream()
- .filter(e -> !e.isQualified())
- .findAny().isPresent();
+ return !name.equals("jdk") && !name.startsWith("jdk.internal.");
}
-}
\ No newline at end of file
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/src/classes/build/tools/jigsaw/javadoc-graphs.properties Thu Mar 30 19:55:04 2017 +0200
@@ -0,0 +1,2 @@
+arrowcolor=#999999
+requiresMandatedColor=#999999
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/src/classes/build/tools/taglet/ModuleGraph.java Thu Mar 30 19:55:04 2017 +0200
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package build.tools.taglet;
+
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
+import javax.lang.model.element.Element;
+import com.sun.source.doctree.DocTree;
+import jdk.javadoc.doclet.Taglet;
+import static jdk.javadoc.doclet.Taglet.Location.*;
+
+/**
+ * A block tag to optionally insert a reference to a module graph.
+ */
+public class ModuleGraph implements Taglet {
+ private static final boolean enableModuleGraph =
+ Boolean.getBoolean("enableModuleGraph");
+
+ /** Returns the set of locations in which a taglet may be used. */
+ @Override
+ public Set<Location> getAllowedLocations() {
+ return EnumSet.of(MODULE);
+ }
+
+ @Override
+ public boolean isInlineTag() {
+ return false;
+ }
+
+ @Override
+ public String getName() {
+ return "moduleGraph";
+ }
+
+ @Override
+ public String toString(List<? extends DocTree> tags, Element element) {
+ if (!enableModuleGraph) {
+ return "";
+ }
+
+ String moduleName = element.getSimpleName().toString();
+ String imageFile = moduleName + "-graph.png";
+ int thumbnailHeight = -1;
+ String hoverImage = "";
+ if (!moduleName.equals("java.base")) {
+ thumbnailHeight = 100; // also appears in the stylesheet
+ hoverImage = "<span>"
+ + getImage(moduleName, imageFile, -1, true)
+ + "</span>";
+ }
+ return "<dt>"
+ + "<span class=\"simpleTagLabel\">Module Graph:</span>\n"
+ + "</dt>"
+ + "<dd>"
+ + "<a class=moduleGraph href=\"" + imageFile + "\">"
+ + getImage(moduleName, imageFile, thumbnailHeight, false)
+ + hoverImage
+ + "</a>"
+ + "</dd>";
+ }
+
+ private static final String VERTICAL_ALIGN = "vertical-align:top";
+ private static final String BORDER = "border: solid lightgray 1px;";
+
+ private String getImage(String moduleName, String file, int height, boolean useBorder) {
+ return String.format("<img style=\"%s\" alt=\"Module graph for %s\" src=\"%s\"%s>",
+ useBorder ? BORDER + " " + VERTICAL_ALIGN : VERTICAL_ALIGN,
+ moduleName,
+ file,
+ (height <= 0 ? "" : " height=\"" + height + "\""));
+ }
+}
--- a/jdk/src/java.base/share/classes/java/lang/String.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/String.java Thu Mar 30 19:55:04 2017 +0200
@@ -2672,7 +2672,6 @@
* point</a> is passed through uninterpreted.
*
* @return an IntStream of char values from this sequence
- * @since 9
*/
@Override
public IntStream chars() {
@@ -2692,7 +2691,6 @@
* {@code int} values which are then passed to the stream.
*
* @return an IntStream of Unicode code points from this sequence
- * @since 9
*/
@Override
public IntStream codePoints() {
--- a/jdk/src/java.base/share/classes/java/lang/System.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/System.java Thu Mar 30 19:55:04 2017 +0200
@@ -1568,6 +1568,14 @@
* obtained by calling {@link LoggerFinder#getLogger(java.lang.String,
* java.lang.reflect.Module) LoggerFinder.getLogger(name, module)}, where
* {@code module} is the caller's module.
+ * In cases where {@code System.getLogger} is called from a context where
+ * there is no caller frame on the stack (e.g when called directly
+ * from a JNI attached thread), {@code IllegalCallerException} is thrown.
+ * To obtain a logger in such a context, use an auxiliary class that will
+ * implicitly be identified as the caller, or use the system {@link
+ * LoggerFinder#getLoggerFinder() LoggerFinder} to obtain a logger instead.
+ * Note that doing the latter may eagerly initialize the underlying
+ * logging system.
*
* @apiNote
* This method may defer calling the {@link
@@ -1580,6 +1588,8 @@
* @return an instance of {@link Logger} that can be used by the calling
* class.
* @throws NullPointerException if {@code name} is {@code null}.
+ * @throws IllegalCallerException if there is no Java caller frame on the
+ * stack.
*
* @since 9
*/
@@ -1587,6 +1597,9 @@
public static Logger getLogger(String name) {
Objects.requireNonNull(name);
final Class<?> caller = Reflection.getCallerClass();
+ if (caller == null) {
+ throw new IllegalCallerException("no caller frame");
+ }
return LazyLoggers.getLogger(name, caller.getModule());
}
@@ -1600,8 +1613,16 @@
* The returned logger will perform message localization as specified
* by {@link LoggerFinder#getLocalizedLogger(java.lang.String,
* java.util.ResourceBundle, java.lang.reflect.Module)
- * LoggerFinder.getLocalizedLogger(name, bundle, module}, where
+ * LoggerFinder.getLocalizedLogger(name, bundle, module)}, where
* {@code module} is the caller's module.
+ * In cases where {@code System.getLogger} is called from a context where
+ * there is no caller frame on the stack (e.g when called directly
+ * from a JNI attached thread), {@code IllegalCallerException} is thrown.
+ * To obtain a logger in such a context, use an auxiliary class that
+ * will implicitly be identified as the caller, or use the system {@link
+ * LoggerFinder#getLoggerFinder() LoggerFinder} to obtain a logger instead.
+ * Note that doing the latter may eagerly initialize the underlying
+ * logging system.
*
* @apiNote
* This method is intended to be used after the system is fully initialized.
@@ -1620,6 +1641,8 @@
* resource bundle for message localization.
* @throws NullPointerException if {@code name} is {@code null} or
* {@code bundle} is {@code null}.
+ * @throws IllegalCallerException if there is no Java caller frame on the
+ * stack.
*
* @since 9
*/
@@ -1628,6 +1651,9 @@
final ResourceBundle rb = Objects.requireNonNull(bundle);
Objects.requireNonNull(name);
final Class<?> caller = Reflection.getCallerClass();
+ if (caller == null) {
+ throw new IllegalCallerException("no caller frame");
+ }
final SecurityManager sm = System.getSecurityManager();
// We don't use LazyLoggers if a resource bundle is specified.
// Bootstrap sensitive classes in the JDK do not use resource bundles
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Constructor.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Constructor.java Thu Mar 30 19:55:04 2017 +0200
@@ -174,7 +174,6 @@
* @throws SecurityException if the request is denied by the security manager
* or this is a constructor for {@code java.lang.Class}
*
- * @since 9
* @spec JPMS
*/
@Override
--- a/jdk/src/java.base/share/classes/java/nio/MappedByteBuffer.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/nio/MappedByteBuffer.java Thu Mar 30 19:55:04 2017 +0200
@@ -213,7 +213,6 @@
/**
* {@inheritDoc}
- * @since 9
*/
@Override
public final MappedByteBuffer position(int newPosition) {
@@ -223,7 +222,6 @@
/**
* {@inheritDoc}
- * @since 9
*/
@Override
public final MappedByteBuffer limit(int newLimit) {
@@ -233,7 +231,6 @@
/**
* {@inheritDoc}
- * @since 9
*/
@Override
public final MappedByteBuffer mark() {
@@ -243,7 +240,6 @@
/**
* {@inheritDoc}
- * @since 9
*/
@Override
public final MappedByteBuffer reset() {
@@ -253,7 +249,6 @@
/**
* {@inheritDoc}
- * @since 9
*/
@Override
public final MappedByteBuffer clear() {
@@ -263,7 +258,6 @@
/**
* {@inheritDoc}
- * @since 9
*/
@Override
public final MappedByteBuffer flip() {
@@ -273,7 +267,6 @@
/**
* {@inheritDoc}
- * @since 9
*/
@Override
public final MappedByteBuffer rewind() {
--- a/jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template Thu Mar 30 19:55:04 2017 +0200
@@ -1069,7 +1069,6 @@
/**
* {@inheritDoc}
- * @since 9
*/
@Override
public
@@ -1083,7 +1082,6 @@
/**
* {@inheritDoc}
- * @since 9
*/
@Override
public
@@ -1097,7 +1095,6 @@
/**
* {@inheritDoc}
- * @since 9
*/
@Override
public
@@ -1111,7 +1108,6 @@
/**
* {@inheritDoc}
- * @since 9
*/
@Override
public
@@ -1125,7 +1121,6 @@
/**
* {@inheritDoc}
- * @since 9
*/
@Override
public
@@ -1139,7 +1134,6 @@
/**
* {@inheritDoc}
- * @since 9
*/
@Override
public
@@ -1153,7 +1147,6 @@
/**
* {@inheritDoc}
- * @since 9
*/
@Override
public
--- a/jdk/src/java.base/share/classes/java/security/SecureRandom.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/security/SecureRandom.java Thu Mar 30 19:55:04 2017 +0200
@@ -651,8 +651,6 @@
* {@code SecureRandom}.
*
* @return the string representation
- *
- * @since 9
*/
@Override
public String toString() {
--- a/jdk/src/java.base/share/classes/java/security/SecureRandomSpi.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/security/SecureRandomSpi.java Thu Mar 30 19:55:04 2017 +0200
@@ -211,8 +211,6 @@
* {@code SecureRandom}.
*
* @return the string representation
- *
- * @since 9
*/
@Override
public String toString() {
--- a/jdk/src/java.base/share/classes/java/time/chrono/Era.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/time/chrono/Era.java Thu Mar 30 19:55:04 2017 +0200
@@ -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
@@ -310,8 +310,8 @@
* The parameters control the style of the returned text and the locale.
* <p>
* If no textual mapping is found then the {@link #getValue() numeric value} is returned.
- * <p>
- * This default implementation is suitable for all implementations.
+ *
+ * @apiNote This default implementation is suitable for most implementations.
*
* @param style the style of the text required, not null
* @param locale the locale to use, not null
--- a/jdk/src/java.base/share/classes/java/time/chrono/JapaneseEra.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/time/chrono/JapaneseEra.java Thu Mar 30 19:55:04 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, 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
@@ -240,19 +240,10 @@
}
/**
- * Gets the textual representation of this era.
- * <p>
- * This returns the textual name used to identify the era,
- * suitable for presentation to the user.
- * The parameters control the style of the returned text and the locale.
- * <p>
- * If no textual mapping is found then the {@link #getValue() numeric value}
- * is returned.
+ * {@inheritDoc}
*
- * @param style the style of the text required, not null
- * @param locale the locale to use, not null
- * @return the text value of the era, not null
- * @since 9
+ * @param style {@inheritDoc}
+ * @param locale {@inheritDoc}
*/
@Override
public String getDisplayName(TextStyle style, Locale locale) {
--- a/jdk/src/java.base/share/classes/java/util/jar/Pack200.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/util/jar/Pack200.java Thu Mar 30 19:55:04 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, 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
@@ -452,13 +452,13 @@
String CODE_ATTRIBUTE_PFX = "pack.code.attribute.";
/**
- * The unpacker's progress as a percentage, as periodically
- * updated by the unpacker.
+ * The packer's progress as a percentage, as periodically
+ * updated by the packer.
* Values of 0 - 100 are normal, and -1 indicates a stall.
* Progress can be monitored by polling the value of this
* property.
* <p>
- * At a minimum, the unpacker must set progress to 0
+ * At a minimum, the packer must set progress to 0
* at the beginning of a packing operation, and to 100
* at the end.
*/
@@ -623,7 +623,7 @@
* property.
* <p>
* At a minimum, the unpacker must set progress to 0
- * at the beginning of a packing operation, and to 100
+ * at the beginning of an unpacking operation, and to 100
* at the end.
*/
String PROGRESS = "unpack.progress";
@@ -631,7 +631,7 @@
/**
* Get the set of this engine's properties. This set is
* a "live view", so that changing its
- * contents immediately affects the Packer engine, and
+ * contents immediately affects the Unpacker engine, and
* changes from the engine (such as progress indications)
* are immediately visible in the map.
*
--- a/jdk/src/java.base/share/classes/jdk/internal/module/IllegalAccessLogger.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/IllegalAccessLogger.java Thu Mar 30 19:55:04 2017 +0200
@@ -25,6 +25,7 @@
package jdk.internal.module;
+import java.io.PrintStream;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Module;
import java.net.URL;
@@ -42,6 +43,9 @@
import java.util.function.Supplier;
import java.util.stream.Collectors;
+import jdk.internal.loader.BootLoader;
+import sun.security.action.GetPropertyAction;
+
/**
* Supports logging of access to members of API packages that are exported or
* opened via backdoor mechanisms to code in unnamed modules.
@@ -49,16 +53,25 @@
public final class IllegalAccessLogger {
- // true to print stack trace
- private static final boolean PRINT_STACK_TRACE;
- static {
- String s = System.getProperty("sun.reflect.debugModuleAccessChecks");
- PRINT_STACK_TRACE = "access".equals(s);
+ /**
+ * Holder class to lazily create the StackWalker object and determine
+ * if the stack trace should be printed
+ */
+ static class Holder {
+ static final StackWalker STACK_WALKER;
+ static final boolean PRINT_STACK_TRACE;
+
+ static {
+ PrivilegedAction<StackWalker> pa = () ->
+ StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
+ STACK_WALKER = AccessController.doPrivileged(pa);
+
+ String name = "sun.reflect.debugModuleAccessChecks";
+ String value = GetPropertyAction.privilegedGetProperty(name, null);
+ PRINT_STACK_TRACE = "access" .equals(value);
+ }
}
- private static final StackWalker STACK_WALKER
- = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
-
// the maximum number of frames to capture
private static final int MAX_STACK_FRAMES = 32;
@@ -72,10 +85,15 @@
private final Map<Module, Map<String, String>> exported;
private final Map<Module, Map<String, String>> opened;
+ // the print stream to send the warnings
+ private final PrintStream warningStream;
+
private IllegalAccessLogger(Map<Module, Map<String, String>> exported,
- Map<Module, Map<String, String>> opened) {
+ Map<Module, Map<String, String>> opened,
+ PrintStream warningStream) {
this.exported = deepCopy(exported);
this.opened = deepCopy(opened);
+ this.warningStream = warningStream;
}
/**
@@ -168,7 +186,7 @@
*/
private void log(Class<?> caller, String what, Supplier<String> msgSupplier) {
// stack trace without the top-most frames in java.base
- List<StackWalker.StackFrame> stack = STACK_WALKER.walk(s ->
+ List<StackWalker.StackFrame> stack = Holder.STACK_WALKER.walk(s ->
s.dropWhile(this::isJavaBase)
.limit(MAX_STACK_FRAMES)
.collect(Collectors.toList())
@@ -184,13 +202,13 @@
// log message if first usage
if (firstUsage) {
String msg = msgSupplier.get();
- if (PRINT_STACK_TRACE) {
+ if (Holder.PRINT_STACK_TRACE) {
synchronized (OUTPUT_LOCK) {
- System.err.println(msg);
- stack.forEach(f -> System.err.println("\tat " + f));
+ warningStream.println(msg);
+ stack.forEach(f -> warningStream.println("\tat " + f));
}
} else {
- System.err.println(msg);
+ warningStream.println(msg);
}
}
}
@@ -265,8 +283,10 @@
* A builder for IllegalAccessLogger objects.
*/
public static class Builder {
+ private final Module UNNAMED = BootLoader.getUnnamedModule();
private Map<Module, Map<String, String>> exported;
private Map<Module, Map<String, String>> opened;
+ private PrintStream warningStream = System.err;
public Builder() { }
@@ -276,30 +296,37 @@
this.opened = deepCopy(opened);
}
- public void logAccessToExportedPackage(Module m, String pn, String how) {
- if (!m.isExported(pn)) {
+ public Builder logAccessToExportedPackage(Module m, String pn, String how) {
+ if (!m.isExported(pn, UNNAMED)) {
if (exported == null)
exported = new HashMap<>();
exported.computeIfAbsent(m, k -> new HashMap<>()).putIfAbsent(pn, how);
}
+ return this;
}
- public void logAccessToOpenPackage(Module m, String pn, String how) {
+ public Builder logAccessToOpenPackage(Module m, String pn, String how) {
// opens implies exported at run-time.
logAccessToExportedPackage(m, pn, how);
- if (!m.isOpen(pn)) {
+ if (!m.isOpen(pn, UNNAMED)) {
if (opened == null)
opened = new HashMap<>();
opened.computeIfAbsent(m, k -> new HashMap<>()).putIfAbsent(pn, how);
}
+ return this;
+ }
+
+ public Builder warningStream(PrintStream warningStream) {
+ this.warningStream = Objects.requireNonNull(warningStream);
+ return this;
}
/**
* Builds the logger.
*/
public IllegalAccessLogger build() {
- return new IllegalAccessLogger(exported, opened);
+ return new IllegalAccessLogger(exported, opened, warningStream);
}
}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java Thu Mar 30 19:55:04 2017 +0200
@@ -515,44 +515,42 @@
* additional packages specified on the command-line.
*/
private static void addExtraExportsAndOpens(Layer bootLayer) {
- IllegalAccessLogger.Builder builder = new IllegalAccessLogger.Builder();
-
// --add-exports
String prefix = "jdk.module.addexports.";
Map<String, List<String>> extraExports = decode(prefix);
if (!extraExports.isEmpty()) {
- addExtraExportsOrOpens(bootLayer, extraExports, false, builder);
+ addExtraExportsOrOpens(bootLayer, extraExports, false);
}
// --add-opens
prefix = "jdk.module.addopens.";
Map<String, List<String>> extraOpens = decode(prefix);
if (!extraOpens.isEmpty()) {
- addExtraExportsOrOpens(bootLayer, extraOpens, true, builder);
+ addExtraExportsOrOpens(bootLayer, extraOpens, true);
}
// --permit-illegal-access
if (getAndRemoveProperty("jdk.module.permitIllegalAccess") != null) {
warn("--permit-illegal-access will be removed in the next major release");
+ IllegalAccessLogger.Builder builder = new IllegalAccessLogger.Builder();
+ Module unnamed = BootLoader.getUnnamedModule();
bootLayer.modules().stream().forEach(m -> {
m.getDescriptor()
.packages()
.stream()
- .filter(pn -> !m.isOpen(pn))
+ .filter(pn -> !m.isOpen(pn, unnamed)) // skip if opened by --add-opens
.forEach(pn -> {
builder.logAccessToOpenPackage(m, pn, "--permit-illegal-access");
Modules.addOpensToAllUnnamed(m, pn);
});
});
+ IllegalAccessLogger.setIllegalAccessLogger(builder.build());
}
-
- IllegalAccessLogger.setIllegalAccessLogger(builder.build());
}
private static void addExtraExportsOrOpens(Layer bootLayer,
Map<String, List<String>> map,
- boolean opens,
- IllegalAccessLogger.Builder builder)
+ boolean opens)
{
String option = opens ? ADD_OPENS : ADD_EXPORTS;
for (Map.Entry<String, List<String>> e : map.entrySet()) {
@@ -600,10 +598,8 @@
}
if (allUnnamed) {
if (opens) {
- builder.logAccessToOpenPackage(m, pn, option);
Modules.addOpensToAllUnnamed(m, pn);
} else {
- builder.logAccessToExportedPackage(m, pn, option);
Modules.addExportsToAllUnnamed(m, pn);
}
} else {
--- a/jdk/src/java.base/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.base/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -26,6 +26,7 @@
/**
* Defines the foundational APIs of the Java SE Platform.
*
+ * @moduleGraph
* @since 9
*/
module java.base {
--- a/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java Thu Mar 30 19:55:04 2017 +0200
@@ -85,7 +85,6 @@
import java.util.stream.Stream;
import jdk.internal.misc.VM;
-import jdk.internal.module.IllegalAccessLogger;
import jdk.internal.module.Modules;
@@ -429,20 +428,14 @@
abort(null, "java.launcher.jar.error3", jarname);
}
- // Add-Exports and Add-Opens to allow illegal access
+ // Add-Exports and Add-Opens
String exports = mainAttrs.getValue(ADD_EXPORTS);
if (exports != null) {
- String warn = getLocalizedMessage("java.launcher.permitaccess.warning",
- jarname, ADD_EXPORTS);
- System.err.println(warn);
- addExportsOrOpens(exports, false, ADD_EXPORTS);
+ addExportsOrOpens(exports, false);
}
String opens = mainAttrs.getValue(ADD_OPENS);
if (opens != null) {
- String warn = getLocalizedMessage("java.launcher.permitaccess.warning",
- jarname, ADD_OPENS);
- System.err.println(warn);
- addExportsOrOpens(opens, true, ADD_OPENS);
+ addExportsOrOpens(opens, true);
}
/*
@@ -467,15 +460,7 @@
* Process the Add-Exports or Add-Opens value. The value is
* {@code <module>/<package> ( <module>/<package>)*}.
*/
- static void addExportsOrOpens(String value, boolean open, String how) {
- IllegalAccessLogger.Builder builder;
- IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger();
- if (logger == null) {
- builder = new IllegalAccessLogger.Builder();
- } else {
- builder = logger.toBuilder();
- }
-
+ static void addExportsOrOpens(String value, boolean open) {
for (String moduleAndPackage : value.split(" ")) {
String[] s = moduleAndPackage.trim().split("/");
if (s.length == 2) {
@@ -485,18 +470,14 @@
Layer.boot().findModule(mn).ifPresent(m -> {
if (m.getDescriptor().packages().contains(pn)) {
if (open) {
- builder.logAccessToOpenPackage(m, pn, how);
Modules.addOpensToAllUnnamed(m, pn);
} else {
- builder.logAccessToExportedPackage(m, pn, how);
Modules.addExportsToAllUnnamed(m, pn);
}
}
});
}
}
-
- IllegalAccessLogger.setIllegalAccessLogger(builder.build());
}
// From src/share/bin/java.c:
--- a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties Thu Mar 30 19:55:04 2017 +0200
@@ -211,6 +211,4 @@
java.launcher.module.error3=\
Error: Unable to load main class {0} from module {1}\n\
\t{2}
-java.launcher.permitaccess.warning=\
- WARNING: Main manifest of {0} contains {1} attribute to permit illegal access
--- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java Thu Mar 30 19:55:04 2017 +0200
@@ -1025,6 +1025,13 @@
cf = CertificateFactory.getInstance("X509");
}
+ // -trustcacerts can only be specified on -importcert.
+ // Reset it so that warnings on CA cert will remain for
+ // -printcert, etc.
+ if (command != IMPORTCERT) {
+ trustcacerts = false;
+ }
+
if (trustcacerts) {
caks = KeyStoreUtil.getCacertsKeyStore();
}
@@ -1758,9 +1765,8 @@
if (keyPass == null) {
keyPass = promptForKeyPass(alias, null, storePass);
}
+ checkWeak(rb.getString("the.generated.certificate"), chain[0]);
keyStore.setKeyEntry(alias, privKey, keyPass, chain);
-
- checkWeak(rb.getString("the.generated.certificate"), chain[0]);
}
/**
@@ -2118,6 +2124,10 @@
}
try {
+ Certificate c = srckeystore.getCertificate(alias);
+ if (c != null) {
+ checkWeak("<" + newAlias + ">", c);
+ }
keyStore.setEntry(newAlias, entry, pp);
// Place the check so that only successful imports are blocked.
// For example, we don't block a failed SecretEntry import.
@@ -2127,10 +2137,6 @@
"The.destination.pkcs12.keystore.has.different.storepass.and.keypass.Please.retry.with.destkeypass.specified."));
}
}
- Certificate c = srckeystore.getCertificate(alias);
- if (c != null) {
- checkWeak("<" + newAlias + ">", c);
- }
return 1;
} catch (KeyStoreException kse) {
Object[] source2 = {alias, kse.toString()};
@@ -2814,8 +2820,8 @@
}
if (noprompt) {
+ checkWeak(rb.getString("the.input"), cert);
keyStore.setCertificateEntry(alias, cert);
- checkWeak(rb.getString("the.input"), cert);
return true;
}
@@ -3049,6 +3055,11 @@
MessageFormat form = new MessageFormat
(rb.getString(".PATTERN.printX509Cert.with.weak"));
PublicKey pkey = cert.getPublicKey();
+ String sigName = cert.getSigAlgName();
+ // No need to warn about sigalg of a trust anchor
+ if (!isTrustedCert(cert)) {
+ sigName = withWeak(sigName);
+ }
Object[] source = {cert.getSubjectDN().toString(),
cert.getIssuerDN().toString(),
cert.getSerialNumber().toString(16),
@@ -3056,7 +3067,7 @@
cert.getNotAfter().toString(),
getCertFingerPrint("SHA-1", cert),
getCertFingerPrint("SHA-256", cert),
- withWeak(cert.getSigAlgName()),
+ sigName,
withWeak(pkey),
cert.getVersion()
};
@@ -3111,7 +3122,7 @@
* or null otherwise. A label is added.
*/
private static Pair<String,Certificate>
- getTrustedSigner(Certificate cert, KeyStore ks) throws Exception {
+ getSigner(Certificate cert, KeyStore ks) throws Exception {
if (ks.getCertificateAlias(cert) != null) {
return new Pair<>("", cert);
}
@@ -3467,9 +3478,9 @@
// do we trust the cert at the top?
Certificate topCert = replyCerts[replyCerts.length-1];
boolean fromKeyStore = true;
- Pair<String,Certificate> root = getTrustedSigner(topCert, keyStore);
+ Pair<String,Certificate> root = getSigner(topCert, keyStore);
if (root == null && trustcacerts && caks != null) {
- root = getTrustedSigner(topCert, caks);
+ root = getSigner(topCert, caks);
fromKeyStore = false;
}
if (root == null) {
@@ -4301,9 +4312,19 @@
return result;
}
+ private boolean isTrustedCert(Certificate cert) throws KeyStoreException {
+ if (caks != null && caks.getCertificateAlias(cert) != null) {
+ return true;
+ } else {
+ String inKS = keyStore.getCertificateAlias(cert);
+ return inKS != null && keyStore.isCertificateEntry(inKS);
+ }
+ }
+
private void checkWeak(String label, String sigAlg, Key key) {
- if (!DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, sigAlg, null)) {
+ if (sigAlg != null && !DISABLED_CHECK.permits(
+ SIG_PRIMITIVE_SET, sigAlg, null)) {
weakWarnings.add(String.format(
rb.getString("whose.sigalg.risk"), label, sigAlg));
}
@@ -4316,7 +4337,8 @@
}
}
- private void checkWeak(String label, Certificate[] certs) {
+ private void checkWeak(String label, Certificate[] certs)
+ throws KeyStoreException {
for (int i = 0; i < certs.length; i++) {
Certificate cert = certs[i];
if (cert instanceof X509Certificate) {
@@ -4325,15 +4347,18 @@
if (certs.length > 1) {
fullLabel = oneInMany(label, i, certs.length);
}
- checkWeak(fullLabel, xc.getSigAlgName(), xc.getPublicKey());
+ checkWeak(fullLabel, xc);
}
}
}
- private void checkWeak(String label, Certificate cert) {
+ private void checkWeak(String label, Certificate cert)
+ throws KeyStoreException {
if (cert instanceof X509Certificate) {
X509Certificate xc = (X509Certificate)cert;
- checkWeak(label, xc.getSigAlgName(), xc.getPublicKey());
+ // No need to check the sigalg of a trust anchor
+ String sigAlg = isTrustedCert(cert) ? null : xc.getSigAlgName();
+ checkWeak(label, sigAlg, xc.getPublicKey());
}
}
--- a/jdk/src/java.datatransfer/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.datatransfer/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -24,8 +24,9 @@
*/
/**
- * Defines an API for transferring data between and within applications.
+ * Defines the API for transferring data between and within applications.
*
+ * @moduleGraph
* @since 9
*/
module java.datatransfer {
--- a/jdk/src/java.desktop/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -27,6 +27,7 @@
* Defines the AWT and Swing user interface toolkits, plus APIs for
* accessibility, audio, imaging, printing, and JavaBeans.
*
+ * @moduleGraph
* @since 9
*/
module java.desktop {
--- a/jdk/src/java.instrument/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.instrument/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -27,6 +27,7 @@
* Defines services that allow agents to
* instrument programs running on the JVM.
*
+ * @moduleGraph
* @since 9
*/
module java.instrument {
--- a/jdk/src/java.logging/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.logging/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -26,6 +26,7 @@
/**
* Defines the Java Logging API.
*
+ * @moduleGraph
* @since 9
*/
module java.logging {
--- a/jdk/src/java.management.rmi/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.management.rmi/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -46,6 +46,7 @@
* and load the appropriate {@code JMXConnectorServerProvider} service
* implementation for the given protocol.
*
+ * @moduleGraph
* @since 9
*/
module java.management.rmi {
--- a/jdk/src/java.management/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.management/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -29,6 +29,7 @@
* The JMX API consists of interfaces for monitoring and management of the
* JVM and other components in the Java runtime.
*
+ * @moduleGraph
* @since 9
*/
module java.management {
--- a/jdk/src/java.naming/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.naming/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -26,6 +26,7 @@
/**
* Defines the Java Naming and Directory Interface (JNDI) API.
*
+ * @moduleGraph
* @since 9
*/
module java.naming {
--- a/jdk/src/java.prefs/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.prefs/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -26,6 +26,7 @@
/**
* Defines the Preferences API.
*
+ * @moduleGraph
* @since 9
*/
module java.prefs {
--- a/jdk/src/java.rmi/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.rmi/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -26,6 +26,7 @@
/**
* Defines the Remote Method Invocation (RMI) API.
*
+ * @moduleGraph
* @since 9
*/
module java.rmi {
--- a/jdk/src/java.scripting/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.scripting/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -26,6 +26,7 @@
/**
* Defines the Scripting API.
*
+ * @moduleGraph
* @since 9
*/
module java.scripting {
--- a/jdk/src/java.se.ee/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.se.ee/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -29,6 +29,7 @@
* This module requires {@code java.se} and supplements it with modules
* that define CORBA and Java EE APIs. These modules are upgradeable.
*
+ * @moduleGraph
* @since 9
*/
@SuppressWarnings("deprecation")
--- a/jdk/src/java.se/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.se/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -29,6 +29,7 @@
* The modules defining CORBA and Java EE APIs are not required by
* this module, but they are required by {@code java.se.ee}.
*
+ * @moduleGraph
* @since 9
*/
module java.se {
--- a/jdk/src/java.security.jgss/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.security.jgss/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -28,6 +28,7 @@
* <P>
* This module also contains GSS-API mechanisms including Kerberos v5 and SPNEGO.
*
+ * @moduleGraph
* @since 9
*/
module java.security.jgss {
--- a/jdk/src/java.security.sasl/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.security.sasl/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -30,6 +30,7 @@
* This module also contains SASL mechanisms including DIGEST-MD5,
* CRAM-MD5, and NTLM.
*
+ * @moduleGraph
* @since 9
*/
module java.security.sasl {
--- a/jdk/src/java.smartcardio/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.smartcardio/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -26,6 +26,7 @@
/**
* Defines the Java Smart Card I/O API.
*
+ * @moduleGraph
* @since 9
*/
module java.smartcardio {
--- a/jdk/src/java.sql.rowset/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.sql.rowset/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -26,6 +26,7 @@
/**
* Defines the JDBC RowSet API.
*
+ * @moduleGraph
* @since 9
*/
module java.sql.rowset {
--- a/jdk/src/java.sql/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.sql/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -26,6 +26,7 @@
/**
* Defines the JDBC API.
*
+ * @moduleGraph
* @since 9
*/
module java.sql {
--- a/jdk/src/java.transaction/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.transaction/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -29,6 +29,7 @@
* The subset consists of RMI exception types which are mapped to CORBA system
* exceptions by the 'Java Language to IDL Mapping Specification'.
*
+ * @moduleGraph
* @since 9
*/
@Deprecated(since="9", forRemoval=true)
--- a/jdk/src/java.xml.crypto/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/java.xml.crypto/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -24,8 +24,9 @@
*/
/**
- * Defines an API for XML cryptography.
+ * Defines the API for XML cryptography.
*
+ * @moduleGraph
* @since 9
*/
module java.xml.crypto {
--- a/jdk/src/jdk.attach/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.attach/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -26,6 +26,7 @@
/**
* Defines the attach API.
*
+ * @moduleGraph
* @since 9
*/
module jdk.attach {
--- a/jdk/src/jdk.charsets/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.charsets/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -23,6 +23,13 @@
* questions.
*/
+/**
+ * {@link java.nio.charset.Charset Charset} provider for the charsets that
+ * are not in {@code java.base} (mostly double byte and IBM charsets).
+ *
+ * @moduleGraph
+ * @since 9
+ */
module jdk.charsets {
provides java.nio.charset.spi.CharsetProvider
with sun.nio.cs.ext.ExtendedCharsets;
--- a/jdk/src/jdk.crypto.cryptoki/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.crypto.cryptoki/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -26,6 +26,7 @@
/**
* The SunPKCS11 security provider.
*
+ * @moduleGraph
* @since 9
*/
module jdk.crypto.cryptoki {
--- a/jdk/src/jdk.crypto.ec/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.crypto.ec/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -26,6 +26,7 @@
/**
* The SunEC security provider.
*
+ * @moduleGraph
* @since 9
*/
module jdk.crypto.ec {
--- a/jdk/src/jdk.crypto.mscapi/windows/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.crypto.mscapi/windows/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -26,6 +26,7 @@
/**
* The SunMSCAPI security provider.
*
+ * @moduleGraph
* @since 9
*/
module jdk.crypto.mscapi {
--- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -26,6 +26,7 @@
/**
* The OracleUCrypto security provider.
*
+ * @moduleGraph
* @since 9
*/
module jdk.crypto.ucrypto {
--- a/jdk/src/jdk.httpserver/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.httpserver/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -23,6 +23,12 @@
* questions.
*/
+/**
+ * Defines the JDK-specific API for HTTP server.
+ *
+ * @moduleGraph
+ * @since 9
+ */
module jdk.httpserver {
exports com.sun.net.httpserver;
--- a/jdk/src/jdk.jartool/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.jartool/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -23,6 +23,13 @@
* questions.
*/
+/**
+ * Defines tools for manipulating Java Archive (JAR) files,
+ * including the jar and jarsigner tools.
+ *
+ * @moduleGraph
+ * @since 9
+ */
module jdk.jartool {
exports com.sun.jarsigner;
exports jdk.security.jarsigner;
--- a/jdk/src/jdk.jcmd/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.jcmd/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -23,6 +23,13 @@
* questions.
*/
+/**
+ * Defines tools for diagnostics and troubleshooting a JVM,
+ * including the jcmd, jps, jstat and other diagnostics tools.
+ *
+ * @moduleGraph
+ * @since 9
+ */
module jdk.jcmd {
requires jdk.attach;
requires jdk.internal.jvmstat;
--- a/jdk/src/jdk.jconsole/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.jconsole/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -23,6 +23,13 @@
* questions.
*/
+/**
+ * Defines the JMX graphical tool, jconsole, for monitoring and managing
+ * a running application.
+ *
+ * @moduleGraph
+ * @since 9
+ */
module jdk.jconsole {
requires transitive java.desktop;
requires transitive java.management;
--- a/jdk/src/jdk.jdi/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.jdi/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -26,6 +26,7 @@
/**
* Defines the Java Debugger Interface.
*
+ * @moduleGraph
* @since 9
*/
module jdk.jdi {
--- a/jdk/src/jdk.jdwp.agent/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.jdwp.agent/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -26,6 +26,7 @@
/**
* Java Debug Wire Protocol.
*
+ * @moduleGraph
* @since 9
*/
module jdk.jdwp.agent {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java Thu Mar 30 19:55:04 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, 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
@@ -35,8 +35,12 @@
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
+import java.util.Locale;
import java.util.MissingResourceException;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
import jdk.internal.jimage.BasicImageReader;
import jdk.internal.jimage.ImageHeader;
import jdk.internal.jimage.ImageLocation;
@@ -99,7 +103,7 @@
}
static class OptionsValues {
- Task task = Task.LIST;
+ Task task = null;
String directory = ".";
String include = "";
boolean fullVersion;
@@ -172,24 +176,31 @@
}
try {
- List<String> unhandled = OPTION_HELPER.handleOptions(this, args);
+ String command;
+ String[] remaining = args;
+ try {
+ command = args[0];
+ options.task = Enum.valueOf(Task.class, args[0].toUpperCase(Locale.ENGLISH));
+ remaining = args.length > 1 ? Arrays.copyOfRange(args, 1, args.length)
+ : new String[0];
+ } catch (IllegalArgumentException ex) {
+ command = null;
+ options.task = null;
+ }
- if(!unhandled.isEmpty()) {
- try {
- options.task = Enum.valueOf(Task.class, unhandled.get(0).toUpperCase());
- } catch (IllegalArgumentException ex) {
- throw TASK_HELPER.newBadArgs("err.not.a.task", unhandled.get(0));
- }
+ // process arguments
+ List<String> unhandled = OPTION_HELPER.handleOptions(this, remaining);
+ for (String f : unhandled) {
+ options.jimages.add(new File(f));
+ }
- for(int i = 1; i < unhandled.size(); i++) {
- options.jimages.add(new File(unhandled.get(i)));
- }
- } else if (!options.help && !options.version && !options.fullVersion) {
- throw TASK_HELPER.newBadArgs("err.invalid.task", "<unspecified>");
+ if (options.task == null && !options.help && !options.version && !options.fullVersion) {
+ throw TASK_HELPER.newBadArgs("err.not.a.task",
+ command != null ? command : "<unspecified>");
}
if (options.help) {
- if (unhandled.isEmpty()) {
+ if (options.task == null) {
log.println(TASK_HELPER.getMessage("main.usage", PROGNAME));
Arrays.asList(RECOGNIZED_OPTIONS).stream()
.filter(option -> !option.isHidden())
@@ -203,15 +214,19 @@
log.println(TASK_HELPER.getMessage("main.usage." +
options.task.toString().toLowerCase()));
} catch (MissingResourceException ex) {
- throw TASK_HELPER.newBadArgs("err.not.a.task", unhandled.get(0));
+ throw TASK_HELPER.newBadArgs("err.not.a.task", command);
}
}
return EXIT_OK;
}
if (options.version || options.fullVersion) {
+ if (options.task == null && !unhandled.isEmpty()) {
+ throw TASK_HELPER.newBadArgs("err.not.a.task",
+ Stream.of(args).collect(Collectors.joining(" ")));
+ }
+
TASK_HELPER.showVersion(options.fullVersion);
-
if (unhandled.isEmpty()) {
return EXIT_OK;
}
@@ -435,7 +450,7 @@
iterate(this::listTitle, null, this::verify);
break;
default:
- throw TASK_HELPER.newBadArgs("err.invalid.task",
+ throw TASK_HELPER.newBadArgs("err.not.a.task",
options.task.name()).showUsage(true);
}
return true;
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java Thu Mar 30 19:55:04 2017 +0200
@@ -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
@@ -24,6 +24,8 @@
*/
package jdk.tools.jlink.internal;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleFinder;
import java.lang.reflect.Layer;
import java.nio.ByteOrder;
import java.nio.file.Path;
@@ -33,6 +35,8 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+
+import jdk.internal.module.ModulePath;
import jdk.tools.jlink.plugin.Plugin;
import jdk.tools.jlink.plugin.PluginException;
import jdk.tools.jlink.builder.ImageBuilder;
@@ -147,8 +151,8 @@
private final Path output;
private final Set<String> modules;
private final Set<String> limitmods;
-
private final ByteOrder endian;
+ private final ModuleFinder finder;
/**
* jlink configuration,
@@ -160,31 +164,23 @@
* @param endian Jimage byte order. Native order by default
*/
public JlinkConfiguration(Path output,
- List<Path> modulepaths,
- Set<String> modules,
- Set<String> limitmods,
- ByteOrder endian) {
- this.output = output;
- this.modulepaths = modulepaths == null ? Collections.emptyList() : modulepaths;
- this.modules = modules == null ? Collections.emptySet() : modules;
- this.limitmods = limitmods == null ? Collections.emptySet() : limitmods;
- this.endian = endian == null ? ByteOrder.nativeOrder() : endian;
- }
+ List<Path> modulepaths,
+ Set<String> modules,
+ Set<String> limitmods,
+ ByteOrder endian) {
+ if (Objects.requireNonNull(modulepaths).isEmpty()) {
+ throw new IllegalArgumentException("Empty module path");
+ }
+ if (Objects.requireNonNull(modules).isEmpty()) {
+ throw new IllegalArgumentException("Empty modules");
+ }
- /**
- * jlink configuration,
- *
- * @param output Output directory, must not exist.
- * @param modulepaths Modules paths
- * @param modules Root modules to resolve
- * @param limitmods Limit the universe of observable modules
- */
- public JlinkConfiguration(Path output,
- List<Path> modulepaths,
- Set<String> modules,
- Set<String> limitmods) {
- this(output, modulepaths, modules, limitmods,
- ByteOrder.nativeOrder());
+ this.output = output;
+ this.modulepaths = modulepaths;
+ this.modules = modules;
+ this.limitmods = Objects.requireNonNull(limitmods);
+ this.endian = Objects.requireNonNull(endian);
+ this.finder = moduleFinder();
}
/**
@@ -222,6 +218,45 @@
return limitmods;
}
+ /**
+ * Returns {@link ModuleFinder} that finds all observable modules
+ * for this jlink configuration.
+ */
+ public ModuleFinder finder() {
+ return finder;
+ }
+
+ /**
+ * Returns a {@link Configuration} of the given module path,
+ * root modules with full service binding.
+ */
+ public Configuration resolveAndBind()
+ {
+ return Configuration.empty().resolveAndBind(finder,
+ ModuleFinder.of(),
+ modules);
+ }
+
+ /**
+ * Returns a {@link Configuration} of the given module path,
+ * root modules with no service binding.
+ */
+ public Configuration resolve()
+ {
+ return Configuration.empty().resolve(finder,
+ ModuleFinder.of(),
+ modules);
+ }
+
+ private ModuleFinder moduleFinder() {
+ Path[] entries = modulepaths.toArray(new Path[0]);
+ ModuleFinder finder = ModulePath.of(Runtime.version(), true, entries);
+ if (!limitmods.isEmpty()) {
+ finder = JlinkTask.limitFinder(finder, limitmods, modules);
+ }
+ return finder;
+ }
+
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java Thu Mar 30 19:55:04 2017 +0200
@@ -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
@@ -110,6 +110,12 @@
Path path = Paths.get(arg);
task.options.output = path;
}, "--output"),
+ new Option<JlinkTask>(false, (task, opt, arg) -> {
+ task.options.bindServices = true;
+ }, "--bind-services"),
+ new Option<JlinkTask>(false, (task, opt, arg) -> {
+ task.options.suggestProviders = true;
+ }, "--suggest-providers", "", true),
new Option<JlinkTask>(true, (task, opt, arg) -> {
String[] values = arg.split("=");
// check values
@@ -141,6 +147,9 @@
}
}, "--endian"),
new Option<JlinkTask>(false, (task, opt, arg) -> {
+ task.options.verbose = true;
+ }, "--verbose", "-v"),
+ new Option<JlinkTask>(false, (task, opt, arg) -> {
task.options.version = true;
}, "--version"),
new Option<JlinkTask>(true, (task, opt, arg) -> {
@@ -185,6 +194,7 @@
static class OptionsValues {
boolean help;
String saveoptsfile;
+ boolean verbose;
boolean version;
boolean fullVersion;
final List<Path> modulePath = new ArrayList<>();
@@ -195,6 +205,8 @@
Path packagedModulesPath;
ByteOrder endian = ByteOrder.nativeOrder();
boolean ignoreSigning = false;
+ boolean bindServices = false;
+ boolean suggestProviders = false;
}
int run(String[] args) {
@@ -203,7 +215,11 @@
new PrintWriter(System.err, true));
}
try {
- optionsHelper.handleOptionsNoUnhandled(this, args);
+ List<String> remaining = optionsHelper.handleOptions(this, args);
+ if (remaining.size() > 0 && !options.suggestProviders) {
+ throw taskHelper.newBadArgs("err.orphan.arguments", toString(remaining))
+ .showUsage(true);
+ }
if (options.help) {
optionsHelper.showHelp(PROGNAME);
return EXIT_OK;
@@ -217,17 +233,24 @@
return EXIT_OK;
}
- if (taskHelper.getExistingImage() == null) {
- if (options.modulePath.isEmpty()) {
- throw taskHelper.newBadArgs("err.modulepath.must.be.specified").showUsage(true);
- }
- createImage();
- } else {
+ if (taskHelper.getExistingImage() != null) {
postProcessOnly(taskHelper.getExistingImage());
+ return EXIT_OK;
}
- if (options.saveoptsfile != null) {
- Files.write(Paths.get(options.saveoptsfile), getSaveOpts().getBytes());
+ if (options.modulePath.isEmpty()) {
+ throw taskHelper.newBadArgs("err.modulepath.must.be.specified")
+ .showUsage(true);
+ }
+
+ JlinkConfiguration config = initJlinkConfig();
+ if (options.suggestProviders) {
+ suggestProviders(config, remaining);
+ } else {
+ createImage(config);
+ if (options.saveoptsfile != null) {
+ Files.write(Paths.get(options.saveoptsfile), getSaveOpts().getBytes());
+ }
}
return EXIT_OK;
@@ -266,25 +289,13 @@
Objects.requireNonNull(config.getOutput());
plugins = plugins == null ? new PluginsConfiguration() : plugins;
- if (config.getModulepaths().isEmpty()) {
- throw new IllegalArgumentException("Empty module paths");
- }
-
- ModuleFinder finder = newModuleFinder(config.getModulepaths(),
- config.getLimitmods(),
- config.getModules());
-
- if (config.getModules().isEmpty()) {
- throw new IllegalArgumentException("No modules to add");
- }
-
// First create the image provider
ImageProvider imageProvider =
- createImageProvider(finder,
- config.getModules(),
- config.getByteOrder(),
+ createImageProvider(config,
null,
IGNORE_SIGNING_DEFAULT,
+ false,
+ false,
null);
// Then create the Plugin Stack
@@ -319,20 +330,24 @@
// the token for "all modules on the module path"
private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
- private void createImage() throws Exception {
- if (options.output == null) {
- throw taskHelper.newBadArgs("err.output.must.be.specified").showUsage(true);
- }
-
+ private JlinkConfiguration initJlinkConfig() throws BadArgs {
if (options.addMods.isEmpty()) {
throw taskHelper.newBadArgs("err.mods.must.be.specified", "--add-modules")
- .showUsage(true);
+ .showUsage(true);
}
Set<String> roots = new HashSet<>();
for (String mod : options.addMods) {
if (mod.equals(ALL_MODULE_PATH)) {
- ModuleFinder finder = modulePathFinder();
+ Path[] entries = options.modulePath.toArray(new Path[0]);
+ ModuleFinder finder = ModulePath.of(Runtime.version(), true, entries);
+ if (!options.limitMods.isEmpty()) {
+ // finder for the observable modules specified in
+ // the --module-path and --limit-modules options
+ finder = limitFinder(finder, options.limitMods, Collections.emptySet());
+ }
+
+ // all observable modules are roots
finder.findAll()
.stream()
.map(ModuleReference::descriptor)
@@ -343,40 +358,34 @@
}
}
- ModuleFinder finder = newModuleFinder(options.modulePath,
- options.limitMods,
- roots);
+ return new JlinkConfiguration(options.output,
+ options.modulePath,
+ roots,
+ options.limitMods,
+ options.endian);
+ }
+ private void createImage(JlinkConfiguration config) throws Exception {
+ if (options.output == null) {
+ throw taskHelper.newBadArgs("err.output.must.be.specified").showUsage(true);
+ }
// First create the image provider
- ImageProvider imageProvider = createImageProvider(finder,
- roots,
- options.endian,
+ ImageProvider imageProvider = createImageProvider(config,
options.packagedModulesPath,
options.ignoreSigning,
+ options.bindServices,
+ options.verbose,
log);
// Then create the Plugin Stack
- ImagePluginStack stack = ImagePluginConfiguration.
- parseConfiguration(taskHelper.getPluginsConfig(options.output, options.launchers));
+ ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(
+ taskHelper.getPluginsConfig(options.output, options.launchers));
//Ask the stack to proceed
stack.operate(imageProvider);
}
- /**
- * Returns a module finder to find the observable modules specified in
- * the --module-path and --limit-modules options
- */
- private ModuleFinder modulePathFinder() {
- Path[] entries = options.modulePath.toArray(new Path[0]);
- ModuleFinder finder = ModulePath.of(Runtime.version(), true, entries);
- if (!options.limitMods.isEmpty()) {
- finder = limitFinder(finder, options.limitMods, Collections.emptySet());
- }
- return finder;
- }
-
/*
* Returns a module finder of the given module path that limits
* the observable modules to those in the transitive closure of
@@ -405,22 +414,32 @@
return Paths.get(uri);
}
- private static ImageProvider createImageProvider(ModuleFinder finder,
- Set<String> roots,
- ByteOrder order,
+
+ private static ImageProvider createImageProvider(JlinkConfiguration config,
Path retainModulesPath,
boolean ignoreSigning,
+ boolean bindService,
+ boolean verbose,
PrintWriter log)
throws IOException
{
- if (roots.isEmpty()) {
- throw new IllegalArgumentException("empty modules and limitmods");
- }
+ Configuration cf = bindService ? config.resolveAndBind()
+ : config.resolve();
- Configuration cf = Configuration.empty()
- .resolve(finder,
- ModuleFinder.of(),
- roots);
+ if (verbose && log != null) {
+ // print modules to be linked in
+ cf.modules().stream()
+ .sorted(Comparator.comparing(ResolvedModule::name))
+ .forEach(rm -> log.format("module %s (%s)%n",
+ rm.name(), rm.reference().location().get()));
+
+ // print provider info
+ Set<ModuleReference> references = cf.modules().stream()
+ .map(ResolvedModule::reference).collect(Collectors.toSet());
+
+ String msg = String.format("%n%s:", taskHelper.getMessage("providers.header"));
+ printProviders(log, msg, references);
+ }
// emit a warning for any incubating modules in the configuration
if (log != null) {
@@ -438,16 +457,16 @@
Map<String, Path> mods = cf.modules().stream()
.collect(Collectors.toMap(ResolvedModule::name, JlinkTask::toPathLocation));
- return new ImageHelper(cf, mods, order, retainModulesPath, ignoreSigning);
+ return new ImageHelper(cf, mods, config.getByteOrder(), retainModulesPath, ignoreSigning);
}
/*
* Returns a ModuleFinder that limits observability to the given root
* modules, their transitive dependences, plus a set of other modules.
*/
- private static ModuleFinder limitFinder(ModuleFinder finder,
- Set<String> roots,
- Set<String> otherMods) {
+ public static ModuleFinder limitFinder(ModuleFinder finder,
+ Set<String> roots,
+ Set<String> otherMods) {
// resolve all root modules
Configuration cf = Configuration.empty()
@@ -484,6 +503,147 @@
};
}
+ /*
+ * Returns a map of each service type to the modules that use it
+ */
+ private static Map<String, Set<String>> uses(Set<ModuleReference> modules) {
+ // collects the services used by the modules and print uses
+ Map<String, Set<String>> uses = new HashMap<>();
+ modules.stream()
+ .map(ModuleReference::descriptor)
+ .forEach(md -> md.uses().forEach(s ->
+ uses.computeIfAbsent(s, _k -> new HashSet<>()).add(md.name()))
+ );
+ return uses;
+ }
+
+ private static void printProviders(PrintWriter log,
+ String header,
+ Set<ModuleReference> modules) {
+ printProviders(log, header, modules, uses(modules));
+ }
+
+ /*
+ * Prints the providers that are used by the services specified in
+ * the given modules.
+ *
+ * The specified uses maps a service type name to the modules
+ * using the service type and that may or may not be present
+ * the given modules.
+ */
+ private static void printProviders(PrintWriter log,
+ String header,
+ Set<ModuleReference> modules,
+ Map<String, Set<String>> uses) {
+ if (modules.isEmpty())
+ return;
+
+ // Build a map of a service type to the provider modules
+ Map<String, Set<ModuleDescriptor>> providers = new HashMap<>();
+ modules.stream()
+ .map(ModuleReference::descriptor)
+ .forEach(md -> {
+ md.provides().stream()
+ .filter(p -> uses.containsKey(p.service()))
+ .forEach(p -> providers.computeIfAbsent(p.service(), _k -> new HashSet<>())
+ .add(md));
+ });
+
+ if (!providers.isEmpty()) {
+ log.println(header);
+ }
+
+ // print the providers of the service types used by the specified modules
+ // sorted by the service type name and then provider's module name
+ providers.entrySet().stream()
+ .sorted(Map.Entry.comparingByKey())
+ .forEach(e -> {
+ String service = e.getKey();
+ e.getValue().stream()
+ .sorted(Comparator.comparing(ModuleDescriptor::name))
+ .forEach(md ->
+ md.provides().stream()
+ .filter(p -> p.service().equals(service))
+ .forEach(p -> log.format(" module %s provides %s, used by %s%n",
+ md.name(), p.service(),
+ uses.get(p.service()).stream()
+ .sorted()
+ .collect(Collectors.joining(","))))
+ );
+ });
+ }
+
+ private void suggestProviders(JlinkConfiguration config, List<String> args)
+ throws BadArgs
+ {
+ if (args.size() > 1) {
+ throw taskHelper.newBadArgs("err.orphan.argument",
+ toString(args.subList(1, args.size())))
+ .showUsage(true);
+ }
+
+ if (options.bindServices) {
+ log.println(taskHelper.getMessage("no.suggested.providers"));
+ return;
+ }
+
+ ModuleFinder finder = config.finder();
+ if (args.isEmpty()) {
+ // print providers used by the modules resolved without service binding
+ Configuration cf = config.resolve();
+ Set<ModuleReference> mrefs = cf.modules().stream()
+ .map(ResolvedModule::reference)
+ .collect(Collectors.toSet());
+
+ // print uses of the modules that would be linked into the image
+ mrefs.stream()
+ .sorted(Comparator.comparing(mref -> mref.descriptor().name()))
+ .forEach(mref -> {
+ ModuleDescriptor md = mref.descriptor();
+ log.format("module %s located (%s)%n", md.name(),
+ mref.location().get());
+ md.uses().stream().sorted()
+ .forEach(s -> log.format(" uses %s%n", s));
+ });
+
+ String msg = String.format("%n%s:", taskHelper.getMessage("suggested.providers.header"));
+ printProviders(log, msg, finder.findAll(), uses(mrefs));
+
+ } else {
+ // comma-separated service types, if specified
+ Set<String> names = Stream.of(args.get(0).split(","))
+ .collect(Collectors.toSet());
+ // find the modules that provide the specified service
+ Set<ModuleReference> mrefs = finder.findAll().stream()
+ .filter(mref -> mref.descriptor().provides().stream()
+ .map(ModuleDescriptor.Provides::service)
+ .anyMatch(names::contains))
+ .collect(Collectors.toSet());
+
+ // the specified services may or may not be in the modules that
+ // would be linked in. So find uses declared in all observable modules
+ Map<String, Set<String>> uses = uses(finder.findAll());
+
+ // check if any name given on the command line are unused service
+ mrefs.stream()
+ .flatMap(mref -> mref.descriptor().provides().stream()
+ .map(ModuleDescriptor.Provides::service))
+ .forEach(names::remove);
+ if (!names.isEmpty()) {
+ log.println(taskHelper.getMessage("warn.unused.services",
+ toString(names)));
+ }
+
+ String msg = String.format("%n%s:", taskHelper.getMessage("suggested.providers.header"));
+ printProviders(log, msg, mrefs, uses);
+ }
+ }
+
+ private static String toString(Collection<String> collection) {
+ return collection.stream().sorted()
+ .collect(Collectors.joining(","));
+ }
+
private String getSaveOpts() {
StringBuilder sb = new StringBuilder();
sb.append('#').append(new Date()).append("\n");
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java Thu Mar 30 19:55:04 2017 +0200
@@ -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
@@ -46,6 +46,7 @@
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
import jdk.tools.jlink.internal.plugins.ExcludeJmodSectionPlugin;
@@ -101,8 +102,15 @@
final boolean hidden;
final String name;
final String shortname;
+ final boolean terminalOption;
- public Option(boolean hasArg, Processing<T> processing, boolean hidden, String name, String shortname) {
+ public Option(boolean hasArg,
+ Processing<T> processing,
+ boolean hidden,
+ String name,
+ String shortname,
+ boolean isTerminal)
+ {
if (!name.startsWith("--")) {
throw new RuntimeException("option name missing --, " + name);
}
@@ -115,24 +123,33 @@
this.hidden = hidden;
this.name = name;
this.shortname = shortname;
+ this.terminalOption = isTerminal;
+ }
+
+ public Option(boolean hasArg, Processing<T> processing, String name, String shortname, boolean isTerminal) {
+ this(hasArg, processing, false, name, shortname, isTerminal);
}
public Option(boolean hasArg, Processing<T> processing, String name, String shortname) {
- this(hasArg, processing, false, name, shortname);
+ this(hasArg, processing, false, name, shortname, false);
}
public Option(boolean hasArg, Processing<T> processing, boolean hidden, String name) {
- this(hasArg, processing, hidden, name, "");
+ this(hasArg, processing, hidden, name, "", false);
}
public Option(boolean hasArg, Processing<T> processing, String name) {
- this(hasArg, processing, false, name, "");
+ this(hasArg, processing, false, name, "", false);
}
public boolean isHidden() {
return hidden;
}
+ public boolean isTerminal() {
+ return terminalOption;
+ }
+
public boolean matches(String opt) {
return opt.equals(name) ||
opt.equals(shortname) ||
@@ -179,12 +196,12 @@
private static class PluginOption extends Option<PluginsHelper> {
public PluginOption(boolean hasArg,
Processing<PluginsHelper> processing, boolean hidden, String name, String shortname) {
- super(hasArg, processing, hidden, name, shortname);
+ super(hasArg, processing, hidden, name, shortname, false);
}
public PluginOption(boolean hasArg,
Processing<PluginsHelper> processing, boolean hidden, String name) {
- super(hasArg, processing, hidden, name, "");
+ super(hasArg, processing, hidden, name, "", false);
}
public String resourcePrefix() {
@@ -498,21 +515,13 @@
return null;
}
- // used by jimage. Return unhandled arguments like "create", "describe".
+ /**
+ * Handles all options. This method stops processing the argument
+ * at the first non-option argument i.e. not starts with `-`, or
+ * at the first terminal option and returns the remaining arguments,
+ * if any.
+ */
public List<String> handleOptions(T task, String[] args) throws BadArgs {
- return handleOptions(task, args, true);
- }
-
- // used by jlink. No unhandled arguments like "create", "describe".
- void handleOptionsNoUnhandled(T task, String[] args) throws BadArgs {
- handleOptions(task, args, false);
- }
-
- // shared code that handles options for both jlink and jimage. jimage uses arguments like
- // "create", "describe" etc. as "task names". Those arguments are unhandled here and returned
- // as "unhandled arguments list". jlink does not want such arguments. "collectUnhandled" flag
- // tells whether to allow for unhandled arguments or not.
- private List<String> handleOptions(T task, String[] args, boolean collectUnhandled) throws BadArgs {
// findbugs warning, copy instead of keeping a reference.
command = Arrays.copyOf(args, args.length);
@@ -521,7 +530,6 @@
// Unit tests can call Task multiple time in same JVM.
pluginOptions = new PluginsHelper(null);
- List<String> rest = collectUnhandled? new ArrayList<>() : null;
// process options
for (int i = 0; i < args.length; i++) {
if (args[i].startsWith("-")) {
@@ -531,7 +539,6 @@
if (option == null) {
pluginOption = pluginOptions.getOption(name);
if (pluginOption == null) {
-
throw new BadArgs("err.unknown.option", name).
showUsage(true);
}
@@ -556,20 +563,23 @@
pluginOption.process(pluginOptions, name, param);
} else {
option.process(task, name, param);
+ if (option.isTerminal()) {
+ return ++i < args.length
+ ? Stream.of(Arrays.copyOfRange(args, i, args.length))
+ .collect(Collectors.toList())
+ : Collections.emptyList();
+
+ }
}
if (opt.ignoreRest()) {
i = args.length;
}
} else {
- if (collectUnhandled) {
- rest.add(args[i]);
- } else {
- throw new BadArgs("err.orphan.argument", args[i]).
- showUsage(true);
- }
+ return Stream.of(Arrays.copyOfRange(args, i, args.length))
+ .collect(Collectors.toList());
}
}
- return rest;
+ return Collections.emptyList();
}
private Option<T> getOption(String name) {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java Thu Mar 30 19:55:04 2017 +0200
@@ -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
@@ -34,6 +34,7 @@
import java.io.File;
import java.io.IOException;
import java.lang.module.ModuleFinder;
+import java.nio.ByteOrder;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
@@ -93,9 +94,12 @@
public void build() throws IOException {
// jlink main arguments
- Jlink.JlinkConfiguration jlinkConfig = new Jlink.JlinkConfiguration(
- new File("").toPath(), // Unused
- modulePath, addModules, limitModules);
+ Jlink.JlinkConfiguration jlinkConfig =
+ new Jlink.JlinkConfiguration(new File("").toPath(), // Unused
+ modulePath,
+ addModules,
+ limitModules,
+ ByteOrder.nativeOrder());
// plugin configuration
List<Plugin> plugins = new ArrayList<Plugin>();
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties Thu Mar 30 19:55:04 2017 +0200
@@ -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
@@ -24,15 +24,12 @@
#
main.usage.summary=\
-Usage: {0} <options> --module-path <modulepath> --add-modules <mods> --output\n\
-\<path> use --help for a list of possible options
+Usage: {0} <options> --module-path <modulepath> --add-modules <module>[,<module>...]\n\
+\Use --help for a list of possible options
main.usage=\
-Usage: {0} <options> --module-path <modulepath> --add-modules <mods> --output\n\
-\<path> Possible options include:
-
-error.prefix=Error:
-warn.prefix=Warning:
+Usage: {0} <options> --module-path <modulepath> --add-modules <module>[,<module>...]\n\
+\Possible options include:
main.opt.help=\
\ -h, --help Print this help message
@@ -54,9 +51,18 @@
\ --output <path> Location of output path
main.opt.launcher=\
-\ --launcher <command>=<module> Launcher command name for the module\n\
-\ --launcher <command>=<module>/<main>\n\
-\ Launcher command name for the module and the main class
+\ --launcher <name>=<module>[/<mainclass>]\n\
+\ Add a launcher command of the given\n\
+\ name for the module and the main class\n\
+\ if specified
+
+main.opt.bind-services=\
+\ --bind-services Do full service binding
+
+main.opt.suggest-providers=\
+\ --suggest-providers [<name>,...] Suggest providers of services used by\n\
+\ the modules that would be linked, or\n\
+\ of the given service types
main.command.files=\
\ @<filename> Read options from file
@@ -75,6 +81,9 @@
\ signed modular JARs are not copied to\n\
\ the runtime image.
+main.opt.verbose=\
+\ -v, --verbose Enable verbose tracing
+
main.msg.bug=\
An exception has occurred in jlink. \
Please file a bug at the Java Bug Database (http://bugreport.java.com/bugreport/) \
@@ -95,6 +104,9 @@
\n\
+error.prefix=Error:
+warn.prefix=Warning:
+
err.unknown.byte.order:unknown byte order {0}
err.launcher.main.class.empty:launcher main class name cannot be empty: {0}
err.launcher.module.name.empty:launcher module name cannot be empty: {0}
@@ -111,12 +123,12 @@
err.dir.exists={0} already exists
err.badpattern=bad pattern {0}
err.unknown.option=unknown option: {0}
-err.orphan.argument=orphan argument: {0}
err.missing.arg=no value given for {0}
err.internal.error=internal error: {0} {1} {2}
err.invalid.arg.for.option=invalid argument for option: {0}
err.option.after.class=option must be specified before classes: {0}
err.option.unsupported={0} not supported: {1}
+err.orphan.arguments=invalid argument: {0}
err.config.defaults=property {0} is missing from configuration
err.config.defaults.value=wrong value in defaults property: {0}
err.bom.generation=bom file generation failed: {0}
@@ -126,3 +138,7 @@
warn.signing=WARNING: signed modular JAR {0} is currently not supported
warn.invalid.arg=invalid classname or pathname not exist: {0}
warn.split.package=package {0} defined in {1} {2}
+warn.unused.services=Services specified in --suggest-providers not used: {0}
+no.suggested.providers=--bind-services option is specified. No additional providers suggested.
+suggested.providers.header=Suggested providers
+providers.header=Providers
--- a/jdk/src/jdk.jlink/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.jlink/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -23,6 +23,12 @@
* questions.
*/
+/**
+ * Defines the Java linker tool, jlink.
+ *
+ * @moduleGraph
+ * @since 9
+ */
module jdk.jlink {
requires jdk.internal.opt;
requires jdk.jdeps;
--- a/jdk/src/jdk.jsobject/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.jsobject/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -23,6 +23,12 @@
* questions.
*/
+/**
+ * Defines the API for the JavaScript Object.
+ *
+ * @moduleGraph
+ * @since 9
+ */
module jdk.jsobject {
requires java.desktop;
exports netscape.javascript;
--- a/jdk/src/jdk.jstatd/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.jstatd/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -23,6 +23,13 @@
* questions.
*/
+/**
+ * Defines the tool for starting a daemon for the jstat tool to monitor
+ * JVM statistics remotely.
+ *
+ * @moduleGraph
+ * @since 9
+ */
module jdk.jstatd {
requires java.rmi;
requires jdk.internal.jvmstat;
@@ -32,4 +39,3 @@
provides sun.jvmstat.monitor.MonitoredHostService with sun.jvmstat.perfdata.monitor.protocol.rmi.MonitoredHostRmiService;
}
-
--- a/jdk/src/jdk.localedata/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.localedata/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -23,6 +23,12 @@
* questions.
*/
+/**
+ * Locale data provider for locales other than {@linkplain java.util.Locale#US US locale}.
+ *
+ * @moduleGraph
+ * @since 9
+ */
module jdk.localedata {
provides sun.util.locale.provider.LocaleDataMetaInfo with
sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo,
--- a/jdk/src/jdk.management.agent/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.management.agent/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -23,6 +23,12 @@
* questions.
*/
+/**
+ * Define the JMX management agent.
+ *
+ * @moduleGraph
+ * @since 9
+ */
module jdk.management.agent {
requires java.management;
requires java.management.rmi;
--- a/jdk/src/jdk.management/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.management/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -23,6 +23,12 @@
* questions.
*/
+/**
+ * Defines the JDK-specific Management Interfaces for JVM.
+ *
+ * @moduleGraph
+ * @since 9
+ */
module jdk.management {
requires transitive java.management;
--- a/jdk/src/jdk.naming.dns/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.naming.dns/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -23,6 +23,12 @@
* questions.
*/
+/**
+ * DNS Java Naming provider.
+ *
+ * @moduleGraph
+ * @since 9
+ */
module jdk.naming.dns {
requires java.naming;
--- a/jdk/src/jdk.naming.rmi/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.naming.rmi/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -23,6 +23,12 @@
* questions.
*/
+/**
+ * RMI Java Naming provider.
+ *
+ * @moduleGraph
+ * @since 9
+ */
module jdk.naming.rmi {
requires java.naming;
requires java.rmi;
--- a/jdk/src/jdk.net/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.net/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -23,6 +23,12 @@
* questions.
*/
+/**
+ * Defines the JDK-specific Networking API.
+ *
+ * @moduleGraph
+ * @since 9
+ */
module jdk.net {
exports jdk.net;
}
--- a/jdk/src/jdk.sctp/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.sctp/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -23,6 +23,12 @@
* questions.
*/
+/**
+ * Defines the JDK-specific API for SCTP.
+ *
+ * @moduleGraph
+ * @since 9
+ */
module jdk.sctp {
exports com.sun.nio.sctp;
}
--- a/jdk/src/jdk.security.auth/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.security.auth/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -27,6 +27,7 @@
* Contains the implementation of the javax.security.auth.* interfaces and
* various authentication modules.
*
+ * @moduleGraph
* @since 9
*/
module jdk.security.auth {
--- a/jdk/src/jdk.security.jgss/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.security.jgss/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -27,6 +27,7 @@
* Defines Java extensions to the GSS-API and an implementation of the SASL
* GSSAPI mechanism.
*
+ * @moduleGraph
* @since 9
*/
module jdk.security.jgss {
--- a/jdk/src/jdk.zipfs/share/classes/module-info.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/src/jdk.zipfs/share/classes/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -23,6 +23,12 @@
* questions.
*/
+/**
+ * Zip file system provider.
+ *
+ * @moduleGraph
+ * @since 9
+ */
module jdk.zipfs {
provides java.nio.file.spi.FileSystemProvider with jdk.nio.zipfs.ZipFileSystemProvider;
}
--- a/jdk/test/ProblemList.txt Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/test/ProblemList.txt Thu Mar 30 19:55:04 2017 +0200
@@ -180,8 +180,6 @@
java/nio/channels/DatagramChannel/ChangingAddress.java 7141822 macosx-all
-java/nio/channels/Selector/OutOfBand.java 7132677 macosx-all
-
java/nio/file/WatchService/Basic.java 7158947 solaris-all Solaris 11
java/nio/file/WatchService/MayFlies.java 7158947 solaris-all Solaris 11
java/nio/file/WatchService/LotsOfEvents.java 7158947 solaris-all Solaris 11
--- a/jdk/test/TEST.groups Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/test/TEST.groups Thu Mar 30 19:55:04 2017 +0200
@@ -73,6 +73,7 @@
jdk/internal/misc \
jdk/internal/ref \
jdk/internal/jimage \
+ jdk/internal/math \
jdk/modules \
vm
@@ -141,8 +142,7 @@
java/util/stream
jdk_math = \
- java/math \
- jdk/internal/math
+ java/math
jdk_io = \
java/io
--- a/jdk/test/java/nio/channels/DatagramChannel/NetworkConfiguration.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/test/java/nio/channels/DatagramChannel/NetworkConfiguration.java Thu Mar 30 19:55:04 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2011, 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
@@ -57,22 +57,11 @@
return ip6Interfaces.get(nif);
}
- // IPv6 not supported for Windows XP/Server 2003
- static boolean isIPv6Supported() {
- if (System.getProperty("os.name").startsWith("Windows")) {
- String ver = System.getProperty("os.version");
- int major = Integer.parseInt(ver.split("\\.")[0]);
- return (major >= 6);
- }
- return true;
- }
-
static NetworkConfiguration probe() throws IOException {
Map<NetworkInterface,List<InetAddress>> ip4Interfaces =
new HashMap<NetworkInterface,List<InetAddress>>();
Map<NetworkInterface,List<InetAddress>> ip6Interfaces =
new HashMap<NetworkInterface,List<InetAddress>>();
- boolean isIPv6Supported = isIPv6Supported();
// find the interfaces that support IPv4 and IPv6
List<NetworkInterface> nifs = Collections
@@ -92,7 +81,7 @@
}
list.add(addr);
ip4Interfaces.put(nif, list);
- } else if (isIPv6Supported && (addr instanceof Inet6Address)) {
+ } else if (addr instanceof Inet6Address) {
List<InetAddress> list = ip6Interfaces.get(nif);
if (list == null) {
list = new LinkedList<InetAddress>();
--- a/jdk/test/java/nio/channels/FileChannel/Transfer4GBFile.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/test/java/nio/channels/FileChannel/Transfer4GBFile.java Thu Mar 30 19:55:04 2017 +0200
@@ -52,11 +52,6 @@
// Test transferTo with large file
@Test
public void xferTest04() throws Exception { // for bug 4638365
- // Windows and Linux can't handle the really large file sizes for a
- // truncate or a positional write required by the test for 4563125
- String osName = System.getProperty("os.name");
- if (!(osName.startsWith("SunOS") || osName.contains("OS X")))
- return;
File source = File.createTempFile("blah", null);
source.deleteOnExit();
long testSize = ((long)Integer.MAX_VALUE) * 2;
--- a/jdk/test/java/nio/channels/FileChannel/TransferTo6GBFile.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/test/java/nio/channels/FileChannel/TransferTo6GBFile.java Thu Mar 30 19:55:04 2017 +0200
@@ -50,11 +50,6 @@
// Test transferTo with file positions larger than 2 and 4GB
@Test
public void xferTest08() throws Exception { // for bug 6253145
- // Creating a sparse 6GB file on Windows takes too long
- String osName = System.getProperty("os.name");
- if (osName.startsWith("Windows"))
- return;
-
final long G = 1024L * 1024L * 1024L;
// Create 6GB file
--- a/jdk/test/java/nio/channels/Selector/OutOfBand.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/test/java/nio/channels/Selector/OutOfBand.java Thu Mar 30 19:55:04 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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,6 +23,9 @@
/* @test
* @bug 6213702
+ * @requires (os.family != "mac") | (os.version == "10.10.5")
+ * | (os.simpleVersion != "10.8" & os.simpleVersion != "10.9"
+ * & os.simpleVersion != "10.10")
* @summary OOB data causes a SocketChannel, with OOBINLINE disabled, to be
* selected
*/
--- a/jdk/test/java/nio/channels/Selector/SelectorLimit.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/test/java/nio/channels/Selector/SelectorLimit.java Thu Mar 30 19:55:04 2017 +0200
@@ -66,15 +66,6 @@
static final int MIN_KEYS = 100;
public static void main(String[] args) throws Exception {
- // win9X can't handle many connections at once
- String osName = System.getProperty("os.name");
- if (osName.toLowerCase().startsWith("win")) {
- if (!(osName.equals("Windows NT")
- || osName.equals("Windows 2000")
- || osName.equals("Windows XP")))
- return;
- }
-
ServerSocketChannel ssc = ServerSocketChannel.open();
TestUtil.bind(ssc);
Listener lth = new Listener(ssc);
--- a/jdk/test/sun/security/tools/keytool/WeakAlg.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/test/sun/security/tools/keytool/WeakAlg.java Thu Mar 30 19:55:04 2017 +0200
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8171319
+ * @bug 8171319 8177569
* @summary keytool should print out warnings when reading or generating
* cert/cert req using weak algorithms
* @library /test/lib
@@ -78,7 +78,8 @@
.shouldMatch("<b>.*512-bit RSA key.*risk")
.shouldContain("512-bit RSA key (weak)");
- // Multiple warnings for multiple cert in -printcert or -list or -exportcert
+ // Multiple warnings for multiple cert in -printcert
+ // or -list or -exportcert
// -certreq, -printcertreq, -gencert
checkCertReq("a", "", null);
@@ -184,7 +185,7 @@
.shouldMatch("The input.*MD5withRSA.*risk")
.shouldNotContain("[no]");
- // cert is self-signed cacerts
+ // JDK-8177569: no warning for sigalg of trusted cert
String weakSigAlgCA = null;
KeyStore ks = KeyStoreUtil.getCacertsKeyStore();
if (ks != null) {
@@ -208,12 +209,40 @@
}
}
if (weakSigAlgCA != null) {
+ // The following 2 commands still have a warning on why not using
+ // the -cacerts option directly.
+ kt("-list -keystore " + KeyStoreUtil.getCacerts())
+ .shouldNotContain("risk");
+ kt("-list -v -keystore " + KeyStoreUtil.getCacerts())
+ .shouldNotContain("risk");
+
+ // -printcert will always show warnings
+ kt("-printcert -file ca.cert")
+ .shouldContain("name: " + weakSigAlgCA + " (weak)")
+ .shouldContain("Warning")
+ .shouldMatch("The certificate.*" + weakSigAlgCA + ".*risk");
+ kt("-printcert -file ca.cert -trustcacerts") // -trustcacerts useless
+ .shouldContain("name: " + weakSigAlgCA + " (weak)")
+ .shouldContain("Warning")
+ .shouldMatch("The certificate.*" + weakSigAlgCA + ".*risk");
+
+ // Importing with -trustcacerts ignore CA cert's sig alg
kt("-delete -alias d");
kt("-importcert -alias d -trustcacerts -file ca.cert", "no")
.shouldContain("Certificate already exists in system-wide CA")
+ .shouldNotContain("risk")
+ .shouldContain("Do you still want to add it to your own keystore?");
+ kt("-importcert -alias d -trustcacerts -file ca.cert -noprompt")
+ .shouldNotContain("risk")
+ .shouldNotContain("[no]");
+
+ // but not without -trustcacerts
+ kt("-delete -alias d");
+ kt("-importcert -alias d -file ca.cert", "no")
+ .shouldContain("name: " + weakSigAlgCA + " (weak)")
.shouldContain("Warning")
.shouldMatch("The input.*" + weakSigAlgCA + ".*risk")
- .shouldContain("Do you still want to add it to your own keystore?");
+ .shouldContain("Trust this certificate?");
kt("-importcert -alias d -file ca.cert -noprompt")
.shouldContain("Warning")
.shouldMatch("The input.*" + weakSigAlgCA + ".*risk")
@@ -266,6 +295,26 @@
// install reply
reStore();
+ certreq("c", "");
+ gencert("a-c", "");
+ kt("-importcert -alias c -file a-c.cert")
+ .shouldContain("Warning")
+ .shouldMatch("Issuer <a>.*MD5withRSA.*risk");
+
+ // JDK-8177569: no warning for sigalg of trusted cert
+ reStore();
+ // Change a into a TrustedCertEntry
+ kt("-exportcert -alias a -file a.cert");
+ kt("-delete -alias a");
+ kt("-importcert -alias a -file a.cert -noprompt");
+ kt("-list -alias a -v")
+ .shouldNotContain("weak")
+ .shouldNotContain("Warning");
+ // This time a is trusted and no warning on its weak sig alg
+ kt("-importcert -alias c -file a-c.cert")
+ .shouldNotContain("Warning");
+
+ reStore();
gencert("a-b", "");
gencert("b-c", "");
--- a/jdk/test/tools/jlink/IntegrationTest.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/test/tools/jlink/IntegrationTest.java Thu Mar 30 19:55:04 2017 +0200
@@ -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
@@ -25,6 +25,7 @@
import java.io.FileReader;
import java.io.IOException;
import java.io.UncheckedIOException;
+import java.nio.ByteOrder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -135,11 +136,6 @@
}
System.out.println(jl);
- JlinkConfiguration config
- = new JlinkConfiguration(null, null, null, null);
-
- System.out.println(config);
-
Plugin p = Jlink.newPlugin("toto", Collections.emptyMap(), null);
if (p != null) {
throw new Exception("Plugin should be null");
@@ -163,7 +159,7 @@
Set<String> limits = new HashSet<>();
limits.add("java.management");
JlinkConfiguration config = new Jlink.JlinkConfiguration(output,
- modulePaths, mods, limits, null);
+ modulePaths, mods, limits, ByteOrder.nativeOrder());
List<Plugin> lst = new ArrayList<>();
--- a/jdk/test/tools/jlink/JLinkTest.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/test/tools/jlink/JLinkTest.java Thu Mar 30 19:55:04 2017 +0200
@@ -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
@@ -274,7 +274,7 @@
String[] userOptions = {"--compress", "2", "foo" };
String moduleName = "orphanarg1";
helper.generateDefaultJModule(moduleName, "composite2");
- helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: orphan argument: foo");
+ helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: invalid argument: foo");
}
// orphan argument - JDK-8166810
@@ -282,7 +282,7 @@
String[] userOptions = {"--output", "foo", "bar" };
String moduleName = "orphanarg2";
helper.generateDefaultJModule(moduleName, "composite2");
- helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: orphan argument: bar");
+ helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: invalid argument: bar");
}
// basic check for --help - JDK-8173717
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/bindservices/BindServices.java Thu Mar 30 19:55:04 2017 +0200
@@ -0,0 +1,200 @@
+/*
+ * 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.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+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.spi.ToolProvider;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static jdk.testlibrary.Asserts.assertTrue;
+import static jdk.testlibrary.ProcessTools.*;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+/**
+ * @test
+ * @bug 8174826
+ * @library /lib/testlibrary
+ * @modules jdk.compiler jdk.jlink
+ * @build BindServices CompilerUtils jdk.testlibrary.ProcessTools
+ * @run testng BindServices
+ */
+
+public class BindServices {
+ private static final String JAVA_HOME = System.getProperty("java.home");
+ private static final String TEST_SRC = System.getProperty("test.src");
+
+ private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+ private static final Path MODS_DIR = Paths.get("mods");
+
+ private static final String MODULE_PATH =
+ Paths.get(JAVA_HOME, "jmods").toString() +
+ File.pathSeparator + MODS_DIR.toString();
+
+ // the names of the modules in this test
+ private static String[] modules = new String[] {"m1", "m2", "m3"};
+
+
+ private static boolean hasJmods() {
+ if (!Files.exists(Paths.get(JAVA_HOME, "jmods"))) {
+ System.err.println("Test skipped. NO jmods directory");
+ return false;
+ }
+ return true;
+ }
+
+ /*
+ * Compiles all modules used by the test
+ */
+ @BeforeTest
+ public void compileAll() throws Throwable {
+ if (!hasJmods()) return;
+
+ for (String mn : modules) {
+ Path msrc = SRC_DIR.resolve(mn);
+ assertTrue(CompilerUtils.compile(msrc, MODS_DIR,
+ "--module-source-path", SRC_DIR.toString()));
+ }
+ }
+
+ @Test
+ public void noServiceBinding() throws Throwable {
+ if (!hasJmods()) return;
+
+ Path dir = Paths.get("noServiceBinding");
+
+ // no service binding and does not link m2,m3 providers.
+ JLink.run("--output", dir.toString(),
+ "--module-path", MODULE_PATH,
+ "--add-modules", "m1").output();
+
+ testImage(dir, "m1");
+ }
+
+ @Test
+ public void fullServiceBinding() throws Throwable {
+ if (!hasJmods()) return;
+
+ Path dir = Paths.get("fullServiceBinding");
+
+ // full service binding
+ // m2 is a provider used by m1. During service binding, when m2 is
+ // resolved, m2 uses p2.T that causes m3 to be linked as it is a
+ // provider to p2.T
+ JLink.run("--output", dir.toString(),
+ "--module-path", MODULE_PATH,
+ "--add-modules", "m1",
+ "--bind-services",
+ "--limit-modules", "m1,m2,m3,java.base");
+
+ testImage(dir, "m1", "m2", "m3");
+ }
+
+ @Test
+ public void testVerbose() throws Throwable {
+ if (!hasJmods()) return;
+
+ Path dir = Paths.get("verbose");
+
+ List<String> output =
+ JLink.run("--output", dir.toString(),
+ "--module-path", MODULE_PATH,
+ "--add-modules", "m1",
+ "--bind-services",
+ "--verbose",
+ "--limit-modules", "m1,m2,m3,java.base").output();
+
+ List<String> expected = List.of(
+ "module m1 (" + MODS_DIR.resolve("m1").toUri().toString() + ")",
+ "module m2 (" + MODS_DIR.resolve("m2").toUri().toString() + ")",
+ "module m3 (" + MODS_DIR.resolve("m3").toUri().toString() + ")",
+ "module m1 provides p1.S, used by m1",
+ "module m2 provides p1.S, used by m1",
+ "module m2 provides p2.T, used by m2",
+ "module m3 provides p2.T, used by m2"
+ );
+
+ assertTrue(output.containsAll(expected));
+
+ testImage(dir, "m1", "m2", "m3");
+ }
+
+ /*
+ * Tests the given ${java.home} to only contain the specified modules
+ */
+ private void testImage(Path javaHome, String... modules) throws Throwable {
+ Path java = javaHome.resolve("bin").resolve("java");
+ String[] cmd = Stream.concat(
+ Stream.of(java.toString(), "-m", "m1/p1.Main"),
+ Stream.of(modules)).toArray(String[]::new);
+
+ assertTrue(executeProcess(cmd).outputTo(System.out)
+ .errorTo(System.out)
+ .getExitValue() == 0);
+ }
+
+ static class JLink {
+ static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink")
+ .orElseThrow(() ->
+ new RuntimeException("jlink tool not found")
+ );
+
+ static JLink run(String... options) {
+ JLink jlink = new JLink();
+ assertTrue(jlink.execute(options) == 0);
+ return jlink;
+ }
+
+ final List<String> output = new ArrayList<>();
+ private int execute(String... options) {
+ System.out.println("jlink " +
+ Stream.of(options).collect(Collectors.joining(" ")));
+
+ StringWriter writer = new StringWriter();
+ PrintWriter pw = new PrintWriter(writer);
+ int rc = JLINK_TOOL.run(pw, pw, options);
+ System.out.println(writer.toString());
+ Stream.of(writer.toString().split("\\v"))
+ .map(String::trim)
+ .forEach(output::add);
+ return rc;
+ }
+
+ boolean contains(String s) {
+ return output.contains(s);
+ }
+
+ List<String> output() {
+ return output;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/bindservices/SuggestProviders.java Thu Mar 30 19:55:04 2017 +0200
@@ -0,0 +1,209 @@
+/*
+ * 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.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+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.spi.ToolProvider;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static jdk.testlibrary.Asserts.assertTrue;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+/**
+ * @test
+ * @bug 8174826
+ * @library /lib/testlibrary
+ * @modules jdk.charsets jdk.compiler jdk.jlink
+ * @build SuggestProviders CompilerUtils
+ * @run testng SuggestProviders
+ */
+
+public class SuggestProviders {
+ private static final String JAVA_HOME = System.getProperty("java.home");
+ private static final String TEST_SRC = System.getProperty("test.src");
+
+ private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+ private static final Path MODS_DIR = Paths.get("mods");
+
+ private static final String MODULE_PATH =
+ Paths.get(JAVA_HOME, "jmods").toString() +
+ File.pathSeparator + MODS_DIR.toString();
+
+ // the names of the modules in this test
+ private static String[] modules = new String[] {"m1", "m2", "m3"};
+
+
+ private static boolean hasJmods() {
+ if (!Files.exists(Paths.get(JAVA_HOME, "jmods"))) {
+ System.err.println("Test skipped. NO jmods directory");
+ return false;
+ }
+ return true;
+ }
+
+ /*
+ * Compiles all modules used by the test
+ */
+ @BeforeTest
+ public void compileAll() throws Throwable {
+ if (!hasJmods()) return;
+
+ for (String mn : modules) {
+ Path msrc = SRC_DIR.resolve(mn);
+ assertTrue(CompilerUtils.compile(msrc, MODS_DIR,
+ "--module-source-path", SRC_DIR.toString()));
+ }
+ }
+
+ @Test
+ public void suggestProviders() throws Throwable {
+ if (!hasJmods()) return;
+
+ List<String> output = JLink.run("--module-path", MODULE_PATH,
+ "--add-modules", "m1",
+ "--suggest-providers").output();
+ // check a subset of services used by java.base
+ List<String> expected = List.of(
+ "uses java.lang.System$LoggerFinder",
+ "uses java.net.ContentHandlerFactory",
+ "uses java.net.spi.URLStreamHandlerProvider",
+ "uses java.nio.channels.spi.AsynchronousChannelProvider",
+ "uses java.nio.channels.spi.SelectorProvider",
+ "uses java.nio.charset.spi.CharsetProvider",
+ "uses java.nio.file.spi.FileSystemProvider",
+ "uses java.nio.file.spi.FileTypeDetector",
+ "uses java.security.Provider",
+ "uses java.util.spi.ToolProvider",
+ "uses p1.S",
+ "module jdk.charsets provides java.nio.charset.spi.CharsetProvider, used by java.base",
+ "module jdk.compiler provides java.util.spi.ToolProvider, used by java.base",
+ "module jdk.jlink provides java.util.spi.ToolProvider, used by java.base",
+ "module m1 provides p1.S, used by m1",
+ "module m2 provides p1.S, used by m1"
+ );
+
+ assertTrue(output.containsAll(expected));
+ }
+
+ @Test
+ public void providersForServices() throws Throwable {
+ if (!hasJmods()) return;
+
+ List<String> output =
+ JLink.run("--module-path", MODULE_PATH,
+ "--add-modules", "m1",
+ "--suggest-providers",
+ "java.nio.charset.spi.CharsetProvider,p1.S,p2.T").output();
+
+ System.out.println(output);
+ List<String> expected = List.of(
+ "module jdk.charsets provides java.nio.charset.spi.CharsetProvider, used by java.base",
+ "module m1 provides p1.S, used by m1",
+ "module m2 provides p1.S, used by m1",
+ "module m2 provides p2.T, used by m2",
+ "module m3 provides p2.T, used by m2"
+ );
+
+ assertTrue(output.containsAll(expected));
+ }
+
+ @Test
+ public void unusedService() throws Throwable {
+ if (!hasJmods()) return;
+
+ List<String> output =
+ JLink.run("--module-path", MODULE_PATH,
+ "--add-modules", "m1",
+ "--suggest-providers",
+ "nonExistentType").output();
+
+ System.out.println(output);
+ List<String> expected = List.of(
+ "Services specified in --suggest-providers not used: nonExistentType"
+ );
+
+ assertTrue(output.containsAll(expected));
+ }
+
+ @Test
+ public void noSuggestProviders() throws Throwable {
+ if (!hasJmods()) return;
+
+ List<String> output =
+ JLink.run("--module-path", MODULE_PATH,
+ "--add-modules", "m1",
+ "--bind-services",
+ "--limit-modules", "m1,m2,m3,java.base",
+ "--suggest-providers").output();
+
+ String expected = "--bind-services option is specified. No additional providers suggested.";
+ assertTrue(output.contains(expected));
+
+ }
+
+ static class JLink {
+ static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink")
+ .orElseThrow(() ->
+ new RuntimeException("jlink tool not found")
+ );
+
+ static JLink run(String... options) {
+ JLink jlink = new JLink();
+ assertTrue(jlink.execute(options) == 0);
+ return jlink;
+ }
+
+ final List<String> output = new ArrayList<>();
+ private int execute(String... options) {
+ System.out.println("jlink " +
+ Stream.of(options).collect(Collectors.joining(" ")));
+
+ StringWriter writer = new StringWriter();
+ PrintWriter pw = new PrintWriter(writer);
+ int rc = JLINK_TOOL.run(pw, pw, options);
+ System.out.println(writer.toString());
+ Stream.of(writer.toString().split("\\v"))
+ .map(String::trim)
+ .forEach(output::add);
+ return rc;
+ }
+
+ boolean contains(String s) {
+ return output.contains(s);
+ }
+
+ List<String> output() {
+ return output;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/bindservices/src/m1/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -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.
+ */
+
+module m1 {
+ exports p1;
+ uses p1.S;
+ provides p1.S with p1.Impl;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/bindservices/src/m1/p1/Impl.java Thu Mar 30 19:55:04 2017 +0200
@@ -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 p1;
+
+public class Impl implements S {
+ public String name() {
+ return this.getClass().getName();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/bindservices/src/m1/p1/Main.java Thu Mar 30 19:55:04 2017 +0200
@@ -0,0 +1,53 @@
+/*
+ * 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 p1;
+
+import java.lang.module.ModuleFinder;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * This tests if JAVA_HOME is linked only with the specified modules.
+ */
+public class Main {
+ public static void main(String... args) {
+ Set<String> modules = ModuleFinder.ofSystem().findAll().stream()
+ .map(mref -> mref.descriptor().name())
+ .filter(mn -> !mn.equals("java.base"))
+ .collect(Collectors.toSet());
+
+ Set<String> notLinked = Stream.of(args).filter(mn -> !modules.contains(mn))
+ .collect(Collectors.toSet());
+ if (!notLinked.isEmpty()) {
+ throw new RuntimeException("Expected modules not linked in the image: "
+ + notLinked);
+ }
+ Stream.of(args).forEach(modules::remove);
+
+ if (!modules.isEmpty()) {
+ throw new RuntimeException("Unexpected modules linked in the image: "
+ + modules);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/bindservices/src/m1/p1/S.java Thu Mar 30 19:55:04 2017 +0200
@@ -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.
+ */
+
+package p1;
+
+public interface S {
+ String name();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/bindservices/src/m2/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -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.
+ */
+
+module m2 {
+ requires m1;
+ exports p2;
+ uses p2.T;
+ provides p1.S with p2.Impl;
+ provides p2.T with p2.Impl;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/bindservices/src/m2/p2/Impl.java Thu Mar 30 19:55:04 2017 +0200
@@ -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.
+ */
+
+package p2;
+
+public class Impl implements p1.S, T {
+ public String name() {
+ return this.getClass().getName();
+ }
+
+ public void run() {
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/bindservices/src/m2/p2/T.java Thu Mar 30 19:55:04 2017 +0200
@@ -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.
+ */
+
+package p2;
+
+public interface T {
+ void run();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/bindservices/src/m3/module-info.java Thu Mar 30 19:55:04 2017 +0200
@@ -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 m3 {
+ requires m2;
+ provides p2.T with p3.Impl;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/bindservices/src/m3/p3/Impl.java Thu Mar 30 19:55:04 2017 +0200
@@ -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.
+ */
+
+package p3;
+
+public class Impl implements p2.T {
+ public void run() {
+ }
+}
--- a/jdk/test/tools/launcher/modules/permit/PermitIllegalAccess.java Sat Mar 25 00:31:29 2017 +0100
+++ b/jdk/test/tools/launcher/modules/permit/PermitIllegalAccess.java Thu Mar 30 19:55:04 2017 +0200
@@ -29,7 +29,10 @@
* @summary Basic test for java --permit-illegal-access
*/
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.stream.Stream;
import jdk.testlibrary.ProcessTools;
import jdk.testlibrary.OutputAnalyzer;
@@ -58,10 +61,13 @@
* Launches AttemptAccess to execute an action, returning the OutputAnalyzer
* to analyze the output/exitCode.
*/
- private OutputAnalyzer tryAction(String action, int count) throws Exception {
- String arg = "" + count;
- return ProcessTools
- .executeTestJava("-cp", TEST_CLASSES, TEST_MAIN, action, arg)
+ private OutputAnalyzer tryAction(String action, int count, String... args)
+ throws Exception
+ {
+ Stream<String> s1 = Stream.of(args);
+ Stream<String> s2 = Stream.of("-cp", TEST_CLASSES, TEST_MAIN, action, "" + count);
+ String[] opts = Stream.concat(s1, s2).toArray(String[]::new);
+ return ProcessTools.executeTestJava(opts)
.outputTo(System.out)
.errorTo(System.out);
}
@@ -70,16 +76,10 @@
* Launches AttemptAccess with --permit-illegal-access to execute an action,
* returning the OutputAnalyzer to analyze the output/exitCode.
*/
- private OutputAnalyzer tryActionPermittingIllegalAccess(String action,
- int count)
+ private OutputAnalyzer tryActionPermittingIllegalAccess(String action, int count)
throws Exception
{
- String arg = "" + count;
- return ProcessTools
- .executeTestJava("-cp", TEST_CLASSES, "--permit-illegal-access",
- TEST_MAIN, action, arg)
- .outputTo(System.out)
- .errorTo(System.out);
+ return tryAction(action, count, "--permit-illegal-access");
}
/**
@@ -195,6 +195,61 @@
}
/**
+ * Permit access to succeed with --add-exports. No warning should be printed.
+ */
+ public void testAccessWithAddExports() throws Exception {
+ tryAction("access", 1, "--add-exports", "java.base/sun.security.x509=ALL-UNNAMED")
+ .stdoutShouldNotContain(WARNING)
+ .stdoutShouldNotContain("IllegalAccessException")
+ .stderrShouldNotContain(WARNING)
+ .stderrShouldNotContain("IllegalAccessException")
+ .shouldHaveExitValue(0);
+ }
+
+ /**
+ * Permit access to succeed with --add-exports and --permit-illegal-access.
+ * The only warning emitted should be the startup warning.
+ */
+ public void testAccessWithePermittedAddExports() throws Exception {
+ tryAction("access", 1, "--permit-illegal-access",
+ "--add-exports", "java.base/sun.security.x509=ALL-UNNAMED")
+ .stdoutShouldNotContain(WARNING)
+ .stdoutShouldNotContain("IllegalAccessException")
+ .stderrShouldContain(STARTUP_WARNING)
+ .stderrShouldNotContain("IllegalAccessException")
+ .stderrShouldNotContain(ILLEGAL_ACCESS_WARNING)
+ .shouldHaveExitValue(0);
+ }
+
+ /**
+ * Permit setAccessible to succeed with --add-opens. No warning should be printed.
+ */
+ public void testSetAccessibleWithAddOpens() throws Exception {
+ tryAction("setAccessible", 1, "--add-opens", "java.base/java.lang=ALL-UNNAMED")
+ .stdoutShouldNotContain(WARNING)
+ .stdoutShouldNotContain("InaccessibleObjectException")
+ .stderrShouldNotContain(WARNING)
+ .stderrShouldNotContain("InaccessibleObjectException")
+ .shouldHaveExitValue(0);
+ }
+
+ /**
+ * Permit setAccessible to succeed with both --add-opens and --permit-illegal-access.
+ * The only warning emitted should be the startup warning.
+ */
+ public void testSetAccessiblePermittedWithAddOpens() throws Exception {
+ tryAction("setAccessible", 1, "--permit-illegal-access",
+ "--add-opens", "java.base/java.lang=ALL-UNNAMED")
+ .stdoutShouldNotContain(WARNING)
+ .stdoutShouldNotContain("InaccessibleObjectException")
+ .stderrShouldContain(STARTUP_WARNING)
+ .stderrShouldNotContain("InaccessibleObjectException")
+ .stderrShouldNotContain(ILLEGAL_ACCESS_WARNING)
+ .shouldHaveExitValue(0);
+ }
+
+
+ /**
* Returns the number of lines in the given input that contain the
* given char sequence.
*/