This commit is contained in:
Pavel Rappo 2016-12-19 16:05:38 +00:00
commit 4548261e7b
195 changed files with 8030 additions and 2450 deletions

View File

@ -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?

View File

@ -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

View File

@ -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 :=

View File

@ -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 \
, \
))

View File

@ -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), \

View File

@ -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), \

View File

@ -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 += \

View File

@ -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;

View File

@ -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<ModuleDescriptor> 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<String> 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<ModuleDescriptor> javaGroup;
private final Set<ModuleDescriptor> jdkGroup;
GenGraphs(Set<ModuleDescriptor> javaGroup, Set<ModuleDescriptor> 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<ModuleDescriptor> javaGroup;
private final Set<ModuleDescriptor> jdkGroup;
Map<String, ModuleDescriptor> 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<ModuleDescriptor> javaGroup, Set<ModuleDescriptor> 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<String> roots) throws IOException {
Configuration cf =
Configuration.empty().resolveRequires(ModuleFinder.ofSystem(),
ModuleFinder.of(),
roots);
Set<ModuleDescriptor> 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<String> 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<String> graph,
Map<String, ModuleDescriptor> nameToModule)
throws IOException
{
Set<ModuleDescriptor> 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<String> graph = gengraph(cf);
descriptors.forEach(md -> {
String mn = md.name();
Set<String> 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<String> 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<String> rpg = requiresTransitiveGraph(cf);
Graph<String> 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<String> requiresTransitiveGraph(Configuration cf) {
private Graph<String> requiresTransitiveGraph(Configuration cf, boolean includeBase) {
Graph.Builder<String> 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));
}

View File

@ -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;
}

View File

@ -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;;) {

View File

@ -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 =

View File

@ -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;
}
}
}
}

View File

@ -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<String> HASHED_MODULES = hashedModules();
static Set<String> hashedModules() {
Module javaBase = Layer.boot().findModule("java.base").get();
Optional<ModuleHashes> ohashes =
SharedSecrets.getJavaLangModuleAccess()
.hashes(javaBase.getDescriptor());
if (ohashes.isPresent()) {
Set<String> names = new HashSet<>(ohashes.get().names());
Optional<ResolvedModule> 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<String> names = new HashSet<>(hashes.names());
names.add("java.base");
return names;
}

View File

@ -227,7 +227,9 @@ public final class StrictMath {
* @return the value <i>e</i><sup>{@code a}</sup>,
* where <i>e</i> 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 <i>e</i>) of a {@code double}

View File

@ -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(); }

View File

@ -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<Modifier> mods;
private final String name;
private final Version compiledVersion;
private Requires(Set<Modifier> ms, String mn) {
private Requires(Set<Modifier> 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<Modifier> ms, String mn, boolean unused) {
private Requires(Set<Modifier> 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<Version> compiledVersion() {
return Optional.ofNullable(compiledVersion);
}
/**
* Compares this module dependence to another.
*
* <p> 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. </p>
* 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. </p>
*
* @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
*
* <p> 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. </p>
* 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. </p>
*
* <p> This method satisfies the general contract of the {@link
* java.lang.Object#equals(Object) Object.equals} method. </p>
@ -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.
*
* <p> The hash code is based upon the module name and modifiers. It
* satisfies the general contract of the {@link Object#hashCode
* Object.hashCode} method. </p>
* <p> 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. </p>
*
* @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<String> uses;
private final Set<Provides> provides;
// "Extended" information, added post-compilation by tools
private final Version version;
// Added post-compilation by tools
private final Set<String> packages;
private final String mainClass;
private final String osName;
private final String osArch;
private final String osVersion;
private final Set<String> 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> opens,
Set<String> uses,
Set<Provides> provides,
Version version,
Set<String> packages,
String mainClass,
String osName,
String osArch,
String osVersion,
Set<String> 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<String> 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<String> 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<String> 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> opens,
Set<String> uses,
Set<Provides> provides,
Version version,
Set<String> packages,
String mainClass,
String osName,
String osArch,
String osVersion,
Set<String> 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<ModuleHashes> 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<String, Requires> requires = new HashMap<>();
final Map<String, Exports> exports = new HashMap<>();
final Map<String, Opens> opens = new HashMap<>();
final Set<String> concealedPackages = new HashSet<>();
final Set<String> uses = new HashSet<>();
final Map<String, Provides> 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<String> exportedPackages() {
return exports.keySet();
}
/* package */ boolean isAutomatic() {
return automatic;
/**
* Returns the set of packages that are opened (unconditionally or
* unconditionally).
*/
/* package */Set<String> 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<Requires.Modifier> 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<Requires.Modifier> 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<String> exportedAndOpenPackages() {
if (opens.isEmpty())
return exports.keySet();
Set<String> 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> requires = new HashSet<>(this.requires.values());
Set<String> packages = new HashSet<>(exportedAndOpenPackages());
Set<String> packages = new HashSet<>();
packages.addAll(exports.keySet());
packages.addAll(opens.keySet());
packages.addAll(concealedPackages);
Set<Exports> exports = new HashSet<>(this.exports.values());
@ -1999,6 +2040,7 @@ public class ModuleDescriptor
Set<Provides> 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<Set<String>> 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<Set<String>> 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 <K,V> Map<K,V> emptyOrUnmodifiableMap(Map<K,V> 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<String> exportedPackages(ModuleDescriptor.Builder builder) {
return builder.exportedPackages();
}
@Override
public Requires newRequires(Set<Requires.Modifier> ms, String mn) {
return new Requires(ms, mn, true);
public Set<String> openPackages(ModuleDescriptor.Builder builder) {
return builder.openPackages();
}
@Override
public Requires newRequires(Set<Requires.Modifier> 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> opens,
Set<String> uses,
Set<Provides> provides,
Version version,
Set<String> packages,
String mainClass,
String osName,
String osArch,
String osVersion,
Set<String> 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<ModuleHashes> hashes(ModuleDescriptor descriptor) {
return descriptor.hashes();
}
@Override
public Configuration resolveRequiresAndUses(ModuleFinder finder,
Collection<String> roots,
@ -2482,20 +2521,6 @@ public class ModuleDescriptor
{
return Configuration.resolveRequiresAndUses(finder, roots, check, traceOutput);
}
@Override
public ModuleReference newPatchedModule(ModuleDescriptor descriptor,
URI location,
Supplier<ModuleReader> 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);
}
});
}

View File

@ -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 <em>system modules</em>. 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}.
*
* <p> 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)) {

View File

@ -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.
*
* <p> 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.
* <p> 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<ModuleReader> 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<ModuleReader> 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<ModuleReader> readerSupplier,
HashSupplier hasher)
{
this(descriptor, location, readerSupplier, false, hasher);
}
/**
* Constructs a new instance of this class.
*
* <p> 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<ModuleReader> 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<URI> location() {
public final Optional<URI> location() {
return Optional.ofNullable(location);
}
/**
* Opens the module content for reading.
*
* <p> This method opens the module content by invoking the {@link
* Supplier#get() get()} method of the {@code readSupplier} specified at
* construction time. </p>
*
* @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.
*
* <p> The hash code is based upon the components of the reference, and
* satisfies the general contract of the {@link Object#hashCode
* Object.hashCode} method. </p>
*
* @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.
*
* <p> 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. </p>
*
* <p> This method satisfies the general contract of the {@link
* java.lang.Object#equals(Object) Object.equals} method. </p>
*
* @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;
}

View File

@ -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<ModuleHashes> 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);

View File

@ -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);
}
}
/**

View File

@ -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.
*
* <p> Creating a {@code Layer} can fail for the following reasons: </p>

View File

@ -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 <other>
Map<String, Set<Module>> openPackages = this.openPackages;
if (openPackages != null) {
@ -643,6 +643,12 @@ public final class Module implements AnnotatedElement {
* <em>open</em>) to the given module. It also has no effect if
* invoked on an {@link ModuleDescriptor#isOpen open} module. </p>
*
* @apiNote As specified in section 5.4.3 of the <cite>The Java&trade;
* Virtual Machine Specification </cite>, 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
* <em>open</em> the given package to the given module.
* If this module has <em>opened</em> 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<Layer> layers(ClassLoader loader) {
return Layer.layers(loader);
}
@Override
public boolean isStaticallyExported(Module module, String pn, Module other) {
return module.isStaticallyExportedOrOpen(pn, other, false);
}
});
}
}

View File

@ -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:
* <blockquote>
* <dl>
* <dt> {@code SSLEngine}
* <dd> The function's first argument allows the current {@code SSLEngine}
* to be inspected, including the handshake session and configuration
* settings.
* <dt> {@code List<String>}
* <dd> The function's second argument lists the application protocol names
* advertised by the TLS peer.
* <dt> {@code String}
* <dd> 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.)
* </dl>
* </blockquote>
*
* For example, the following call registers a callback function that
* examines the TLS handshake parameters and selects an application protocol
* name:
* <pre>{@code
* serverEngine.setHandshakeApplicationProtocolSelector(
* (serverEngine, clientProtocols) -> {
* SSLSession session = serverEngine.getHandshakeSession();
* return chooseApplicationProtocol(
* serverEngine,
* clientProtocols,
* session.getProtocol(),
* session.getCipherSuite());
* });
* }</pre>
*
* @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<SSLEngine, List<String>, 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<SSLEngine, List<String>, String>
getHandshakeApplicationProtocolSelector() {
throw new UnsupportedOperationException();
}
}

View File

@ -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 <code>Socket</code>s 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:
* <blockquote>
* <dl>
* <dt> {@code SSLSocket}
* <dd> The function's first argument allows the current {@code SSLSocket}
* to be inspected, including the handshake session and configuration
* settings.
* <dt> {@code List<String>}
* <dd> The function's second argument lists the application protocol names
* advertised by the TLS peer.
* <dt> {@code String}
* <dd> 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.)
* </dl>
* </blockquote>
*
* For example, the following call registers a callback function that
* examines the TLS handshake parameters and selects an application protocol
* name:
* <pre>{@code
* serverSocket.setHandshakeApplicationProtocolSelector(
* (serverSocket, clientProtocols) -> {
* SSLSession session = serverSocket.getHandshakeSession();
* return chooseApplicationProtocol(
* serverSocket,
* clientProtocols,
* session.getProtocol(),
* session.getCipherSuite());
* });
* }</pre>
*
* @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<SSLSocket, List<String>, 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<SSLSocket, List<String>, String>
getHandshakeApplicationProtocolSelector() {
throw new UnsupportedOperationException();
}
}

View File

@ -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() {

View File

@ -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<String> exportedPackages(ModuleDescriptor.Builder builder);
/**
* Returns the set of packages that are opened (unconditionally or
* unconditionally).
*/
Set<String> openPackages(ModuleDescriptor.Builder builder);
/**
* Returns a {@code ModuleDescriptor.Requires} of the given modifiers
* and module name.
*/
Requires newRequires(Set<Requires.Modifier> ms, String mn);
Requires newRequires(Set<Requires.Modifier> 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> opens,
Set<String> uses,
Set<Provides> provides,
Version version,
Set<String> packages,
String mainClass,
String osName,
String osArch,
String osVersion,
Set<String> packages,
ModuleHashes hashes,
int hashCode);
/**
* Returns the object with the hashes of other modules
*/
Optional<ModuleHashes> 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<ModuleReader> readerSupplier);
/**
* Creates a ModuleFinder for a module path.
*/
ModuleFinder newModulePath(Runtime.Version version,
boolean isLinkPhase,
Path... entries);
}

View File

@ -123,4 +123,12 @@ public interface JavaLangReflectModuleAccess {
* given class loader.
*/
Stream<Layer> 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);
}

View File

@ -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<Requires.Modifier> 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<Requires.Modifier> 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<Exports.Modifier> ms,
String pn,
Set<String> 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<Opens.Modifier> 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<Opens.Modifier> ms,
String pn,
Set<String> 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<Exports.Modifier> 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<String> 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<String, byte[]> 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);
}
}

View File

@ -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;
}
}

View File

