diff --git a/jdk/make/copy/Copy-java.base.gmk b/jdk/make/copy/Copy-java.base.gmk
index 07fe8f3d56e..2f26a834718 100644
--- a/jdk/make/copy/Copy-java.base.gmk
+++ b/jdk/make/copy/Copy-java.base.gmk
@@ -100,8 +100,7 @@ else
# Allow override by ALT_JVMCFG_SRC if it exists
JVMCFG_SRC := $(if $(wildcard $(ALT_JVMCFG_SRC)),$(ALT_JVMCFG_SRC),$(JVMCFG_SRC))
endif
-JVMCFG_DIR := $(LIB_DST_DIR)$(OPENJDK_TARGET_CPU_LIBDIR)
-JVMCFG := $(JVMCFG_DIR)/jvm.cfg
+JVMCFG := $(LIB_DST_DIR)/jvm.cfg
# To do: should this also support -zeroshark?
diff --git a/jdk/make/copy/Copy-java.desktop.gmk b/jdk/make/copy/Copy-java.desktop.gmk
index 51db98a356a..49d6b86aeb2 100644
--- a/jdk/make/copy/Copy-java.desktop.gmk
+++ b/jdk/make/copy/Copy-java.desktop.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2016, 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
@@ -64,7 +64,7 @@ ifneq ($(FREETYPE_BUNDLE_LIB_PATH), )
ifeq ($(OPENJDK_TARGET_OS), windows)
FREETYPE_TARGET_LIB := $(LIB_DST_DIR)/$(call SHARED_LIBRARY,freetype)
else
- FREETYPE_TARGET_LIB := $(LIB_DST_DIR)$(OPENJDK_TARGET_CPU_LIBDIR)/$(call SHARED_LIBRARY,freetype).6
+ FREETYPE_TARGET_LIB := $(LIB_DST_DIR)/$(call SHARED_LIBRARY,freetype).6
endif
# We can't use $(install-file) in this rule because it preserves symbolic links and
diff --git a/jdk/make/launcher/Launcher-java.base.gmk b/jdk/make/launcher/Launcher-java.base.gmk
index 4d4b981c097..f70d90029a6 100644
--- a/jdk/make/launcher/Launcher-java.base.gmk
+++ b/jdk/make/launcher/Launcher-java.base.gmk
@@ -74,7 +74,7 @@ $(eval $(call SetupBuildLauncher, keytool, \
BUILD_JEXEC :=
BUILD_JEXEC_SRC :=
BUILD_JEXEC_INC :=
-BUILD_JEXEC_DST_DIR := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base$(OPENJDK_TARGET_CPU_LIBDIR)
+BUILD_JEXEC_DST_DIR := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base
#
# UNHANDLED:
@@ -138,7 +138,7 @@ endif
BUILD_JSPAWNHELPER :=
BUILD_JSPAWNHELPER_SRC := $(JDK_TOPDIR)/src/java.base/unix/native/jspawnhelper
JSPAWNHELPER_CFLAGS := -I$(JDK_TOPDIR)/src/java.base/unix/native/libjava
-BUILD_JSPAWNHELPER_DST_DIR := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base$(OPENJDK_TARGET_CPU_LIBDIR)
+BUILD_JSPAWNHELPER_DST_DIR := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base
LINK_JSPAWNHELPER_OBJECTS := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjava/childproc.o
BUILD_JSPAWNHELPER_LDFLAGS :=
diff --git a/jdk/make/launcher/Launcher-jdk.aot.gmk b/jdk/make/launcher/Launcher-jdk.aot.gmk
new file mode 100644
index 00000000000..a827a66bc35
--- /dev/null
+++ b/jdk/make/launcher/Launcher-jdk.aot.gmk
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2016, 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.
+#
+
+include LauncherCommon.gmk
+
+$(eval $(call SetupBuildLauncher, jaotc, \
+ MAIN_CLASS := jdk.tools.jaotc.Main, \
+ JAVA_ARGS := -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI \
+ -XX:+UseAOT \
+ -Djvmci.UseProfilingInformation=false \
+ -Dgraal.UseExceptionProbability=false \
+ -Djvmci.Compiler=graal \
+ --add-modules ALL-DEFAULT \
+ , \
+))
diff --git a/jdk/make/launcher/LauncherCommon.gmk b/jdk/make/launcher/LauncherCommon.gmk
index 1bef88f8a42..a4178039d6e 100644
--- a/jdk/make/launcher/LauncherCommon.gmk
+++ b/jdk/make/launcher/LauncherCommon.gmk
@@ -32,13 +32,13 @@ else
ifeq ($(OPENJDK_TARGET_OS), windows)
DISABLE_MAPFILES := true
endif
- ORIGIN_ARG := $(call SET_EXECUTABLE_ORIGIN,/../lib$(OPENJDK_TARGET_CPU_LIBDIR)/jli)
+ ORIGIN_ARG := $(call SET_EXECUTABLE_ORIGIN,/../lib/jli)
# Applications expect to be able to link against libjawt without invoking
# System.loadLibrary("jawt") first. This was the behaviour described in the
# devloper documentation of JAWT and what worked with OpenJDK6.
ifneq ($(findstring $(OPENJDK_TARGET_OS), linux solaris), )
- ORIGIN_ARG += $(call SET_EXECUTABLE_ORIGIN,/../lib$(OPENJDK_TARGET_CPU_LIBDIR))
+ ORIGIN_ARG += $(call SET_EXECUTABLE_ORIGIN,/../lib)
endif
endif
@@ -190,9 +190,9 @@ define SetupBuildLauncherBody
$$(ORIGIN_ARG) \
$$($1_LDFLAGS), \
LDFLAGS_linux := \
- -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base$(OPENJDK_TARGET_CPU_LIBDIR)/jli, \
+ -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base/jli, \
LDFLAGS_solaris := $$($1_LDFLAGS_solaris) \
- -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base$(OPENJDK_TARGET_CPU_LIBDIR)/jli, \
+ -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base/jli, \
MAPFILE := $$($1_MAPFILE), \
LIBS := $(JDKEXE_LIBS) $$($1_LIBS), \
LIBS_unix := $$($1_LIBS_unix), \
diff --git a/jdk/make/lib/Awt2dLibraries.gmk b/jdk/make/lib/Awt2dLibraries.gmk
index 09423e4d770..670434669af 100644
--- a/jdk/make/lib/Awt2dLibraries.gmk
+++ b/jdk/make/lib/Awt2dLibraries.gmk
@@ -418,6 +418,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBLCMS, \
DISABLED_WARNINGS_gcc := format-nonliteral type-limits misleading-indentation, \
DISABLED_WARNINGS_clang := tautological-compare, \
DISABLED_WARNINGS_solstudio := E_STATEMENT_NOT_REACHED, \
+ DISABLED_WARNINGS_microsoft := 4819, \
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/liblcms/mapfile-vers, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
@@ -681,7 +682,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBFONTMANAGER, \
DISABLED_WARNINGS_CXX_solstudio := \
truncwarn wvarhidenmem wvarhidemem wbadlkginit identexpected \
hidevf w_novirtualdescr arrowrtn2, \
- DISABLED_WARNINGS_microsoft := 4267 4244 4018 4090 4996 4146 4334, \
+ DISABLED_WARNINGS_microsoft := 4267 4244 4018 4090 4996 4146 4334 4819, \
MAPFILE := $(BUILD_LIBFONTMANAGER_MAPFILE), \
LDFLAGS := $(subst -Wl$(COMMA)-z$(COMMA)defs,,$(LDFLAGS_JDKLIB)) $(LDFLAGS_CXX_JDK) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk
index 27dad3553ee..6fba2fa6ab3 100644
--- a/jdk/make/lib/CoreLibraries.gmk
+++ b/jdk/make/lib/CoreLibraries.gmk
@@ -340,9 +340,6 @@ endif
LIBJLI_CFLAGS += $(addprefix -I, $(LIBJLI_SRC_DIRS))
-# Append defines depending on target platform
-LIBJLI_CFLAGS += $(OPENJDK_TARGET_CPU_JLI_CFLAGS)
-
ifneq ($(USE_EXTERNAL_LIBZ), true)
LIBJLI_CFLAGS += $(ZLIB_CPPFLAGS)
LIBJLI_EXTRA_FILES += \
diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers
index 5d7cc4a655f..65336defa6d 100644
--- a/jdk/make/mapfiles/libjava/mapfile-vers
+++ b/jdk/make/mapfiles/libjava/mapfile-vers
@@ -150,7 +150,6 @@ SUNWprivate_1.1 {
Java_java_lang_StrictMath_atan;
Java_java_lang_StrictMath_atan2;
Java_java_lang_StrictMath_cos;
- Java_java_lang_StrictMath_exp;
Java_java_lang_StrictMath_log;
Java_java_lang_StrictMath_log10;
Java_java_lang_StrictMath_sin;
diff --git a/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java b/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java
index 3b81f6b421f..99f6d0f8bd7 100644
--- a/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java
+++ b/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java
@@ -26,6 +26,7 @@
package build.tools.jigsaw;
import java.io.IOException;
+import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.module.Configuration;
import java.lang.module.ModuleDescriptor;
@@ -44,7 +45,8 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Function;
-import java.util.stream.Collectors;
+
+import static java.util.stream.Collectors.*;
import static java.lang.module.ModuleDescriptor.Requires.Modifier.TRANSITIVE;
/**
@@ -69,42 +71,25 @@ public class GenGraphs {
.map(ModuleReference::descriptor)
.filter(m -> (m.name().startsWith("java.") &&
!m.name().equals("java.smartcardio")))
- .collect(Collectors.toSet()));
+ .collect(toSet()));
Set jdkModules
= new TreeSet<>(finder.findAll().stream()
.map(ModuleReference::descriptor)
.filter(m -> !javaSEModules.contains(m))
- .collect(Collectors.toSet()));
+ .collect(toSet()));
- GenGraphs genGraphs = new GenGraphs(javaSEModules, jdkModules);
+ GenGraphs genGraphs = new GenGraphs(dir, javaSEModules, jdkModules);
Set mods = new HashSet<>();
for (ModuleReference mref: finder.findAll()) {
- ModuleDescriptor descriptor = mref.descriptor();
- String name = descriptor.name();
- mods.add(name);
- Configuration cf = Configuration.empty()
- .resolveRequires(finder,
- ModuleFinder.of(),
- Set.of(name));
- genGraphs.genDotFile(dir, name, cf);
+ mods.add(mref.descriptor().name());
+ genGraphs.genDotFile(mref);
}
- Configuration cf = Configuration.empty()
- .resolveRequires(finder,
- ModuleFinder.of(),
- mods);
- genGraphs.genDotFile(dir, "jdk", cf);
+ // all modules
+ genGraphs.genDotFile("jdk", mods);
}
- private final Set javaGroup;
- private final Set jdkGroup;
-
- GenGraphs(Set javaGroup, Set jdkGroup) {
- this.javaGroup = Collections.unmodifiableSet(javaGroup);
- this.jdkGroup = Collections.unmodifiableSet(jdkGroup);
- }
-
private static final String ORANGE = "#e76f00";
private static final String BLUE = "#437291";
private static final String GRAY = "#dddddd";
@@ -145,23 +130,70 @@ public class GenGraphs {
}
- private void genDotFile(Path dir, String name, Configuration cf) throws IOException {
- try (PrintStream out
- = new PrintStream(Files.newOutputStream(dir.resolve(name + ".dot")))) {
+ private final Path dir;
+ private final Set javaGroup;
+ private final Set jdkGroup;
- Map nameToModule;
- if (name.equals("java.se.ee")) {
- nameToModule = cf.modules().stream()
- .map(ResolvedModule::reference)
- .map(ModuleReference::descriptor)
- .filter(md -> !md.name().startsWith("jdk."))
- .collect(Collectors.toMap(ModuleDescriptor::name, Function.identity()));
- } else {
- nameToModule = cf.modules().stream()
- .map(ResolvedModule::reference)
- .map(ModuleReference::descriptor)
- .collect(Collectors.toMap(ModuleDescriptor::name, Function.identity()));
+ GenGraphs(Path dir, Set javaGroup, Set jdkGroup) {
+ this.dir = dir;
+ this.javaGroup = Collections.unmodifiableSet(javaGroup);
+ this.jdkGroup = Collections.unmodifiableSet(jdkGroup);
+ }
+
+ /**
+ * Generates a dot file for the given module reference as the root.
+ */
+ void genDotFile(ModuleReference mref) throws IOException {
+ String name = mref.descriptor().name();
+ genDotFile(name, Set.of(name));
+ }
+
+ /**
+ * Generates a dot file for the given set of root modules.
+ */
+ void genDotFile(String name, Set roots) throws IOException {
+ Configuration cf =
+ Configuration.empty().resolveRequires(ModuleFinder.ofSystem(),
+ ModuleFinder.of(),
+ roots);
+
+ Set mds = cf.modules().stream()
+ .map(ResolvedModule::reference)
+ .map(ModuleReference::descriptor)
+ .collect(toSet());
+
+ // generate a dot file for the resolved graph
+ try (OutputStream os = Files.newOutputStream(dir.resolve(name + ".dot"));
+ PrintStream out = new PrintStream(os)) {
+ printGraph(out, name, gengraph(cf),
+ mds.stream()
+ .collect(toMap(ModuleDescriptor::name, Function.identity()))
+ );
+ }
+
+ if (name.equals("java.se") || name.equals("java.se.ee")) {
+ // generate a dot file for Java SE module graph
+ try (OutputStream os = Files.newOutputStream(dir.resolve(name + "-spec.dot"));
+ PrintStream out = new PrintStream(os)) {
+ // transitive reduction on the graph of `requires transitive` edges
+ // filter out jdk.* modules which are implementation dependences
+ Graph graph = requiresTransitiveGraph(cf, true);
+ printGraph(out, name, graph,
+ mds.stream()
+ .filter(md -> !md.name().startsWith("jdk.") &&
+ graph.nodes().contains(md.name()))
+ .collect(toMap(ModuleDescriptor::name, Function.identity()))
+ );
}
+ }
+ }
+
+ private void printGraph(PrintStream out,
+ String name,
+ Graph graph,
+ Map nameToModule)
+ throws IOException
+ {
Set descriptors = new TreeSet<>(nameToModule.values());
out.format("digraph \"%s\" {%n", name);
@@ -182,13 +214,13 @@ public class GenGraphs {
// same ranks
ranks.stream()
- .forEach(group -> out.format("{rank=same %s}%n",
- descriptors.stream()
- .map(ModuleDescriptor::name)
- .filter(group::contains)
- .map(mn -> "\"" + mn + "\"")
- .collect(Collectors.joining(","))
- ));
+ .map(group -> descriptors.stream()
+ .map(ModuleDescriptor::name)
+ .filter(group::contains)
+ .map(mn -> "\"" + mn + "\"")
+ .collect(joining(",")))
+ .filter(group -> group.length() > 0)
+ .forEach(group -> out.format("{rank=same %s}%n", group));
descriptors.stream()
.filter(jdkGroup::contains)
@@ -196,30 +228,28 @@ public class GenGraphs {
.forEach(mn -> out.format(" \"%s\" [fontcolor=\"%s\", group=%s];%n",
mn, BLUE, "jdk"));
- // transitive reduction
- Graph graph = gengraph(cf);
- descriptors.forEach(md -> {
- String mn = md.name();
- Set requiresTransitive = md.requires().stream()
- .filter(d -> d.modifiers().contains(TRANSITIVE))
- .map(d -> d.name())
- .collect(Collectors.toSet());
+ descriptors.stream()
+ .forEach(md -> {
+ String mn = md.name();
+ Set requiresTransitive = md.requires().stream()
+ .filter(d -> d.modifiers().contains(TRANSITIVE))
+ .map(d -> d.name())
+ .collect(toSet());
- graph.adjacentNodes(mn)
- .stream()
- .filter(nameToModule::containsKey)
- .forEach(dn -> {
- String attr = dn.equals("java.base") ? REQUIRES_BASE
- : (requiresTransitive.contains(dn) ? REEXPORTS : REQUIRES);
- int w = weightOf(mn, dn);
- if (w > 1)
- attr += "weight=" + w;
- out.format(" \"%s\" -> \"%s\" [%s];%n", mn, dn, attr);
- });
- });
+ graph.adjacentNodes(mn)
+ .stream()
+ .filter(nameToModule::containsKey)
+ .forEach(dn -> {
+ String attr = dn.equals("java.base") ? REQUIRES_BASE
+ : (requiresTransitive.contains(dn) ? REEXPORTS : REQUIRES);
+ int w = weightOf(mn, dn);
+ if (w > 1)
+ attr += "weight=" + w;
+ out.format(" \"%s\" -> \"%s\" [%s];%n", mn, dn, attr);
+ });
+ });
out.println("}");
- }
}
/**
@@ -239,7 +269,7 @@ public class GenGraphs {
.map(ResolvedModule::name)
.forEach(target -> builder.addEdge(mn, target));
}
- Graph rpg = requiresTransitiveGraph(cf);
+ Graph rpg = requiresTransitiveGraph(cf, false);
return builder.build().reduce(rpg);
}
@@ -247,13 +277,14 @@ public class GenGraphs {
* Returns a Graph containing only requires transitive edges
* with transitive reduction.
*/
- private Graph requiresTransitiveGraph(Configuration cf) {
+ private Graph requiresTransitiveGraph(Configuration cf, boolean includeBase) {
Graph.Builder builder = new Graph.Builder<>();
for (ResolvedModule resolvedModule : cf.modules()) {
ModuleDescriptor descriptor = resolvedModule.reference().descriptor();
String mn = descriptor.name();
descriptor.requires().stream()
- .filter(d -> d.modifiers().contains(TRANSITIVE))
+ .filter(d -> d.modifiers().contains(TRANSITIVE)
+ || (includeBase && d.name().equals("java.base")))
.map(d -> d.name())
.forEach(d -> builder.addEdge(mn, d));
}
diff --git a/jdk/src/java.base/macosx/native/libjli/java_md_macosx.c b/jdk/src/java.base/macosx/native/libjli/java_md_macosx.c
index c6c36594a9d..f21201ced6a 100644
--- a/jdk/src/java.base/macosx/native/libjli/java_md_macosx.c
+++ b/jdk/src/java.base/macosx/native/libjli/java_md_macosx.c
@@ -171,8 +171,6 @@ struct NSAppArgs {
* Main
*/
-#define GetArch() GetArchPath(CURRENT_DATA_MODEL)
-
/* Store the name of the executable once computed */
static char *execname = NULL;
@@ -184,16 +182,6 @@ GetExecName() {
return execname;
}
-const char *
-GetArchPath(int nbits)
-{
- switch(nbits) {
- default:
- return LIBARCHNAME;
- }
-}
-
-
/*
* Exports the JNI interface from libjli
*
@@ -211,7 +199,7 @@ static InvocationFunctions *GetExportedJNIFunctions() {
if (sExportedJNIFunctions != NULL) return sExportedJNIFunctions;
char jrePath[PATH_MAX];
- jboolean gotJREPath = GetJREPath(jrePath, sizeof(jrePath), GetArch(), JNI_FALSE);
+ jboolean gotJREPath = GetJREPath(jrePath, sizeof(jrePath), JNI_FALSE);
if (!gotJREPath) {
JLI_ReportErrorMessage("Failed to GetJREPath()");
return NULL;
@@ -229,7 +217,7 @@ static InvocationFunctions *GetExportedJNIFunctions() {
}
char jvmPath[PATH_MAX];
- jboolean gotJVMPath = GetJVMPath(jrePath, preferredJVM, jvmPath, sizeof(jvmPath), GetArch(), CURRENT_DATA_MODEL);
+ jboolean gotJVMPath = GetJVMPath(jrePath, preferredJVM, jvmPath, sizeof(jvmPath), CURRENT_DATA_MODEL);
if (!gotJVMPath) {
JLI_ReportErrorMessage("Failed to GetJVMPath()");
return NULL;
@@ -390,7 +378,6 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
/* Check data model flags, and exec process, if needed */
{
- char *arch = (char *)GetArch(); /* like sparc or sparcv9 */
char * jvmtype = NULL;
int argc = *pargc;
char **argv = *pargv;
@@ -462,7 +449,7 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
jvmpath does not exist */
if (wanted == running) {
/* Find out where the JRE is that we will be using. */
- if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) {
+ if (!GetJREPath(jrepath, so_jrepath, JNI_FALSE) ) {
JLI_ReportErrorMessage(JRE_ERROR1);
exit(2);
}
@@ -481,7 +468,7 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
exit(4);
}
- if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, arch, wanted)) {
+ if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, wanted)) {
JLI_ReportErrorMessage(CFG_ERROR8, jvmtype, jvmpath);
exit(4);
}
@@ -502,7 +489,7 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
#if defined(DUAL_MODE)
if (running != wanted) {
/* Find out where the JRE is that we will be using. */
- if (!GetJREPath(jrepath, so_jrepath, GetArchPath(wanted), JNI_TRUE)) {
+ if (!GetJREPath(jrepath, so_jrepath, JNI_TRUE)) {
/* give up and let other code report error message */
JLI_ReportErrorMessage(JRE_ERROR2, wanted);
exit(1);
@@ -526,7 +513,7 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
}
/* exec child can do error checking on the existence of the path */
- jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, GetArchPath(wanted), wanted);
+ jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, wanted);
}
#else /* ! DUAL_MODE */
JLI_ReportErrorMessage(JRE_ERROR2, wanted);
@@ -579,7 +566,7 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
*/
static jboolean
GetJVMPath(const char *jrepath, const char *jvmtype,
- char *jvmpath, jint jvmpathsize, const char * arch, int bitsWanted)
+ char *jvmpath, jint jvmpathsize, int bitsWanted)
{
struct stat s;
@@ -613,7 +600,7 @@ GetJVMPath(const char *jrepath, const char *jvmtype,
* Find path to JRE based on .exe's location or registry settings.
*/
static jboolean
-GetJREPath(char *path, jint pathsize, const char * arch, jboolean speculative)
+GetJREPath(char *path, jint pathsize, jboolean speculative)
{
char libjava[MAXPATHLEN];
@@ -841,7 +828,7 @@ static void* hSplashLib = NULL;
void* SplashProcAddress(const char* name) {
if (!hSplashLib) {
char jrePath[PATH_MAX];
- if (!GetJREPath(jrePath, sizeof(jrePath), GetArch(), JNI_FALSE)) {
+ if (!GetJREPath(jrePath, sizeof(jrePath), JNI_FALSE)) {
JLI_ReportErrorMessage(JRE_ERROR1);
return NULL;
}
diff --git a/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/PackerImpl.java b/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/PackerImpl.java
index 203fde39335..fa36c3feda4 100644
--- a/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/PackerImpl.java
+++ b/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/PackerImpl.java
@@ -317,7 +317,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
this(null, je);
}
boolean isClassFile() {
- if (!name.endsWith(".class")) {
+ if (!name.endsWith(".class") || name.endsWith("module-info.class")) {
return false;
}
for (String prefix = name;;) {
diff --git a/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties b/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties
index 14bc2ad8831..c31b1a03a50 100644
--- a/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties
+++ b/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties
@@ -14,15 +14,6 @@ pack.code.attribute.CharacterRangeTable = NH[PHPOHIIH]
pack.class.attribute.SourceID = RUH
pack.class.attribute.CompilationID = RUH
-# Module attributes, supported by the tool and not JSR-200
-pack.class.attribute.Module = RUHFHNH[RUHFH]NH[RUHFHNH[RUH]]NH[RUHFHNH[RUH]]NH[RCH]NH[RCHNH[RCH]]
-pack.class.attribute.ModulePackages = NH[RUH]
-pack.class.attribute.ModuleVersion = RUH
-pack.class.attribute.ModuleMainClass = RCH
-pack.class.attribute.ModuleTarget = RUHRUHRUH
-pack.class.attribute.ModuleHashes = RUHNH[RUHNH[B]]
-
-
# Note: Zero-length ("marker") attributes do not need to be specified here.
# They are automatically defined to have an empty layout.
#pack.class.attribute.Deprecated =
diff --git a/jdk/src/java.base/share/classes/java/lang/FdLibm.java b/jdk/src/java.base/share/classes/java/lang/FdLibm.java
index dfecf79bb18..e1d3085ba70 100644
--- a/jdk/src/java.base/share/classes/java/lang/FdLibm.java
+++ b/jdk/src/java.base/share/classes/java/lang/FdLibm.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, 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
@@ -79,7 +79,8 @@ class FdLibm {
*/
private static double __LO(double x, int low) {
long transX = Double.doubleToRawLongBits(x);
- return Double.longBitsToDouble((transX & 0xFFFF_FFFF_0000_0000L)|low );
+ return Double.longBitsToDouble((transX & 0xFFFF_FFFF_0000_0000L) |
+ (low & 0x0000_0000_FFFF_FFFFL));
}
/**
@@ -96,7 +97,8 @@ class FdLibm {
*/
private static double __HI(double x, int high) {
long transX = Double.doubleToRawLongBits(x);
- return Double.longBitsToDouble((transX & 0x0000_0000_FFFF_FFFFL)|( ((long)high)) << 32 );
+ return Double.longBitsToDouble((transX & 0x0000_0000_FFFF_FFFFL) |
+ ( ((long)high)) << 32 );
}
/**
@@ -580,4 +582,152 @@ class FdLibm {
return s * z;
}
}
+
+ /**
+ * Returns the exponential of x.
+ *
+ * Method
+ * 1. Argument reduction:
+ * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
+ * Given x, find r and integer k such that
+ *
+ * x = k*ln2 + r, |r| <= 0.5*ln2.
+ *
+ * Here r will be represented as r = hi-lo for better
+ * accuracy.
+ *
+ * 2. Approximation of exp(r) by a special rational function on
+ * the interval [0,0.34658]:
+ * Write
+ * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
+ * We use a special Reme algorithm on [0,0.34658] to generate
+ * a polynomial of degree 5 to approximate R. The maximum error
+ * of this polynomial approximation is bounded by 2**-59. In
+ * other words,
+ * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
+ * (where z=r*r, and the values of P1 to P5 are listed below)
+ * and
+ * | 5 | -59
+ * | 2.0+P1*z+...+P5*z - R(z) | <= 2
+ * | |
+ * The computation of exp(r) thus becomes
+ * 2*r
+ * exp(r) = 1 + -------
+ * R - r
+ * r*R1(r)
+ * = 1 + r + ----------- (for better accuracy)
+ * 2 - R1(r)
+ * where
+ * 2 4 10
+ * R1(r) = r - (P1*r + P2*r + ... + P5*r ).
+ *
+ * 3. Scale back to obtain exp(x):
+ * From step 1, we have
+ * exp(x) = 2^k * exp(r)
+ *
+ * Special cases:
+ * exp(INF) is INF, exp(NaN) is NaN;
+ * exp(-INF) is 0, and
+ * for finite argument, only exp(0)=1 is exact.
+ *
+ * Accuracy:
+ * according to an error analysis, the error is always less than
+ * 1 ulp (unit in the last place).
+ *
+ * Misc. info.
+ * For IEEE double
+ * if x > 7.09782712893383973096e+02 then exp(x) overflow
+ * if x < -7.45133219101941108420e+02 then exp(x) underflow
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+ static class Exp {
+ private static final double one = 1.0;
+ private static final double[] half = {0.5, -0.5,};
+ private static final double huge = 1.0e+300;
+ private static final double twom1000= 0x1.0p-1000; // 9.33263618503218878990e-302 = 2^-1000
+ private static final double o_threshold= 0x1.62e42fefa39efp9; // 7.09782712893383973096e+02
+ private static final double u_threshold= -0x1.74910d52d3051p9; // -7.45133219101941108420e+02;
+ private static final double[] ln2HI ={ 0x1.62e42feep-1, // 6.93147180369123816490e-01
+ -0x1.62e42feep-1}; // -6.93147180369123816490e-01
+ private static final double[] ln2LO ={ 0x1.a39ef35793c76p-33, // 1.90821492927058770002e-10
+ -0x1.a39ef35793c76p-33}; // -1.90821492927058770002e-10
+ private static final double invln2 = 0x1.71547652b82fep0; // 1.44269504088896338700e+00
+
+ private static final double P1 = 0x1.555555555553ep-3; // 1.66666666666666019037e-01
+ private static final double P2 = -0x1.6c16c16bebd93p-9; // -2.77777777770155933842e-03
+ private static final double P3 = 0x1.1566aaf25de2cp-14; // 6.61375632143793436117e-05
+ private static final double P4 = -0x1.bbd41c5d26bf1p-20; // -1.65339022054652515390e-06
+ private static final double P5 = 0x1.6376972bea4d0p-25; // 4.13813679705723846039e-08
+
+ // should be able to forgo strictfp due to controlled over/underflow
+ public static strictfp double compute(double x) {
+ double y;
+ double hi = 0.0;
+ double lo = 0.0;
+ double c;
+ double t;
+ int k = 0;
+ int xsb;
+ /*unsigned*/ int hx;
+
+ hx = __HI(x); /* high word of x */
+ xsb = (hx >> 31) & 1; /* sign bit of x */
+ hx &= 0x7fffffff; /* high word of |x| */
+
+ /* filter out non-finite argument */
+ if (hx >= 0x40862E42) { /* if |x| >= 709.78... */
+ if (hx >= 0x7ff00000) {
+ if (((hx & 0xfffff) | __LO(x)) != 0)
+ return x + x; /* NaN */
+ else
+ return (xsb == 0) ? x : 0.0; /* exp(+-inf) = {inf, 0} */
+ }
+ if (x > o_threshold)
+ return huge * huge; /* overflow */
+ if (x < u_threshold) // unsigned compare needed here?
+ return twom1000 * twom1000; /* underflow */
+ }
+
+ /* argument reduction */
+ if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */
+ if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
+ hi = x - ln2HI[xsb];
+ lo=ln2LO[xsb];
+ k = 1 - xsb - xsb;
+ } else {
+ k = (int)(invln2 * x + half[xsb]);
+ t = k;
+ hi = x - t*ln2HI[0]; /* t*ln2HI is exact here */
+ lo = t*ln2LO[0];
+ }
+ x = hi - lo;
+ } else if (hx < 0x3e300000) { /* when |x|<2**-28 */
+ if (huge + x > one)
+ return one + x; /* trigger inexact */
+ } else {
+ k = 0;
+ }
+
+ /* x is now in primary range */
+ t = x * x;
+ c = x - t*(P1 + t*(P2 + t*(P3 + t*(P4 + t*P5))));
+ if (k == 0)
+ return one - ((x*c)/(c - 2.0) - x);
+ else
+ y = one - ((lo - (x*c)/(2.0 - c)) - hi);
+
+ if(k >= -1021) {
+ y = __HI(y, __HI(y) + (k << 20)); /* add k to y's exponent */
+ return y;
+ } else {
+ y = __HI(y, __HI(y) + ((k + 1000) << 20)); /* add k to y's exponent */
+ return y * twom1000;
+ }
+ }
+ }
}
diff --git a/jdk/src/java.base/share/classes/java/lang/StackTraceElement.java b/jdk/src/java.base/share/classes/java/lang/StackTraceElement.java
index 98536259a92..d95ea5ef826 100644
--- a/jdk/src/java.base/share/classes/java/lang/StackTraceElement.java
+++ b/jdk/src/java.base/share/classes/java/lang/StackTraceElement.java
@@ -26,10 +26,13 @@
package java.lang;
import jdk.internal.loader.BuiltinClassLoader;
-import jdk.internal.misc.SharedSecrets;
import jdk.internal.misc.VM;
import jdk.internal.module.ModuleHashes;
+import jdk.internal.module.ModuleReferenceImpl;
+import java.lang.module.ModuleDescriptor.Version;
+import java.lang.module.ModuleReference;
+import java.lang.module.ResolvedModule;
import java.lang.reflect.Layer;
import java.lang.reflect.Module;
import java.util.HashSet;
@@ -477,13 +480,16 @@ public final class StackTraceElement implements java.io.Serializable {
static Set HASHED_MODULES = hashedModules();
static Set hashedModules() {
- Module javaBase = Layer.boot().findModule("java.base").get();
- Optional ohashes =
- SharedSecrets.getJavaLangModuleAccess()
- .hashes(javaBase.getDescriptor());
- if (ohashes.isPresent()) {
- Set names = new HashSet<>(ohashes.get().names());
+ Optional resolvedModule = Layer.boot()
+ .configuration()
+ .findModule("java.base");
+ assert resolvedModule.isPresent();
+ ModuleReference mref = resolvedModule.get().reference();
+ assert mref instanceof ModuleReferenceImpl;
+ ModuleHashes hashes = ((ModuleReferenceImpl)mref).recordedHashes();
+ if (hashes != null) {
+ Set names = new HashSet<>(hashes.names());
names.add("java.base");
return names;
}
diff --git a/jdk/src/java.base/share/classes/java/lang/StrictMath.java b/jdk/src/java.base/share/classes/java/lang/StrictMath.java
index 1491a8478bc..63d895fa13c 100644
--- a/jdk/src/java.base/share/classes/java/lang/StrictMath.java
+++ b/jdk/src/java.base/share/classes/java/lang/StrictMath.java
@@ -227,7 +227,9 @@ public final class StrictMath {
* @return the value e{@code a},
* where e is the base of the natural logarithms.
*/
- public static native double exp(double a);
+ public static double exp(double a) {
+ return FdLibm.Exp.compute(a);
+ }
/**
* Returns the natural logarithm (base e) of a {@code double}
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
index 0c9da2c9e80..d195d3d3db8 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
@@ -172,6 +172,7 @@ public class MethodHandles {
* @throws IllegalAccessException if the access check specified above fails
* @throws SecurityException if denied by the security manager
* @since 9
+ * @see Lookup#dropLookupMode
*/
public static Lookup privateLookupIn(Class> targetClass, Lookup lookup) throws IllegalAccessException {
SecurityManager sm = System.getSecurityManager();
@@ -691,10 +692,15 @@ public class MethodHandles {
* A lookup object on a new lookup class
* {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object}
* may have some mode bits set to zero.
+ * Mode bits can also be
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#dropLookupMode directly cleared}.
+ * Once cleared, mode bits cannot be restored from the downgraded lookup object.
* The purpose of this is to restrict access via the new lookup object,
* so that it can access only names which can be reached by the original
* lookup object, and also by the new lookup class.
* @return the lookup modes, which limit the kinds of access performed by this lookup object
+ * @see #in
+ * @see #dropLookupMode
*/
public int lookupModes() {
return allowedModes & ALL_MODES;
@@ -748,7 +754,8 @@ public class MethodHandles {
* which may change due to this operation.
*
* @param requestedLookupClass the desired lookup class for the new lookup object
- * @return a lookup object which reports the desired lookup class
+ * @return a lookup object which reports the desired lookup class, or the same object
+ * if there is no change
* @throws NullPointerException if the argument is null
*/
public Lookup in(Class> requestedLookupClass) {
@@ -788,6 +795,40 @@ public class MethodHandles {
return new Lookup(requestedLookupClass, newModes);
}
+
+ /**
+ * Creates a lookup on the same lookup class which this lookup object
+ * finds members, but with a lookup mode that has lost the given lookup mode.
+ * The lookup mode to drop is one of {@link #PUBLIC PUBLIC}, {@link #MODULE
+ * MODULE}, {@link #PACKAGE PACKAGE}, {@link #PROTECTED PROTECTED} or {@link #PRIVATE PRIVATE}.
+ * {@link #PROTECTED PROTECTED} is always dropped and so the resulting lookup
+ * mode will never have this access capability. When dropping {@code PACKAGE}
+ * then the resulting lookup will not have {@code PACKAGE} or {@code PRIVATE}
+ * access. When dropping {@code MODULE} then the resulting lookup will not
+ * have {@code MODULE}, {@code PACKAGE}, or {@code PRIVATE} access. If {@code
+ * PUBLIC} is dropped then the resulting lookup has no access.
+ * @param modeToDrop the lookup mode to drop
+ * @return a lookup object which lacks the indicated mode, or the same object if there is no change
+ * @throws IllegalArgumentException if {@code modeToDrop} is not one of {@code PUBLIC},
+ * {@code MODULE}, {@code PACKAGE}, {@code PROTECTED} or {@code PRIVATE}
+ * @since 9
+ * @see MethodHandles#privateLookupIn
+ */
+ public Lookup dropLookupMode(int modeToDrop) {
+ int oldModes = lookupModes();
+ int newModes = oldModes & ~(modeToDrop | PROTECTED);
+ switch (modeToDrop) {
+ case PUBLIC: newModes &= ~(ALL_MODES); break;
+ case MODULE: newModes &= ~(PACKAGE | PRIVATE); break;
+ case PACKAGE: newModes &= ~(PRIVATE); break;
+ case PROTECTED:
+ case PRIVATE: break;
+ default: throw new IllegalArgumentException(modeToDrop + " is not a valid mode to drop");
+ }
+ if (newModes == oldModes) return this; // return self if no change
+ return new Lookup(lookupClass(), newModes);
+ }
+
// Make sure outer class is initialized first.
static { IMPL_NAMES.getClass(); }
diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java
index b527ffaeafb..b10d986ade9 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java
@@ -29,7 +29,6 @@ import java.io.InputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.UncheckedIOException;
-import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -38,7 +37,6 @@ import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -52,7 +50,7 @@ import static jdk.internal.module.Checks.*;
import static java.util.Objects.*;
import jdk.internal.module.Checks;
-import jdk.internal.module.ModuleHashes;
+import jdk.internal.module.ModuleInfo;
/**
@@ -123,8 +121,9 @@ public class ModuleDescriptor
private final Set mods;
private final String name;
+ private final Version compiledVersion;
- private Requires(Set ms, String mn) {
+ private Requires(Set ms, String mn, Version v) {
if (ms.isEmpty()) {
ms = Collections.emptySet();
} else {
@@ -132,11 +131,13 @@ public class ModuleDescriptor
}
this.mods = ms;
this.name = mn;
+ this.compiledVersion = v;
}
- private Requires(Set ms, String mn, boolean unused) {
+ private Requires(Set ms, String mn, Version v, boolean unused) {
this.mods = ms;
this.name = mn;
+ this.compiledVersion = v;
}
/**
@@ -157,13 +158,27 @@ public class ModuleDescriptor
return name;
}
+ /**
+ * Returns the version of the module if recorded at compile-time.
+ *
+ * @return The version of the module if recorded at compile-time
+ */
+ public Optional compiledVersion() {
+ return Optional.ofNullable(compiledVersion);
+ }
+
/**
* Compares this module dependence to another.
*
*
Two {@code Requires} objects are compared by comparing their
* module name lexicographically. Where the module names are equal then
* the sets of modifiers are compared based on a value computed from the
- * ordinal of each modifier.
+ * ordinal of each modifier. Where the module names are equal and the
+ * set of modifiers are equal then the version of the modules recorded
+ * at compile-time are compared. When comparing the versions recorded
+ * at compile-time then a dependence that has a recorded version is
+ * considered to succeed a dependence that does not have a recorded
+ * version.
*
* @return A negative integer, zero, or a positive integer if this module
* dependence is less than, equal to, or greater than the given
@@ -174,8 +189,24 @@ public class ModuleDescriptor
int c = this.name().compareTo(that.name());
if (c != 0)
return c;
- // same name, compare by modifiers
- return Long.compare(this.modsValue(), that.modsValue());
+
+ // modifiers
+ c = Long.compare(this.modsValue(), that.modsValue());
+ if (c != 0)
+ return c;
+
+ // compiledVersion
+ if (this.compiledVersion != null) {
+ if (that.compiledVersion != null)
+ c = this.compiledVersion.compareTo(that.compiledVersion);
+ else
+ c = 1;
+ } else {
+ if (that.compiledVersion != null)
+ c = -1;
+ }
+
+ return c;
}
/**
@@ -195,7 +226,9 @@ public class ModuleDescriptor
*
*
If the given object is not a {@code Requires} then this method
* returns {@code false}. Two module dependence objects are equal if
- * the module names are equal and set of modifiers are equal.
+ * the module names are equal, set of modifiers are equal, and the
+ * compiled version of both modules is equal or not recorded for
+ * both modules.
*
*
This method satisfies the general contract of the {@link
* java.lang.Object#equals(Object) Object.equals} method.
@@ -211,21 +244,25 @@ public class ModuleDescriptor
if (!(ob instanceof Requires))
return false;
Requires that = (Requires)ob;
- return (name.equals(that.name) && mods.equals(that.mods));
+ return name.equals(that.name) && mods.equals(that.mods)
+ && Objects.equals(compiledVersion, that.compiledVersion);
}
/**
* Computes a hash code for this module dependence.
*
- *
The hash code is based upon the module name and modifiers. It
- * satisfies the general contract of the {@link Object#hashCode
- * Object.hashCode} method.
+ *
The hash code is based upon the module name, modifiers, and the
+ * module version if recorded at compile time. It satisfies the general
+ * contract of the {@link Object#hashCode Object.hashCode} method.
*
* @return The hash-code value for this module dependence
*/
@Override
public int hashCode() {
- return name.hashCode() * 43 + mods.hashCode();
+ int hash = name.hashCode() * 43 + mods.hashCode();
+ if (compiledVersion != null)
+ hash = hash * 43 + compiledVersion.hashCode();
+ return hash;
}
/**
@@ -235,7 +272,13 @@ public class ModuleDescriptor
*/
@Override
public String toString() {
- return ModuleDescriptor.toString(mods, name);
+ String what;
+ if (compiledVersion != null) {
+ what = name() + " (@" + compiledVersion + ")";
+ } else {
+ what = name();
+ }
+ return ModuleDescriptor.toString(mods, what);
}
}
@@ -967,9 +1010,8 @@ public class ModuleDescriptor
}
-
- // From module declarations
private final String name;
+ private final Version version;
private final boolean open;
// Indicates if synthesised for a JAR file found on the module path
@@ -984,17 +1026,16 @@ public class ModuleDescriptor
private final Set uses;
private final Set provides;
- // "Extended" information, added post-compilation by tools
- private final Version version;
+ // Added post-compilation by tools
+ private final Set packages;
private final String mainClass;
private final String osName;
private final String osArch;
private final String osVersion;
- private final Set packages;
- private final ModuleHashes hashes;
private ModuleDescriptor(String name,
+ Version version,
boolean open,
boolean automatic,
boolean synthetic,
@@ -1003,16 +1044,14 @@ public class ModuleDescriptor
Set opens,
Set uses,
Set provides,
- Version version,
+ Set packages,
String mainClass,
String osName,
String osArch,
- String osVersion,
- Set packages,
- ModuleHashes hashes)
+ String osVersion)
{
-
this.name = name;
+ this.version = version;
this.open = open;
this.automatic = automatic;
this.synthetic = synthetic;
@@ -1020,18 +1059,16 @@ public class ModuleDescriptor
assert (requires.stream().map(Requires::name).distinct().count()
== requires.size());
this.requires = emptyOrUnmodifiableSet(requires);
-
this.exports = emptyOrUnmodifiableSet(exports);
this.opens = emptyOrUnmodifiableSet(opens);
this.uses = emptyOrUnmodifiableSet(uses);
this.provides = emptyOrUnmodifiableSet(provides);
- this.version = version;
+
+ this.packages = emptyOrUnmodifiableSet(packages);
this.mainClass = mainClass;
this.osName = osName;
this.osArch = osArch;
this.osVersion = osVersion;
- this.hashes = hashes;
- this.packages = emptyOrUnmodifiableSet(packages);
}
/**
@@ -1039,6 +1076,7 @@ public class ModuleDescriptor
*/
ModuleDescriptor(ModuleDescriptor md, Set pkgs) {
this.name = md.name;
+ this.version = md.version;
this.open = md.open;
this.automatic = md.automatic;
this.synthetic = md.synthetic;
@@ -1049,16 +1087,14 @@ public class ModuleDescriptor
this.uses = md.uses;
this.provides = md.provides;
- this.version = md.version;
+ Set packages = new HashSet<>(md.packages);
+ packages.addAll(pkgs);
+ this.packages = emptyOrUnmodifiableSet(packages);
+
this.mainClass = md.mainClass;
this.osName = md.osName;
this.osArch = md.osArch;
this.osVersion = md.osVersion;
- this.hashes = null; // need to ignore
-
- Set packages = new HashSet<>(md.packages);
- packages.addAll(pkgs);
- this.packages = emptyOrUnmodifiableSet(packages);
}
/**
@@ -1066,6 +1102,7 @@ public class ModuleDescriptor
* The arguments are pre-validated and sets are unmodifiable sets.
*/
ModuleDescriptor(String name,
+ Version version,
boolean open,
boolean automatic,
boolean synthetic,
@@ -1074,16 +1111,15 @@ public class ModuleDescriptor
Set opens,
Set uses,
Set provides,
- Version version,
+ Set packages,
String mainClass,
String osName,
String osArch,
String osVersion,
- Set packages,
- ModuleHashes hashes,
int hashCode,
boolean unused) {
this.name = name;
+ this.version = version;
this.open = open;
this.automatic = automatic;
this.synthetic = synthetic;
@@ -1093,12 +1129,10 @@ public class ModuleDescriptor
this.uses = uses;
this.provides = provides;
this.packages = packages;
- this.version = version;
this.mainClass = mainClass;
this.osName = osName;
this.osArch = osArch;
this.osVersion = osVersion;
- this.hashes = hashes;
this.hash = hashCode;
}
@@ -1284,13 +1318,6 @@ public class ModuleDescriptor
return packages;
}
- /**
- * Returns the object with the hashes of other modules
- */
- Optional hashes() {
- return Optional.ofNullable(hashes);
- }
-
/**
* A builder used for building {@link ModuleDescriptor} objects.
@@ -1317,15 +1344,13 @@ public class ModuleDescriptor
public static final class Builder {
final String name;
final boolean strict; // true if module names are checked
- boolean open;
+ final boolean open;
+ final boolean synthetic;
boolean automatic;
- boolean synthetic;
final Map requires = new HashMap<>();
-
final Map exports = new HashMap<>();
final Map opens = new HashMap<>();
final Set concealedPackages = new HashSet<>();
-
final Set uses = new HashSet<>();
final Map provides = new HashMap<>();
Version version;
@@ -1333,7 +1358,6 @@ public class ModuleDescriptor
String osArch;
String osVersion;
String mainClass;
- ModuleHashes hashes;
/**
* Initializes a new builder with the given module name.
@@ -1341,14 +1365,11 @@ public class ModuleDescriptor
* @param strict
* Indicates whether module names are checked or not
*/
- Builder(String name, boolean strict) {
- this.strict = strict;
+ Builder(String name, boolean strict, boolean open, boolean synthetic) {
this.name = (strict) ? requireModuleName(name) : name;
- }
-
- /* package */ Builder open(boolean open) {
+ this.strict = strict;
this.open = open;
- return this;
+ this.synthetic = synthetic;
}
/* package */ Builder automatic(boolean automatic) {
@@ -1356,10 +1377,20 @@ public class ModuleDescriptor
return this;
}
- /* package */ boolean isOpen() { return open; }
+ /**
+ * Returns the set of packages that are exported (unconditionally or
+ * unconditionally).
+ */
+ /* package */ Set exportedPackages() {
+ return exports.keySet();
+ }
- /* package */ boolean isAutomatic() {
- return automatic;
+ /**
+ * Returns the set of packages that are opened (unconditionally or
+ * unconditionally).
+ */
+ /* package */Set openPackages() {
+ return opens.keySet();
}
/**
@@ -1387,6 +1418,36 @@ public class ModuleDescriptor
return this;
}
+ /**
+ * Adds a dependence on a module with the given (and possibly empty)
+ * set of modifiers. The dependence includes the version of the
+ * module that that was recorded at compile-time.
+ *
+ * @param ms
+ * The set of modifiers
+ * @param mn
+ * The module name
+ * @param compiledVersion
+ * The version of the module recorded at compile-time
+ *
+ * @return This builder
+ *
+ * @throws IllegalArgumentException
+ * If the module name is {@code null}, is not a legal Java
+ * identifier, or is equal to the module name that this builder
+ * was initialized to build
+ * @throws IllegalStateException
+ * If the dependence on the module has already been declared
+ */
+ public Builder requires(Set ms,
+ String mn,
+ Version compiledVersion) {
+ Objects.requireNonNull(compiledVersion);
+ if (strict)
+ mn = requireModuleName(mn);
+ return requires(new Requires(ms, mn, compiledVersion));
+ }
+
/**
* Adds a dependence on a module with the given (and possibly empty)
* set of modifiers.
@@ -1408,7 +1469,7 @@ public class ModuleDescriptor
public Builder requires(Set ms, String mn) {
if (strict)
mn = requireModuleName(mn);
- return requires(new Requires(ms, mn));
+ return requires(new Requires(ms, mn, null));
}
/**
@@ -1705,17 +1766,6 @@ public class ModuleDescriptor
return opens(Collections.emptySet(), pn);
}
-
- // Used by ModuleInfo, after a packageFinder is invoked
- /* package */ Set exportedAndOpenPackages() {
- if (opens.isEmpty())
- return exports.keySet();
- Set result = new HashSet<>();
- result.addAll(exports.keySet());
- result.addAll(opens.keySet());
- return result;
- }
-
/**
* Adds a service dependence.
*
@@ -1789,7 +1839,6 @@ public class ModuleDescriptor
if (providerNames.isEmpty())
throw new IllegalArgumentException("Empty providers set");
providerNames.forEach(Checks::requireServiceProviderName);
-
provides.put(service, p);
return this;
}
@@ -1914,7 +1963,7 @@ public class ModuleDescriptor
* If {@code mainClass} is null or is not a legal Java identifier
*/
public Builder mainClass(String mc) {
- mainClass = requireJavaIdentifier("main class name", mc);
+ mainClass = requireBinaryName("main class name", mc);
return this;
}
@@ -1972,16 +2021,6 @@ public class ModuleDescriptor
return this;
}
- /* package */ Builder hashes(ModuleHashes hashes) {
- this.hashes = hashes;
- return this;
- }
-
- /* package */ Builder synthetic(boolean v) {
- this.synthetic = v;
- return this;
- }
-
/**
* Builds and returns a {@code ModuleDescriptor} from its components.
*
@@ -1990,7 +2029,9 @@ public class ModuleDescriptor
public ModuleDescriptor build() {
Set requires = new HashSet<>(this.requires.values());
- Set packages = new HashSet<>(exportedAndOpenPackages());
+ Set packages = new HashSet<>();
+ packages.addAll(exports.keySet());
+ packages.addAll(opens.keySet());
packages.addAll(concealedPackages);
Set exports = new HashSet<>(this.exports.values());
@@ -1999,6 +2040,7 @@ public class ModuleDescriptor
Set provides = new HashSet<>(this.provides.values());
return new ModuleDescriptor(name,
+ version,
open,
automatic,
synthetic,
@@ -2007,13 +2049,11 @@ public class ModuleDescriptor
opens,
uses,
provides,
- version,
+ packages,
mainClass,
osName,
osArch,
- osVersion,
- packages,
- hashes);
+ osVersion);
}
}
@@ -2088,8 +2128,7 @@ public class ModuleDescriptor
&& Objects.equals(osName, that.osName)
&& Objects.equals(osArch, that.osArch)
&& Objects.equals(osVersion, that.osVersion)
- && Objects.equals(packages, that.packages)
- && Objects.equals(hashes, that.hashes));
+ && Objects.equals(packages, that.packages));
}
private transient int hash; // cached hash code
@@ -2122,7 +2161,6 @@ public class ModuleDescriptor
hc = hc * 43 + Objects.hashCode(osArch);
hc = hc * 43 + Objects.hashCode(osVersion);
hc = hc * 43 + Objects.hashCode(packages);
- hc = hc * 43 + Objects.hashCode(hashes);
if (hc == 0)
hc = -1;
hash = hc;
@@ -2145,7 +2183,7 @@ public class ModuleDescriptor
if (!requires.isEmpty())
sb.append(", ").append(requires);
if (!uses.isEmpty())
- sb.append(", ").append(uses);
+ sb.append(", uses: ").append(uses);
if (!exports.isEmpty())
sb.append(", exports: ").append(exports);
if (!opens.isEmpty())
@@ -2171,7 +2209,7 @@ public class ModuleDescriptor
* identifier
*/
public static Builder module(String name) {
- return new Builder(name, true);
+ return new Builder(name, true, false, false);
}
/**
@@ -2199,7 +2237,7 @@ public class ModuleDescriptor
* identifier
*/
public static Builder openModule(String name) {
- return new Builder(name, true).open(true);
+ return new Builder(name, true, true, false);
}
/**
@@ -2221,7 +2259,7 @@ public class ModuleDescriptor
* @see ModuleFinder#of(Path[])
*/
public static Builder automaticModule(String name) {
- return new Builder(name, true).automatic(true);
+ return new Builder(name, true, false, false).automatic(true);
}
@@ -2263,7 +2301,7 @@ public class ModuleDescriptor
Supplier> packageFinder)
throws IOException
{
- return ModuleInfo.read(in, requireNonNull(packageFinder));
+ return ModuleInfo.read(in, requireNonNull(packageFinder)).descriptor();
}
/**
@@ -2281,7 +2319,7 @@ public class ModuleDescriptor
* If an I/O error occurs reading from the input stream
*/
public static ModuleDescriptor read(InputStream in) throws IOException {
- return ModuleInfo.read(in, null);
+ return ModuleInfo.read(in, null).descriptor();
}
/**
@@ -2320,7 +2358,7 @@ public class ModuleDescriptor
public static ModuleDescriptor read(ByteBuffer bb,
Supplier> packageFinder)
{
- return ModuleInfo.read(bb, requireNonNull(packageFinder));
+ return ModuleInfo.read(bb, requireNonNull(packageFinder)).descriptor();
}
/**
@@ -2336,7 +2374,7 @@ public class ModuleDescriptor
* If an invalid module descriptor is detected
*/
public static ModuleDescriptor read(ByteBuffer bb) {
- return ModuleInfo.read(bb, null);
+ return ModuleInfo.read(bb, null).descriptor();
}
private static Map emptyOrUnmodifiableMap(Map map) {
@@ -2377,18 +2415,26 @@ public class ModuleDescriptor
jdk.internal.misc.SharedSecrets
.setJavaLangModuleAccess(new jdk.internal.misc.JavaLangModuleAccess() {
@Override
- public Builder newModuleBuilder(String mn, boolean strict) {
- return new Builder(mn, strict);
+ public Builder newModuleBuilder(String mn,
+ boolean strict,
+ boolean open,
+ boolean synthetic) {
+ return new Builder(mn, strict, open, synthetic);
}
@Override
- public Builder newOpenModuleBuilder(String mn, boolean strict) {
- return new Builder(mn, strict).open(true);
+ public Set exportedPackages(ModuleDescriptor.Builder builder) {
+ return builder.exportedPackages();
}
@Override
- public Requires newRequires(Set ms, String mn) {
- return new Requires(ms, mn, true);
+ public Set openPackages(ModuleDescriptor.Builder builder) {
+ return builder.openPackages();
+ }
+
+ @Override
+ public Requires newRequires(Set ms, String mn, Version v) {
+ return new Requires(ms, mn, v, true);
}
@Override
@@ -2433,6 +2479,7 @@ public class ModuleDescriptor
@Override
public ModuleDescriptor newModuleDescriptor(String name,
+ Version version,
boolean open,
boolean automatic,
boolean synthetic,
@@ -2441,15 +2488,14 @@ public class ModuleDescriptor
Set opens,
Set uses,
Set provides,
- Version version,
+ Set packages,
String mainClass,
String osName,
String osArch,
String osVersion,
- Set packages,
- ModuleHashes hashes,
int hashCode) {
return new ModuleDescriptor(name,
+ version,
open,
automatic,
synthetic,
@@ -2458,22 +2504,15 @@ public class ModuleDescriptor
opens,
uses,
provides,
- version,
+ packages,
mainClass,
osName,
osArch,
osVersion,
- packages,
- hashes,
hashCode,
false);
}
- @Override
- public Optional hashes(ModuleDescriptor descriptor) {
- return descriptor.hashes();
- }
-
@Override
public Configuration resolveRequiresAndUses(ModuleFinder finder,
Collection roots,
@@ -2482,20 +2521,6 @@ public class ModuleDescriptor
{
return Configuration.resolveRequiresAndUses(finder, roots, check, traceOutput);
}
-
- @Override
- public ModuleReference newPatchedModule(ModuleDescriptor descriptor,
- URI location,
- Supplier s) {
- return new ModuleReference(descriptor, location, s, true, null);
- }
-
- @Override
- public ModuleFinder newModulePath(Runtime.Version version,
- boolean isLinkPhase,
- Path... entries) {
- return new ModulePath(version, isLinkPhase, entries);
- }
});
}
diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java
index 4b98bf48416..5d01f698806 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java
@@ -42,6 +42,8 @@ import java.util.Objects;
import java.util.Optional;
import java.util.Set;
+import jdk.internal.module.ModulePath;
+import jdk.internal.module.SystemModuleFinder;
import sun.security.action.GetPropertyAction;
/**
@@ -137,7 +139,7 @@ public interface ModuleFinder {
/**
* Returns a module finder that locates the system modules. The
- * system modules are typically linked into the Java run-time image.
+ * system modules are the modules in the Java run-time image.
* The module finder will always find {@code java.base}.
*
*
If there is a security manager set then its {@link
@@ -166,7 +168,7 @@ public interface ModuleFinder {
Path modules = Paths.get(home, "lib", "modules");
if (Files.isRegularFile(modules)) {
- return new SystemModuleFinder();
+ return SystemModuleFinder.getInstance();
} else {
Path mlib = Paths.get(home, "modules");
if (Files.isDirectory(mlib)) {
diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleReference.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleReference.java
index cbf84cf938d..09a5acec219 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReference.java
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReference.java
@@ -26,96 +26,42 @@
package java.lang.module;
import java.io.IOException;
-import java.io.UncheckedIOException;
import java.net.URI;
import java.util.Objects;
import java.util.Optional;
-import java.util.function.Supplier;
-
-import jdk.internal.module.ModuleHashes.HashSupplier;
/**
* A reference to a module's content.
*
- *
A module reference contains the module's descriptor and its location, if
- * known. It also has the ability to create a {@link ModuleReader} in order to
- * access the module's content, which may be inside the Java run-time system
- * itself or in an artifact such as a modular JAR file.
+ *
A module reference is a concrete implementation of this class that
+ * implements the abstract methods defined by this class. It contains the
+ * module's descriptor and its location, if known. It also has the ability to
+ * create a {@link ModuleReader} in order to access the module's content, which
+ * may be inside the Java run-time system itself or in an artifact such as a
+ * modular JAR file.
*
* @see ModuleFinder
* @see ModuleReader
* @since 9
*/
-public final class ModuleReference {
+public abstract class ModuleReference {
private final ModuleDescriptor descriptor;
private final URI location;
- private final Supplier readerSupplier;
-
- // true if this is a reference to a patched module
- private boolean patched;
-
- // the function that computes the hash of this module reference
- private final HashSupplier hasher;
-
- // cached hash to avoid needing to compute it many times
- private byte[] cachedHash;
-
/**
* Constructs a new instance of this class.
- */
- ModuleReference(ModuleDescriptor descriptor,
- URI location,
- Supplier readerSupplier,
- boolean patched,
- HashSupplier hasher)
-
- {
- this.descriptor = Objects.requireNonNull(descriptor);
- this.location = location;
- this.readerSupplier = Objects.requireNonNull(readerSupplier);
- this.patched = patched;
- this.hasher = hasher;
- }
-
- /**
- * Constructs a new instance of this class.
- */
- ModuleReference(ModuleDescriptor descriptor,
- URI location,
- Supplier readerSupplier,
- HashSupplier hasher)
-
- {
- this(descriptor, location, readerSupplier, false, hasher);
- }
-
-
- /**
- * Constructs a new instance of this class.
- *
- *
The {@code readSupplier} parameter is the supplier of the {@link
- * ModuleReader} that may be used to read the module content. Its {@link
- * Supplier#get() get()} method throws {@link UncheckedIOException} if an
- * I/O error occurs opening the module content. The {@code get()} method
- * throws {@link SecurityException} if opening the module is denied by the
- * security manager.
*
* @param descriptor
* The module descriptor
* @param location
* The module location or {@code null} if not known
- * @param readerSupplier
- * The {@code Supplier} of the {@code ModuleReader}
*/
- public ModuleReference(ModuleDescriptor descriptor,
- URI location,
- Supplier readerSupplier)
- {
- this(descriptor, location, readerSupplier, false, null);
+ protected ModuleReference(ModuleDescriptor descriptor, URI location) {
+ this.descriptor = Objects.requireNonNull(descriptor);
+ this.location = location;
}
/**
@@ -123,11 +69,10 @@ public final class ModuleReference {
*
* @return The module descriptor
*/
- public ModuleDescriptor descriptor() {
+ public final ModuleDescriptor descriptor() {
return descriptor;
}
-
/**
* Returns the location of this module's content, if known.
*
@@ -139,18 +84,13 @@ public final class ModuleReference {
*
* @return The location or an empty {@code Optional} if not known
*/
- public Optional location() {
+ public final Optional location() {
return Optional.ofNullable(location);
}
-
/**
* Opens the module content for reading.
*
- *
This method opens the module content by invoking the {@link
- * Supplier#get() get()} method of the {@code readSupplier} specified at
- * construction time.
- *
* @return A {@code ModuleReader} to read the module
*
* @throws IOException
@@ -158,113 +98,5 @@ public final class ModuleReference {
* @throws SecurityException
* If denied by the security manager
*/
- public ModuleReader open() throws IOException {
- try {
- return readerSupplier.get();
- } catch (UncheckedIOException e) {
- throw e.getCause();
- }
-
- }
-
-
- /**
- * Returns {@code true} if this module has been patched via --patch-module.
- */
- boolean isPatched() {
- return patched;
- }
-
- /**
- * Returns the hash supplier for this module.
- */
- HashSupplier hasher() {
- return hasher;
- }
-
- /**
- * Computes the hash of this module. Returns {@code null} if the hash
- * cannot be computed.
- *
- * @throws java.io.UncheckedIOException if an I/O error occurs
- */
- byte[] computeHash(String algorithm) {
- byte[] result = cachedHash;
- if (result != null)
- return result;
- if (hasher == null)
- return null;
- cachedHash = result = hasher.generate(algorithm);
- return result;
- }
-
- /**
- * Computes a hash code for this module reference.
- *
- *
The hash code is based upon the components of the reference, and
- * satisfies the general contract of the {@link Object#hashCode
- * Object.hashCode} method.
- *
- * @return The hash-code value for this module reference
- */
- @Override
- public int hashCode() {
- int hc = hash;
- if (hc == 0) {
- hc = descriptor.hashCode();
- hc = 43 * hc + readerSupplier.hashCode();
- hc = 43 * hc + Objects.hashCode(location);
- hc = 43 * hc + Objects.hashCode(hasher);
- hc = 43 * hc + Boolean.hashCode(patched);
- if (hc == 0)
- hc = -1;
- hash = hc;
- }
- return hc;
- }
-
- private int hash;
-
- /**
- * Tests this module reference for equality with the given object.
- *
- *
If the given object is not a {@code ModuleReference} then this
- * method returns {@code false}. Two module references are equal if their
- * module descriptors are equal, their locations are equal or both unknown,
- * and were created with equal supplier objects to access the module
- * content.
- *
- *
This method satisfies the general contract of the {@link
- * java.lang.Object#equals(Object) Object.equals} method.
- *
- * @param ob
- * the object to which this object is to be compared
- *
- * @return {@code true} if, and only if, the given object is a module
- * reference that is equal to this module reference
- */
- @Override
- public boolean equals(Object ob) {
- if (!(ob instanceof ModuleReference))
- return false;
- ModuleReference that = (ModuleReference)ob;
-
- return Objects.equals(this.descriptor, that.descriptor)
- && Objects.equals(this.location, that.location)
- && Objects.equals(this.readerSupplier, that.readerSupplier)
- && Objects.equals(this.hasher, that.hasher)
- && this.patched == that.patched;
- }
-
- /**
- * Returns a string describing this module reference.
- *
- * @return A string describing this module reference
- */
- @Override
- public String toString() {
- return ("[module " + descriptor().name()
- + ", location=" + location + "]");
- }
-
+ public abstract ModuleReader open() throws IOException;
}
diff --git a/jdk/src/java.base/share/classes/java/lang/module/Resolver.java b/jdk/src/java.base/share/classes/java/lang/module/Resolver.java
index 5f716b131b7..d2aafdc5d87 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/Resolver.java
+++ b/jdk/src/java.base/share/classes/java/lang/module/Resolver.java
@@ -46,6 +46,7 @@ import java.util.StringJoiner;
import java.util.stream.Collectors;
import jdk.internal.module.ModuleHashes;
+import jdk.internal.module.ModuleReferenceImpl;
/**
* The resolver used by {@link Configuration#resolveRequires} and
@@ -438,24 +439,32 @@ final class Resolver {
*/
private void checkHashes() {
for (ModuleReference mref : nameToReference.values()) {
- ModuleDescriptor descriptor = mref.descriptor();
- // get map of module hashes
- Optional ohashes = descriptor.hashes();
- if (!ohashes.isPresent())
+ // get the recorded hashes, if any
+ if (!(mref instanceof ModuleReferenceImpl))
+ continue;
+ ModuleHashes hashes = ((ModuleReferenceImpl)mref).recordedHashes();
+ if (hashes == null)
continue;
- ModuleHashes hashes = ohashes.get();
+ ModuleDescriptor descriptor = mref.descriptor();
String algorithm = hashes.algorithm();
for (String dn : hashes.names()) {
- ModuleReference other = nameToReference.get(dn);
- if (other == null) {
+ ModuleReference mref2 = nameToReference.get(dn);
+ if (mref2 == null) {
ResolvedModule resolvedModule = findInParent(dn);
if (resolvedModule != null)
- other = resolvedModule.reference();
+ mref2 = resolvedModule.reference();
+ }
+ if (mref2 == null)
+ continue;
+
+ if (!(mref2 instanceof ModuleReferenceImpl)) {
+ fail("Unable to compute the hash of module %s", dn);
}
// skip checking the hash if the module has been patched
+ ModuleReferenceImpl other = (ModuleReferenceImpl)mref2;
if (other != null && !other.isPatched()) {
byte[] recordedHash = hashes.hashFor(dn);
byte[] actualHash = other.computeHash(algorithm);
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java b/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
index a046a748f7c..f585b476504 100644
--- a/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
@@ -28,9 +28,11 @@ package java.lang.reflect;
import java.lang.annotation.Annotation;
import java.security.AccessController;
+import jdk.internal.misc.VM;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
import jdk.internal.reflect.ReflectionFactory;
+import sun.security.action.GetPropertyAction;
/**
* The AccessibleObject class is the base class for Field, Method and
@@ -172,8 +174,10 @@ public class AccessibleObject implements AnnotatedElement {
// package is open to caller
String pn = packageName(declaringClass);
- if (declaringModule.isOpen(pn, callerModule))
+ if (declaringModule.isOpen(pn, callerModule)) {
+ printStackTraceIfOpenedReflectively(declaringModule, pn, callerModule);
return;
+ }
// package is exported to caller and class/member is public
boolean isExported = declaringModule.isExported(pn, callerModule);
@@ -185,8 +189,10 @@ public class AccessibleObject implements AnnotatedElement {
modifiers = ((Field) this).getModifiers();
}
boolean isMemberPublic = Modifier.isPublic(modifiers);
- if (isExported && isClassPublic && isMemberPublic)
+ if (isExported && isClassPublic && isMemberPublic) {
+ printStackTraceIfExportedReflectively(declaringModule, pn, callerModule);
return;
+ }
// not accessible
String msg = "Unable to make ";
@@ -198,7 +204,44 @@ public class AccessibleObject implements AnnotatedElement {
else
msg += "opens";
msg += " " + pn + "\" to " + callerModule;
- Reflection.throwInaccessibleObjectException(msg);
+ InaccessibleObjectException e = new InaccessibleObjectException(msg);
+ if (Reflection.printStackTraceWhenAccessFails()) {
+ e.printStackTrace(System.err);
+ }
+ throw e;
+ }
+
+ private void printStackTraceIfOpenedReflectively(Module module,
+ String pn,
+ Module other) {
+ printStackTraceIfExposedReflectively(module, pn, other, true);
+ }
+
+ private void printStackTraceIfExportedReflectively(Module module,
+ String pn,
+ Module other) {
+ printStackTraceIfExposedReflectively(module, pn, other, false);
+ }
+
+ private void printStackTraceIfExposedReflectively(Module module,
+ String pn,
+ Module other,
+ boolean open)
+ {
+ if (Reflection.printStackTraceWhenAccessSucceeds()
+ && !module.isStaticallyExportedOrOpen(pn, other, open))
+ {
+ String msg = other + " allowed to invoke setAccessible on ";
+ if (this instanceof Field)
+ msg += "field ";
+ msg += this;
+ new Exception(msg) {
+ private static final long serialVersionUID = 42L;
+ public String toString() {
+ return "WARNING: " + getMessage();
+ }
+ }.printStackTrace(System.err);
+ }
}
/**
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java b/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java
index 7466c57ae22..df48c1e707a 100644
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java
@@ -245,7 +245,6 @@ public final class Layer {
* @see Module#addOpens
*/
public Controller addOpens(Module source, String pn, Module target) {
- Objects.requireNonNull(source);
Objects.requireNonNull(source);
Objects.requireNonNull(target);
ensureInLayer(source);
@@ -541,7 +540,7 @@ public final class Layer {
* {@link ClassLoader#registerAsParallelCapable parallel-capable} so as to
* avoid deadlocks during class loading. In addition, the entity creating
* a new layer with this method should arrange that the class loaders are
- * ready to load from these module before there are any attempts to load
+ * ready to load from these modules before there are any attempts to load
* classes or resources.
*
*
Creating a {@code Layer} can fail for the following reasons:
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Module.java b/jdk/src/java.base/share/classes/java/lang/reflect/Module.java
index 29f21cc0108..a71b4b320ab 100644
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Module.java
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Module.java
@@ -559,7 +559,7 @@ public final class Module implements AnnotatedElement {
* Returns {@code true} if this module exports or opens a package to
* the given module via its module declaration.
*/
- private boolean isStaticallyExportedOrOpen(String pn, Module other, boolean open) {
+ boolean isStaticallyExportedOrOpen(String pn, Module other, boolean open) {
// package is open to everyone or
Map> openPackages = this.openPackages;
if (openPackages != null) {
@@ -643,6 +643,12 @@ public final class Module implements AnnotatedElement {
* open) to the given module. It also has no effect if
* invoked on an {@link ModuleDescriptor#isOpen open} module.
*
+ * @apiNote As specified in section 5.4.3 of the The Java™
+ * Virtual Machine Specification , if an attempt to resolve a
+ * symbolic reference fails because of a linkage error, then subsequent
+ * attempts to resolve the reference always fail with the same error that
+ * was thrown as a result of the initial resolution attempt.
+ *
* @param pn
* The package name
* @param other
@@ -656,6 +662,7 @@ public final class Module implements AnnotatedElement {
* @throws IllegalStateException
* If this is a named module and the caller is not this module
*
+ * @jvms 5.4.3 Resolution
* @see #isExported(String,Module)
*/
@CallerSensitive
@@ -676,8 +683,8 @@ public final class Module implements AnnotatedElement {
}
/**
- * If the caller's module is this module then update this module to
- * open the given package to the given module.
+ * If this module has opened a package to at least the caller
+ * module then update this module to open the package to the given module.
* Opening a package with this method allows all types in the package,
* and all their members, not just public types and their public members,
* to be reflected on by the given module when using APIs that support
@@ -699,7 +706,8 @@ public final class Module implements AnnotatedElement {
* If {@code pn} is {@code null}, or this is a named module and the
* package {@code pn} is not a package in this module
* @throws IllegalStateException
- * If this is a named module and the caller is not this module
+ * If this is a named module and this module has not opened the
+ * package to at least the caller
*
* @see #isOpen(String,Module)
* @see AccessibleObject#setAccessible(boolean)
@@ -713,9 +721,8 @@ public final class Module implements AnnotatedElement {
if (isNamed() && !descriptor.isOpen()) {
Module caller = Reflection.getCallerClass().getModule();
- if (caller != this) {
- throw new IllegalStateException(caller + " != " + this);
- }
+ if (caller != this && !isOpen(pn, caller))
+ throw new IllegalStateException(pn + " is not open to " + caller);
implAddExportsOrOpens(pn, other, /*open*/true, /*syncVM*/true);
}
@@ -1568,6 +1575,10 @@ public final class Module implements AnnotatedElement {
public Stream layers(ClassLoader loader) {
return Layer.layers(loader);
}
+ @Override
+ public boolean isStaticallyExported(Module module, String pn, Module other) {
+ return module.isStaticallyExportedOrOpen(pn, other, false);
+ }
});
}
}
diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/SSLEngine.java b/jdk/src/java.base/share/classes/javax/net/ssl/SSLEngine.java
index 300265cbcd4..2c724f73a67 100644
--- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLEngine.java
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLEngine.java
@@ -27,6 +27,8 @@ package javax.net.ssl;
import java.nio.ByteBuffer;
import java.nio.ReadOnlyBufferException;
+import java.util.List;
+import java.util.function.BiFunction;
/**
@@ -1332,4 +1334,89 @@ public abstract class SSLEngine {
public String getHandshakeApplicationProtocol() {
throw new UnsupportedOperationException();
}
+
+ /**
+ * Registers a callback function that selects an application protocol
+ * value for a SSL/TLS/DTLS handshake.
+ * The function overrides any values set using
+ * {@link SSLParameters#setApplicationProtocols
+ * SSLParameters.setApplicationProtocols} and it supports the following
+ * type parameters:
+ *
+ *
+ *
{@code SSLEngine}
+ *
The function's first argument allows the current {@code SSLEngine}
+ * to be inspected, including the handshake session and configuration
+ * settings.
+ *
{@code List}
+ *
The function's second argument lists the application protocol names
+ * advertised by the TLS peer.
+ *
{@code String}
+ *
The function's result is an application protocol name, or null to
+ * indicate that none of the advertised names are acceptable.
+ * If the return value is null (no value chosen) or is a value that
+ * was not advertised by the peer, the underlying protocol will
+ * determine what action to take. (For example, ALPN will send a
+ * "no_application_protocol" alert and terminate the connection.)
+ *
+ *
+ *
+ * For example, the following call registers a callback function that
+ * examines the TLS handshake parameters and selects an application protocol
+ * name:
+ *
+ *
+ * @apiNote
+ * This method should be called by TLS server applications before the TLS
+ * handshake begins. Also, this {@code SSLEngine} should be configured with
+ * parameters that are compatible with the application protocol selected by
+ * the callback function. For example, enabling a poor choice of cipher
+ * suites could result in no suitable application protocol.
+ * See {@link SSLParameters}.
+ *
+ * @implSpec
+ * The implementation in this class throws
+ * {@code UnsupportedOperationException} and performs no other action.
+ *
+ * @param selector the callback function, or null to disable the callback
+ * functionality.
+ * @throws UnsupportedOperationException if the underlying provider
+ * does not implement the operation.
+ * @since 9
+ */
+ public void setHandshakeApplicationProtocolSelector(
+ BiFunction, String> selector) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Retrieves the callback function that selects an application protocol
+ * value during a SSL/TLS/DTLS handshake.
+ * See {@link #setHandshakeApplicationProtocolSelector
+ * setHandshakeApplicationProtocolSelector}
+ * for the function's type parameters.
+ *
+ * @implSpec
+ * The implementation in this class throws
+ * {@code UnsupportedOperationException} and performs no other action.
+ *
+ * @return the callback function, or null if none has been set.
+ * @throws UnsupportedOperationException if the underlying provider
+ * does not implement the operation.
+ * @since 9
+ */
+ public BiFunction, String>
+ getHandshakeApplicationProtocolSelector() {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocket.java b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocket.java
index daaefe08ec7..ebbc9d9eb8d 100644
--- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocket.java
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocket.java
@@ -28,6 +28,8 @@ package javax.net.ssl;
import java.io.IOException;
import java.net.*;
+import java.util.List;
+import java.util.function.BiFunction;
/**
* This class extends Sockets and provides secure
@@ -742,4 +744,89 @@ public abstract class SSLSocket extends Socket
public String getHandshakeApplicationProtocol() {
throw new UnsupportedOperationException();
}
+
+
+ /**
+ * Registers a callback function that selects an application protocol
+ * value for a SSL/TLS/DTLS handshake.
+ * The function overrides any values set using
+ * {@link SSLParameters#setApplicationProtocols
+ * SSLParameters.setApplicationProtocols} and it supports the following
+ * type parameters:
+ *
+ *
+ *
{@code SSLSocket}
+ *
The function's first argument allows the current {@code SSLSocket}
+ * to be inspected, including the handshake session and configuration
+ * settings.
+ *
{@code List}
+ *
The function's second argument lists the application protocol names
+ * advertised by the TLS peer.
+ *
{@code String}
+ *
The function's result is an application protocol name, or null to
+ * indicate that none of the advertised names are acceptable.
+ * If the return value is null (no value chosen) or is a value that
+ * was not advertised by the peer, the underlying protocol will
+ * determine what action to take. (For example, ALPN will send a
+ * "no_application_protocol" alert and terminate the connection.)
+ *
+ *
+ *
+ * For example, the following call registers a callback function that
+ * examines the TLS handshake parameters and selects an application protocol
+ * name:
+ *
+ *
+ * @apiNote
+ * This method should be called by TLS server applications before the TLS
+ * handshake begins. Also, this {@code SSLSocket} should be configured with
+ * parameters that are compatible with the application protocol selected by
+ * the callback function. For example, enabling a poor choice of cipher
+ * suites could result in no suitable application protocol.
+ * See {@link SSLParameters}.
+ *
+ * @implSpec
+ * The implementation in this class throws
+ * {@code UnsupportedOperationException} and performs no other action.
+ *
+ * @param selector the callback function, or null to de-register.
+ * @throws UnsupportedOperationException if the underlying provider
+ * does not implement the operation.
+ * @since 9
+ */
+ public void setHandshakeApplicationProtocolSelector(
+ BiFunction, String> selector) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Retrieves the callback function that selects an application protocol
+ * value during a SSL/TLS/DTLS handshake.
+ * See {@link #setHandshakeApplicationProtocolSelector
+ * setHandshakeApplicationProtocolSelector}
+ * for the function's type parameters.
+ *
+ * @implSpec
+ * The implementation in this class throws
+ * {@code UnsupportedOperationException} and performs no other action.
+ *
+ * @return the callback function, or null if none has been set.
+ * @throws UnsupportedOperationException if the underlying provider
+ * does not implement the operation.
+ * @since 9
+ */
+ public BiFunction, String>
+ getHandshakeApplicationProtocolSelector() {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/StringSharingDecompressor.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/StringSharingDecompressor.java
index d979f984da3..1284a3f129f 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/StringSharingDecompressor.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/StringSharingDecompressor.java
@@ -64,8 +64,10 @@ public class StringSharingDecompressor implements ResourceDecompressor {
private static final int CONSTANT_MethodHandle = 15;
private static final int CONSTANT_MethodType = 16;
private static final int CONSTANT_InvokeDynamic = 18;
+ private static final int CONSTANT_Module = 19;
+ private static final int CONSTANT_Package = 20;
- private static final int[] SIZES = new int[20];
+ private static final int[] SIZES = new int[21];
static {
@@ -83,6 +85,8 @@ public class StringSharingDecompressor implements ResourceDecompressor {
SIZES[CONSTANT_MethodHandle] = 3;
SIZES[CONSTANT_MethodType] = 2;
SIZES[CONSTANT_InvokeDynamic] = 4;
+ SIZES[CONSTANT_Module] = 2;
+ SIZES[CONSTANT_Package] = 2;
}
public static int[] getSizes() {
diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java
index d0b1c19232f..eed7a2d2aff 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java
@@ -38,10 +38,8 @@ import java.lang.module.ModuleReader;
import java.lang.module.ModuleReference;
import java.net.URI;
import java.nio.file.Path;
-import java.util.Map;
import java.util.Collection;
import java.util.List;
-import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;
@@ -59,21 +57,28 @@ public interface JavaLangModuleAccess {
* @param strict
* Indicates whether module names are checked or not
*/
- ModuleDescriptor.Builder newModuleBuilder(String mn, boolean strict);
+ ModuleDescriptor.Builder newModuleBuilder(String mn,
+ boolean strict,
+ boolean open,
+ boolean synthetic);
/**
- * Creates a builder for building an open module with the given module name.
- *
- * @param strict
- * Indicates whether module names are checked or not
+ * Returns the set of packages that are exported (unconditionally or
+ * unconditionally).
*/
- ModuleDescriptor.Builder newOpenModuleBuilder(String mn, boolean strict);
+ Set exportedPackages(ModuleDescriptor.Builder builder);
+
+ /**
+ * Returns the set of packages that are opened (unconditionally or
+ * unconditionally).
+ */
+ Set openPackages(ModuleDescriptor.Builder builder);
/**
* Returns a {@code ModuleDescriptor.Requires} of the given modifiers
* and module name.
*/
- Requires newRequires(Set ms, String mn);
+ Requires newRequires(Set ms, String mn, Version v);
/**
* Returns an unqualified {@code ModuleDescriptor.Exports}
@@ -122,6 +127,7 @@ public interface JavaLangModuleAccess {
* Returns a new {@code ModuleDescriptor} instance.
*/
ModuleDescriptor newModuleDescriptor(String name,
+ Version version,
boolean open,
boolean automatic,
boolean synthetic,
@@ -130,20 +136,13 @@ public interface JavaLangModuleAccess {
Set opens,
Set uses,
Set provides,
- Version version,
+ Set packages,
String mainClass,
String osName,
String osArch,
String osVersion,
- Set packages,
- ModuleHashes hashes,
int hashCode);
- /**
- * Returns the object with the hashes of other modules
- */
- Optional hashes(ModuleDescriptor descriptor);
-
/**
* Resolves a collection of root modules, with service binding
* and the empty configuration as the parent. The post resolution
@@ -154,18 +153,4 @@ public interface JavaLangModuleAccess {
boolean check,
PrintStream traceOutput);
- /**
- * Creates a ModuleReference to a "patched" module.
- */
- ModuleReference newPatchedModule(ModuleDescriptor descriptor,
- URI location,
- Supplier readerSupplier);
-
- /**
- * Creates a ModuleFinder for a module path.
- */
- ModuleFinder newModulePath(Runtime.Version version,
- boolean isLinkPhase,
- Path... entries);
-
}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangReflectModuleAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangReflectModuleAccess.java
index 55772793111..7bf6a1f3977 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangReflectModuleAccess.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangReflectModuleAccess.java
@@ -123,4 +123,12 @@ public interface JavaLangReflectModuleAccess {
* given class loader.
*/
Stream layers(ClassLoader loader);
+
+ /**
+ * Tests if a module exports a package at least {@code other} via its
+ * module declaration.
+ *
+ * @apiNote This is a temporary method for debugging features.
+ */
+ boolean isStaticallyExported(Module module, String pn, Module other);
}
\ No newline at end of file
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/Builder.java b/jdk/src/java.base/share/classes/jdk/internal/module/Builder.java
index 961dd08f28e..2ef9c11d248 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/Builder.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/Builder.java
@@ -30,11 +30,8 @@ import java.lang.module.ModuleDescriptor.Opens;
import java.lang.module.ModuleDescriptor.Provides;
import java.lang.module.ModuleDescriptor.Requires;
import java.lang.module.ModuleDescriptor.Version;
-import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import jdk.internal.misc.JavaLangModuleAccess;
@@ -52,7 +49,7 @@ import jdk.internal.misc.SharedSecrets;
* SystemModules should contain modules for the boot layer.
*/
final class Builder {
- private static final JavaLangModuleAccess jlma =
+ private static final JavaLangModuleAccess JLMA =
SharedSecrets.getJavaLangModuleAccess();
// Static cache of the most recently seen Version to cheaply deduplicate
@@ -60,13 +57,36 @@ final class Builder {
static Version cachedVersion;
/**
- * Returns a {@link Requires} for a dependence on a module
- * with the given (and possibly empty) set of modifiers.
+ * Returns a {@link Requires} for a dependence on a module with the given
+ * (and possibly empty) set of modifiers, and optionally the version
+ * recorded at compile time.
+ */
+ public static Requires newRequires(Set mods,
+ String mn,
+ String compiledVersion)
+ {
+ Version version = null;
+ if (compiledVersion != null) {
+ // use the cached version if the same version string
+ Version ver = cachedVersion;
+ if (ver != null && compiledVersion.equals(ver.toString())) {
+ version = ver;
+ } else {
+ version = Version.parse(compiledVersion);
+ }
+ }
+ return JLMA.newRequires(mods, mn, version);
+ }
+
+ /**
+ * Returns a {@link Requires} for a dependence on a module with the given
+ * (and possibly empty) set of modifiers, and optionally the version
+ * recorded at compile time.
*/
public static Requires newRequires(Set mods,
String mn)
{
- return jlma.newRequires(mods, mn);
+ return newRequires(mods, mn, null);
}
/**
@@ -77,7 +97,7 @@ final class Builder {
public static Exports newExports(Set ms,
String pn,
Set targets) {
- return jlma.newExports(ms, pn, targets);
+ return JLMA.newExports(ms, pn, targets);
}
/**
@@ -85,7 +105,7 @@ final class Builder {
* modifiers.
*/
public static Opens newOpens(Set ms, String pn) {
- return jlma.newOpens(ms, pn);
+ return JLMA.newOpens(ms, pn);
}
/**
@@ -96,7 +116,7 @@ final class Builder {
public static Opens newOpens(Set ms,
String pn,
Set targets) {
- return jlma.newOpens(ms, pn, targets);
+ return JLMA.newOpens(ms, pn, targets);
}
/**
@@ -104,7 +124,7 @@ final class Builder {
* of modifiers.
*/
public static Exports newExports(Set ms, String pn) {
- return jlma.newExports(ms, pn);
+ return JLMA.newExports(ms, pn);
}
/**
@@ -112,7 +132,7 @@ final class Builder {
* implementation classes.
*/
public static Provides newProvides(String st, List pcs) {
- return jlma.newProvides(st, pcs);
+ return JLMA.newProvides(st, pcs);
}
final String name;
@@ -130,8 +150,6 @@ final class Builder {
String osName;
String osArch;
String osVersion;
- String algorithm;
- Map hashes;
Builder(String name) {
this.name = name;
@@ -274,35 +292,14 @@ final class Builder {
return this;
}
- /**
- * Sets the algorithm of the module hashes
- */
- public Builder algorithm(String algorithm) {
- this.algorithm = algorithm;
- return this;
- }
-
- /**
- * Sets the module hash for the given module name
- */
- public Builder moduleHash(String mn, byte[] hash) {
- if (hashes == null)
- hashes = new HashMap<>();
-
- hashes.put(mn, hash);
- return this;
- }
-
/**
* Builds a {@code ModuleDescriptor} from the components.
*/
public ModuleDescriptor build(int hashCode) {
assert name != null;
- ModuleHashes moduleHashes =
- hashes != null ? new ModuleHashes(algorithm, hashes) : null;
-
- return jlma.newModuleDescriptor(name,
+ return JLMA.newModuleDescriptor(name,
+ version,
open,
automatic,
synthetic,
@@ -311,13 +308,11 @@ final class Builder {
opens,
uses,
provides,
- version,
+ packages,
mainClass,
osName,
osArch,
osVersion,
- packages,
- moduleHashes,
hashCode);
}
}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/Checks.java b/jdk/src/java.base/share/classes/jdk/internal/module/Checks.java
index 9f02048b5c8..2fdeaab6211 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/Checks.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/Checks.java
@@ -25,79 +25,200 @@
package jdk.internal.module;
+/**
+ * Utility class for checking module name and binary names.
+ */
+
public final class Checks {
private Checks() { }
- private static void fail(String what, String id, int i) {
- throw new IllegalArgumentException(id
- + ": Invalid " + what + ": "
- + " Illegal character"
- + " at index " + i);
+ /**
+ * Checks a name to ensure that it's a legal module name.
+ *
+ * @throws IllegalArgumentException if name is null or not a legal
+ * module name
+ */
+ public static String requireModuleName(String name) {
+ if (name == null)
+ throw new IllegalArgumentException("Null module name");
+ int next;
+ int off = 0;
+ while ((next = name.indexOf('.', off)) != -1) {
+ if (isJavaIdentifier(name, off, (next - off)) == -1) {
+ String id = name.substring(off, next);
+ throw new IllegalArgumentException(name + ": Invalid module name"
+ + ": '" + id + "' is not a Java identifier");
+ }
+ off = next+1;
+ }
+ int last = isJavaIdentifier(name, off, name.length() - off);
+ if (last == -1) {
+ String id = name.substring(off);
+ throw new IllegalArgumentException(name + ": Invalid module name"
+ + ": '" + id + "' is not a Java identifier");
+ }
+ //if (!Character.isJavaIdentifierStart(last))
+ // throw new IllegalArgumentException(name + ": Module name ends in digit");
+ return name;
}
/**
- * Returns {@code true} if the given identifier is a legal Java identifier.
+ * Returns {@code true} if the given name is a legal module name.
*/
- public static boolean isJavaIdentifier(String id) {
- int n = id.length();
- if (n == 0)
- return false;
- if (!Character.isJavaIdentifierStart(id.codePointAt(0)))
- return false;
- int cp = id.codePointAt(0);
- int i = Character.charCount(cp);
- for (; i < n; i += Character.charCount(cp)) {
- cp = id.codePointAt(i);
- if (!Character.isJavaIdentifierPart(cp) && id.charAt(i) != '.')
+ public static boolean isModuleName(String name) {
+ int next;
+ int off = 0;
+ while ((next = name.indexOf('.', off)) != -1) {
+ if (isJavaIdentifier(name, off, (next - off)) == -1)
return false;
+ off = next+1;
}
- if (cp == '.')
+ int last = isJavaIdentifier(name, off, name.length() - off);
+ if (last == -1)
return false;
-
+ //if (!Character.isJavaIdentifierStart(last))
+ // return false;
return true;
}
/**
- * Checks if a given identifier is a legal Java identifier.
+ * Checks a name to ensure that it's a legal package name.
+ *
+ * @throws IllegalArgumentException if name is null or not a legal
+ * package name
*/
- public static String requireJavaIdentifier(String what, String id) {
- if (id == null)
- throw new IllegalArgumentException("Null " + what);
- int n = id.length();
- if (n == 0)
- throw new IllegalArgumentException("Empty " + what);
- if (!Character.isJavaIdentifierStart(id.codePointAt(0)))
- fail(what, id, 0);
- int cp = id.codePointAt(0);
- int i = Character.charCount(cp);
- int last = 0;
- for (; i < n; i += Character.charCount(cp)) {
- cp = id.codePointAt(i);
- if (!Character.isJavaIdentifierPart(cp) && id.charAt(i) != '.')
- fail(what, id, i);
- last = i;
+ public static String requirePackageName(String name) {
+ return requireBinaryName("package name", name);
+ }
+
+ /**
+ * Checks a name to ensure that it's a legal type name.
+ *
+ * @throws IllegalArgumentException if name is null or not a legal
+ * type name
+ */
+ public static String requireServiceTypeName(String name) {
+ return requireBinaryName("service type name", name);
+ }
+
+ /**
+ * Checks a name to ensure that it's a legal type name.
+ *
+ * @throws IllegalArgumentException if name is null or not a legal
+ * type name
+ */
+ public static String requireServiceProviderName(String name) {
+ return requireBinaryName("service provider name", name);
+ }
+
+ /**
+ * Returns {@code true} if the given name is a legal binary name.
+ */
+ public static boolean isJavaIdentifier(String name) {
+ return isBinaryName(name);
+ }
+
+ /**
+ * Returns {@code true} if the given name is a legal binary name.
+ */
+ public static boolean isBinaryName(String name) {
+ int next;
+ int off = 0;
+ while ((next = name.indexOf('.', off)) != -1) {
+ if (isJavaIdentifier(name, off, (next - off)) == -1)
+ return false;
+ off = next+1;
}
- if (cp == '.')
- fail(what, id, last);
-
- return id;
+ int count = name.length() - off;
+ return (isJavaIdentifier(name, off, count) != -1);
}
- public static String requireModuleName(String id) {
- return requireJavaIdentifier("module name", id);
+ /**
+ * Checks if the given name is a legal binary name.
+ *
+ * @throws IllegalArgumentException if name is null or not a legal
+ * binary name
+ */
+ public static String requireBinaryName(String what, String name) {
+ if (name == null)
+ throw new IllegalArgumentException("Null " + what);
+ int next;
+ int off = 0;
+ while ((next = name.indexOf('.', off)) != -1) {
+ if (isJavaIdentifier(name, off, (next - off)) == -1) {
+ String id = name.substring(off, next);
+ throw new IllegalArgumentException(name + ": Invalid " + what
+ + ": '" + id + "' is not a Java identifier");
+ }
+ off = next + 1;
+ }
+ if (isJavaIdentifier(name, off, name.length() - off) == -1) {
+ String id = name.substring(off, name.length());
+ throw new IllegalArgumentException(name + ": Invalid " + what
+ + ": '" + id + "' is not a Java identifier");
+ }
+ return name;
}
- public static String requirePackageName(String id) {
- return requireJavaIdentifier("package name", id);
+ /**
+ * Returns {@code true} if the last character of the given name is legal
+ * as the last character of a module name.
+ *
+ * @throws IllegalArgumentException if name is empty
+ */
+ public static boolean hasLegalModuleNameLastCharacter(String name) {
+ if (name.isEmpty())
+ throw new IllegalArgumentException("name is empty");
+ int len = name.length();
+ if (isASCIIString(name)) {
+ char c = name.charAt(len-1);
+ return Character.isJavaIdentifierStart(c);
+ } else {
+ int i = 0;
+ int cp = -1;
+ while (i < len) {
+ cp = name.codePointAt(i);
+ i += Character.charCount(cp);
+ }
+ return Character.isJavaIdentifierStart(cp);
+ }
}
- public static String requireServiceTypeName(String id) {
- return requireJavaIdentifier("service type name", id);
+ /**
+ * Returns true if the given string only contains ASCII characters.
+ */
+ private static boolean isASCIIString(String s) {
+ int i = 0;
+ while (i < s.length()) {
+ int c = s.charAt(i);
+ if (c > 0x7F)
+ return false;
+ i++;
+ }
+ return true;
}
- public static String requireServiceProviderName(String id) {
- return requireJavaIdentifier("service provider name", id);
- }
+ /**
+ * Checks if a char sequence is a legal Java identifier, returning the code
+ * point of the last character if legal or {@code -1} if not legal.
+ */
+ private static int isJavaIdentifier(CharSequence cs, int offset, int count) {
+ if (count == 0)
+ return -1;
+ int first = Character.codePointAt(cs, offset);
+ if (!Character.isJavaIdentifierStart(first))
+ return -1;
+ int cp = first;
+ int i = Character.charCount(first);
+ while (i < count) {
+ cp = Character.codePointAt(cs, offset+i);
+ if (!Character.isJavaIdentifierPart(cp))
+ return -1;
+ i += Character.charCount(cp);
+ }
+
+ return cp;
+ }
}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java b/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java
index 908b137eb5a..69c7ee670dd 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java
@@ -68,12 +68,18 @@ public final class ClassFileAttributes {
= SharedSecrets.getJavaLangModuleAccess();
private ModuleDescriptor descriptor;
+ private Version replacementVersion;
public ModuleAttribute(ModuleDescriptor descriptor) {
super(MODULE);
this.descriptor = descriptor;
}
+ public ModuleAttribute(Version v) {
+ super(MODULE);
+ this.replacementVersion = v;
+ }
+
public ModuleAttribute() {
super(MODULE);
}
@@ -86,46 +92,70 @@ public final class ClassFileAttributes {
int codeOff,
Label[] labels)
{
- ModuleAttribute attr = new ModuleAttribute();
-
- // module_name
- String mn = cr.readUTF8(off, buf).replace('/', '.');
+ // module_name (CONSTANT_Module_info)
+ String mn = cr.readModule(off, buf);
off += 2;
// module_flags
int module_flags = cr.readUnsignedShort(off);
boolean open = ((module_flags & ACC_OPEN) != 0);
+ boolean synthetic = ((module_flags & ACC_SYNTHETIC) != 0);
off += 2;
- ModuleDescriptor.Builder builder;
- if (open) {
- builder = JLMA.newOpenModuleBuilder(mn, false);
- } else {
- builder = JLMA.newModuleBuilder(mn, false);
+ ModuleDescriptor.Builder builder = JLMA.newModuleBuilder(mn,
+ false,
+ open,
+ synthetic);
+
+ // module_version
+ String module_version = cr.readUTF8(off, buf);
+ off += 2;
+ if (replacementVersion != null) {
+ builder.version(replacementVersion);
+ } else if (module_version != null) {
+ builder.version(module_version);
}
// requires_count and requires[requires_count]
int requires_count = cr.readUnsignedShort(off);
off += 2;
for (int i=0; i mods;
- if (flags == 0) {
+ if (requires_flags == 0) {
mods = Collections.emptySet();
} else {
mods = new HashSet<>();
- if ((flags & ACC_TRANSITIVE) != 0)
+ if ((requires_flags & ACC_TRANSITIVE) != 0)
mods.add(Requires.Modifier.TRANSITIVE);
- if ((flags & ACC_STATIC_PHASE) != 0)
+ if ((requires_flags & ACC_STATIC_PHASE) != 0)
mods.add(Requires.Modifier.STATIC);
- if ((flags & ACC_SYNTHETIC) != 0)
+ if ((requires_flags & ACC_SYNTHETIC) != 0)
mods.add(Requires.Modifier.SYNTHETIC);
- if ((flags & ACC_MANDATED) != 0)
+ if ((requires_flags & ACC_MANDATED) != 0)
mods.add(Requires.Modifier.MANDATED);
}
- builder.requires(mods, dn);
- off += 4;
+
+
+ // requires_version
+ Version compiledVersion = null;
+ String requires_version = cr.readUTF8(off, buf);
+ off += 2;
+ if (requires_version != null) {
+ compiledVersion = Version.parse(requires_version);
+ }
+
+ if (compiledVersion == null) {
+ builder.requires(mods, dn);
+ } else {
+ builder.requires(mods, dn, compiledVersion);
+ }
}
// exports_count and exports[exports_count]
@@ -133,19 +163,20 @@ public final class ClassFileAttributes {
off += 2;
if (exports_count > 0) {
for (int i=0; i mods;
- if (flags == 0) {
+ if (exports_flags == 0) {
mods = Collections.emptySet();
} else {
mods = new HashSet<>();
- if ((flags & ACC_SYNTHETIC) != 0)
+ if ((exports_flags & ACC_SYNTHETIC) != 0)
mods.add(Exports.Modifier.SYNTHETIC);
- if ((flags & ACC_MANDATED) != 0)
+ if ((exports_flags & ACC_MANDATED) != 0)
mods.add(Exports.Modifier.MANDATED);
}
@@ -154,7 +185,7 @@ public final class ClassFileAttributes {
if (exports_to_count > 0) {
Set targets = new HashSet<>();
for (int j=0; j 0) {
for (int i=0; i mods;
- if (flags == 0) {
+ if (opens_flags == 0) {
mods = Collections.emptySet();
} else {
mods = new HashSet<>();
- if ((flags & ACC_SYNTHETIC) != 0)
+ if ((opens_flags & ACC_SYNTHETIC) != 0)
mods.add(Opens.Modifier.SYNTHETIC);
- if ((flags & ACC_MANDATED) != 0)
+ if ((opens_flags & ACC_MANDATED) != 0)
mods.add(Opens.Modifier.MANDATED);
}
@@ -191,7 +223,7 @@ public final class ClassFileAttributes {
if (opens_to_count > 0) {
Set targets = new HashSet<>();
for (int j=0; j ts = e.targets();
attr.putShort(ts.size());
- ts.forEach(t -> attr.putShort(cw.newUTF8(t.replace('.', '/'))));
+ ts.forEach(target -> attr.putShort(cw.newModule(target)));
} else {
attr.putShort(0);
}
}
-
// opens_counts and opens[opens_counts]
attr.putShort(descriptor.opens().size());
for (Opens obj : descriptor.opens()) {
String pkg = obj.source().replace('.', '/');
- attr.putShort(cw.newUTF8(pkg));
+ attr.putShort(cw.newPackage(pkg));
- int flags = 0;
+ int opens_flags = 0;
if (obj.modifiers().contains(Opens.Modifier.SYNTHETIC))
- flags |= ACC_SYNTHETIC;
+ opens_flags |= ACC_SYNTHETIC;
if (obj.modifiers().contains(Opens.Modifier.MANDATED))
- flags |= ACC_MANDATED;
- attr.putShort(flags);
+ opens_flags |= ACC_MANDATED;
+ attr.putShort(opens_flags);
if (obj.isQualified()) {
Set ts = obj.targets();
attr.putShort(ts.size());
- ts.forEach(t -> attr.putShort(cw.newUTF8(t.replace('.', '/'))));
+ ts.forEach(target -> attr.putShort(cw.newModule(target)));
} else {
attr.putShort(0);
}
@@ -369,7 +417,7 @@ public final class ClassFileAttributes {
*
* // the number of entries in the packages table
* u2 packages_count;
- * { // index to CONSTANT_CONSTANT_utf8_info structure with the package name
+ * { // index to CONSTANT_Package_info structure with the package name
* u2 package_index
* } packages[package_count];
*
@@ -402,7 +450,7 @@ public final class ClassFileAttributes {
// packages
Set packages = new HashSet<>();
for (int i=0; i p.replace('.', '/'))
- .forEach(p -> attr.putShort(cw.newUTF8(p)));
+ .forEach(p -> attr.putShort(cw.newPackage(p)));
return attr;
}
}
- /**
- * ModuleVersion attribute.
- *
- *
{@code
- *
- * ModuleVersion_attribute {
- * // index to CONSTANT_utf8_info structure in constant pool representing
- * // the string "ModuleVersion"
- * u2 attribute_name_index;
- * u4 attribute_length;
- *
- * // index to CONSTANT_CONSTANT_utf8_info structure with the version
- * u2 version_index;
- * }
- *
- * }
- */
- public static class ModuleVersionAttribute extends Attribute {
- private final Version version;
-
- public ModuleVersionAttribute(Version version) {
- super(MODULE_VERSION);
- this.version = version;
- }
-
- public ModuleVersionAttribute() {
- this(null);
- }
-
- @Override
- protected Attribute read(ClassReader cr,
- int off,
- int len,
- char[] buf,
- int codeOff,
- Label[] labels)
- {
- String value = cr.readUTF8(off, buf);
- return new ModuleVersionAttribute(Version.parse(value));
- }
-
- @Override
- protected ByteVector write(ClassWriter cw,
- byte[] code,
- int len,
- int maxStack,
- int maxLocals)
- {
- ByteVector attr = new ByteVector();
- int index = cw.newUTF8(version.toString());
- attr.putShort(index);
- return attr;
- }
- }
-
/**
* ModuleMainClass attribute.
*
@@ -526,7 +519,7 @@ public final class ClassFileAttributes {
int codeOff,
Label[] labels)
{
- String value = cr.readClass(off, buf);
+ String value = cr.readClass(off, buf).replace('/', '.');
return new ModuleMainClassAttribute(value);
}
@@ -538,7 +531,7 @@ public final class ClassFileAttributes {
int maxLocals)
{
ByteVector attr = new ByteVector();
- int index = cw.newClass(mainClass);
+ int index = cw.newClass(mainClass.replace('.', '/'));
attr.putShort(index);
return attr;
}
@@ -555,11 +548,11 @@ public final class ClassFileAttributes {
* u2 attribute_name_index;
* u4 attribute_length;
*
- * // index to CONSTANT_CONSTANT_utf8_info structure with the OS name
+ * // index to CONSTANT_utf8_info structure with the OS name
* u2 os_name_index;
- * // index to CONSTANT_CONSTANT_utf8_info structure with the OS arch
+ * // index to CONSTANT_utf8_info structure with the OS arch
* u2 os_arch_index
- * // index to CONSTANT_CONSTANT_utf8_info structure with the OS version
+ * // index to CONSTANT_utf8_info structure with the OS version
* u2 os_version_index;
* }
*
@@ -656,7 +649,7 @@ public final class ClassFileAttributes {
*
* // the number of entries in the hashes table
* u2 hashes_count;
- * { u2 module_name_index
+ * { u2 module_name_index (index to CONSTANT_Module_info structure)
* u2 hash_length;
* u1 hash[hash_length];
* } hashes[hashes_count];
@@ -691,7 +684,7 @@ public final class ClassFileAttributes {
Map map = new HashMap<>();
for (int i=0; i !ModuleResolution.doNotResolveByDefault(mref))
.map(ModuleReference::descriptor)
.map(ModuleDescriptor::name)
.filter(mn -> f.find(mn).isPresent()) // observable
@@ -277,6 +283,8 @@ public final class ModuleBootstrap {
// time to create configuration
PerfCounters.resolveTime.addElapsedTimeFrom(t3);
+ // check module names and incubating status
+ checkModuleNamesAndStatus(cf);
// mapping of modules to class loaders
Function clf = ModuleLoaderMap.mappingFunction(cf);
@@ -508,12 +516,12 @@ public final class ModuleBootstrap {
String key = e.getKey();
String[] s = key.split("/");
if (s.length != 2)
- fail("Unable to parse: " + key);
+ fail("Unable to parse as /: " + key);
String mn = s[0];
String pn = s[1];
if (mn.isEmpty() || pn.isEmpty())
- fail("Module and package name must be specified:" + key);
+ fail("Module and package name must be specified: " + key);
// The exporting module is in the boot layer
Module m;
@@ -585,7 +593,7 @@ public final class ModuleBootstrap {
int pos = value.indexOf('=');
if (pos == -1)
- fail("Unable to parse: " + value);
+ fail("Unable to parse as =: " + value);
if (pos == 0)
fail("Missing module name in: " + value);
@@ -594,7 +602,7 @@ public final class ModuleBootstrap {
String rhs = value.substring(pos+1);
if (rhs.isEmpty())
- fail("Unable to parse: " + value);
+ fail("Unable to parse as =: " + value);
// value is (,)* or ()*
if (!allowDuplicates && map.containsKey(key))
@@ -626,6 +634,33 @@ public final class ModuleBootstrap {
return (String)System.getProperties().remove(key);
}
+ /**
+ * Checks the names and resolution bit of each module in the configuration,
+ * emitting warnings if needed.
+ */
+ private static void checkModuleNamesAndStatus(Configuration cf) {
+ String incubating = null;
+ for (ResolvedModule rm : cf.modules()) {
+ ModuleReference mref = rm.reference();
+ String mn = mref.descriptor().name();
+
+ // emit warning if module name ends with a non-Java letter
+ if (!Checks.hasLegalModuleNameLastCharacter(mn))
+ warn("Module name \"" + mn + "\" may soon be illegal");
+
+ // emit warning if the WARN_INCUBATING module resolution bit set
+ if (ModuleResolution.hasIncubatingWarning(mref)) {
+ if (incubating == null) {
+ incubating = mn;
+ } else {
+ incubating += ", " + mn;
+ }
+ }
+ }
+ if (incubating != null)
+ warn("Using incubator modules: " + incubating);
+ }
+
/**
* Throws a RuntimeException with the given message
*/
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java
index 107305e0c79..f4e5fcb9fe1 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java
@@ -35,6 +35,7 @@ import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
/**
@@ -50,7 +51,6 @@ public final class ModuleHashes {
byte[] generate(String algorithm);
}
-
private final String algorithm;
private final Map nameToHash;
@@ -142,4 +142,37 @@ public final class ModuleHashes {
}
return new ModuleHashes(algorithm, nameToHash);
}
+
+ /**
+ * This is used by jdk.internal.module.SystemModules class
+ * generated at link time.
+ */
+ public static class Builder {
+ final String algorithm;
+ final Map nameToHash;
+
+ Builder(String algorithm, int initialCapacity) {
+ this.nameToHash = new HashMap<>(initialCapacity);
+ this.algorithm = Objects.requireNonNull(algorithm);
+ }
+
+ /**
+ * Sets the module hash for the given module name
+ */
+ public Builder hashForModule(String mn, byte[] hash) {
+ nameToHash.put(mn, hash);
+ return this;
+ }
+
+ /**
+ * Builds a {@code ModuleHashes}.
+ */
+ public ModuleHashes build() {
+ if (!nameToHash.isEmpty()) {
+ return new ModuleHashes(algorithm, nameToHash);
+ } else {
+ return null;
+ }
+ }
+ }
}
diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java
similarity index 69%
rename from jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java
rename to jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java
index b1c82819aa9..3aac651577c 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java
@@ -23,7 +23,7 @@
* questions.
*/
-package java.lang.module;
+package jdk.internal.module;
import java.io.DataInput;
import java.io.DataInputStream;
@@ -31,10 +31,13 @@ import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
+import java.lang.module.InvalidModuleDescriptorException;
+import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Builder;
import java.lang.module.ModuleDescriptor.Requires;
import java.lang.module.ModuleDescriptor.Exports;
import java.lang.module.ModuleDescriptor.Opens;
+import java.lang.module.ModuleDescriptor.Version;
import java.nio.ByteBuffer;
import java.nio.BufferUnderflowException;
import java.util.ArrayList;
@@ -46,7 +49,9 @@ import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
-import jdk.internal.module.ModuleHashes;
+import jdk.internal.misc.JavaLangModuleAccess;
+import jdk.internal.misc.SharedSecrets;
+import jdk.internal.module.ModuleResolution;
import static jdk.internal.module.ClassFileConstants.*;
@@ -58,7 +63,10 @@ import static jdk.internal.module.ClassFileConstants.*;
* and fine control over the throwing of InvalidModuleDescriptorException.
*/
-final class ModuleInfo {
+public final class ModuleInfo {
+
+ private static final JavaLangModuleAccess JLMA
+ = SharedSecrets.getJavaLangModuleAccess();
// supplies the set of packages when ModulePackages attribute not present
private final Supplier> packageFinder;
@@ -75,14 +83,42 @@ final class ModuleInfo {
this(pf, true);
}
+ /**
+ * A holder class for the ModuleDescriptor that is created by reading the
+ * Module and other standard class file attributes. It also holds the objects
+ * that represent the non-standard class file attributes that are read from
+ * the class file.
+ */
+ public static final class Attributes {
+ private final ModuleDescriptor descriptor;
+ private final ModuleHashes recordedHashes;
+ private final ModuleResolution moduleResolution;
+ Attributes(ModuleDescriptor descriptor,
+ ModuleHashes recordedHashes,
+ ModuleResolution moduleResolution) {
+ this.descriptor = descriptor;
+ this.recordedHashes = recordedHashes;
+ this.moduleResolution = moduleResolution;
+ }
+ public ModuleDescriptor descriptor() {
+ return descriptor;
+ }
+ public ModuleHashes recordedHashes() {
+ return recordedHashes;
+ }
+ public ModuleResolution moduleResolution() {
+ return moduleResolution;
+ }
+ }
+
+
/**
* Reads a {@code module-info.class} from the given input stream.
*
* @throws InvalidModuleDescriptorException
* @throws IOException
*/
- public static ModuleDescriptor read(InputStream in,
- Supplier> pf)
+ public static Attributes read(InputStream in, Supplier> pf)
throws IOException
{
try {
@@ -100,9 +136,7 @@ final class ModuleInfo {
* @throws InvalidModuleDescriptorException
* @throws UncheckedIOException
*/
- public static ModuleDescriptor read(ByteBuffer bb,
- Supplier> pf)
- {
+ public static Attributes read(ByteBuffer bb, Supplier> pf) {
try {
return new ModuleInfo(pf).doRead(new DataInputWrapper(bb));
} catch (IllegalArgumentException | IllegalStateException e) {
@@ -121,9 +155,7 @@ final class ModuleInfo {
* @throws InvalidModuleDescriptorException
* @throws UncheckedIOException
*/
- static ModuleDescriptor readIgnoringHashes(ByteBuffer bb,
- Supplier> pf)
- {
+ public static Attributes readIgnoringHashes(ByteBuffer bb, Supplier> pf) {
try {
return new ModuleInfo(pf, false).doRead(new DataInputWrapper(bb));
} catch (IllegalArgumentException | IllegalStateException e) {
@@ -144,7 +176,7 @@ final class ModuleInfo {
* because an identifier is not a legal Java identifier, duplicate
* exports, and many other reasons
*/
- private ModuleDescriptor doRead(DataInput in) throws IOException {
+ private Attributes doRead(DataInput in) throws IOException {
int magic = in.readInt();
if (magic != 0xCAFEBABE)
@@ -163,8 +195,9 @@ final class ModuleInfo {
throw invalidModuleDescriptor("access_flags should be ACC_MODULE");
int this_class = in.readUnsignedShort();
- if (this_class != 0)
- throw invalidModuleDescriptor("this_class must be 0");
+ String mn = cpool.getClassName(this_class);
+ if (!"module-info".equals(mn))
+ throw invalidModuleDescriptor("this_class should be module-info");
int super_class = in.readUnsignedShort();
if (super_class > 0)
@@ -189,10 +222,10 @@ final class ModuleInfo {
Builder builder = null;
Set packages = null;
- String version = null;
String mainClass = null;
String[] osValues = null;
ModuleHashes hashes = null;
+ ModuleResolution moduleResolution = null;
for (int i = 0; i < attributes_count ; i++) {
int name_index = in.readUnsignedShort();
@@ -215,10 +248,6 @@ final class ModuleInfo {
packages = readModulePackagesAttribute(in, cpool);
break;
- case MODULE_VERSION :
- version = readModuleVersionAttribute(in, cpool);
- break;
-
case MODULE_MAIN_CLASS :
mainClass = readModuleMainClassAttribute(in, cpool);
break;
@@ -235,6 +264,10 @@ final class ModuleInfo {
}
break;
+ case MODULE_RESOLUTION :
+ moduleResolution = readModuleResolution(in, cpool);
+ break;
+
default:
if (isAttributeDisallowed(attribute_name)) {
throw invalidModuleDescriptor(attribute_name
@@ -263,23 +296,33 @@ final class ModuleInfo {
usedPackageFinder = true;
}
if (packages != null) {
- for (String pn : builder.exportedAndOpenPackages()) {
- if (!packages.contains(pn)) {
- String tail;
- if (usedPackageFinder) {
- tail = " not found by package finder";
- } else {
- tail = " missing from ModulePackages attribute";
+ Set exportedPackages = JLMA.exportedPackages(builder);
+ Set openPackages = JLMA.openPackages(builder);
+ if (packages.containsAll(exportedPackages)
+ && packages.containsAll(openPackages)) {
+ packages.removeAll(exportedPackages);
+ packages.removeAll(openPackages);
+ } else {
+ // the set of packages is not complete
+ Set exportedAndOpenPackages = new HashSet<>();
+ exportedAndOpenPackages.addAll(exportedPackages);
+ exportedAndOpenPackages.addAll(openPackages);
+ for (String pn : exportedAndOpenPackages) {
+ if (!packages.contains(pn)) {
+ String tail;
+ if (usedPackageFinder) {
+ tail = " not found by package finder";
+ } else {
+ tail = " missing from ModulePackages attribute";
+ }
+ throw invalidModuleDescriptor("Package " + pn + tail);
}
- throw invalidModuleDescriptor("Package " + pn + tail);
}
- packages.remove(pn);
+ assert false; // should not get here
}
builder.contains(packages);
}
- if (version != null)
- builder.version(version);
if (mainClass != null)
builder.mainClass(mainClass);
if (osValues != null) {
@@ -287,10 +330,9 @@ final class ModuleInfo {
if (osValues[1] != null) builder.osArch(osValues[1]);
if (osValues[2] != null) builder.osVersion(osValues[2]);
}
- if (hashes != null)
- builder.hashes(hashes);
- return builder.build();
+ ModuleDescriptor descriptor = builder.build();
+ return new Attributes(descriptor, hashes, moduleResolution);
}
/**
@@ -302,38 +344,55 @@ final class ModuleInfo {
{
// module_name
int module_name_index = in.readUnsignedShort();
- String mn = cpool.getUtf8AsBinaryName(module_name_index);
-
- Builder builder = new ModuleDescriptor.Builder(mn, /*strict*/ false);
+ String mn = cpool.getModuleName(module_name_index);
int module_flags = in.readUnsignedShort();
boolean open = ((module_flags & ACC_OPEN) != 0);
- if (open)
- builder.open(true);
- if ((module_flags & ACC_SYNTHETIC) != 0)
- builder.synthetic(true);
+ boolean synthetic = ((module_flags & ACC_SYNTHETIC) != 0);
+
+ Builder builder = JLMA.newModuleBuilder(mn, false, open, synthetic);
+
+ int module_version_index = in.readUnsignedShort();
+ if (module_version_index != 0) {
+ String vs = cpool.getUtf8(module_version_index);
+ builder.version(vs);
+ }
int requires_count = in.readUnsignedShort();
boolean requiresJavaBase = false;
for (int i=0; i mods;
- if (flags == 0) {
+ if (requires_flags == 0) {
mods = Collections.emptySet();
} else {
mods = new HashSet<>();
- if ((flags & ACC_TRANSITIVE) != 0)
+ if ((requires_flags & ACC_TRANSITIVE) != 0)
mods.add(Requires.Modifier.TRANSITIVE);
- if ((flags & ACC_STATIC_PHASE) != 0)
+ if ((requires_flags & ACC_STATIC_PHASE) != 0)
mods.add(Requires.Modifier.STATIC);
- if ((flags & ACC_SYNTHETIC) != 0)
+ if ((requires_flags & ACC_SYNTHETIC) != 0)
mods.add(Requires.Modifier.SYNTHETIC);
- if ((flags & ACC_MANDATED) != 0)
+ if ((requires_flags & ACC_MANDATED) != 0)
mods.add(Requires.Modifier.MANDATED);
}
- builder.requires(mods, dn);
+
+ int requires_version_index = in.readUnsignedShort();
+ Version compiledVersion = null;
+ if (requires_version_index != 0) {
+ String vs = cpool.getUtf8(requires_version_index);
+ compiledVersion = Version.parse(vs);
+ }
+
+ if (compiledVersion == null) {
+ builder.requires(mods, dn);
+ } else {
+ builder.requires(mods, dn, compiledVersion);
+ }
+
if (dn.equals("java.base"))
requiresJavaBase = true;
}
@@ -350,18 +409,18 @@ final class ModuleInfo {
int exports_count = in.readUnsignedShort();
if (exports_count > 0) {
for (int i=0; i mods;
- int flags = in.readUnsignedShort();
- if (flags == 0) {
+ int exports_flags = in.readUnsignedShort();
+ if (exports_flags == 0) {
mods = Collections.emptySet();
} else {
mods = new HashSet<>();
- if ((flags & ACC_SYNTHETIC) != 0)
+ if ((exports_flags & ACC_SYNTHETIC) != 0)
mods.add(Exports.Modifier.SYNTHETIC);
- if ((flags & ACC_MANDATED) != 0)
+ if ((exports_flags & ACC_MANDATED) != 0)
mods.add(Exports.Modifier.MANDATED);
}
@@ -370,7 +429,7 @@ final class ModuleInfo {
Set targets = new HashSet<>(exports_to_count);
for (int j=0; j mods;
- int flags = in.readUnsignedShort();
- if (flags == 0) {
+ int opens_flags = in.readUnsignedShort();
+ if (opens_flags == 0) {
mods = Collections.emptySet();
} else {
mods = new HashSet<>();
- if ((flags & ACC_SYNTHETIC) != 0)
+ if ((opens_flags & ACC_SYNTHETIC) != 0)
mods.add(Opens.Modifier.SYNTHETIC);
- if ((flags & ACC_MANDATED) != 0)
+ if ((opens_flags & ACC_MANDATED) != 0)
mods.add(Opens.Modifier.MANDATED);
}
@@ -406,7 +465,7 @@ final class ModuleInfo {
Set targets = new HashSet<>(open_to_count);
for (int j=0; j 0) {
for (int i=0; i 0) {
for (int i=0; i providers = new ArrayList<>(with_count);
for (int j=0; j packages = new HashSet<>(package_count);
for (int i=0; i map = new HashMap<>(hash_count);
for (int i=0; i binary name
}
- String getClassNameAsBinaryName(int index) {
- String value = getClassName(index);
+ String getPackageName(int index) {
+ checkIndex(index);
+ Entry e = pool[index];
+ if (e.tag != CONSTANT_Package) {
+ throw invalidModuleDescriptor("CONSTANT_Package expected at entry: "
+ + index);
+ }
+ String value = getUtf8(((IndexEntry) e).index);
+ checkUnqualifiedName("CONSTANT_Package", index, value);
return value.replace('/', '.'); // internal form -> binary name
}
+ String getModuleName(int index) {
+ checkIndex(index);
+ Entry e = pool[index];
+ if (e.tag != CONSTANT_Module) {
+ throw invalidModuleDescriptor("CONSTANT_Module expected at entry: "
+ + index);
+ }
+ String value = getUtf8(((IndexEntry) e).index);
+ return decodeModuleName(index, value);
+ }
+
String getUtf8(int index) {
checkIndex(index);
Entry e = pool[index];
@@ -733,15 +835,103 @@ final class ModuleInfo {
return (String) (((ValueEntry) e).value);
}
- String getUtf8AsBinaryName(int index) {
- String value = getUtf8(index);
- return value.replace('/', '.'); // internal -> binary name
- }
-
void checkIndex(int index) {
if (index < 1 || index >= pool.length)
throw invalidModuleDescriptor("Index into constant pool out of range");
}
+
+ void checkUnqualifiedName(String what, int index, String value) {
+ int len = value.length();
+ if (len == 0) {
+ throw invalidModuleDescriptor(what + " at entry " + index
+ + " has zero length");
+ }
+ for (int i=0; i= len) {
+ throw invalidModuleDescriptor("CONSTANT_Module at entry "
+ + index + " has illegal "
+ + "escape sequence");
+ }
+ int next = value.codePointAt(j);
+ if (next != '\\' && next != ':' && next != '@') {
+ throw invalidModuleDescriptor("CONSTANT_Module at entry "
+ + index + " has illegal "
+ + "escape sequence");
+ }
+ sb.appendCodePoint(next);
+ i += Character.charCount(next);
+ } else {
+ sb.appendCodePoint(cp);
+ }
+
+ i += Character.charCount(cp);
+ }
+ return sb.toString();
+ }
}
/**
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java
index 07bb40205cf..952a328b71b 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java
@@ -70,6 +70,9 @@ public final class ModuleInfoExtender {
// the hashes for the Hashes attribute
private ModuleHashes hashes;
+ // the value of the ModuleResolution attribute
+ private ModuleResolution moduleResolution;
+
private ModuleInfoExtender(InputStream in) {
this.in = in;
}
@@ -120,6 +123,14 @@ public final class ModuleInfoExtender {
return this;
}
+ /**
+ * Sets the value for the ModuleResolution attribute.
+ */
+ public ModuleInfoExtender moduleResolution(ModuleResolution mres) {
+ this.moduleResolution = mres;
+ return this;
+ }
+
/**
* A ClassVisitor that supports adding class file attributes. If an
* attribute already exists then the first occurence of the attribute
@@ -183,21 +194,20 @@ public final class ModuleInfoExtender {
if (packages != null)
cv.addAttribute(new ModulePackagesAttribute(packages));
- if (version != null)
- cv.addAttribute(new ModuleVersionAttribute(version));
if (mainClass != null)
cv.addAttribute(new ModuleMainClassAttribute(mainClass));
if (osName != null || osArch != null || osVersion != null)
cv.addAttribute(new ModuleTargetAttribute(osName, osArch, osVersion));
if (hashes != null)
cv.addAttribute(new ModuleHashesAttribute(hashes));
+ if (moduleResolution != null)
+ cv.addAttribute(new ModuleResolutionAttribute(moduleResolution.value()));
List attrs = new ArrayList<>();
// prototypes of attributes that should be parsed
- attrs.add(new ModuleAttribute());
+ attrs.add(new ModuleAttribute(version));
attrs.add(new ModulePackagesAttribute());
- attrs.add(new ModuleVersionAttribute());
attrs.add(new ModuleMainClassAttribute());
attrs.add(new ModuleTargetAttribute());
attrs.add(new ModuleHashesAttribute());
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java
index 5e4efff1486..5a17442106c 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java
@@ -49,13 +49,12 @@ public final class ModuleInfoWriter {
* returning it in a byte array.
*/
private static byte[] toModuleInfo(ModuleDescriptor md) {
-
ClassWriter cw = new ClassWriter(0);
- cw.visit(Opcodes.V1_9, ACC_MODULE, null, null, null, null);
+ cw.visit(Opcodes.V1_9, ACC_MODULE, "module-info", null, null, null);
cw.visitAttribute(new ModuleAttribute(md));
- // for tests: write the Packages attribute when there are packages that
- // aren't exported or open
+ // for tests: write the ModulePackages attribute when there are packages
+ // that aren't exported or open
Stream exported = md.exports().stream()
.map(ModuleDescriptor.Exports::source);
Stream open = md.opens().stream()
@@ -64,10 +63,10 @@ public final class ModuleInfoWriter {
if (md.packages().size() > exportedOrOpen)
cw.visitAttribute(new ModulePackagesAttribute(md.packages()));
- md.version().ifPresent(v -> cw.visitAttribute(new ModuleVersionAttribute(v)));
+ // write ModuleMainClass if the module has a main class
md.mainClass().ifPresent(mc -> cw.visitAttribute(new ModuleMainClassAttribute(mc)));
- // write the TargetPlatform attribute if have any of OS name/arch/version
+ // write ModuleTarget attribute if have any of OS name/arch/version
String osName = md.osName().orElse(null);
String osArch = md.osArch().orElse(null);
String osVersion = md.osVersion().orElse(null);
@@ -76,7 +75,6 @@ public final class ModuleInfoWriter {
}
cw.visitEnd();
-
return cw.toByteArray();
}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java
index 97966bd0012..a80b407d809 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java
@@ -149,9 +149,22 @@ public final class ModulePatcher {
// return a module reference to the patched module
URI location = mref.location().orElse(null);
- return JLMA.newPatchedModule(descriptor,
- location,
- () -> new PatchedModuleReader(paths, mref));
+
+ ModuleHashes recordedHashes = null;
+ ModuleResolution mres = null;
+ if (mref instanceof ModuleReferenceImpl) {
+ ModuleReferenceImpl impl = (ModuleReferenceImpl)mref;
+ recordedHashes = impl.recordedHashes();
+ mres = impl.moduleResolution();
+ }
+
+ return new ModuleReferenceImpl(descriptor,
+ location,
+ () -> new PatchedModuleReader(paths, mref),
+ this,
+ recordedHashes,
+ null,
+ mres);
}
diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModulePath.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModulePath.java
similarity index 95%
rename from jdk/src/java.base/share/classes/java/lang/module/ModulePath.java
rename to jdk/src/java.base/share/classes/jdk/internal/module/ModulePath.java
index 15df0307180..fb7871d3c31 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/ModulePath.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModulePath.java
@@ -23,7 +23,7 @@
* questions.
*/
-package java.lang.module;
+package jdk.internal.module;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
@@ -32,7 +32,12 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
+import java.lang.module.FindException;
+import java.lang.module.InvalidModuleDescriptorException;
+import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Requires;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
import java.net.URI;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
@@ -59,7 +64,6 @@ import java.util.zip.ZipFile;
import jdk.internal.jmod.JmodFile;
import jdk.internal.jmod.JmodFile.Section;
-import jdk.internal.module.Checks;
import jdk.internal.perf.PerfCounter;
import jdk.internal.util.jar.VersionedStream;
@@ -74,7 +78,7 @@ import jdk.internal.util.jar.VersionedStream;
* modules in JMOD files.
*/
-class ModulePath implements ModuleFinder {
+public class ModulePath implements ModuleFinder {
private static final String MODULE_INFO = "module-info.class";
// the version to use for multi-release modular JARs
@@ -90,7 +94,7 @@ class ModulePath implements ModuleFinder {
// map of module name to module reference map for modules already located
private final Map cachedModules = new HashMap<>();
- ModulePath(Runtime.Version version, boolean isLinkPhase, Path... entries) {
+ public ModulePath(Runtime.Version version, boolean isLinkPhase, Path... entries) {
this.releaseVersion = version;
this.isLinkPhase = isLinkPhase;
this.entries = entries.clone();
@@ -99,7 +103,7 @@ class ModulePath implements ModuleFinder {
}
}
- ModulePath(Path... entries) {
+ public ModulePath(Path... entries) {
this(JarFile.runtimeVersion(), false, entries);
}
@@ -343,11 +347,11 @@ class ModulePath implements ModuleFinder {
*/
private ModuleReference readJMod(Path file) throws IOException {
try (JmodFile jf = new JmodFile(file)) {
- ModuleDescriptor md;
+ ModuleInfo.Attributes attrs;
try (InputStream in = jf.getInputStream(Section.CLASSES, MODULE_INFO)) {
- md = ModuleDescriptor.read(in, () -> jmodPackages(jf));
+ attrs = ModuleInfo.read(in, () -> jmodPackages(jf));
}
- return ModuleReferences.newJModModule(md, file);
+ return ModuleReferences.newJModModule(attrs, file);
}
}
@@ -557,13 +561,14 @@ class ModulePath implements ModuleFinder {
ZipFile.OPEN_READ,
releaseVersion))
{
- ModuleDescriptor md;
+ ModuleInfo.Attributes attrs;
JarEntry entry = jf.getJarEntry(MODULE_INFO);
if (entry == null) {
// no module-info.class so treat it as automatic module
try {
- md = deriveModuleDescriptor(jf);
+ ModuleDescriptor md = deriveModuleDescriptor(jf);
+ attrs = new ModuleInfo.Attributes(md, null, null);
} catch (IllegalArgumentException iae) {
throw new FindException(
"Unable to derive module descriptor for: "
@@ -571,11 +576,11 @@ class ModulePath implements ModuleFinder {
}
} else {
- md = ModuleDescriptor.read(jf.getInputStream(entry),
- () -> jarPackages(jf));
+ attrs = ModuleInfo.read(jf.getInputStream(entry),
+ () -> jarPackages(jf));
}
- return ModuleReferences.newJarModule(md, file);
+ return ModuleReferences.newJarModule(attrs, file);
}
}
@@ -604,15 +609,15 @@ class ModulePath implements ModuleFinder {
*/
private ModuleReference readExplodedModule(Path dir) throws IOException {
Path mi = dir.resolve(MODULE_INFO);
- ModuleDescriptor md;
+ ModuleInfo.Attributes attrs;
try (InputStream in = Files.newInputStream(mi)) {
- md = ModuleDescriptor.read(new BufferedInputStream(in),
- () -> explodedPackages(dir));
+ attrs = ModuleInfo.read(new BufferedInputStream(in),
+ () -> explodedPackages(dir));
} catch (NoSuchFileException e) {
// for now
return null;
}
- return ModuleReferences.newExplodedModule(md, dir);
+ return ModuleReferences.newExplodedModule(attrs, dir);
}
/**
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferenceImpl.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferenceImpl.java
new file mode 100644
index 00000000000..2ab42bdb4a2
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferenceImpl.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.module;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleReader;
+import java.lang.module.ModuleReference;
+import java.net.URI;
+import java.util.Objects;
+import java.util.function.Supplier;
+
+/**
+ * A ModuleReference implementation that supports referencing a module that
+ * is patched and/or can be tied to other modules by means of hashes.
+ */
+
+public class ModuleReferenceImpl extends ModuleReference {
+
+ private final Supplier readerSupplier;
+
+ // non-null if the module is patched
+ private final ModulePatcher patcher;
+
+ // the hashes of other modules recorded in this module
+ private final ModuleHashes recordedHashes;
+
+ // the function that computes the hash of this module
+ private final ModuleHashes.HashSupplier hasher;
+
+ // ModuleResolution flags
+ private final ModuleResolution moduleResolution;
+
+ // cached hash of this module to avoid needing to compute it many times
+ private byte[] cachedHash;
+
+ /**
+ * Constructs a new instance of this class.
+ */
+ ModuleReferenceImpl(ModuleDescriptor descriptor,
+ URI location,
+ Supplier readerSupplier,
+ ModulePatcher patcher,
+ ModuleHashes recordedHashes,
+ ModuleHashes.HashSupplier hasher,
+ ModuleResolution moduleResolution)
+ {
+ super(descriptor, Objects.requireNonNull(location));
+ this.readerSupplier = readerSupplier;
+ this.patcher = patcher;
+ this.recordedHashes = recordedHashes;
+ this.hasher = hasher;
+ this.moduleResolution = moduleResolution;
+ }
+
+ @Override
+ public ModuleReader open() throws IOException {
+ try {
+ return readerSupplier.get();
+ } catch (UncheckedIOException e) {
+ throw e.getCause();
+ }
+ }
+
+ /**
+ * Returns {@code true} if this module has been patched via --patch-module.
+ */
+ public boolean isPatched() {
+ return (patcher != null);
+ }
+
+ /**
+ * Returns the hashes recorded in this module or {@code null} if there
+ * are no hashes recorded.
+ */
+ public ModuleHashes recordedHashes() {
+ return recordedHashes;
+ }
+
+ /**
+ * Returns the supplier that computes the hash of this module.
+ */
+ ModuleHashes.HashSupplier hasher() {
+ return hasher;
+ }
+
+ /**
+ * Returns the ModuleResolution flags.
+ */
+ public ModuleResolution moduleResolution() {
+ return moduleResolution;
+ }
+
+ /**
+ * Computes the hash of this module. Returns {@code null} if the hash
+ * cannot be computed.
+ *
+ * @throws java.io.UncheckedIOException if an I/O error occurs
+ */
+ public byte[] computeHash(String algorithm) {
+ byte[] result = cachedHash;
+ if (result != null)
+ return result;
+ if (hasher == null)
+ return null;
+ cachedHash = result = hasher.generate(algorithm);
+ return result;
+ }
+
+ @Override
+ public int hashCode() {
+ int hc = hash;
+ if (hc == 0) {
+ hc = descriptor().hashCode();
+ hc = 43 * hc + Objects.hashCode(location());
+ hc = 43 * hc + Objects.hashCode(patcher);
+ if (hc == 0)
+ hc = -1;
+ hash = hc;
+ }
+ return hc;
+ }
+
+ private int hash;
+
+ @Override
+ public boolean equals(Object ob) {
+ if (!(ob instanceof ModuleReferenceImpl))
+ return false;
+ ModuleReferenceImpl that = (ModuleReferenceImpl)ob;
+
+ // assume module content, recorded hashes, etc. are the same
+ // when the modules have equal module descriptors, are at the
+ // same location, and are patched by the same patcher.
+ return Objects.equals(this.descriptor(), that.descriptor())
+ && Objects.equals(this.location(), that.location())
+ && Objects.equals(this.patcher, that.patcher);
+ }
+
+ @Override
+ public String toString() {
+ return super.toString();
+ }
+
+}
diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java
similarity index 92%
rename from jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java
rename to jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java
index e53ba0441d3..a2aff8f76be 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java
@@ -23,13 +23,15 @@
* questions.
*/
-package java.lang.module;
+package jdk.internal.module;
import java.io.File;
import java.io.IOError;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
+import java.lang.module.ModuleReader;
+import java.lang.module.ModuleReference;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.file.Files;
@@ -51,10 +53,7 @@ import java.util.zip.ZipFile;
import jdk.internal.jmod.JmodFile;
import jdk.internal.misc.JavaLangAccess;
import jdk.internal.misc.SharedSecrets;
-import jdk.internal.module.ModuleBootstrap;
-import jdk.internal.module.ModuleHashes;
import jdk.internal.module.ModuleHashes.HashSupplier;
-import jdk.internal.module.ModulePatcher;
import jdk.internal.util.jar.VersionedStream;
import sun.net.www.ParseUtil;
@@ -75,12 +74,18 @@ class ModuleReferences {
* Creates a ModuleReference to a module or to patched module when
* creating modules for the boot Layer and --patch-module is specified.
*/
- private static ModuleReference newModule(ModuleDescriptor md,
+ private static ModuleReference newModule(ModuleInfo.Attributes attrs,
URI uri,
Supplier supplier,
HashSupplier hasher) {
- ModuleReference mref = new ModuleReference(md, uri, supplier, hasher);
+ ModuleReference mref = new ModuleReferenceImpl(attrs.descriptor(),
+ uri,
+ supplier,
+ null,
+ attrs.recordedHashes(),
+ hasher,
+ attrs.moduleResolution());
if (JLA.getBootLayer() == null)
mref = ModuleBootstrap.patcher().patchIfNeeded(mref);
@@ -90,29 +95,29 @@ class ModuleReferences {
/**
* Creates a ModuleReference to a module packaged as a modular JAR.
*/
- static ModuleReference newJarModule(ModuleDescriptor md, Path file) {
+ static ModuleReference newJarModule(ModuleInfo.Attributes attrs, Path file) {
URI uri = file.toUri();
Supplier supplier = () -> new JarModuleReader(file, uri);
HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a);
- return newModule(md, uri, supplier, hasher);
+ return newModule(attrs, uri, supplier, hasher);
}
/**
* Creates a ModuleReference to a module packaged as a JMOD.
*/
- static ModuleReference newJModModule(ModuleDescriptor md, Path file) {
+ static ModuleReference newJModModule(ModuleInfo.Attributes attrs, Path file) {
URI uri = file.toUri();
Supplier supplier = () -> new JModModuleReader(file, uri);
HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a);
- return newModule(md, file.toUri(), supplier, hasher);
+ return newModule(attrs, uri, supplier, hasher);
}
/**
* Creates a ModuleReference to an exploded module.
*/
- static ModuleReference newExplodedModule(ModuleDescriptor md, Path dir) {
+ static ModuleReference newExplodedModule(ModuleInfo.Attributes attrs, Path dir) {
Supplier supplier = () -> new ExplodedModuleReader(dir);
- return newModule(md, dir.toUri(), supplier, null);
+ return newModule(attrs, dir.toUri(), supplier, null);
}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleResolution.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleResolution.java
new file mode 100644
index 00000000000..76c42368c63
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleResolution.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.module;
+
+import java.lang.module.ModuleReference;
+import static jdk.internal.module.ClassFileConstants.*;
+
+/**
+ * Represents the Module Resolution flags.
+ */
+public final class ModuleResolution {
+
+ final int value;
+
+ ModuleResolution(int value) {
+ this.value = value;
+ }
+
+ public static ModuleResolution empty() {
+ return new ModuleResolution(0);
+ }
+
+ public boolean doNotResolveByDefault() {
+ return (value & DO_NOT_RESOLVE_BY_DEFAULT) != 0;
+ }
+
+ public boolean hasDeprecatedWarning() {
+ return (value & WARN_DEPRECATED) != 0;
+ }
+
+ public boolean hasDeprecatedForRemovalWarning() {
+ return (value & WARN_DEPRECATED_FOR_REMOVAL) != 0;
+ }
+
+ public boolean hasIncubatingWarning() {
+ return (value & WARN_INCUBATING) != 0;
+ }
+
+ public ModuleResolution withDoNotResolveByDefault() {
+ return new ModuleResolution(value | DO_NOT_RESOLVE_BY_DEFAULT);
+ }
+
+ public ModuleResolution withDeprecated() {
+ if ((value & (WARN_DEPRECATED_FOR_REMOVAL | WARN_INCUBATING)) != 0)
+ throw new InternalError("cannot add deprecated to " + value);
+ return new ModuleResolution(value | WARN_DEPRECATED);
+ }
+
+ public ModuleResolution withDeprecatedForRemoval() {
+ if ((value & (WARN_DEPRECATED | WARN_INCUBATING)) != 0)
+ throw new InternalError("cannot add deprecated for removal to " + value);
+ return new ModuleResolution(value | WARN_DEPRECATED_FOR_REMOVAL);
+ }
+ public ModuleResolution withIncubating() {
+ if ((value & (WARN_DEPRECATED | WARN_DEPRECATED_FOR_REMOVAL)) != 0)
+ throw new InternalError("cannot add incubating to " + value);
+ return new ModuleResolution(value | WARN_INCUBATING);
+ }
+
+ public int value() {
+ return value;
+ }
+
+ public static boolean doNotResolveByDefault(ModuleReference mref) {
+ // get the DO_NOT_RESOLVE_BY_DEFAULT flag, if any
+ if (!(mref instanceof ModuleReferenceImpl))
+ return false;
+
+ ModuleResolution mres = ((ModuleReferenceImpl)mref).moduleResolution();
+ if (mres != null)
+ return mres.doNotResolveByDefault();
+
+ return false;
+ }
+
+ public static boolean hasIncubatingWarning(ModuleReference mref) {
+ if (!(mref instanceof ModuleReferenceImpl))
+ return false;
+
+ ModuleResolution mres = ((ModuleReferenceImpl)mref).moduleResolution();
+ if (mres != null)
+ return mres.hasIncubatingWarning();
+
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[value=" + value + "]";
+ }
+}
diff --git a/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModuleFinder.java
similarity index 77%
rename from jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java
rename to jdk/src/java.base/share/classes/jdk/internal/module/SystemModuleFinder.java
index 6de8ce824cf..5ec0a62ca69 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModuleFinder.java
@@ -23,12 +23,16 @@
* questions.
*/
-package java.lang.module;
+package jdk.internal.module;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReader;
+import java.lang.module.ModuleReference;
import java.net.URI;
import java.net.URLConnection;
import java.nio.ByteBuffer;
@@ -36,7 +40,6 @@ import java.util.ArrayDeque;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
@@ -54,11 +57,7 @@ import jdk.internal.jimage.ImageReader;
import jdk.internal.jimage.ImageReaderFactory;
import jdk.internal.misc.JavaNetUriAccess;
import jdk.internal.misc.SharedSecrets;
-import jdk.internal.module.ModuleBootstrap;
-import jdk.internal.module.ModuleHashes;
import jdk.internal.module.ModuleHashes.HashSupplier;
-import jdk.internal.module.SystemModules;
-import jdk.internal.module.ModulePatcher;
import jdk.internal.perf.PerfCounter;
/**
@@ -69,7 +68,7 @@ import jdk.internal.perf.PerfCounter;
* Packages attribute.
*/
-class SystemModuleFinder implements ModuleFinder {
+public class SystemModuleFinder implements ModuleFinder {
private static final JavaNetUriAccess JNUA = SharedSecrets.getJavaNetUriAccess();
@@ -84,11 +83,12 @@ class SystemModuleFinder implements ModuleFinder {
// ImageReader used to access all modules in the image
private static final ImageReader imageReader;
- // the set of modules in the run-time image
- private static final Set modules;
+ // singleton finder to find modules in the run-time images
+ private static final SystemModuleFinder INSTANCE;
- // maps module name to module reference
- private static final Map nameToModule;
+ public static SystemModuleFinder getInstance() {
+ return INSTANCE;
+ }
/**
* For now, the module references are created eagerly on the assumption
@@ -98,72 +98,11 @@ class SystemModuleFinder implements ModuleFinder {
long t0 = System.nanoTime();
imageReader = ImageReaderFactory.getImageReader();
- String[] names = moduleNames();
- ModuleDescriptor[] descriptors = descriptors(names);
-
- int n = names.length;
- moduleCount.add(n);
-
- ModuleReference[] mods = new ModuleReference[n];
-
- @SuppressWarnings(value = {"rawtypes", "unchecked"})
- Entry[] map
- = (Entry[])new Entry[n];
-
- for (int i = 0; i < n; i++) {
- ModuleDescriptor md = descriptors[i];
-
- // create the ModuleReference
- ModuleReference mref = toModuleReference(md, hashSupplier(i, names[i]));
-
- mods[i] = mref;
- map[i] = Map.entry(names[i], mref);
-
- // counters
- packageCount.add(md.packages().size());
- exportsCount.add(md.exports().size());
- }
-
- modules = Set.of(mods);
- nameToModule = Map.ofEntries(map);
+ INSTANCE = new SystemModuleFinder();
initTime.addElapsedTimeFrom(t0);
}
- /*
- * Returns an array of ModuleDescriptor of the given module names.
- *
- * This obtains ModuleDescriptors from SystemModules class that is generated
- * from the jlink system-modules plugin. ModuleDescriptors have already
- * been validated at link time.
- *
- * If java.base is patched, or fastpath is disabled for troubleshooting
- * purpose, it will fall back to find system modules via jrt file system.
- */
- private static ModuleDescriptor[] descriptors(String[] names) {
- // fastpath is enabled by default.
- // It can be disabled for troubleshooting purpose.
- boolean disabled =
- System.getProperty("jdk.system.module.finder.disabledFastPath") != null;
-
- // fast loading of ModuleDescriptor of system modules
- if (isFastPathSupported() && !disabled)
- return SystemModules.modules();
-
- // if fast loading of ModuleDescriptors is disabled
- // fallback to read module-info.class
- ModuleDescriptor[] descriptors = new ModuleDescriptor[names.length];
- for (int i = 0; i < names.length; i++) {
- String mn = names[i];
- ImageLocation loc = imageReader.findLocation(mn, "module-info.class");
- descriptors[i] = ModuleDescriptor.read(imageReader.getResourceBuffer(loc));
-
- // add the recorded hashes of tied modules
- Hashes.add(descriptors[i]);
- }
- return descriptors;
- }
-
private static boolean isFastPathSupported() {
return SystemModules.MODULE_NAMES.length > 0;
}
@@ -178,69 +117,95 @@ class SystemModuleFinder implements ModuleFinder {
return imageReader.getModuleNames();
}
- private static ModuleReference toModuleReference(ModuleDescriptor md,
- HashSupplier hash)
- {
- String mn = md.name();
- URI uri = JNUA.create("jrt", "/".concat(mn));
+ // the set of modules in the run-time image
+ private final Set modules;
- Supplier readerSupplier = new Supplier<>() {
- @Override
- public ModuleReader get() {
- return new ImageModuleReader(mn, uri);
- }
- };
+ // maps module name to module reference
+ private final Map nameToModule;
- ModuleReference mref =
- new ModuleReference(md, uri, readerSupplier, hash);
+ // module name to hashes
+ private final Map hashes;
- // may need a reference to a patched module if --patch-module specified
- mref = ModuleBootstrap.patcher().patchIfNeeded(mref);
+ private SystemModuleFinder() {
+ String[] names = moduleNames();
+ int n = names.length;
+ moduleCount.add(n);
- return mref;
- }
+ // fastpath is enabled by default.
+ // It can be disabled for troubleshooting purpose.
+ boolean disabled =
+ System.getProperty("jdk.system.module.finder.disabledFastPath") != null;
- private static HashSupplier hashSupplier(int index, String name) {
- if (isFastPathSupported()) {
- return new HashSupplier() {
- @Override
- public byte[] generate(String algorithm) {
- return SystemModules.MODULES_TO_HASH[index];
- }
- };
+ ModuleDescriptor[] descriptors;
+ ModuleHashes[] recordedHashes;
+ ModuleResolution[] moduleResolutions;
+
+ // fast loading of ModuleDescriptor of system modules
+ if (isFastPathSupported() && !disabled) {
+ descriptors = SystemModules.descriptors();
+ recordedHashes = SystemModules.hashes();
+ moduleResolutions = SystemModules.moduleResolutions();
} else {
- return Hashes.hashFor(name);
- }
- }
-
- /*
- * This helper class is only used when SystemModules is patched.
- * It will get the recorded hashes from module-info.class.
- */
- private static class Hashes {
- static Map hashes = new HashMap<>();
-
- static void add(ModuleDescriptor descriptor) {
- Optional ohashes = descriptor.hashes();
- if (ohashes.isPresent()) {
- hashes.putAll(ohashes.get().hashes());
+ // if fast loading of ModuleDescriptors is disabled
+ // fallback to read module-info.class
+ descriptors = new ModuleDescriptor[n];
+ recordedHashes = new ModuleHashes[n];
+ moduleResolutions = new ModuleResolution[n];
+ for (int i = 0; i < names.length; i++) {
+ String mn = names[i];
+ ImageLocation loc = imageReader.findLocation(mn, "module-info.class");
+ ModuleInfo.Attributes attrs =
+ ModuleInfo.read(imageReader.getResourceBuffer(loc), null);
+ descriptors[i] = attrs.descriptor();
+ recordedHashes[i] = attrs.recordedHashes();
+ moduleResolutions[i] = attrs.moduleResolution();
}
}
- static HashSupplier hashFor(String name) {
- if (!hashes.containsKey(name))
- return null;
-
- return new HashSupplier() {
- @Override
- public byte[] generate(String algorithm) {
- return hashes.get(name);
+ Map hashes = null;
+ boolean secondSeen = false;
+ // record the hashes to build HashSupplier
+ for (ModuleHashes mh : recordedHashes) {
+ if (mh != null) {
+ // if only one module contain ModuleHashes, use it
+ if (hashes == null) {
+ hashes = mh.hashes();
+ } else {
+ if (!secondSeen) {
+ hashes = new HashMap<>(hashes);
+ secondSeen = true;
+ }
+ hashes.putAll(mh.hashes());
}
- };
+ }
}
- }
+ this.hashes = (hashes == null) ? Map.of() : hashes;
- SystemModuleFinder() { }
+ ModuleReference[] mods = new ModuleReference[n];
+
+ @SuppressWarnings(value = {"rawtypes", "unchecked"})
+ Entry[] map
+ = (Entry[])new Entry[n];
+
+ for (int i = 0; i < n; i++) {
+ ModuleDescriptor md = descriptors[i];
+
+ // create the ModuleReference
+ ModuleReference mref = toModuleReference(md,
+ recordedHashes[i],
+ hashSupplier(names[i]),
+ moduleResolutions[i]);
+ mods[i] = mref;
+ map[i] = Map.entry(names[i], mref);
+
+ // counters
+ packageCount.add(md.packages().size());
+ exportsCount.add(md.exports().size());
+ }
+
+ modules = Set.of(mods);
+ nameToModule = Map.ofEntries(map);
+ }
@Override
public Optional find(String name) {
@@ -253,6 +218,41 @@ class SystemModuleFinder implements ModuleFinder {
return modules;
}
+ private ModuleReference toModuleReference(ModuleDescriptor md,
+ ModuleHashes recordedHashes,
+ HashSupplier hasher,
+ ModuleResolution mres) {
+ String mn = md.name();
+ URI uri = JNUA.create("jrt", "/".concat(mn));
+
+ Supplier readerSupplier = new Supplier<>() {
+ @Override
+ public ModuleReader get() {
+ return new ImageModuleReader(mn, uri);
+ }
+ };
+
+ ModuleReference mref =
+ new ModuleReferenceImpl(md, uri, readerSupplier, null,
+ recordedHashes, hasher, mres);
+
+ // may need a reference to a patched module if --patch-module specified
+ mref = ModuleBootstrap.patcher().patchIfNeeded(mref);
+
+ return mref;
+ }
+
+ private HashSupplier hashSupplier(String name) {
+ if (!hashes.containsKey(name))
+ return null;
+
+ return new HashSupplier() {
+ @Override
+ public byte[] generate(String algorithm) {
+ return hashes.get(name);
+ }
+ };
+ }
/**
* A ModuleReader for reading resources from a module linked into the
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java
index 299c6220450..7f2dbd0aad1 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java
@@ -29,14 +29,14 @@ import java.lang.module.ModuleDescriptor;
/*
* SystemModules class will be generated at link time to create
- * ModuleDescriptor for the installed modules directly to improve
+ * ModuleDescriptor for the system modules directly to improve
* the module descriptor reconstitution time.
*
* This will skip parsing of module-info.class file and validating
* names such as module name, package name, service and provider type names.
* It also avoids taking a defensive copy of any collection.
*
- * @see jdk.tools.jlink.internal.plugins.SystemModuleDescriptorPlugin
+ * @see jdk.tools.jlink.internal.plugins.SystemModulesPlugin
*/
public final class SystemModules {
/**
@@ -48,11 +48,6 @@ public final class SystemModules {
*/
public static final String[] MODULE_NAMES = new String[0];
- /**
- * Hash of system modules.
- */
- public static byte[][] MODULES_TO_HASH = new byte[0][];
-
/**
* Number of packages in the boot layer from the installed modules.
*
@@ -66,8 +61,24 @@ public final class SystemModules {
*
* When running an exploded image it returns an empty array.
*/
- public static ModuleDescriptor[] modules() {
- throw new InternalError("should not reach here");
+ public static ModuleDescriptor[] descriptors() {
+ throw new InternalError("expected to be overridden at link time");
}
+ /**
+ * Returns a non-empty array of ModuleHashes recorded in each module
+ * in the run-time image.
+ *
+ * When running an exploded image it returns an empty array.
+ */
+ public static ModuleHashes[] hashes() {
+ throw new InternalError("expected to be overridden at link time");
+ }
+
+ /**
+ * Returns a non-empty array of ModuleResolutions in the run-time image.
+ */
+ public static ModuleResolution[] moduleResolutions() {
+ throw new InternalError("expected to be overridden at link time");
+ }
}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java
index 90593f58fc3..4d91a001690 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java
@@ -2490,6 +2490,40 @@ public class ClassReader {
return readUTF8(items[readUnsignedShort(index)], buf);
}
+ /**
+ * Reads a CONSTANT_Module_info item in {@code b}. This method is intended
+ * for {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.
+ *
+ * @param index
+ * the start index of an unsigned short value in {@link #b b},
+ * whose value is the index of a module constant pool item.
+ * @param buf
+ * buffer to be used to read the item. This buffer must be
+ * sufficiently large. It is not automatically resized.
+ * @return the String corresponding to the specified module item.
+ */
+ public String readModule(int index, char[] buf) {
+ return readUTF8(items[readUnsignedShort(index)], buf);
+ }
+
+ /**
+ * Reads a CONSTANT_Pakcage_info item in {@code b}. This method is
+ * intended for {@link Attribute} sub slasses, and is normally not needed
+ * by class generators or adapters.
+ *
+ * @param index
+ * the start index of an unsigned short value in {@link #b b},
+ * whose value is the index of a package constant pool item.
+ * @param buf
+ * buffer to be used to read the item. This buffer must be
+ * sufficiently large. It is not automatically resized.
+ * @return the String corresponding to the specified package item.
+ */
+ public String readPackage(int index, char[] buf) {
+ return readUTF8(items[readUnsignedShort(index)], buf);
+ }
+
/**
* Reads a numeric or string constant pool item in {@link #b b}. This
* method is intended for {@link Attribute} sub classes, and is normally not
@@ -2516,6 +2550,8 @@ public class ClassReader {
case ClassWriter.DOUBLE:
return Double.longBitsToDouble(readLong(index));
case ClassWriter.CLASS:
+ case ClassWriter.MODULE:
+ case ClassWriter.PACKAGE:
return Type.getObjectType(readUTF8(index, buf));
case ClassWriter.STR:
return readUTF8(index, buf);
diff --git a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java
index a577f933270..bd0978c0c09 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java
@@ -271,6 +271,16 @@ public class ClassWriter extends ClassVisitor {
*/
static final int INDY = 18;
+ /**
+ * The type of CONSTANT_Module constant pool items.
+ */
+ static final int MODULE = 19;
+
+ /**
+ * The type of CONSTANT_Package constant pool items.
+ */
+ static final int PACKAGE = 20;
+
/**
* The base value for all CONSTANT_MethodHandle constant pool items.
* Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9
@@ -1160,6 +1170,50 @@ public class ClassWriter extends ClassVisitor {
return newClassItem(value).index;
}
+ /**
+ * Adds a module name to the constant pool.
+ *
+ * Does nothing if the constant pool already contains a similar item.
+ * This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.
+ *
+ * @param value
+ * the module name
+ * @return the index of a new or already existing module reference item.
+ */
+ public int newModule(String value) {
+ key2.set(MODULE, value, null, null);
+ Item result = get(key2);
+ if (result == null) {
+ pool.put12(MODULE, newUTF8(value));
+ result = new Item(index++, key2);
+ put(result);
+ }
+ return result.index;
+ }
+
+ /**
+ * Adds a package name to the constant pool.
+ *
+ * Does nothing if the constant pool already contains a similar item.
+ * This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.
+ *
+ * @param value
+ * the internal name of the package.
+ * @return the index of a new or already existing package reference item.
+ */
+ public int newPackage(String value) {
+ key2.set(PACKAGE, value, null, null);
+ Item result = get(key2);
+ if (result == null) {
+ pool.put12(PACKAGE, newUTF8(value));
+ result = new Item(index++, key2);
+ put(result);
+ }
+ return result.index;
+ }
+
/**
* Adds a method type reference to the constant pool of the class being
* build. Does nothing if the constant pool already contains a similar item.
diff --git a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Item.java b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Item.java
index 25ed37718dd..b0b80907d9d 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Item.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Item.java
@@ -239,6 +239,8 @@ final class Item {
this.strVal3 = strVal3;
switch (type) {
case ClassWriter.CLASS:
+ case ClassWriter.MODULE:
+ case ClassWriter.PACKAGE:
this.intVal = 0; // intVal of a class must be zero, see visitInnerClass
case ClassWriter.UTF8:
case ClassWriter.STR:
@@ -311,6 +313,8 @@ final class Item {
case ClassWriter.UTF8:
case ClassWriter.STR:
case ClassWriter.CLASS:
+ case ClassWriter.MODULE:
+ case ClassWriter.PACKAGE:
case ClassWriter.MTYPE:
case ClassWriter.TYPE_NORMAL:
return i.strVal1.equals(strVal1);
diff --git a/jdk/src/java.base/share/classes/jdk/internal/ref/Cleaner.java b/jdk/src/java.base/share/classes/jdk/internal/ref/Cleaner.java
index 84c0f618a91..5522c0c1ff0 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/ref/Cleaner.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/ref/Cleaner.java
@@ -58,7 +58,6 @@ import java.security.PrivilegedAction;
public class Cleaner
extends PhantomReference