@ -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<requires_count; i++) {
String dn = cr.readUTF8(off, buf).replace('/', '.');
int flags = cr.readUnsignedShort(off + 2);
// CONSTANT_Module_info
String dn = cr.readModule(off, buf);
off += 2;
// requires_flags
int requires_flags = cr.readUnsignedShort(off);
off += 2;
Set<Requires.Modifier> 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<exports_count; i++) {
String pkg = cr.readUTF8(off, buf).replace('/', '.');
// CONSTANT_Package_info
String pkg = cr.readPackage(off, buf).replace('/', '.');
off += 2;
int flags = cr.readUnsignedShort(off);
int exports_flags = cr.readUnsignedShort(off);
off += 2;
Set<Exports.Modifier> 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<String> targets = new HashSet<>();
for (int j=0; j<exports_to_count; j++) {
String t = cr.readUTF8(off, buf).replace('/', '.');
String t = cr.readModule(off, buf);
off += 2;
targets.add(t);
}
@ -170,19 +201,20 @@ public final class ClassFileAttributes {
off += 2;
if (open_count > 0) {
for (int i=0; i<open_count; i++) {
String pkg = cr.readUTF8(off, buf).replace('/', '.');
// CONSTANT_Package_info
String pkg = cr.readPackage(off, buf).replace('/', '.');
off += 2;
int flags = cr.readUnsignedShort(off);
int opens_flags = cr.readUnsignedShort(off);
off += 2;
Set<Opens.Modifier> 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<String> targets = new HashSet<>();
for (int j=0; j<opens_to_count; j++) {
String t = cr.readUTF8(off, buf).replace('/', '.');
String t = cr.readModule(off, buf);
off += 2;
targets.add(t);
}
@ -232,8 +264,7 @@ public final class ClassFileAttributes {
}
}
attr.descriptor = builder.build();
return attr;
return new ModuleAttribute(builder.build());
}
@Override
@ -248,7 +279,7 @@ public final class ClassFileAttributes {
// module_name
String mn = descriptor.name();
int module_name_index = cw.newUTF8(mn.replace('.', '/'));
int module_name_index = cw.newModule(mn);
attr.putShort(module_name_index);
// module_flags
@ -259,66 +290,83 @@ public final class ClassFileAttributes {
module_flags |= ACC_SYNTHETIC;
attr.putShort(module_flags);
// module_version
Version v = descriptor.version().orElse(null);
if (v == null) {
attr.putShort(0);
} else {
int module_version_index = cw.newUTF8(v.toString());
attr.putShort(module_version_index);
}
// requires_count
attr.putShort(descriptor.requires().size());
// requires[requires_count]
for (Requires md : descriptor.requires()) {
String dn = md.name();
int flags = 0;
if (md.modifiers().contains(Requires.Modifier.TRANSITIVE))
flags |= ACC_TRANSITIVE;
if (md.modifiers().contains(Requires.Modifier.STATIC))
flags |= ACC_STATIC_PHASE;
if (md.modifiers().contains(Requires.Modifier.SYNTHETIC))
flags |= ACC_SYNTHETIC;
if (md.modifiers().contains(Requires.Modifier.MANDATED))
flags |= ACC_MANDATED;
int index = cw.newUTF8(dn.replace('.', '/'));
attr.putShort(index);
attr.putShort(flags);
for (Requires r : descriptor.requires()) {
int requires_index = cw.newModule(r.name());
attr.putShort(requires_index);
int requires_flags = 0;
if (r.modifiers().contains(Requires.Modifier.TRANSITIVE))
requires_flags |= ACC_TRANSITIVE;
if (r.modifiers().contains(Requires.Modifier.STATIC))
requires_flags |= ACC_STATIC_PHASE;
if (r.modifiers().contains(Requires.Modifier.SYNTHETIC))
requires_flags |= ACC_SYNTHETIC;
if (r.modifiers().contains(Requires.Modifier.MANDATED))
requires_flags |= ACC_MANDATED;
attr.putShort(requires_flags);
int requires_version_index;
v = r.compiledVersion().orElse(null);
if (v == null) {
requires_version_index = 0;
} else {
requires_version_index = cw.newUTF8(v.toString());
}
attr.putShort(requires_version_index);
}
// exports_count and exports[exports_count];
attr.putShort(descriptor.exports().size());
for (Exports e : descriptor.exports()) {
String pkg = e.source().replace('.', '/');
attr.putShort(cw.newUTF8(pkg));
attr.putShort(cw.newPackage(pkg));
int flags = 0;
int exports_flags = 0;
if (e.modifiers().contains(Exports.Modifier.SYNTHETIC))
flags |= ACC_SYNTHETIC;
exports_flags |= ACC_SYNTHETIC;
if (e.modifiers().contains(Exports.Modifier.MANDATED))
flags |= ACC_MANDATED;
attr.putShort(flags);
exports_flags |= ACC_MANDATED;
attr.putShort(exports_flags);
if (e.isQualified()) {
Set<String> 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<String> 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<String> packages = new HashSet<>();
for (int i=0; i<package_count; i++) {
String pkg = cr.readUTF8(off, buf).replace('/', '.');
String pkg = cr.readPackage(off, buf).replace('/', '.');
packages.add(pkg);
off += 2;
}
@ -427,68 +475,13 @@ public final class ClassFileAttributes {
// packages
packages.stream()
.map(p -> p.replace('.', '/'))
.forEach(p -> attr.putShort(cw.newUTF8(p)));
.forEach(p -> attr.putShort(cw.newPackage(p)));
return attr;
}
}
/**
* ModuleVersion attribute.
*
* <pre> {@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;
* }
*
* } </pre>
*/
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<String, byte[]> map = new HashMap<>();
for (int i=0; i<hashes_count; i++) {
String mn = cr.readUTF8(off, buf).replace('/', '.');
String mn = cr.readModule(off, buf);
off += 2;
int hash_length = cr.readUnsignedShort(off);
@ -728,7 +721,7 @@ public final class ClassFileAttributes {
for (String mn : names) {
byte[] hash = hashes.hashFor(mn);
assert hash != null;
attr.putShort(cw.newUTF8(mn.replace('.', '/')));
attr.putShort(cw.newModule(mn));
attr.putShort(hash.length);
for (byte b: hash) {
@ -740,4 +733,58 @@ public final class ClassFileAttributes {
}
}
/**
* ModuleResolution_attribute {
* u2 attribute_name_index; // "ModuleResolution"
* u4 attribute_length; // 2
* u2 resolution_flags;
*
* The value of the resolution_flags item is a mask of flags used to denote
* properties of module resolution. The flags are as follows:
*
* // Optional
* 0x0001 (DO_NOT_RESOLVE_BY_DEFAULT)
*
* // At most one of:
* 0x0002 (WARN_DEPRECATED)
* 0x0004 (WARN_DEPRECATED_FOR_REMOVAL)
* 0x0008 (WARN_INCUBATING)
*/
static class ModuleResolutionAttribute extends Attribute {
private final int value;
ModuleResolutionAttribute() {
super(MODULE_RESOLUTION);
value = 0;
}
ModuleResolutionAttribute(int value) {
super(MODULE_RESOLUTION);
this.value = value;
}
@Override
protected Attribute read(ClassReader cr,
int off,
int len,
char[] buf,
int codeOff,
Label[] labels)
{
int flags = cr.readUnsignedShort(off);
return new ModuleResolutionAttribute(flags);
}
@Override
protected ByteVector write(ClassWriter cw,
byte[] code,
int len,
int maxStack,
int maxLocals)
{
ByteVector attr = new ByteVector();
attr.putShort(value);
return attr;
}
}
}

View File

@ -38,10 +38,10 @@ public class ClassFileConstants {
public static final String SDE = "SourceDebugExtension";
public static final String MODULE_PACKAGES = "ModulePackages";
public static final String MODULE_VERSION = "ModuleVersion";
public static final String MODULE_MAIN_CLASS = "ModuleMainClass";
public static final String MODULE_TARGET = "ModuleTarget";
public static final String MODULE_HASHES = "ModuleHashes";
public static final String MODULE_RESOLUTION = "ModuleResolution";
// access, requires, exports, and opens flags
public static final int ACC_MODULE = 0x8000;
@ -51,4 +51,10 @@ public class ClassFileConstants {
public static final int ACC_SYNTHETIC = 0x1000;
public static final int ACC_MANDATED = 0x8000;
// ModuleResolution_attribute resolution flags
public static final int DO_NOT_RESOLVE_BY_DEFAULT = 0x0001;
public static final int WARN_DEPRECATED = 0x0002;
public static final int WARN_DEPRECATED_FOR_REMOVAL = 0x0004;
public static final int WARN_INCUBATING = 0x0008;
}

View File

@ -195,7 +195,9 @@ public final class ModuleBootstrap {
// module is the unnamed module of the application class loader. This
// is implemented by resolving "java.se" and all (non-java.*) modules
// that export an API. If "java.se" is not observable then all java.*
// modules are resolved.
// modules are resolved. Modules that have the DO_NOT_RESOLVE_BY_DEFAULT
// bit set in their ModuleResolution attribute flags are excluded from
// the default set of roots.
if (mainModule == null || addAllDefaultModules) {
boolean hasJava = false;
if (systemModules.find(JAVA_SE).isPresent()) {
@ -212,6 +214,9 @@ public final class ModuleBootstrap {
if (hasJava && mn.startsWith("java."))
continue;
if (ModuleResolution.doNotResolveByDefault(mref))
continue;
// add as root if observable and exports at least one package
if ((finder == systemModules || finder.find(mn).isPresent())) {
ModuleDescriptor descriptor = mref.descriptor();
@ -231,6 +236,7 @@ public final class ModuleBootstrap {
ModuleFinder f = finder; // observable modules
systemModules.findAll()
.stream()
.filter(mref -> !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<String, ClassLoader> 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 <module>/<package>: " + 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 <module>=<value>: " + 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 <module>=<value>: " + value);
// value is <module>(,<module>)* or <file>(<pathsep><file>)*
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
*/

View File

@ -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<String, byte[]> 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<String, byte[]> 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;
}
}
}
}

View File

@ -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<Set<String>> 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<Set<String>> pf)
public static Attributes read(InputStream in, Supplier<Set<String>> pf)
throws IOException
{
try {
@ -100,9 +136,7 @@ final class ModuleInfo {
* @throws InvalidModuleDescriptorException
* @throws UncheckedIOException
*/
public static ModuleDescriptor read(ByteBuffer bb,
Supplier<Set<String>> pf)
{
public static Attributes read(ByteBuffer bb, Supplier<Set<String>> 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<Set<String>> pf)
{
public static Attributes readIgnoringHashes(ByteBuffer bb, Supplier<Set<String>> 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<String> 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<String> exportedPackages = JLMA.exportedPackages(builder);
Set<String> 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<String> 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<requires_count; i++) {
int index = in.readUnsignedShort();
int flags = in.readUnsignedShort();
String dn = cpool.getUtf8AsBinaryName(index);
int requires_index = in.readUnsignedShort();
String dn = cpool.getModuleName(requires_index);
int requires_flags = in.readUnsignedShort();
Set<Requires.Modifier> 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<exports_count; i++) {
int index = in.readUnsignedShort();
String pkg = cpool.getUtf8AsBinaryName(index);
int exports_index = in.readUnsignedShort();
String pkg = cpool.getPackageName(exports_index);
Set<Exports.Modifier> 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<String> targets = new HashSet<>(exports_to_count);
for (int j=0; j<exports_to_count; j++) {
int exports_to_index = in.readUnsignedShort();
targets.add(cpool.getUtf8AsBinaryName(exports_to_index));
targets.add(cpool.getModuleName(exports_to_index));
}
builder.exports(mods, pkg, targets);
} else {
@ -386,18 +445,18 @@ final class ModuleInfo {
+ " module must be 0 length");
}
for (int i=0; i<opens_count; i++) {
int index = in.readUnsignedShort();
String pkg = cpool.getUtf8AsBinaryName(index);
int opens_index = in.readUnsignedShort();
String pkg = cpool.getPackageName(opens_index);
Set<Opens.Modifier> 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<String> targets = new HashSet<>(open_to_count);
for (int j=0; j<open_to_count; j++) {
int opens_to_index = in.readUnsignedShort();
targets.add(cpool.getUtf8AsBinaryName(opens_to_index));
targets.add(cpool.getModuleName(opens_to_index));
}
builder.opens(mods, pkg, targets);
} else {
@ -419,7 +478,7 @@ final class ModuleInfo {
if (uses_count > 0) {
for (int i=0; i<uses_count; i++) {
int index = in.readUnsignedShort();
String sn = cpool.getClassNameAsBinaryName(index);
String sn = cpool.getClassName(index);
builder.uses(sn);
}
}
@ -428,12 +487,12 @@ final class ModuleInfo {
if (provides_count > 0) {
for (int i=0; i<provides_count; i++) {
int index = in.readUnsignedShort();
String sn = cpool.getClassNameAsBinaryName(index);
String sn = cpool.getClassName(index);
int with_count = in.readUnsignedShort();
List<String> providers = new ArrayList<>(with_count);
for (int j=0; j<with_count; j++) {
index = in.readUnsignedShort();
String pn = cpool.getClassNameAsBinaryName(index);
String pn = cpool.getClassName(index);
providers.add(pn);
}
builder.provides(sn, providers);
@ -453,22 +512,16 @@ final class ModuleInfo {
Set<String> packages = new HashSet<>(package_count);
for (int i=0; i<package_count; i++) {
int index = in.readUnsignedShort();
String pn = cpool.getUtf8AsBinaryName(index);
packages.add(pn);
String pn = cpool.getPackageName(index);
boolean added = packages.add(pn);
if (!added) {
throw invalidModuleDescriptor("Package " + pn + " in ModulePackages"
+ "attribute more than once");
}
}
return packages;
}
/**
* Reads the ModuleVersion attribute
*/
private String readModuleVersionAttribute(DataInput in, ConstantPool cpool)
throws IOException
{
int index = in.readUnsignedShort();
return cpool.getUtf8(index);
}
/**
* Reads the ModuleMainClass attribute
*/
@ -476,7 +529,7 @@ final class ModuleInfo {
throws IOException
{
int index = in.readUnsignedShort();
return cpool.getClassNameAsBinaryName(index);
return cpool.getClassName(index);
}
/**
@ -516,7 +569,7 @@ final class ModuleInfo {
Map<String, byte[]> map = new HashMap<>(hash_count);
for (int i=0; i<hash_count; i++) {
int module_name_index = in.readUnsignedShort();
String mn = cpool.getUtf8AsBinaryName(module_name_index);
String mn = cpool.getModuleName(module_name_index);
int hash_length = in.readUnsignedShort();
if (hash_length == 0) {
throw invalidModuleDescriptor("hash_length == 0");
@ -529,6 +582,31 @@ final class ModuleInfo {
return new ModuleHashes(algorithm, map);
}
/**
* Reads the ModuleResolution attribute.
*/
private ModuleResolution readModuleResolution(DataInput in,
ConstantPool cpool)
throws IOException
{
int flags = in.readUnsignedShort();
int reason = 0;
if ((flags & WARN_DEPRECATED) != 0)
reason = WARN_DEPRECATED;
if ((flags & WARN_DEPRECATED_FOR_REMOVAL) != 0) {
if (reason != 0)
throw invalidModuleDescriptor("Bad module resolution flags:" + flags);
reason = WARN_DEPRECATED_FOR_REMOVAL;
}
if ((flags & WARN_INCUBATING) != 0) {
if (reason != 0)
throw invalidModuleDescriptor("Bad module resolution flags:" + flags);
}
return new ModuleResolution(flags);
}
/**
* Returns true if the given attribute can be present at most once
@ -540,10 +618,10 @@ final class ModuleInfo {
name.equals(SOURCE_FILE) ||
name.equals(SDE) ||
name.equals(MODULE_PACKAGES) ||
name.equals(MODULE_VERSION) ||
name.equals(MODULE_MAIN_CLASS) ||
name.equals(MODULE_TARGET) ||
name.equals(MODULE_HASHES))
name.equals(MODULE_HASHES) ||
name.equals(MODULE_RESOLUTION))
return true;
return false;
@ -604,6 +682,8 @@ final class ModuleInfo {
static final int CONSTANT_MethodHandle = 15;
static final int CONSTANT_MethodType = 16;
static final int CONSTANT_InvokeDynamic = 18;
static final int CONSTANT_Module = 19;
static final int CONSTANT_Package = 20;
private static class Entry {
protected Entry(int tag) {
@ -653,6 +733,8 @@ final class ModuleInfo {
break;
case CONSTANT_Class:
case CONSTANT_Package:
case CONSTANT_Module:
case CONSTANT_String:
int index = in.readUnsignedShort();
pool[i] = new IndexEntry(tag, index);
@ -715,14 +797,34 @@ final class ModuleInfo {
throw invalidModuleDescriptor("CONSTANT_Class expected at entry: "
+ index);
}
return getUtf8(((IndexEntry) e).index);
String value = getUtf8(((IndexEntry) e).index);
checkUnqualifiedName("CONSTANT_Class", index, value);
return value.replace('/', '.'); // internal form -> 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; i++) {
char c = value.charAt(i);
if (c == '.' || c == ';' || c == '[') {
throw invalidModuleDescriptor(what + " at entry " + index
+ " has illegal character: '"
+ c + "'");
}
}
}
/**
* "Decode" a module name that has been read from the constant pool.
*/
String decodeModuleName(int index, String value) {
int len = value.length();
if (len == 0) {
throw invalidModuleDescriptor("CONSTANT_Module at entry "
+ index + " is zero length");
}
int i = 0;
while (i < len) {
int cp = value.codePointAt(i);
if (cp == ':' || cp == '@' || cp < 0x20) {
throw invalidModuleDescriptor("CONSTANT_Module at entry "
+ index + " has illegal character: "
+ Character.getName(cp));
}
// blackslash is the escape character
if (cp == '\\')
return decodeModuleName(index, i, value);
i += Character.charCount(cp);
}
return value;
}
/**
* "Decode" a module name that has been read from the constant pool and
* partly checked for illegal characters (up to position {@code i}).
*/
String decodeModuleName(int index, int i, String value) {
StringBuilder sb = new StringBuilder();
// copy the code points that have been checked
int j = 0;
while (j < i) {
int cp = value.codePointAt(j);
sb.appendCodePoint(cp);
j += Character.charCount(cp);
}
// decode from position {@code i} to end
int len = value.length();
while (i < len) {
int cp = value.codePointAt(i);
if (cp == ':' || cp == '@' || cp < 0x20) {
throw invalidModuleDescriptor("CONSTANT_Module at entry "
+ index + " has illegal character: "
+ Character.getName(cp));
}
// blackslash is the escape character
if (cp == '\\') {
j = i + Character.charCount(cp);
if (j >= 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();
}
}
/**

View File

@ -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<Attribute> 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());

View File

@ -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<String> exported = md.exports().stream()
.map(ModuleDescriptor.Exports::source);
Stream<String> 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();
}

View File

@ -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);
}

View File

@ -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<String, ModuleReference> 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);
}
/**

View File

@ -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<ModuleReader> 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<ModuleReader> 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();
}
}

View File

@ -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<ModuleReader> 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<ModuleReader> 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<ModuleReader> 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<ModuleReader> supplier = () -> new ExplodedModuleReader(dir);
return newModule(md, dir.toUri(), supplier, null);
return newModule(attrs, dir.toUri(), supplier, null);
}

View File

@ -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 + "]";
}
}

View File

@ -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<ModuleReference> 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<String, ModuleReference> 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<String, ModuleReference>[] map
= (Entry<String, ModuleReference>[])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<ModuleReference> modules;
Supplier<ModuleReader> readerSupplier = new Supplier<>() {
@Override
public ModuleReader get() {
return new ImageModuleReader(mn, uri);
}
};
// maps module name to module reference
private final Map<String, ModuleReference> nameToModule;
ModuleReference mref =
new ModuleReference(md, uri, readerSupplier, hash);
// module name to hashes
private final Map<String, byte[]> 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<String, byte[]> hashes = new HashMap<>();
static void add(ModuleDescriptor descriptor) {
Optional<ModuleHashes> 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<String, byte[]> 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<String, ModuleReference>[] map
= (Entry<String, ModuleReference>[])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<ModuleReference> 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<ModuleReader> 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

View File

@ -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");
}
}

View File

@ -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.</i>
*
* @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.</i>
*
* @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}. <i>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);

View File

@ -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.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @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.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @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.

View File

@ -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);

View File

@ -58,7 +58,6 @@ import java.security.PrivilegedAction;
public class Cleaner
extends PhantomReference<Object>
implements Runnable
{
// Dummy reference queue, needed because the PhantomReference constructor
@ -153,12 +152,4 @@ public class Cleaner
}});
}
}
@Override public void run() {
SecurityManager security = System.getSecurityManager();
if (security != null)
security.checkPackageAccess("jdk.internal.ref");
this.clean();
}
}

View File

@ -31,6 +31,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.misc.VM;
import sun.security.action.GetPropertyAction;
@ -218,8 +219,16 @@ public class Reflection {
if (c.isPrimitive())
return true;
// check that memberModule exports the package to currentModule
return memberModule.isExported(c.getPackageName(), currentModule);
String pkg = c.getPackageName();
boolean allowed = memberModule.isExported(pkg, currentModule);
if (allowed && memberModule.isNamed() && printStackTraceWhenAccessSucceeds()) {
if (!SharedSecrets.getJavaLangReflectModuleAccess()
.isStaticallyExported(memberModule, pkg, currentModule)) {
String msg = currentModule + " allowed access to member of " + memberClass;
new Exception(msg).printStackTrace(System.err);
}
}
return allowed;
}
/**
@ -348,25 +357,43 @@ public class Reflection {
}
// true to print a stack trace when IAE is thrown
// true to print a stack trace when access fails
private static volatile boolean printStackWhenAccessFails;
// true if printStackWhenAccessFails has been initialized
private static volatile boolean printStackWhenAccessFailsSet;
// true to print a stack trace when access succeeds
private static volatile boolean printStackWhenAccessSucceeds;
private static void printStackTraceIfNeeded(Throwable e) {
if (!printStackWhenAccessFailsSet && VM.initLevel() >= 1) {
// true if printStack* values are initialized
private static volatile boolean printStackPropertiesSet;
private static void ensurePrintStackPropertiesSet() {
if (!printStackPropertiesSet && VM.initLevel() >= 1) {
String s = GetPropertyAction.privilegedGetProperty(
"sun.reflect.debugModuleAccessChecks");
printStackWhenAccessFails =
(s != null && !s.equalsIgnoreCase("false"));
printStackWhenAccessFailsSet = true;
}
if (printStackWhenAccessFails) {
e.printStackTrace();
if (s != null) {
printStackWhenAccessFails = !s.equalsIgnoreCase("false");
printStackWhenAccessSucceeds = s.equalsIgnoreCase("access");
}
printStackPropertiesSet = true;
}
}
public static void enableStackTraces() {
printStackWhenAccessFails = true;
printStackWhenAccessSucceeds = true;
printStackPropertiesSet = true;
}
public static boolean printStackTraceWhenAccessFails() {
ensurePrintStackPropertiesSet();
return printStackWhenAccessFails;
}
public static boolean printStackTraceWhenAccessSucceeds() {
ensurePrintStackPropertiesSet();
return printStackWhenAccessSucceeds;
}
/**
* Throws IllegalAccessException with the an exception message based on
* the access that is denied.
@ -416,17 +443,10 @@ public class Reflection {
throws IllegalAccessException
{
IllegalAccessException e = new IllegalAccessException(msg);
printStackTraceIfNeeded(e);
ensurePrintStackPropertiesSet();
if (printStackWhenAccessFails) {
e.printStackTrace(System.err);
}
throw e;
}
/**
* Throws InaccessibleObjectException with the given exception message.
*/
public static void throwInaccessibleObjectException(String msg) {
InaccessibleObjectException e = new InaccessibleObjectException(msg);
printStackTraceIfNeeded(e);
throw e;
}
}

View File

@ -180,7 +180,8 @@ module java.base {
java.management,
jdk.jvmstat;
exports jdk.internal.ref to
java.desktop;
java.desktop,
jdk.unsupported;
exports jdk.internal.reflect to
java.corba,
java.logging,
@ -219,7 +220,8 @@ module java.base {
exports sun.nio.ch to
java.management,
jdk.crypto.token,
jdk.sctp;
jdk.sctp,
jdk.unsupported;
exports sun.nio.cs to
java.desktop,
jdk.charsets;

View File

@ -36,6 +36,7 @@ import java.security.AlgorithmConstraints;
import java.security.AccessControlContext;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
import java.util.function.BiFunction;
import javax.crypto.*;
import javax.crypto.spec.*;
@ -122,6 +123,14 @@ abstract class Handshaker {
// Negotiated ALPN value
String applicationProtocol = null;
// Application protocol callback function (for SSLEngine)
BiFunction<SSLEngine,List<String>,String>
appProtocolSelectorSSLEngine = null;
// Application protocol callback function (for SSLSocket)
BiFunction<SSLSocket,List<String>,String>
appProtocolSelectorSSLSocket = null;
// The maximum expected network packet size for SSL/TLS/DTLS records.
int maximumPacketSize = 0;
@ -500,6 +509,22 @@ abstract class Handshaker {
return applicationProtocol;
}
/**
* Sets the Application Protocol selector function for SSLEngine.
*/
void setApplicationProtocolSelectorSSLEngine(
BiFunction<SSLEngine,List<String>,String> selector) {
this.appProtocolSelectorSSLEngine = selector;
}
/**
* Sets the Application Protocol selector function for SSLSocket.
*/
void setApplicationProtocolSelectorSSLSocket(
BiFunction<SSLSocket,List<String>,String> selector) {
this.appProtocolSelectorSSLSocket = selector;
}
/**
* Sets the cipher suites preference.
*/

View File

@ -27,8 +27,9 @@ package sun.security.ssl;
import java.io.*;
import java.nio.*;
import java.util.*;
import java.security.*;
import java.util.*;
import java.util.function.BiFunction;
import javax.crypto.BadPaddingException;
@ -206,6 +207,10 @@ public final class SSLEngineImpl extends SSLEngine {
// The value under negotiation will be obtained from handshaker.
String applicationProtocol = null;
// Callback function that selects the application protocol value during
// the SSL/TLS handshake.
BiFunction<SSLEngine, List<String>, String> applicationProtocolSelector;
// Have we been told whether we're client or server?
private boolean serverModeSet = false;
private boolean roleIsServer;
@ -442,6 +447,8 @@ public final class SSLEngineImpl extends SSLEngine {
handshaker.setEnabledCipherSuites(enabledCipherSuites);
handshaker.setEnableSessionCreation(enableSessionCreation);
handshaker.setApplicationProtocols(applicationProtocols);
handshaker.setApplicationProtocolSelectorSSLEngine(
applicationProtocolSelector);
outputRecord.initHandshaker();
}
@ -2264,6 +2271,21 @@ public final class SSLEngineImpl extends SSLEngine {
return null;
}
@Override
public synchronized void setHandshakeApplicationProtocolSelector(
BiFunction<SSLEngine, List<String>, String> selector) {
applicationProtocolSelector = selector;
if ((handshaker != null) && !handshaker.activated()) {
handshaker.setApplicationProtocolSelectorSSLEngine(selector);
}
}
@Override
public synchronized BiFunction<SSLEngine, List<String>, String>
getHandshakeApplicationProtocolSelector() {
return this.applicationProtocolSelector;
}
/**
* Returns a printable representation of this end of the connection.
*/

View File

@ -37,6 +37,7 @@ import java.security.AlgorithmConstraints;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.BiFunction;
import javax.crypto.BadPaddingException;
import javax.net.ssl.*;
@ -223,6 +224,10 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl {
// The value under negotiation will be obtained from handshaker.
String applicationProtocol = null;
// Callback function that selects the application protocol value during
// the SSL/TLS handshake.
BiFunction<SSLSocket, List<String>, String> applicationProtocolSelector;
/*
* READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
* IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES.
@ -1370,6 +1375,8 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl {
handshaker.setEnabledCipherSuites(enabledCipherSuites);
handshaker.setEnableSessionCreation(enableSessionCreation);
handshaker.setApplicationProtocols(applicationProtocols);
handshaker.setApplicationProtocolSelectorSSLSocket(
applicationProtocolSelector);
}
/**
@ -2658,6 +2665,21 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl {
return null;
}
@Override
public synchronized void setHandshakeApplicationProtocolSelector(
BiFunction<SSLSocket, List<String>, String> selector) {
applicationProtocolSelector = selector;
if ((handshaker != null) && !handshaker.activated()) {
handshaker.setApplicationProtocolSelectorSSLSocket(selector);
}
}
@Override
public synchronized BiFunction<SSLSocket, List<String>, String>
getHandshakeApplicationProtocolSelector() {
return this.applicationProtocolSelector;
}
//
// We allocate a separate thread to deliver handshake completion
// events. This ensures that the notifications don't block the

View File

@ -34,6 +34,7 @@ import java.security.cert.*;
import java.security.interfaces.*;
import java.security.spec.ECParameterSpec;
import java.math.BigInteger;
import java.util.function.BiFunction;
import javax.crypto.SecretKey;
import javax.net.ssl.*;
@ -532,31 +533,39 @@ final class ServerHandshaker extends Handshaker {
ALPNExtension clientHelloALPN = (ALPNExtension)
mesg.extensions.get(ExtensionType.EXT_ALPN);
if ((clientHelloALPN != null) && (localApl.length > 0)) {
// Use the application protocol callback when provided.
// Otherwise use the local list of application protocols.
boolean hasAPCallback =
((engine != null && appProtocolSelectorSSLEngine != null) ||
(conn != null && appProtocolSelectorSSLSocket != null));
// Intersect the requested and the locally supported,
// and save for later.
String negotiatedValue = null;
List<String> protocols = clientHelloALPN.getPeerAPs();
if (!hasAPCallback) {
if ((clientHelloALPN != null) && (localApl.length > 0)) {
// Use server preference order
for (String ap : localApl) {
if (protocols.contains(ap)) {
negotiatedValue = ap;
break;
// Intersect the requested and the locally supported,
// and save for later.
String negotiatedValue = null;
List<String> protocols = clientHelloALPN.getPeerAPs();
// Use server preference order
for (String ap : localApl) {
if (protocols.contains(ap)) {
negotiatedValue = ap;
break;
}
}
}
if (negotiatedValue == null) {
fatalSE(Alerts.alert_no_application_protocol,
new SSLHandshakeException(
"No matching ALPN values"));
}
applicationProtocol = negotiatedValue;
if (negotiatedValue == null) {
fatalSE(Alerts.alert_no_application_protocol,
new SSLHandshakeException(
"No matching ALPN values"));
}
applicationProtocol = negotiatedValue;
} else {
applicationProtocol = "";
}
} else {
applicationProtocol = "";
}
} // Otherwise, applicationProtocol will be set by the callback.
session = null; // forget about the current session
//
@ -892,8 +901,36 @@ final class ServerHandshaker extends Handshaker {
}
// Prepare the ALPN response
if (applicationProtocol != null && !applicationProtocol.isEmpty()) {
m1.extensions.add(new ALPNExtension(applicationProtocol));
if (clientHelloALPN != null) {
List<String> peerAPs = clientHelloALPN.getPeerAPs();
// check for a callback function
if (hasAPCallback) {
if (conn != null) {
applicationProtocol =
appProtocolSelectorSSLSocket.apply(conn, peerAPs);
} else {
applicationProtocol =
appProtocolSelectorSSLEngine.apply(engine, peerAPs);
}
}
// check for no-match and that the selected name was also proposed
// by the TLS peer
if (applicationProtocol == null ||
(!applicationProtocol.isEmpty() &&
!peerAPs.contains(applicationProtocol))) {
fatalSE(Alerts.alert_no_application_protocol,
new SSLHandshakeException(
"No matching ALPN values"));
} else if (!applicationProtocol.isEmpty()) {
m1.extensions.add(new ALPNExtension(applicationProtocol));
}
} else {
// Nothing was negotiated, returned at end of the handshake
applicationProtocol = "";
}
if (debug != null && Debug.isOn("handshake")) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1994, 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,12 +64,6 @@ Java_java_lang_StrictMath_atan(JNIEnv *env, jclass unused, jdouble d)
return (jdouble) jatan((double)d);
}
JNIEXPORT jdouble JNICALL
Java_java_lang_StrictMath_exp(JNIEnv *env, jclass unused, jdouble d)
{
return (jdouble) jexp((double)d);
}
JNIEXPORT jdouble JNICALL
Java_java_lang_StrictMath_log(JNIEnv *env, jclass unused, jdouble d)
{

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 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
@ -109,13 +109,9 @@ final class ProcessImpl extends Process {
private String helperPath(String javahome, String osArch) {
switch (this) {
case SOLARIS:
if (osArch.equals("x86")) { osArch = "i386"; }
else if (osArch.equals("x86_64")) { osArch = "amd64"; }
// fall through...
case LINUX:
case AIX:
return javahome + "/lib/" + osArch + "/jspawnhelper";
case BSD:
return javahome + "/lib/jspawnhelper";

View File

@ -0,0 +1,36 @@
/*
* 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.
*/
// jdk.vm.compiler uses Unsafe and VM classes from jdk.internal.misc
exports jdk.internal.misc to jdk.vm.compiler;
opens jdk.internal.misc to jdk.vm.compiler;
// jdk.vm.compiler uses com.sun.crypto.provider to generate crypto intrinsics
opens com.sun.crypto.provider to jdk.vm.compiler;
exports jdk.internal.module to jdk.vm.compiler;
// AOT uses jdk.internal.misc.Unsafe
exports jdk.internal.misc to jdk.aot;

View File

@ -54,10 +54,8 @@ char *FindExecName(char *program);
const char *SetExecname(char **argv);
const char *GetExecName();
static jboolean GetJVMPath(const char *jrepath, const char *jvmtype,
char *jvmpath, jint jvmpathsize, const char * arch,
int bitsWanted);
static jboolean GetJREPath(char *path, jint pathsize, const char * arch,
jboolean speculative);
char *jvmpath, jint jvmpathsize, int bitsWanted);
static jboolean GetJREPath(char *path, jint pathsize, jboolean speculative);
#if defined(_AIX)
#include "java_md_aix.h"

View File

@ -52,9 +52,6 @@
#endif
#ifdef __solaris__
# ifndef LIBARCHNAME
# error "The macro LIBARCHNAME was not defined on the compile line"
# endif
# include <sys/systeminfo.h>
# include <sys/elf.h>
# include <stdio.h>
@ -188,12 +185,13 @@ JvmExists(const char *path) {
return JNI_FALSE;
}
/*
* contains a lib/$LIBARCHNAME/{server,client}/libjvm.so ?
* contains a lib/{server,client}/libjvm.so ?
*/
static jboolean
ContainsLibJVM(const char *env) {
char clientPattern[PATH_MAX + 1];
char serverPattern[PATH_MAX + 1];
/* the usual suspects */
char clientPattern[] = "lib/client";
char serverPattern[] = "lib/server";
char *envpath;
char *path;
jboolean clientPatternFound;
@ -204,10 +202,6 @@ ContainsLibJVM(const char *env) {
return JNI_FALSE;
}
/* the usual suspects */
JLI_Snprintf(clientPattern, PATH_MAX, "lib/%s/client", LIBARCHNAME);
JLI_Snprintf(serverPattern, PATH_MAX, "lib/%s/server", LIBARCHNAME);
/* to optimize for time, test if any of our usual suspects are present. */
clientPatternFound = JLI_StrStr(env, clientPattern) != NULL;
serverPatternFound = JLI_StrStr(env, serverPattern) != NULL;
@ -322,7 +316,6 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
/* Check data model flags, and exec process, if needed */
{
char *arch = LIBARCHNAME; /* like sparc or sparcv9 */
char * jvmtype = NULL;
int argc = *pargc;
char **argv = *pargv;
@ -408,12 +401,12 @@ 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);
}
JLI_Snprintf(jvmcfg, so_jvmcfg, "%s%slib%s%s%sjvm.cfg",
jrepath, FILESEP, FILESEP, arch, FILESEP);
JLI_Snprintf(jvmcfg, so_jvmcfg, "%s%slib%s%sjvm.cfg",
jrepath, FILESEP, FILESEP, FILESEP);
/* Find the specified JVM type */
if (ReadKnownVMs(jvmcfg, JNI_FALSE) < 1) {
JLI_ReportErrorMessage(CFG_ERROR7);
@ -427,7 +420,7 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
exit(4);
}
if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, arch, 0 )) {
if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, 0 )) {
JLI_ReportErrorMessage(CFG_ERROR8, jvmtype, jvmpath);
exit(4);
}
@ -457,8 +450,8 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
* We will set the LD_LIBRARY_PATH as follows:
*
* o $JVMPATH (directory portion only)
* o $JRE/lib/$LIBARCHNAME
* o $JRE/../lib/$LIBARCHNAME
* o $JRE/lib
* o $JRE/../lib
*
* followed by the user's previous effective LD_LIBRARY_PATH, if
* any.
@ -518,10 +511,10 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
{ /* New scope to declare local variable */
char *new_jvmpath = JLI_StringDup(jvmpath);
new_runpath_size = ((runpath != NULL) ? JLI_StrLen(runpath) : 0) +
2 * JLI_StrLen(jrepath) + 2 * JLI_StrLen(arch) +
2 * JLI_StrLen(jrepath) +
#ifdef AIX
/* On AIX we additionally need 'jli' in the path because ld doesn't support $ORIGIN. */
JLI_StrLen(jrepath) + JLI_StrLen(arch) + JLI_StrLen("/lib//jli:") +
JLI_StrLen(jrepath) + JLI_StrLen("/lib//jli:") +
#endif
JLI_StrLen(new_jvmpath) + 52;
new_runpath = JLI_MemAlloc(new_runpath_size);
@ -539,17 +532,17 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
sprintf(new_runpath, LD_LIBRARY_PATH "="
"%s:"
"%s/lib/%s:"
"%s/lib:"
#ifdef AIX
"%s/lib/%s/jli:" /* Needed on AIX because ld doesn't support $ORIGIN. */
"%s/lib/jli:" /* Needed on AIX because ld doesn't support $ORIGIN. */
#endif
"%s/../lib/%s",
"%s/../lib",
new_jvmpath,
jrepath, arch,
jrepath,
#ifdef AIX
jrepath, arch,
jrepath,
#endif
jrepath, arch
jrepath
);
JLI_MemFree(new_jvmpath);
@ -640,14 +633,14 @@ 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;
if (JLI_StrChr(jvmtype, '/')) {
JLI_Snprintf(jvmpath, jvmpathsize, "%s/" JVM_DLL, jvmtype);
} else {
JLI_Snprintf(jvmpath, jvmpathsize, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype);
JLI_Snprintf(jvmpath, jvmpathsize, "%s/lib/%s/" JVM_DLL, jrepath, jvmtype);
}
JLI_TraceLauncher("Does `%s' exist ... ", jvmpath);
@ -665,14 +658,14 @@ 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];
struct stat s;
if (GetApplicationHome(path, pathsize)) {
/* Is JRE co-located with the application? */
JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/%s/" JAVA_DLL, path, arch);
JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/" JAVA_DLL, path);
if (access(libjava, F_OK) == 0) {
JLI_TraceLauncher("JRE path is %s\n", path);
return JNI_TRUE;
@ -683,7 +676,7 @@ GetJREPath(char *path, jint pathsize, const char * arch, jboolean speculative)
return JNI_FALSE;
}
/* Does the app ship a private JRE in <apphome>/jre directory? */
JLI_Snprintf(libjava, sizeof(libjava), "%s/jre/lib/%s/" JAVA_DLL, path, arch);
JLI_Snprintf(libjava, sizeof(libjava), "%s/jre/lib/" JAVA_DLL, path);
if (access(libjava, F_OK) == 0) {
JLI_StrCat(path, "/jre");
JLI_TraceLauncher("JRE path is %s\n", path);
@ -692,7 +685,7 @@ GetJREPath(char *path, jint pathsize, const char * arch, jboolean speculative)
}
if (GetApplicationHomeFromDll(path, pathsize)) {
JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/%s/" JAVA_DLL, path, arch);
JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/" JAVA_DLL, path);
if (stat(libjava, &s) == 0) {
JLI_TraceLauncher("JRE path is %s\n", path);
return JNI_TRUE;
@ -858,12 +851,12 @@ void* SplashProcAddress(const char* name) {
char jrePath[MAXPATHLEN];
char splashPath[MAXPATHLEN];
if (!GetJREPath(jrePath, sizeof(jrePath), LIBARCHNAME, JNI_FALSE)) {
if (!GetJREPath(jrePath, sizeof(jrePath), JNI_FALSE)) {
JLI_ReportErrorMessage(JRE_ERROR1);
return NULL;
}
ret = JLI_Snprintf(splashPath, sizeof(splashPath), "%s/lib/%s/%s",
jrePath, LIBARCHNAME, SPLASHSCREEN_SO);
ret = JLI_Snprintf(splashPath, sizeof(splashPath), "%s/lib/%s",
jrePath, SPLASHSCREEN_SO);
if (ret >= (int) sizeof(splashPath)) {
JLI_ReportErrorMessage(JRE_ERROR11);

View File

@ -37,273 +37,10 @@
#include "java_net_Inet4AddressImpl.h"
#if defined(__GLIBC__) || (defined(__FreeBSD__) && (__FreeBSD_version >= 601104))
#define HAS_GLIBC_GETHOSTBY_R 1
#endif
#if defined(_ALLBSD_SOURCE) && !defined(HAS_GLIBC_GETHOSTBY_R)
#if defined(MACOSX)
extern jobjectArray lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6);
/* Use getaddrinfo(3), which is thread safe */
/************************************************************************
* Inet4AddressImpl
*/
/*
* Class: java_net_Inet4AddressImpl
* Method: getLocalHostName
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
Java_java_net_Inet4AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
char hostname[NI_MAXHOST+1];
hostname[0] = '\0';
if (gethostname(hostname, NI_MAXHOST)) {
/* Something went wrong, maybe networking is not setup? */
strcpy(hostname, "localhost");
} else {
struct addrinfo hints, *res;
int error;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
hints.ai_family = AF_UNSPEC;
error = getaddrinfo(hostname, NULL, &hints, &res);
if (error == 0) {
/* host is known to name service */
error = getnameinfo(res->ai_addr,
res->ai_addrlen,
hostname,
NI_MAXHOST,
NULL,
0,
NI_NAMEREQD);
/* if getnameinfo fails hostname is still the value
from gethostname */
freeaddrinfo(res);
}
}
return (*env)->NewStringUTF(env, hostname);
}
/*
* Find an internet address for a given hostname. Note that this
* code only works for addresses of type INET. The translation
* of %d.%d.%d.%d to an address (int) occurs in java now, so the
* String "host" shouldn't *ever* be a %d.%d.%d.%d string
*
* Class: java_net_Inet4AddressImpl
* Method: lookupAllHostAddr
* Signature: (Ljava/lang/String;)[[B
*/
JNIEXPORT jobjectArray JNICALL
Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
jstring host) {
const char *hostname;
jobject name;
jobjectArray ret = 0;
int retLen = 0;
int getaddrinfo_error=0;
struct addrinfo hints, *res, *resNew = NULL;
initInetAddressIDs(env);
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
if (IS_NULL(host)) {
JNU_ThrowNullPointerException(env, "host is null");
return 0;
}
hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
CHECK_NULL_RETURN(hostname, NULL);
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
hints.ai_family = AF_INET;
/*
* Workaround for Solaris bug 4160367 - if a hostname contains a
* white space then 0.0.0.0 is returned
*/
if (isspace((unsigned char)hostname[0])) {
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
(char *)hostname);
JNU_ReleaseStringPlatformChars(env, host, hostname);
return NULL;
}
getaddrinfo_error = getaddrinfo(hostname, NULL, &hints, &res);
#ifdef MACOSX
if (getaddrinfo_error) {
// If getaddrinfo fails try getifaddrs.
ret = lookupIfLocalhost(env, hostname, JNI_FALSE);
if (ret != NULL || (*env)->ExceptionCheck(env)) {
JNU_ReleaseStringPlatformChars(env, host, hostname);
return ret;
}
}
#endif
if (getaddrinfo_error) {
/* report error */
NET_ThrowUnknownHostExceptionWithGaiError(
env, hostname, getaddrinfo_error);
JNU_ReleaseStringPlatformChars(env, host, hostname);
return NULL;
} else {
int i = 0;
struct addrinfo *itr, *last = NULL, *iterator = res;
while (iterator != NULL) {
int skip = 0;
itr = resNew;
while (itr != NULL) {
struct sockaddr_in *addr1, *addr2;
addr1 = (struct sockaddr_in *)iterator->ai_addr;
addr2 = (struct sockaddr_in *)itr->ai_addr;
if (addr1->sin_addr.s_addr ==
addr2->sin_addr.s_addr) {
skip = 1;
break;
}
itr = itr->ai_next;
}
if (!skip) {
struct addrinfo *next
= (struct addrinfo*) malloc(sizeof(struct addrinfo));
if (!next) {
JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
ret = NULL;
goto cleanupAndReturn;
}
memcpy(next, iterator, sizeof(struct addrinfo));
next->ai_next = NULL;
if (resNew == NULL) {
resNew = next;
} else {
last->ai_next = next;
}
last = next;
i++;
}
iterator = iterator->ai_next;
}
retLen = i;
iterator = resNew;
i = 0;
name = (*env)->NewStringUTF(env, hostname);
if (IS_NULL(name)) {
goto cleanupAndReturn;
}
ret = (*env)->NewObjectArray(env, retLen, ia_class, NULL);
if (IS_NULL(ret)) {
/* we may have memory to free at the end of this */
goto cleanupAndReturn;
}
while (iterator != NULL) {
/* We need 4 bytes to store ipv4 address; */
int len = 4;
jobject iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
if (IS_NULL(iaObj)) {
/* we may have memory to free at the end of this */
ret = NULL;
goto cleanupAndReturn;
}
setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)(iterator->ai_addr))->sin_addr.s_addr));
setInetAddress_hostName(env, iaObj, name);
(*env)->SetObjectArrayElement(env, ret, retLen - i -1, iaObj);
i++;
iterator = iterator->ai_next;
}
}
cleanupAndReturn:
{
struct addrinfo *iterator, *tmp;
iterator = resNew;
while (iterator != NULL) {
tmp = iterator;
iterator = iterator->ai_next;
free(tmp);
}
JNU_ReleaseStringPlatformChars(env, host, hostname);
}
freeaddrinfo(res);
return ret;
}
/*
* Class: java_net_Inet4AddressImpl
* Method: getHostByAddr
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
Java_java_net_Inet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
jbyteArray addrArray) {
jstring ret = NULL;
char host[NI_MAXHOST+1];
jfieldID fid;
int error = 0;
jint family;
struct sockaddr *him ;
int len = 0;
jbyte caddr[4];
jint addr;
struct sockaddr_in him4;
struct sockaddr *sa;
/*
* For IPv4 addresses construct a sockaddr_in structure.
*/
(*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
addr = ((caddr[0]<<24) & 0xff000000);
addr |= ((caddr[1] <<16) & 0xff0000);
addr |= ((caddr[2] <<8) & 0xff00);
addr |= (caddr[3] & 0xff);
memset((char *) &him4, 0, sizeof(him4));
him4.sin_addr.s_addr = htonl(addr);
him4.sin_family = AF_INET;
sa = (struct sockaddr *) &him4;
len = sizeof(him4);
error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
if (!error) {
ret = (*env)->NewStringUTF(env, host);
}
if (ret == NULL) {
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL);
}
return ret;
}
#else /* defined(_ALLBSD_SOURCE) && !defined(HAS_GLIBC_GETHOSTBY_R) */
/* the initial size of our hostent buffers */
#ifndef NI_MAXHOST
#define NI_MAXHOST 1025
@ -405,6 +142,17 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
error = getaddrinfo(hostname, NULL, &hints, &res);
#ifdef MACOSX
if (error) {
// If getaddrinfo fails try getifaddrs, see bug 8170910.
ret = lookupIfLocalhost(env, hostname, JNI_FALSE);
if (ret != NULL || (*env)->ExceptionCheck(env)) {
JNU_ReleaseStringPlatformChars(env, host, hostname);
return ret;
}
}
#endif
if (error) {
/* report error */
NET_ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
@ -475,7 +223,7 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
}
}
cleanupAndReturn:
cleanupAndReturn:
{
struct addrinfo *iterator, *tmp;
iterator = resNew;
@ -535,8 +283,6 @@ Java_java_net_Inet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
return ret;
}
#endif /* _ALLBSD_SOURCE */
#define SET_NONBLOCKING(fd) { \
int flags = fcntl(fd, F_GETFL); \
flags |= O_NONBLOCK; \

View File

@ -150,22 +150,6 @@ IsJavaw()
return _isjavaw;
}
/*
* Returns the arch path, to get the current arch use the
* macro GetArch, nbits here is ignored for now.
*/
const char *
GetArchPath(int nbits)
{
#ifdef _M_AMD64
return "amd64";
#elif defined(_M_IA64)
return "ia64";
#else
return "i386";
#endif
}
/*
*
*/
@ -207,8 +191,8 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
exit(2);
}
JLI_Snprintf(jvmcfg, so_jvmcfg, "%s%slib%s%s%sjvm.cfg",
jrepath, FILESEP, FILESEP, (char*)GetArch(), FILESEP);
JLI_Snprintf(jvmcfg, so_jvmcfg, "%s%slib%sjvm.cfg",
jrepath, FILESEP, FILESEP);
/* Find the specified JVM type */
if (ReadKnownVMs(jvmcfg, JNI_FALSE) < 1) {

View File

@ -34,10 +34,18 @@ import javax.swing.plaf.basic.BasicMenuBarUI;
import sun.lwawt.macosx.LWCToolkit;
import sun.security.action.GetBooleanAction;
import sun.security.action.GetPropertyAction;
// MenuBar implementation for Mac L&F
public class AquaMenuBarUI extends BasicMenuBarUI implements ScreenMenuBarProvider {
static {
java.security.AccessController.doPrivileged(
(java.security.PrivilegedAction<Void>) () -> {
System.loadLibrary("osxui");
return null;
});
}
// Utilities
public void uninstallUI(final JComponent c) {
if (fScreenMenuBar != null) {
@ -134,7 +142,7 @@ public class AquaMenuBarUI extends BasicMenuBarUI implements ScreenMenuBarProvid
ScreenMenuBar fScreenMenuBar;
boolean useScreenMenuBar = getScreenMenuBarProperty();
static boolean getScreenMenuBarProperty() {
public static boolean getScreenMenuBarProperty() {
// Do not allow AWT to set the screen menu bar if it's embedded in another UI toolkit
if (LWCToolkit.isEmbedded()) return false;
if (AccessController.doPrivileged(

View File

@ -141,12 +141,24 @@ public final class CFontManager extends SunFontManager {
}
}
protected void registerFontsInDir(String dirName, boolean useJavaRasterizer, int fontRank, boolean defer, boolean resolveSymLinks) {
loadNativeDirFonts(dirName);
protected void registerFontsInDir(final String dirName, boolean useJavaRasterizer,
int fontRank, boolean defer, boolean resolveSymLinks) {
String[] files = AccessController.doPrivileged((PrivilegedAction<String[]>) () -> {
return new File(dirName).list(getTrueTypeFilter());
});
if (files == null) {
return;
} else {
for (String f : files) {
loadNativeDirFonts(dirName+File.separator+f);
}
}
super.registerFontsInDir(dirName, useJavaRasterizer, fontRank, defer, resolveSymLinks);
}
private native void loadNativeDirFonts(String dirName);
private native void loadNativeDirFonts(String fontPath);
private native void loadNativeFonts();
void registerFont(String fontName, String fontFamilyName) {

View File

@ -33,11 +33,14 @@ import java.awt.Dialog.ModalityType;
import java.awt.event.*;
import java.beans.*;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.*;
import sun.awt.*;
import sun.awt.AWTAccessor.ComponentAccessor;
import sun.awt.AWTAccessor.WindowAccessor;
import sun.java2d.SurfaceData;
import sun.java2d.opengl.CGLSurfaceData;
import sun.lwawt.*;
@ -1031,6 +1034,11 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
return !peer.isSimpleWindow() && target.getFocusableWindowState();
}
private boolean isBlocked() {
LWWindowPeer blocker = (peer != null) ? peer.getBlocker() : null;
return (blocker != null);
}
/*
* An utility method for the support of the auto request focus.
* Updates the focusable state of the window under certain
@ -1063,29 +1071,70 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
return true;
}
private boolean isOneOfOwnersOrSelf(CPlatformWindow window) {
while (window != null) {
if (this == window) {
return true;
}
window = window.owner;
}
return false;
}
private CPlatformWindow getRootOwner() {
CPlatformWindow rootOwner = this;
while (rootOwner.owner != null) {
rootOwner = rootOwner.owner;
}
return rootOwner;
}
private void orderAboveSiblings() {
if (owner == null) {
return;
// Recursively pop up the windows from the very bottom, (i.e. root owner) so that
// the windows are ordered above their nearest owner; ancestors of the window,
// which is going to become 'main window', are placed above their siblings.
CPlatformWindow rootOwner = getRootOwner();
if (rootOwner.isVisible()) {
CWrapper.NSWindow.orderFront(rootOwner.getNSWindowPtr());
}
final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor();
orderAboveSiblingsImpl(windowAccessor.getOwnedWindows(rootOwner.target));
}
// NOTE: the logic will fail if we have a hierarchy like:
// visible root owner
// invisible owner
// visible dialog
// However, this is an unlikely scenario for real life apps
if (owner.isVisible()) {
// Recursively pop up the windows from the very bottom so that only
// the very top-most one becomes the main window
owner.orderAboveSiblings();
private void orderAboveSiblingsImpl(Window[] windows) {
ArrayList<Window> childWindows = new ArrayList<Window>();
// Order the window to front of the stack of child windows
final long nsWindowSelfPtr = getNSWindowPtr();
final long nsWindowOwnerPtr = owner.getNSWindowPtr();
CWrapper.NSWindow.orderFront(nsWindowOwnerPtr);
CWrapper.NSWindow.orderWindow(nsWindowSelfPtr, CWrapper.NSWindow.NSWindowAbove, nsWindowOwnerPtr);
final ComponentAccessor componentAccessor = AWTAccessor.getComponentAccessor();
final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor();
// Go through the list of windows and perform ordering.
for (Window w : windows) {
final Object p = componentAccessor.getPeer(w);
if (p instanceof LWWindowPeer) {
CPlatformWindow pw = (CPlatformWindow)((LWWindowPeer)p).getPlatformWindow();
if (pw != null && pw.isVisible()) {
// If the window is one of ancestors of 'main window' or is going to become main by itself,
// the window should be ordered above its siblings; otherwise the window is just ordered
// above its nearest parent.
if (pw.isOneOfOwnersOrSelf(this)) {
CWrapper.NSWindow.orderFront(pw.getNSWindowPtr());
} else {
CWrapper.NSWindow.orderWindow(pw.getNSWindowPtr(), CWrapper.NSWindow.NSWindowAbove,
pw.owner.getNSWindowPtr());
}
pw.applyWindowLevel(w);
}
}
// Retrieve the child windows for each window from the list and store them for future use.
// Note: we collect data about child windows even for invisible owners, since they may have
// visible children.
childWindows.addAll(Arrays.asList(windowAccessor.getOwnedWindows(w)));
}
// If some windows, which have just been ordered, have any child windows, let's start new iteration
// and order these child windows.
if (!childWindows.isEmpty()) {
orderAboveSiblingsImpl(childWindows.toArray(new Window[0]));
}
applyWindowLevel(target);
}
protected void applyWindowLevel(Window target) {

View File

@ -25,6 +25,7 @@
package sun.lwawt.macosx;
import com.apple.laf.AquaMenuBarUI;
import java.awt.peer.TaskbarPeer;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
@ -43,6 +44,7 @@ import java.security.*;
import java.util.*;
import java.util.concurrent.Callable;
import java.net.MalformedURLException;
import javax.swing.UIManager;
import sun.awt.*;
import sun.awt.datatransfer.DataTransferer;
@ -935,4 +937,13 @@ public final class LWCToolkit extends LWToolkit {
protected PlatformWindow getPlatformWindowUnderMouse() {
return CPlatformWindow.nativeGetTopmostPlatformWindowUnderMouse();
}
@Override
public void updateScreenMenuBarUI() {
if (AquaMenuBarUI.getScreenMenuBarProperty()) {
UIManager.put("MenuBarUI", "com.apple.laf.AquaMenuBarUI");
} else {
UIManager.put("MenuBarUI", null);
}
}
}

View File

@ -430,7 +430,22 @@ AWT_ASSERT_APPKIT_THREAD;
[super dealloc];
}
// Tests wheather the corresponding Java paltform window is visible or not
// Tests whether window is blocked by modal dialog/window
- (BOOL) isBlocked {
BOOL isBlocked = NO;
JNIEnv *env = [ThreadUtilities getJNIEnv];
jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
if (platformWindow != NULL) {
static JNF_MEMBER_CACHE(jm_isBlocked, jc_CPlatformWindow, "isBlocked", "()Z");
isBlocked = JNFCallBooleanMethod(env, platformWindow, jm_isBlocked) == JNI_TRUE ? YES : NO;
(*env)->DeleteLocalRef(env, platformWindow);
}
return isBlocked;
}
// Tests whether the corresponding Java platform window is visible or not
+ (BOOL) isJavaPlatformWindowVisible:(NSWindow *)window {
BOOL isVisible = NO;
@ -454,8 +469,9 @@ AWT_ASSERT_APPKIT_THREAD;
- (void) orderChildWindows:(BOOL)focus {
AWT_ASSERT_APPKIT_THREAD;
if (self.isMinimizing) {
if (self.isMinimizing || [self isBlocked]) {
// Do not perform any ordering, if iconify is in progress
// or the window is blocked by a modal window
return;
}
@ -809,18 +825,20 @@ AWT_ASSERT_APPKIT_THREAD;
- (void)sendEvent:(NSEvent *)event {
if ([event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown) {
// Move parent windows to front and make sure that a child window is displayed
// in front of its nearest parent.
if (self.ownerWindow != nil) {
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
if (platformWindow != NULL) {
static JNF_MEMBER_CACHE(jm_orderAboveSiblings, jc_CPlatformWindow, "orderAboveSiblings", "()V");
JNFCallVoidMethod(env,platformWindow, jm_orderAboveSiblings);
(*env)->DeleteLocalRef(env, platformWindow);
if ([self isBlocked]) {
// Move parent windows to front and make sure that a child window is displayed
// in front of its nearest parent.
if (self.ownerWindow != nil) {
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
if (platformWindow != NULL) {
static JNF_MEMBER_CACHE(jm_orderAboveSiblings, jc_CPlatformWindow, "orderAboveSiblings", "()V");
JNFCallVoidMethod(env,platformWindow, jm_orderAboveSiblings);
(*env)->DeleteLocalRef(env, platformWindow);
}
}
[self orderChildWindows:YES];
}
[self orderChildWindows:YES];
NSPoint p = [NSEvent mouseLocation];
NSRect frame = [self.nsWindow frame];

View File

@ -115,19 +115,18 @@
if (keyWindow != nil) {
return;
}
}
else {
static JNF_CLASS_CACHE(jc_CMenuItem, "sun/lwawt/macosx/CMenuItem");
static JNF_MEMBER_CACHE(jm_handleAction, jc_CMenuItem, "handleAction", "(JI)V"); // AWT_THREADING Safe (event)
NSUInteger modifiers = [currEvent modifierFlags];
jint javaModifiers = NsKeyModifiersToJavaModifiers(modifiers, NO);
JNFCallVoidMethod(env, fPeer, jm_handleAction, UTC(currEvent), javaModifiers); // AWT_THREADING Safe (event)
}
}
static JNF_CLASS_CACHE(jc_CMenuItem, "sun/lwawt/macosx/CMenuItem");
static JNF_MEMBER_CACHE(jm_handleAction, jc_CMenuItem, "handleAction", "(JI)V"); // AWT_THREADING Safe (event)
NSUInteger modifiers = [currEvent modifierFlags];
jint javaModifiers = NsKeyModifiersToJavaModifiers(modifiers, NO);
JNFCallVoidMethod(env, fPeer, jm_handleAction, UTC(currEvent), javaModifiers); // AWT_THREADING Safe (event)
}
JNF_COCOA_EXIT(env);
}
- (void) setJavaLabel:(NSString *)theLabel shortcut:(NSString *)theKeyEquivalent modifierMask:(jint)modifiers {

View File

@ -404,19 +404,14 @@ Java_sun_font_CFontManager_loadNativeDirFonts
{
JNF_COCOA_ENTER(env);
NSString *nsFilePath = JNFJavaToNSString(env, filename);
FSRef iFile;
OSStatus status = CreateFSRef(&iFile, nsFilePath);
if (status == noErr) {
ATSFontContainerRef oContainer;
status = ATSFontActivateFromFileReference(&iFile, kATSFontContextLocal,
kATSFontFormatUnspecified,
NULL, kNilOptions,
&oContainer);
}
NSString *path = JNFJavaToNSString(env, filename);
NSURL *url = [NSURL fileURLWithPath:(NSString *)path];
bool res = CTFontManagerRegisterFontsForURL((CFURLRef)url, kCTFontManagerScopeProcess, nil);
#ifdef DEBUG
NSLog(@"path is : %@", (NSString*)path);
NSLog(@"url is : %@", (NSString*)url);
printf("res is %d\n", res);
#endif
JNF_COCOA_EXIT(env);
}

View File

@ -591,7 +591,7 @@ CGGI_CreateImageForGlyph
static inline GlyphInfo *
CGGI_CreateImageForUnicode
(CGGI_GlyphCanvas *canvas, const AWTStrike *strike,
const CGGI_RenderingMode *mode, const UniChar uniChar)
const CGGI_RenderingMode *mode, const UnicodeScalarValue uniChar)
{
// save the state of the world
CGContextSaveGState(canvas->context);
@ -668,7 +668,7 @@ CGGI_FillImagesForGlyphsWithSizedCanvas(CGGI_GlyphCanvas *canvas,
const AWTStrike *strike,
const CGGI_RenderingMode *mode,
jlong glyphInfos[],
const UniChar uniChars[],
const UnicodeScalarValue uniChars[],
const CGGlyph glyphs[],
const CFIndex len)
{
@ -720,7 +720,7 @@ static NSString *threadLocalLCDCanvasKey =
static inline void
CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike,
const CGGI_RenderingMode *mode,
const UniChar uniChars[], const CGGlyph glyphs[],
const UnicodeScalarValue uniChars[], const CGGlyph glyphs[],
const size_t maxWidth, const size_t maxHeight,
const CFIndex len)
{
@ -767,7 +767,7 @@ CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike,
static inline void
CGGI_CreateGlyphInfos(jlong *glyphInfos, const AWTStrike *strike,
const CGGI_RenderingMode *mode,
const UniChar uniChars[], const CGGlyph glyphs[],
const UnicodeScalarValue uniChars[], const CGGlyph glyphs[],
CGSize advances[], CGRect bboxes[], const CFIndex len)
{
AWTFont *font = strike->fAWTFont;
@ -817,7 +817,7 @@ CGGI_CreateGlyphsAndScanForComplexities(jlong *glyphInfos,
const AWTStrike *strike,
const CGGI_RenderingMode *mode,
jint rawGlyphCodes[],
UniChar uniChars[], CGGlyph glyphs[],
UnicodeScalarValue uniChars[], CGGlyph glyphs[],
CGSize advances[], CGRect bboxes[],
const CFIndex len)
{
@ -860,7 +860,7 @@ CGGlyphImages_GetGlyphImagePtrs(jlong glyphInfos[],
CGRect bboxes[len];
CGSize advances[len];
CGGlyph glyphs[len];
UniChar uniChars[len];
UnicodeScalarValue uniChars[len];
CGGI_CreateGlyphsAndScanForComplexities(glyphInfos, strike, &mode,
rawGlyphCodes, uniChars, glyphs,
@ -871,7 +871,7 @@ CGGlyphImages_GetGlyphImagePtrs(jlong glyphInfos[],
// just do one malloc, and carve it up for all the buffers
void *buffer = malloc(sizeof(CGRect) * sizeof(CGSize) *
sizeof(CGGlyph) * sizeof(UniChar) * len);
sizeof(CGGlyph) * sizeof(UnicodeScalarValue) * len);
if (buffer == NULL) {
[[NSException exceptionWithName:NSMallocException
reason:@"Failed to allocate memory for the temporary glyph strike and measurement buffers." userInfo:nil] raise];
@ -880,7 +880,7 @@ CGGlyphImages_GetGlyphImagePtrs(jlong glyphInfos[],
CGRect *bboxes = (CGRect *)(buffer);
CGSize *advances = (CGSize *)(bboxes + sizeof(CGRect) * len);
CGGlyph *glyphs = (CGGlyph *)(advances + sizeof(CGGlyph) * len);
UniChar *uniChars = (UniChar *)(glyphs + sizeof(UniChar) * len);
UnicodeScalarValue *uniChars = (UnicodeScalarValue *)(glyphs + sizeof(UnicodeScalarValue) * len);
CGGI_CreateGlyphsAndScanForComplexities(glyphInfos, strike, &mode,
rawGlyphCodes, uniChars, glyphs,

View File

@ -32,7 +32,9 @@
#pragma mark --- CoreText Support ---
#define HI_SURROGATE_START 0xD800
#define HI_SURROGATE_END 0xDBFF
#define LO_SURROGATE_START 0xDC00
#define LO_SURROGATE_END 0xDFFF
/*
* Transform Unicode characters into glyphs.

View File

@ -103,24 +103,34 @@ void CTS_GetGlyphsAsIntsForCharacters
size_t i;
for (i = 0; i < count; i++) {
UniChar unicode = unicodes[i];
UniChar nextUnicode = (i+1) < count ? unicodes[i+1] : 0;
bool surrogatePair = unicode >= HI_SURROGATE_START && unicode <= HI_SURROGATE_END
&& nextUnicode >= LO_SURROGATE_START && nextUnicode <= LO_SURROGATE_END;
CGGlyph glyph = glyphs[i];
if (glyph > 0) {
glyphsAsInts[i] = glyph;
if (surrogatePair) i++;
continue;
}
UniChar unicode = unicodes[i];
const CTFontRef fallback = JRSFontCreateFallbackFontForCharacters((CTFontRef)font->fFont, &unicode, 1);
const CTFontRef fallback = JRSFontCreateFallbackFontForCharacters((CTFontRef)font->fFont, &unicodes[i],
surrogatePair ? 2 : 1);
if (fallback) {
CTFontGetGlyphsForCharacters(fallback, &unicode, &glyph, 1);
CTFontGetGlyphsForCharacters(fallback, &unicodes[i], &glyphs[i], surrogatePair ? 2 : 1);
glyph = glyphs[i];
CFRelease(fallback);
}
if (glyph > 0) {
glyphsAsInts[i] = -unicode; // set the glyph code to the negative unicode value
int codePoint = surrogatePair ? (((int)(unicode - HI_SURROGATE_START)) << 10)
+ nextUnicode - LO_SURROGATE_START + 0x10000 : unicode;
glyphsAsInts[i] = -codePoint; // set the glyph code to the negative unicode value
} else {
glyphsAsInts[i] = 0; // CoreText couldn't find a glyph for this character either
}
if (surrogatePair) i++;
}
}
@ -158,8 +168,18 @@ CTFontRef CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode
return (CTFontRef)font->fFont;
}
UTF16Char character = -glyphCode;
return CTS_CopyCTFallbackFontAndGlyphForUnicode(font, &character, glyphRef, 1);
int codePoint = -glyphCode;
if (codePoint >= 0x10000) {
UTF16Char chars[2];
CGGlyph glyphs[2];
CTS_BreakupUnicodeIntoSurrogatePairs(codePoint, chars);
CTFontRef result = CTS_CopyCTFallbackFontAndGlyphForUnicode(font, chars, glyphs, 2);
*glyphRef = glyphs[0];
return result;
} else {
UTF16Char character = codePoint;
return CTS_CopyCTFallbackFontAndGlyphForUnicode(font, &character, glyphRef, 1);
}
}
// Breakup a 32 bit unicode value into the component surrogate pairs

View File

@ -541,10 +541,10 @@ public class TIFFIFD extends TIFFDirectory {
}
// Stream position initially at beginning, left at end
// if ignoreUnknownFields is true, do not load fields for which
// if readUnknownTags is false, do not load fields for which
// a tag cannot be found in an allowed TagSet.
public void initialize(ImageInputStream stream, boolean isPrimaryIFD,
boolean ignoreUnknownFields) throws IOException {
boolean ignoreMetadata, boolean readUnknownTags) throws IOException {
removeTIFFFields();
@ -553,10 +553,16 @@ public class TIFFIFD extends TIFFDirectory {
List<TIFFTagSet> tagSetList = getTagSetList();
// Configure essential tag variables if this is the primary IFD and
// either all metadata are being ignored, or metadata are not being
// ignored but both unknown tags are being ignored and the tag set
// list does not contain the baseline tags.
boolean ensureEssentialTags = false;
TIFFTagSet baselineTagSet = null;
if (isPrimaryIFD && ignoreUnknownFields
&& !tagSetList.contains(BaselineTIFFTagSet.getInstance())) {
if (isPrimaryIFD &&
(ignoreMetadata ||
(!readUnknownTags &&
!tagSetList.contains(BaselineTIFFTagSet.getInstance())))) {
ensureEssentialTags = true;
initializeEssentialTags();
baselineTagSet = BaselineTIFFTagSet.getInstance();
@ -590,9 +596,12 @@ public class TIFFIFD extends TIFFDirectory {
tag = baselineTagSet.getTag(tagNumber);
}
// Ignore unknown fields, fields with unknown type, and fields
// Ignore non-essential fields, unknown fields unless forcibly
// being read, fields with unknown type, and fields
// with count out of int range.
if((tag == null && ignoreUnknownFields)
if((ignoreMetadata &&
(!ensureEssentialTags || !essentialTags.contains(tagNumber)))
|| (tag == null && !readUnknownTags)
|| (tag != null && !tag.isDataTypeOK(type))
|| longCount > Integer.MAX_VALUE) {
// Skip the value/offset so as to leave the stream
@ -701,7 +710,8 @@ public class TIFFIFD extends TIFFDirectory {
tagSets.add(tag.getTagSet());
TIFFIFD subIFD = new TIFFIFD(tagSets);
subIFD.initialize(stream, false, ignoreUnknownFields);
subIFD.initialize(stream, false, ignoreMetadata,
readUnknownTags);
TIFFField f = new TIFFField(tag, type, e.offset, subIFD);
addTIFFField(f);
} else {

View File

@ -82,12 +82,13 @@ public class TIFFImageMetadata extends IIOMetadata {
}
public void initializeFromStream(ImageInputStream stream,
boolean ignoreUnknownFields)
boolean ignoreMetadata,
boolean readUnknownTags)
throws IOException {
rootIFD.initialize(stream, true, ignoreUnknownFields);
rootIFD.initialize(stream, true, ignoreMetadata, readUnknownTags);
}
public void addShortOrLongField(int tagNumber, int value) {
public void addShortOrLongField(int tagNumber, long value) {
TIFFField field = new TIFFField(rootIFD.getTag(tagNumber), value);
rootIFD.addTIFFField(field);
}

View File

@ -305,16 +305,19 @@ public class TIFFImageReader extends ImageReader {
try {
// Create an object to store the image metadata
List<TIFFTagSet> tagSets;
boolean readUnknownTags = false;
if (imageReadParam instanceof TIFFImageReadParam) {
tagSets
= ((TIFFImageReadParam) imageReadParam).getAllowedTagSets();
TIFFImageReadParam tp = (TIFFImageReadParam)imageReadParam;
tagSets = tp.getAllowedTagSets();
readUnknownTags = tp.getReadUnknownTags();
} else {
tagSets = new ArrayList<TIFFTagSet>(1);
tagSets.add(BaselineTIFFTagSet.getInstance());
}
this.imageMetadata = new TIFFImageMetadata(tagSets);
imageMetadata.initializeFromStream(stream, ignoreMetadata);
imageMetadata.initializeFromStream(stream, ignoreMetadata,
readUnknownTags);
} catch (IIOException iioe) {
throw iioe;
} catch (IOException ioe) {

View File

@ -3015,7 +3015,7 @@ public class TIFFImageWriter extends ImageWriter {
List<TIFFTagSet> tagSets = new ArrayList<TIFFTagSet>(1);
tagSets.add(BaselineTIFFTagSet.getInstance());
TIFFIFD rootIFD = new TIFFIFD(tagSets);
rootIFD.initialize(stream, true, true);
rootIFD.initialize(stream, true, false, false);
stream.reset();
return rootIFD;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 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
@ -22,17 +22,24 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.peer.CheckboxMenuItemPeer;
import java.awt.event.*;
import java.util.EventListener;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
import javax.accessibility.*;
import sun.awt.AWTAccessor;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.EventListener;
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleAction;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleValue;
import sun.awt.AWTAccessor;
/**
* This class represents a check box that can be included in a menu.
@ -43,7 +50,8 @@ import sun.awt.AWTAccessor;
* of {@code CheckBoxMenuItem}:
* <p>
* <img src="doc-files/MenuBar-1.gif"
* alt="Menu labeled Examples, containing items Basic, Simple, Check, and More Examples. The Check item is a CheckBoxMenuItem instance, in the off state."
* alt="Menu labeled Examples, containing items Basic, Simple, Check, and More
* Examples. The Check item is a CheckBoxMenuItem instance, in the off state."
* style="float:center; margin: 7px 10px;">
* <p>
* The item labeled {@code Check} shows a check box menu item
@ -84,9 +92,9 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access
* @see #getState()
* @see #setState(boolean)
*/
boolean state = false;
private volatile boolean state;
transient ItemListener itemListener;
private transient volatile ItemListener itemListener;
private static final String base = "chkmenuitem";
private static int nameCounter = 0;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 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
@ -22,15 +22,20 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.event.KeyEvent;
import java.awt.peer.MenuPeer;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Vector;
import java.util.Enumeration;
import java.awt.peer.MenuPeer;
import java.awt.event.KeyEvent;
import javax.accessibility.*;
import java.util.Vector;
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import sun.awt.AWTAccessor;
/**
@ -78,7 +83,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible {
* @serial
* @see #countItems()
*/
Vector<MenuItem> items = new Vector<>();
private final Vector<MenuItem> items = new Vector<>();
/**
* This field indicates whether the menu has the
@ -92,7 +97,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible {
* @serial
* @see #isTearOff()
*/
boolean tearOff;
private final boolean tearOff;
/**
* This field will be set to {@code true}
@ -102,7 +107,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible {
*
* @serial
*/
boolean isHelpMenu;
volatile boolean isHelpMenu;
private static final String base = "menu";
private static int nameCounter = 0;
@ -415,8 +420,8 @@ public class Menu extends MenuItem implements MenuContainer, Accessible {
if (peer != null) {
peer.delItem(index);
mi.removeNotify();
mi.parent = null;
}
mi.parent = null;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 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
@ -22,16 +22,21 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.event.KeyEvent;
import java.awt.peer.MenuBarPeer;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Vector;
import java.util.Enumeration;
import java.util.Vector;
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import sun.awt.AWTAccessor;
import java.awt.peer.MenuBarPeer;
import java.awt.event.KeyEvent;
import javax.accessibility.*;
/**
* The {@code MenuBar} class encapsulates the platform's
@ -94,7 +99,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible
* @serial
* @see #countMenus()
*/
Vector<Menu> menus = new Vector<>();
private final Vector<Menu> menus = new Vector<>();
/**
* This menu is a special menu dedicated to
@ -106,7 +111,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible
* @see #getHelpMenu()
* @see #setHelpMenu(Menu)
*/
Menu helpMenu;
private volatile Menu helpMenu;
private static final String base = "menubar";
private static int nameCounter = 0;
@ -252,8 +257,8 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible
if (peer != null) {
peer.delMenu(index);
m.removeNotify();
m.parent = null;
}
m.parent = null;
if (helpMenu == m) {
helpMenu = null;
m.isHelpMenu = false;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 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
@ -22,21 +22,28 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.peer.MenuComponentPeer;
import java.awt.event.ActionEvent;
import java.awt.peer.MenuComponentPeer;
import java.io.IOException;
import java.io.ObjectInputStream;
import sun.awt.AppContext;
import sun.awt.AWTAccessor;
import sun.awt.ComponentFactory;
import javax.accessibility.*;
import java.security.AccessControlContext;
import java.security.AccessController;
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleComponent;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleSelection;
import javax.accessibility.AccessibleState;
import javax.accessibility.AccessibleStateSet;
import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import sun.awt.ComponentFactory;
/**
* The abstract class {@code MenuComponent} is the superclass
* of all menu-related components. In this respect, the class
@ -60,13 +67,13 @@ public abstract class MenuComponent implements java.io.Serializable {
}
transient volatile MenuComponentPeer peer;
transient MenuContainer parent;
transient volatile MenuContainer parent;
/**
* The {@code AppContext} of the {@code MenuComponent}.
* This is set in the constructor and never changes.
*/
transient AppContext appContext;
private transient volatile AppContext appContext;
/**
* The menu component's font. This value can be
@ -77,7 +84,7 @@ public abstract class MenuComponent implements java.io.Serializable {
* @see #setFont(Font)
* @see #getFont()
*/
volatile Font font;
private volatile Font font;
/**
* The menu component's name, which defaults to {@code null}.
@ -85,7 +92,7 @@ public abstract class MenuComponent implements java.io.Serializable {
* @see #getName()
* @see #setName(String)
*/
private String name;
private volatile String name;
/**
* A variable to indicate whether a name is explicitly set.
@ -94,14 +101,14 @@ public abstract class MenuComponent implements java.io.Serializable {
* @serial
* @see #setName(String)
*/
private boolean nameExplicitlySet = false;
private volatile boolean nameExplicitlySet;
/**
* Defaults to {@code false}.
* @serial
* @see #dispatchEvent(AWTEvent)
*/
boolean newEventsOnly = false;
volatile boolean newEventsOnly;
/*
* The menu's AccessControlContext.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 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
@ -22,15 +22,25 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.peer.MenuItemPeer;
import java.awt.event.*;
import java.util.EventListener;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
import javax.accessibility.*;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.EventListener;
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleAction;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleValue;
import sun.awt.AWTAccessor;
/**
@ -111,7 +121,7 @@ public class MenuItem extends MenuComponent implements Accessible {
* @see #isEnabled()
* @see #setEnabled(boolean)
*/
boolean enabled = true;
private volatile boolean enabled = true;
/**
* {@code label} is the label of a menu item.
@ -121,7 +131,7 @@ public class MenuItem extends MenuComponent implements Accessible {
* @see #getLabel()
* @see #setLabel(String)
*/
String label;
volatile String label;
/**
* This field indicates the command that has been issued
@ -134,7 +144,7 @@ public class MenuItem extends MenuComponent implements Accessible {
* @see #setActionCommand(String)
* @see #getActionCommand()
*/
String actionCommand;
private volatile String actionCommand;
/**
* The eventMask is ONLY set by subclasses via enableEvents.
@ -144,9 +154,9 @@ public class MenuItem extends MenuComponent implements Accessible {
*
* @serial
*/
long eventMask;
volatile long eventMask;
transient ActionListener actionListener;
private transient volatile ActionListener actionListener;
/**
* A sequence of key stokes that ia associated with
@ -160,7 +170,7 @@ public class MenuItem extends MenuComponent implements Accessible {
* @see #setShortcut(MenuShortcut)
* @see #deleteShortcut()
*/
private MenuShortcut shortcut = null;
private volatile MenuShortcut shortcut;
private static final String base = "menuitem";
private static int nameCounter = 0;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 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
@ -26,8 +26,9 @@
package java.awt;
import java.awt.peer.PopupMenuPeer;
import javax.accessibility.*;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import sun.awt.AWTAccessor;
@ -48,7 +49,7 @@ public class PopupMenu extends Menu {
private static final String base = "popup";
static int nameCounter = 0;
transient boolean isTrayIconPopup = false;
transient volatile boolean isTrayIconPopup;
static {
AWTAccessor.setPopupMenuAccessor(

View File

@ -4122,6 +4122,10 @@ public class Window extends Container implements Accessible {
public void setTrayIconWindow(Window w, boolean isTrayIconWindow) {
w.isTrayIconWindow = isTrayIconWindow;
}
public Window[] getOwnedWindows(Window w) {
return w.getOwnedWindows_NoClientCode();
}
}); // WindowAccessor
} // static

View File

@ -279,7 +279,7 @@ public class DragSourceContext
}
/**
* Sets the cursor for this drag operation to the specified
* Sets the custom cursor for this drag operation to the specified
* {@code Cursor}. If the specified {@code Cursor}
* is {@code null}, the default drag cursor behavior is
* activated for this drag operation, otherwise it is deactivated.
@ -298,9 +298,11 @@ public class DragSourceContext
}
/**
* Returns the current drag {@code Cursor}.
* Returns the current custom drag {@code Cursor}.
*
* @return the current drag {@code Cursor}
* @return the current custom drag {@code Cursor}, if it was set
* otherwise returns {@code null}.
* @see #setCursor
*/
public Cursor getCursor() { return cursor; }

View File

@ -64,27 +64,71 @@ import java.awt.Image;
public abstract class AbstractMultiResolutionImage extends java.awt.Image
implements MultiResolutionImage {
/**
* This method simply delegates to the same method on the base image and
* it is equivalent to: {@code getBaseImage().getWidth(observer)}.
*
* @return the width of the base image, or -1 if the width is not yet known
* @see #getBaseImage()
*
* @since 9
*/
@Override
public int getWidth(ImageObserver observer) {
return getBaseImage().getWidth(observer);
}
/**
* This method simply delegates to the same method on the base image and
* it is equivalent to: {@code getBaseImage().getHeight(observer)}.
*
* @return the height of the base image, or -1 if the height is not yet known
* @see #getBaseImage()
*
* @since 9
*/
@Override
public int getHeight(ImageObserver observer) {
return getBaseImage().getHeight(observer);
}
/**
* This method simply delegates to the same method on the base image and
* it is equivalent to: {@code getBaseImage().getSource()}.
*
* @return the image producer that produces the pixels for the base image
* @see #getBaseImage()
*
* @since 9
*/
@Override
public ImageProducer getSource() {
return getBaseImage().getSource();
}
/**
* As per the contract of the base {@code Image#getGraphics()} method,
* this implementation will always throw {@code UnsupportedOperationException}
* since only off-screen images can return a {@code Graphics} object.
*
* @return throws {@code UnsupportedOperationException}
* @throws UnsupportedOperationException this method is not supported
*/
@Override
public Graphics getGraphics() {
throw new UnsupportedOperationException("getGraphics() not supported"
+ " on Multi-Resolution Images");
}
/**
* This method simply delegates to the same method on the base image and
* it is equivalent to: {@code getBaseImage().getProperty(name, observer)}.
*
* @return the value of the named property in the base image
* @see #getBaseImage()
*
* @since 9
*/
@Override
public Object getProperty(String name, ImageObserver observer) {
return getBaseImage().getProperty(name, observer);

View File

@ -216,22 +216,27 @@ second on the inferred color space.</p>
<h4><a name="MetadataIssuesRead"/>Metadata Issues</h4>
By default all fields in the TIFF image file directory (IFD) are loaded into
the native image metadata object. In cases where the IFD includes fields which
contain large amounts of data this could be very inefficient. Which fields
are loaded may be controlled by setting which TIFF tags the reader is allowed
to recognize and whether it is ignoring metadata. The reader is informed to
disregard metadata as usual via the <code>ignoreMetadata</code> parameter of
By default all recognized fields in the TIFF image file directory (IFD) are
loaded into the native image metadata object. Which fields are loaded may be
controlled by setting which TIFF tags the reader is allowed to recognize,
whether to read fields with unrecognized tags, and whether to ignore all
metadata. The reader is informed to disregard all metadata as usual via the
<code>ignoreMetadata</code> parameter of
<code>ImageReader.setInput(Object,boolean,boolean)</code>. It is
informed of which <a href="../../plugins/tiff/TIFFTag.html">TIFFTag</a>s to
recognize or not to recognize via
<code>TIFFImageReadParam.addAllowedTagSet(TIFFTagSet)</code>
and
<code>TIFFImageReadParam.addAllowedTagSet(TIFFTagSet)</code> and
<code>TIFFImageReadParam.removeAllowedTagSet(TIFFTagSet)</code>.
If <code>ignoreMetadata</code> is <code>true</code>, then the reader will
load into the native image metadata object only those fields which have a
<code>TIFFTag</code> contained in the one of the allowed
<code>TIFFTagSet</code>s.
If <code>ignoreMetadata</code> is <code>true</code>, then only metadata
essential to reading the image will be loaded into the native image metadata
object. If <code>ignoreMetadata</code> is <code>false</code>, then the reader
will by default load into the native image metadata object only those fields
which are either essential to reading the image or have a <code>TIFFTag</code>
contained in the one of the allowed <code>TIFFTagSet</code>s. Reading of
fields with tags not in the allowed <code>TIFFTagSet</code>s may be forced
by passing in a <code>TIFFImageReadParam</code> on which
<code>TIFFImageReadParam.setReadUnknownTags(boolean)</code> has been
invoked with parameter <code>true</code>.
<p>Use of a <a href="../../plugins/tiff/TIFFDirectory.html">TIFFDirectory</a>
object may simplify gaining access to metadata values. An instance of
@ -534,7 +539,7 @@ Technical Note #2</a></td>
<tr>
<td>ZLib</td>
<td>"Deflate/Inflate" compression (see note following this table)</td>
<td><a href="http://partners.adobe.com/asn/developer/pdfs/tn/TIFFphotoshop.pdf">
<td><a href="http://partners.adobe.com/public/developer/en/tiff/TIFFphotoshop.pdf">
Adobe Photoshop&#174; TIFF Technical Notes</a> (PDF)</td>
</tr>
<tr>
@ -545,9 +550,9 @@ Adobe Photoshop&#174; TIFF Technical Notes</a> (PDF)</td>
<tr>
<td>Deflate</td>
<td>"Zip-in-TIFF" compression (see note following this table)</td>
<td><a href="http://www.isi.edu/in-notes/rfc1950.txt">
<td><a href="https://tools.ietf.org/html/rfc1950">
ZLIB Compressed Data Format Specification</a>,
<a href="http://www.isi.edu/in-notes/rfc1951.txt">
<a href="https://tools.ietf.org/html/rfc1951">
DEFLATE Compressed Data Format Specification</a></td>
</tr>
<tr>

View File

@ -224,7 +224,7 @@ public final class BaselineTIFFTagSet extends TIFFTagSet {
* A value to be used with the "Compression" tag.
*
* @see #TAG_COMPRESSION
* @see <a href="http://www.isi.edu/in-notes/rfc1951.txt">DEFLATE specification</a>
* @see <a href="https://tools.ietf.org/html/rfc1951">DEFLATE specification</a>
* @see <a href="http://partners.adobe.com/public/developer/en/tiff/TIFFphotoshop.pdf"> TIFF Specification Supplement 2</a>
*/
public static final int COMPRESSION_DEFLATE = 32946;

View File

@ -29,7 +29,7 @@ import java.util.List;
/**
* A class representing the extra tags found in a
* <a href="http://tools.ietf.org/html/rfc2306"> TIFF-F</a> (RFC 2036) file.
* <a href="http://tools.ietf.org/html/rfc2306.html">TIFF-F</a> (RFC 2036) file.
*
* @since 9
*/

View File

@ -30,10 +30,7 @@ import java.util.List;
/**
* A class representing the tags found in a GeoTIFF IFD. GeoTIFF is a
* standard for annotating georeferenced or geocoded raster imagery.
* The GeoTIFF specification may be found at <a
* href="http://www.remotesensing.org/geotiff/spec/geotiffhome.html">
* {@code http://www.remotesensing.org/geotiff/spec/geotiffhome.html}
* </a>. This class does <i>not</i> handle the <i>GeoKey</i>s referenced
* This class does <i>not</i> handle the <i>GeoKey</i>s referenced
* from a <i>GeoKeyDirectoryTag</i> as those are not TIFF tags per se.
*
* <p>The definitions of the data types referenced by the field

View File

@ -263,14 +263,16 @@ import com.sun.imageio.plugins.tiff.TIFFIFD;
*/
public final class TIFFField implements Cloneable {
private static final String[] typeNames = {
private static final long MAX_UINT32 = 0xffffffffL;
private static final String[] TYPE_NAMES = {
null,
"Byte", "Ascii", "Short", "Long", "Rational",
"SByte", "Undefined", "SShort", "SLong", "SRational",
"Float", "Double", "IFDPointer"
};
private static final boolean[] isIntegral = {
private static final boolean[] IS_INTEGRAL = {
false,
true, false, true, true, false,
true, true, true, true, false,
@ -544,6 +546,9 @@ public final class TIFFField implements Cloneable {
* @throws IllegalArgumentException if {@code data} is an instance of
* a class incompatible with the specified type.
* @throws IllegalArgumentException if the size of the data array is wrong.
* @throws IllegalArgumentException if the type of the data array is
* {@code TIFF_LONG}, {@code TIFF_RATIONAL}, or {@code TIFF_IFD_POINTER}
* and any of the elements is negative or greater than {@code 0xffffffff}.
*/
public TIFFField(TIFFTag tag, int type, int count, Object data) {
if(tag == null) {
@ -587,15 +592,50 @@ public final class TIFFField implements Cloneable {
case TIFFTag.TIFF_LONG:
isDataArrayCorrect = data instanceof long[]
&& ((long[])data).length == count;
if (isDataArrayCorrect) {
for (long datum : (long[])data) {
if (datum < 0) {
throw new IllegalArgumentException
("Negative value supplied for TIFF_LONG");
}
if (datum > MAX_UINT32) {
throw new IllegalArgumentException
("Too large value supplied for TIFF_LONG");
}
}
}
break;
case TIFFTag.TIFF_IFD_POINTER:
isDataArrayCorrect = data instanceof long[]
&& ((long[])data).length == 1;
if (((long[])data)[0] < 0) {
throw new IllegalArgumentException
("Negative value supplied for TIFF_IFD_POINTER");
}
if (((long[])data)[0] > MAX_UINT32) {
throw new IllegalArgumentException
("Too large value supplied for TIFF_IFD_POINTER");
}
break;
case TIFFTag.TIFF_RATIONAL:
isDataArrayCorrect = data instanceof long[][]
&& ((long[][])data).length == count
&& ((long[][])data)[0].length == 2;
&& ((long[][])data).length == count;
if (isDataArrayCorrect) {
for (long[] datum : (long[][])data) {
if (datum.length != 2) {
isDataArrayCorrect = false;
break;
}
if (datum[0] < 0 || datum[1] < 0) {
throw new IllegalArgumentException
("Negative value supplied for TIFF_RATIONAL");
}
if (datum[0] > MAX_UINT32 || datum[1] > MAX_UINT32) {
throw new IllegalArgumentException
("Too large value supplied for TIFF_RATIONAL");
}
}
}
break;
case TIFFTag.TIFF_SSHORT:
isDataArrayCorrect = data instanceof short[]
@ -607,8 +647,15 @@ public final class TIFFField implements Cloneable {
break;
case TIFFTag.TIFF_SRATIONAL:
isDataArrayCorrect = data instanceof int[][]
&& ((int[][])data).length == count
&& ((int[][])data)[0].length == 2;
&& ((int[][])data).length == count;
if (isDataArrayCorrect) {
for (int[] datum : (int[][])data) {
if (datum.length != 2) {
isDataArrayCorrect = false;
break;
}
}
}
break;
case TIFFTag.TIFF_FLOAT:
isDataArrayCorrect = data instanceof float[]
@ -658,27 +705,32 @@ public final class TIFFField implements Cloneable {
/**
* Constructs a {@code TIFFField} with a single non-negative integral
* value.
* The field will have type
* {@link TIFFTag#TIFF_SHORT TIFF_SHORT} if
* {@code val < 65536} and type
* {@link TIFFTag#TIFF_LONG TIFF_LONG} otherwise. The count
* of the field will be unity.
* value. The field will have type {@link TIFFTag#TIFF_SHORT TIFF_SHORT}
* if {@code value} is in {@code [0,0xffff]}, and type
* {@link TIFFTag#TIFF_LONG TIFF_LONG} if {@code value} is in
* {@code [0x10000,0xffffffff]}. The count of the field will be unity.
*
* @param tag The tag to associate with this field.
* @param value The value to associate with this field.
* @throws NullPointerException if {@code tag == null}.
* @throws IllegalArgumentException if the derived type is unacceptable
* for the supplied {@code TIFFTag}.
* @throws IllegalArgumentException if {@code value < 0}.
* @throws IllegalArgumentException if {@code value} is not in
* {@code [0,0xffffffff]}.
* @throws IllegalArgumentException if {@code value} is in
* {@code [0,0xffff]} and {@code TIFF_SHORT} is an unacceptable type
* for the {@code TIFFTag}, or if {@code value} is in
* {@code [0x10000,0xffffffff]} and {@code TIFF_LONG} is an unacceptable
* type for the {@code TIFFTag}.
*/
public TIFFField(TIFFTag tag, int value) {
public TIFFField(TIFFTag tag, long value) {
if(tag == null) {
throw new NullPointerException("tag == null!");
}
if (value < 0) {
throw new IllegalArgumentException("value < 0!");
}
if (value > MAX_UINT32) {
throw new IllegalArgumentException("value > 0xffffffff!");
}
this.tag = tag;
this.tagNumber = tag.getNumber();
@ -687,7 +739,8 @@ public final class TIFFField implements Cloneable {
if (value < 65536) {
if (!tag.isDataTypeOK(TIFFTag.TIFF_SHORT)) {
throw new IllegalArgumentException("Illegal data type "
+ TIFFTag.TIFF_SHORT + " for " + tag.getName() + " tag");
+ getTypeName(TIFFTag.TIFF_SHORT) + " for tag "
+ "\"" + tag.getName() + "\"");
}
this.type = TIFFTag.TIFF_SHORT;
char[] cdata = new char[1];
@ -696,7 +749,8 @@ public final class TIFFField implements Cloneable {
} else {
if (!tag.isDataTypeOK(TIFFTag.TIFF_LONG)) {
throw new IllegalArgumentException("Illegal data type "
+ TIFFTag.TIFF_LONG + " for " + tag.getName() + " tag");
+ getTypeName(TIFFTag.TIFF_LONG) + " for tag "
+ "\"" + tag.getName() + "\"");
}
this.type = TIFFTag.TIFF_LONG;
long[] ldata = new long[1];
@ -799,7 +853,7 @@ public final class TIFFField implements Cloneable {
throw new IllegalArgumentException("Unknown data type "+dataType);
}
return typeNames[dataType];
return TYPE_NAMES[dataType];
}
/**
@ -812,7 +866,7 @@ public final class TIFFField implements Cloneable {
*/
public static int getTypeByName(String typeName) {
for (int i = TIFFTag.MIN_DATATYPE; i <= TIFFTag.MAX_DATATYPE; i++) {
if (typeName.equals(typeNames[i])) {
if (typeName.equals(TYPE_NAMES[i])) {
return i;
}
}
@ -887,7 +941,7 @@ public final class TIFFField implements Cloneable {
* @return Whether the field type is integral.
*/
public boolean isIntegral() {
return isIntegral[type];
return IS_INTEGRAL[type];
}
/**

View File

@ -46,11 +46,18 @@ import javax.imageio.ImageReadParam;
* {@code ExifParentTIFFTagSet}, and {@code GeoTIFFTagSet}
* are included.
*
* <p> Forcing reading of fields corresponding to {@code TIFFTag}s
* not in any of the allowed {@code TIFFTagSet}s may be effected via
* {@link #setReadUnknownTags setReadUnknownTags}.
*
* @since 9
*/
public final class TIFFImageReadParam extends ImageReadParam {
private List<TIFFTagSet> allowedTagSets = new ArrayList<TIFFTagSet>(4);
private final List<TIFFTagSet> allowedTagSets =
new ArrayList<TIFFTagSet>(4);
private boolean readUnknownTags = false;
/**
* Constructs a {@code TIFFImageReadParam}. Tags defined by
@ -72,7 +79,8 @@ public final class TIFFImageReadParam extends ImageReadParam {
/**
* Adds a {@code TIFFTagSet} object to the list of allowed
* tag sets.
* tag sets. Attempting to add a duplicate object to the list
* has no effect.
*
* @param tagSet a {@code TIFFTagSet}.
*
@ -83,7 +91,9 @@ public final class TIFFImageReadParam extends ImageReadParam {
if (tagSet == null) {
throw new IllegalArgumentException("tagSet == null!");
}
allowedTagSets.add(tagSet);
if (!allowedTagSets.contains(tagSet)) {
allowedTagSets.add(tagSet);
}
}
/**
@ -113,4 +123,27 @@ public final class TIFFImageReadParam extends ImageReadParam {
public List<TIFFTagSet> getAllowedTagSets() {
return allowedTagSets;
}
/**
* Set whether to read fields corresponding to {@code TIFFTag}s not in
* the allowed {@code TIFFTagSet}s. The default setting is {@code false}.
* If the TIFF {@code ImageReader} is ignoring metadata, then a setting
* of {@code true} is overridden as all metadata are ignored except those
* essential to reading the image itself.
*
* @param readUnknownTags Whether to read fields of unrecognized tags
*/
public void setReadUnknownTags(boolean readUnknownTags) {
this.readUnknownTags = readUnknownTags;
}
/**
* Retrieve the setting of whether to read fields corresponding to unknown
* {@code TIFFTag}s.
*
* @return Whether to read fields of unrecognized tags
*/
public boolean getReadUnknownTags() {
return readUnknownTags;
}
}

View File

@ -182,6 +182,8 @@ public abstract class DefaultRowSorter<M, I> extends RowSorter<M> {
*/
private int modelRowCount;
// Whether to print warning about JDK-8160087
private static boolean warning8160087 = true;
/**
* Creates an empty <code>DefaultRowSorter</code>.
@ -489,10 +491,7 @@ public abstract class DefaultRowSorter<M, I> extends RowSorter<M> {
*/
public int convertRowIndexToView(int index) {
if (modelToView == null) {
if (index < 0 || index >= modelRowCount) {
throw new IndexOutOfBoundsException("Invalid index");
}
return index;
return convertUnsortedUnfiltered(index);
}
return modelToView[index];
}
@ -504,14 +503,30 @@ public abstract class DefaultRowSorter<M, I> extends RowSorter<M> {
*/
public int convertRowIndexToModel(int index) {
if (viewToModel == null) {
if (index < 0 || index >= modelRowCount) {
throw new IndexOutOfBoundsException("Invalid index");
}
return index;
return convertUnsortedUnfiltered(index);
}
return viewToModel[index].modelIndex;
}
private int convertUnsortedUnfiltered(int index) {
if (index < 0 || index >= modelRowCount) {
if(index >= modelRowCount &&
index < getModelWrapper().getRowCount()) {
// 8160087
if(warning8160087) {
warning8160087 = false;
System.err.println("WARNING: row index is bigger than " +
"sorter's row count. Most likely this is a wrong " +
"sorter usage.");
}
} else {
throw new IndexOutOfBoundsException("Invalid index");
}
}
return index;
}
private boolean isUnsorted() {
List<? extends SortKey> keys = getSortKeys();
int keySize = keys.size();

View File

@ -27,6 +27,7 @@ package javax.swing;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.*;
import java.beans.JavaBean;
import java.beans.BeanProperty;
@ -41,6 +42,8 @@ import java.io.IOException;
import javax.swing.plaf.*;
import javax.accessibility.*;
import sun.awt.SunToolkit;
/**
* An implementation of a menu bar. You add <code>JMenu</code> objects to the
* menu bar to construct a menu. When the user selects a <code>JMenu</code>
@ -144,6 +147,10 @@ public class JMenuBar extends JComponent implements Accessible,MenuElement
* @see JComponent#updateUI
*/
public void updateUI() {
Toolkit tk = Toolkit.getDefaultToolkit();
if (tk instanceof SunToolkit) {
((SunToolkit)tk).updateScreenMenuBarUI();
}
setUI((MenuBarUI)UIManager.getUI(this));
}

View File

@ -47,6 +47,7 @@ import java.util.Arrays;
import java.util.Collections;
import sun.awt.AWTAccessor;
import sun.swing.SwingUtilities2;
/**
* The "viewport" or "porthole" through which you see the underlying
@ -1034,9 +1035,16 @@ public class JViewport extends JComponent implements Accessible
private boolean isBlitting() {
Component view = getView();
return (scrollMode == BLIT_SCROLL_MODE) &&
(view instanceof JComponent) && view.isOpaque();
(view instanceof JComponent) && view.isOpaque() && !isFPScale();
}
private boolean isFPScale() {
GraphicsConfiguration gc = getGraphicsConfiguration();
if (gc != null) {
return SwingUtilities2.isFloatingPointScale(gc.getDefaultTransform());
}
return false;
}
/**
* Returns the <code>JViewport</code>'s one child or <code>null</code>.

View File

@ -45,7 +45,11 @@ import sun.java2d.SunGraphicsEnvironment;
import sun.security.action.GetPropertyAction;
import com.sun.java.swing.SwingUtilities3;
import java.awt.geom.AffineTransform;
import sun.java2d.SunGraphics2D;
import sun.java2d.pipe.Region;
import sun.swing.SwingAccessor;
import sun.swing.SwingUtilities2;
import sun.swing.SwingUtilities2.RepaintListener;
/**
@ -1517,9 +1521,12 @@ public class RepaintManager
// standard Image buffer.
boolean paintCompleted = false;
Image offscreen;
int sw = w + 1;
int sh = h + 1;
if (repaintManager.useVolatileDoubleBuffer() &&
(offscreen = getValidImage(repaintManager.
getVolatileOffscreenBuffer(bufferComponent, w, h))) != null) {
getVolatileOffscreenBuffer(bufferComponent, sw, sh))) != null) {
VolatileImage vImage = (java.awt.image.VolatileImage)offscreen;
GraphicsConfiguration gc = bufferComponent.
getGraphicsConfiguration();
@ -1529,7 +1536,7 @@ public class RepaintManager
VolatileImage.IMAGE_INCOMPATIBLE) {
repaintManager.resetVolatileDoubleBuffer(gc);
offscreen = repaintManager.getVolatileOffscreenBuffer(
bufferComponent,w, h);
bufferComponent, sw, sh);
vImage = (java.awt.image.VolatileImage)offscreen;
}
paintDoubleBuffered(paintingComponent, vImage, g, x, y,
@ -1589,8 +1596,18 @@ public class RepaintManager
* Paints a portion of a component to an offscreen buffer.
*/
protected void paintDoubleBuffered(JComponent c, Image image,
Graphics g, int clipX, int clipY,
int clipW, int clipH) {
Graphics g, int clipX, int clipY,
int clipW, int clipH) {
if (image instanceof VolatileImage && isPixelsCopying(c, g)) {
paintDoubleBufferedFPScales(c, image, g, clipX, clipY, clipW, clipH);
} else {
paintDoubleBufferedImpl(c, image, g, clipX, clipY, clipW, clipH);
}
}
private void paintDoubleBufferedImpl(JComponent c, Image image,
Graphics g, int clipX, int clipY,
int clipW, int clipH) {
Graphics osg = image.getGraphics();
int bw = Math.min(clipW, image.getWidth(null));
int bh = Math.min(clipH, image.getHeight(null));
@ -1629,6 +1646,76 @@ public class RepaintManager
}
}
private void paintDoubleBufferedFPScales(JComponent c, Image image,
Graphics g, int clipX, int clipY,
int clipW, int clipH) {
Graphics osg = image.getGraphics();
Graphics2D g2d = (Graphics2D) g;
Graphics2D osg2d = (Graphics2D) osg;
AffineTransform identity = new AffineTransform();
int bw = Math.min(clipW, image.getWidth(null));
int bh = Math.min(clipH, image.getHeight(null));
int x, y, maxx, maxy;
AffineTransform tx = g2d.getTransform();
double scaleX = tx.getScaleX();
double scaleY = tx.getScaleY();
double trX = tx.getTranslateX();
double trY = tx.getTranslateY();
boolean translucent = volatileBufferType != Transparency.OPAQUE;
Composite oldComposite = g2d.getComposite();
try {
for (x = clipX, maxx = clipX + clipW; x < maxx; x += bw) {
for (y = clipY, maxy = clipY + clipH; y < maxy; y += bh) {
// draw x, y, bw, bh
int pixelx1 = Region.clipRound(x * scaleX + trX);
int pixely1 = Region.clipRound(y * scaleY + trY);
int pixelx2 = Region.clipRound((x + bw) * scaleX + trX);
int pixely2 = Region.clipRound((y + bh) * scaleY + trY);
int pixelw = pixelx2 - pixelx1;
int pixelh = pixely2 - pixely1;
osg2d.setTransform(identity);
if (translucent) {
final Color oldBg = g2d.getBackground();
g2d.setBackground(c.getBackground());
g2d.clearRect(pixelx1, pixely1, pixelw, pixelh);
g2d.setBackground(oldBg);
}
osg2d.setClip(0, 0, pixelw, pixelh);
osg2d.translate(trX - pixelx1, trY - pixely1);
osg2d.scale(scaleX, scaleY);
c.paintToOffscreen(osg, x, y, bw, bh, maxx, maxy);
g2d.setTransform(identity);
g2d.setClip(pixelx1, pixely1, pixelw, pixelh);
AffineTransform stx = new AffineTransform();
stx.translate(pixelx1, pixely1);
stx.scale(scaleX, scaleY);
g2d.setTransform(stx);
if (translucent) {
g2d.setComposite(AlphaComposite.Src);
}
g2d.drawImage(image, 0, 0, c);
if (translucent) {
g2d.setComposite(oldComposite);
}
g2d.setTransform(tx);
}
}
} finally {
osg.dispose();
}
}
/**
* If <code>image</code> is non-null with a positive size it
* is returned, otherwise null is returned.
@ -1671,8 +1758,32 @@ public class RepaintManager
*/
protected void dispose() {
}
}
private boolean isPixelsCopying(JComponent c, Graphics g) {
AffineTransform tx = getTransform(g);
GraphicsConfiguration gc = c.getGraphicsConfiguration();
if (tx == null || gc == null
|| !SwingUtilities2.isFloatingPointScale(tx)) {
return false;
}
AffineTransform gcTx = gc.getDefaultTransform();
return gcTx.getScaleX() == tx.getScaleX()
&& gcTx.getScaleY() == tx.getScaleY();
}
private static AffineTransform getTransform(Graphics g) {
if (g instanceof SunGraphics2D) {
return ((SunGraphics2D) g).transform;
} else if (g instanceof Graphics2D) {
return ((Graphics2D) g).getTransform();
}
return null;
}
}
private class DoubleBufferInfo {
public Image image;

View File

@ -571,7 +571,9 @@ public class MetalFileChooserUI extends BasicFileChooserUI {
/**
* Obsolete class, not used in this version.
* @deprecated As of JDK version 9. Obsolete class.
*/
@Deprecated(since = "9")
protected class SingleClickListener extends MouseAdapter {
/**
* Constructs an instance of {@code SingleClickListener}.
@ -584,7 +586,9 @@ public class MetalFileChooserUI extends BasicFileChooserUI {
/**
* Obsolete class, not used in this version.
* @deprecated As of JDK version 9. Obsolete class.
*/
@Deprecated(since = "9")
@SuppressWarnings("serial") // Superclass is not serializable across versions
protected class FileRenderer extends DefaultListCellRenderer {
}

View File

@ -26,6 +26,7 @@ package javax.swing.text;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.lang.ref.SoftReference;
import java.security.AccessController;
import java.security.PrivilegedAction;
@ -750,7 +751,6 @@ public class WrappedPlainView extends BoxView implements TabExpander {
* valid location in the associated document
* @see View#modelToView
*/
@SuppressWarnings("deprecation")
public Shape modelToView(int pos, Shape a, Position.Bias b)
throws BadLocationException {
Rectangle alloc = a.getBounds();
@ -777,9 +777,11 @@ public class WrappedPlainView extends BoxView implements TabExpander {
if (pos > p0) {
Segment segment = SegmentCache.getSharedSegment();
loadText(segment, p0, pos);
alloc.x += Utilities.getTabbedTextWidth(segment, metrics,
alloc.x, WrappedPlainView.this, p0);
float x = alloc.x;
x += Utilities.getTabbedTextWidth(segment, metrics, x,
WrappedPlainView.this, p0);
SegmentCache.releaseSharedSegment(segment);
return new Rectangle2D.Float(x, alloc.y, alloc.width, alloc.height);
}
return alloc;
}

View File

@ -360,6 +360,12 @@ public final class AWTAccessor {
* Marks the specified window as an utility window for TrayIcon.
*/
void setTrayIconWindow(Window w, boolean isTrayIconWindow);
/**
* Return an array containing all the windows this
* window currently owns.
*/
Window[] getOwnedWindows(Window w);
}
/**

View File

@ -1857,6 +1857,9 @@ public abstract class SunToolkit extends Toolkit
return time == null ? -1 : time;
}
public void updateScreenMenuBarUI() {
}
// Cosntant alpha
public boolean isWindowOpacitySupported() {
return false;

View File

@ -3101,10 +3101,10 @@ public final class SunGraphics2D
if (scaleX == 1 && scaleY == 1) {
return null;
}
sx1 = Region.clipScale(sx1, scaleX);
sx2 = Region.clipScale(sx2, scaleX);
sy1 = Region.clipScale(sy1, scaleY);
sy2 = Region.clipScale(sy2, scaleY);
sx1 = Region.clipRound(sx1 * scaleX);
sx2 = Region.clipRound(sx2 * scaleX);
sy1 = Region.clipRound(sy1 * scaleY);
sy2 = Region.clipRound(sy2 * scaleY);
AffineTransform tx = null;
if (xform != null) {

View File

@ -305,6 +305,12 @@ public final class JLightweightFrame extends LightweightFrame implements RootPan
int startY = (int)Math.floor(y * scaleY);
int width = (int)Math.ceil((x + w) * scaleX) - startX;
int height = (int)Math.ceil((y + h) * scaleY) - startY;
if (startX + width > linestride) {
width = linestride - startX;
}
if (startY + height > bbImage.getHeight()) {
height = bbImage.getHeight() - startY;
}
for (int i = 0; i < height; i++) {
int from = (startY + i) * linestride + startX;

Some files were not shown because too many files have changed in this diff Show More