Merge
This commit is contained in:
commit
57ccffec8d
@ -96,7 +96,13 @@ TOOL_CHARSETMAPPING = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classe
|
||||
TOOL_SPP = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes build.tools.spp.Spp
|
||||
|
||||
# Nimbus is used somewhere in the swing build.
|
||||
|
||||
ifeq ($(BOOT_JDK_MODULAR), true)
|
||||
COMPILENIMBUS_ADD_MODS := -addmods java.xml.bind
|
||||
endif
|
||||
|
||||
TOOL_GENERATENIMBUS = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
|
||||
$(COMPILENIMBUS_ADD_MODS) \
|
||||
build.tools.generatenimbus.Generator
|
||||
|
||||
TOOL_WRAPPERGENERATOR = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
|
||||
|
@ -62,10 +62,13 @@ $(eval $(call SetupJavaCompilation,BUILD_BREAKITERATOR_LD, \
|
||||
BIN := $(BREAK_ITERATOR_CLASSES)/jdk.localedata))
|
||||
|
||||
ifeq ($(BOOT_JDK_MODULAR), true)
|
||||
BREAK_ITERATOR_BOOTCLASSPATH := -Xpatch:$(BREAK_ITERATOR_CLASSES) \
|
||||
-XaddExports:java.base/sun.text=ALL-UNNAMED \
|
||||
-XaddExports:java.base/sun.text.resources=ALL-UNNAMED \
|
||||
-XaddExports:jdk.localedata/sun.text.resources.ext=ALL-UNNAMED
|
||||
BREAK_ITERATOR_BOOTCLASSPATH := \
|
||||
-Xpatch:java.base=$(BREAK_ITERATOR_CLASSES)/java.base \
|
||||
-Xpatch:jdk.localedata=$(BREAK_ITERATOR_CLASSES)/jdk.localedata \
|
||||
-XaddExports:java.base/sun.text=ALL-UNNAMED \
|
||||
-XaddExports:java.base/sun.text.resources=ALL-UNNAMED \
|
||||
-XaddExports:jdk.localedata/sun.text.resources.ext=ALL-UNNAMED \
|
||||
#
|
||||
else
|
||||
BREAK_ITERATOR_BOOTCLASSPATH := -Xbootclasspath/p:$(call PathList, \
|
||||
$(BREAK_ITERATOR_CLASSES)/java.base \
|
||||
|
@ -31,7 +31,7 @@ $(eval $(call IncludeCustomExtension, jdk, launcher/Launcher-java.desktop.gmk))
|
||||
ifndef BUILD_HEADLESS_ONLY
|
||||
$(eval $(call SetupBuildLauncher, appletviewer, \
|
||||
MAIN_CLASS := sun.applet.Main, \
|
||||
JAVA_ARGS := -addmods ALL-SYSTEM, \
|
||||
JAVA_ARGS := -addmods ALL-DEFAULT, \
|
||||
LIBS_unix := $(X_LIBS), \
|
||||
))
|
||||
endif
|
||||
|
@ -27,4 +27,5 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jrunscript, \
|
||||
MAIN_CLASS := com.sun.tools.script.shell.Main, \
|
||||
JAVA_ARGS := -addmods ALL-DEFAULT, \
|
||||
))
|
||||
|
@ -27,7 +27,8 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, javac, \
|
||||
MAIN_CLASS := com.sun.tools.javac.Main, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
|
||||
JAVA_ARGS := -addmods ALL-DEFAULT, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
|
||||
-DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
|
||||
))
|
||||
|
||||
|
@ -27,6 +27,7 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, javadoc, \
|
||||
MAIN_CLASS := jdk.javadoc.internal.tool.Main, \
|
||||
JAVA_ARGS := -addmods ALL-DEFAULT, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
|
||||
-DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
|
||||
))
|
||||
|
@ -32,6 +32,7 @@ $(eval $(call SetupBuildLauncher, jimage,\
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jlink,\
|
||||
MAIN_CLASS := jdk.tools.jlink.internal.Main, \
|
||||
JAVA_ARGS := -addmods ALL-DEFAULT, \
|
||||
CFLAGS := -DENABLE_ARG_FILES \
|
||||
-DEXPAND_CLASSPATH_WILDCARDS \
|
||||
-DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
|
||||
|
@ -27,6 +27,6 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jjs, \
|
||||
MAIN_CLASS := jdk.nashorn.tools.jjs.Main, \
|
||||
JAVA_ARGS := -addmods ALL-SYSTEM, \
|
||||
JAVA_ARGS := -addmods ALL-DEFAULT, \
|
||||
CFLAGS := -DENABLE_ARG_FILES, \
|
||||
))
|
||||
|
@ -102,7 +102,7 @@ public class LinuxFileSystemProvider extends UnixFileSystemProvider {
|
||||
|
||||
@Override
|
||||
FileTypeDetector getFileTypeDetector() {
|
||||
String userHome = GetPropertyAction.getProperty("user.home");
|
||||
String userHome = GetPropertyAction.privilegedGetProperty("user.home");
|
||||
Path userMimeTypes = Paths.get(userHome, ".mime.types");
|
||||
Path etcMimeTypes = Paths.get("/etc/mime.types");
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 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
|
||||
@ -53,7 +53,7 @@ iepoll(int epfd, struct epoll_event *events, int numfds, jlong timeout)
|
||||
start = t.tv_sec * 1000 + t.tv_usec / 1000;
|
||||
|
||||
for (;;) {
|
||||
int res = epoll_wait(epfd, events, numfds, timeout);
|
||||
int res = epoll_wait(epfd, events, numfds, remaining);
|
||||
if (res < 0 && errno == EINTR) {
|
||||
if (remaining >= 0) {
|
||||
gettimeofday(&t, NULL);
|
||||
|
@ -84,7 +84,8 @@ class KQueueArrayWrapper {
|
||||
static {
|
||||
IOUtil.load();
|
||||
initStructSizes();
|
||||
String datamodel = GetPropertyAction.getProperty("sun.arch.data.model");
|
||||
String datamodel =
|
||||
GetPropertyAction.privilegedGetProperty("sun.arch.data.model");
|
||||
is64bit = "64".equals(datamodel);
|
||||
}
|
||||
|
||||
|
@ -29,8 +29,6 @@ import java.nio.file.*;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
import java.security.AccessController;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
import static sun.nio.fs.MacOSXNativeDispatcher.*;
|
||||
|
||||
|
@ -46,8 +46,8 @@ public class MacOSXFileSystemProvider extends BsdFileSystemProvider {
|
||||
|
||||
@Override
|
||||
FileTypeDetector getFileTypeDetector() {
|
||||
Path userMimeTypes = Paths.get(
|
||||
GetPropertyAction.getProperty("user.home"), ".mime.types");
|
||||
Path userMimeTypes = Paths.get(GetPropertyAction
|
||||
.privilegedGetProperty("user.home"), ".mime.types");
|
||||
|
||||
return chain(new MimeTypesFileTypeDetector(userMimeTypes),
|
||||
new UTIFileTypeDetector());
|
||||
|
@ -1896,7 +1896,7 @@ public class File
|
||||
|
||||
// temporary directory location
|
||||
private static final File tmpdir = new File(
|
||||
GetPropertyAction.getProperty("java.io.tmpdir"));
|
||||
GetPropertyAction.privilegedGetProperty("java.io.tmpdir"));
|
||||
static File location() {
|
||||
return tmpdir;
|
||||
}
|
||||
|
@ -470,7 +470,7 @@ public final class Class<T> implements java.io.Serializable,
|
||||
* expression with an empty argument list. The class is initialized if it
|
||||
* has not already been initialized.
|
||||
*
|
||||
* <p>Note that this method propagates any exception thrown by the
|
||||
* @deprecated This method propagates any exception thrown by the
|
||||
* nullary constructor, including a checked exception. Use of
|
||||
* this method effectively bypasses the compile-time exception
|
||||
* checking that would otherwise be performed by the compiler.
|
||||
@ -500,6 +500,7 @@ public final class Class<T> implements java.io.Serializable,
|
||||
* of this class.
|
||||
*/
|
||||
@CallerSensitive
|
||||
@Deprecated(since="9")
|
||||
public T newInstance()
|
||||
throws InstantiationException, IllegalAccessException
|
||||
{
|
||||
|
@ -2615,7 +2615,7 @@ public abstract class ClassLoader {
|
||||
ServicesCatalog createOrGetServicesCatalog() {
|
||||
ServicesCatalog catalog = servicesCatalog;
|
||||
if (catalog == null) {
|
||||
catalog = new ServicesCatalog();
|
||||
catalog = ServicesCatalog.create();
|
||||
boolean set = trySetObjectField("servicesCatalog", catalog);
|
||||
if (!set) {
|
||||
// beaten by someone else
|
||||
|
@ -468,7 +468,7 @@ public final class ProcessBuilder
|
||||
*/
|
||||
public abstract static class Redirect {
|
||||
private static final File NULL_FILE = new File(
|
||||
(GetPropertyAction.getProperty("os.name")
|
||||
(GetPropertyAction.privilegedGetProperty("os.name")
|
||||
.startsWith("Windows") ? "NUL" : "/dev/null")
|
||||
);
|
||||
|
||||
|
@ -78,7 +78,8 @@ final class StackStreamFactory {
|
||||
* Performance work and extensive testing is needed to replace the
|
||||
* VM built-in backtrace filled in Throwable with the StackWalker.
|
||||
*/
|
||||
final static boolean isDebug = getProperty("stackwalk.debug", false);
|
||||
final static boolean isDebug =
|
||||
"true".equals(GetPropertyAction.privilegedGetProperty("stackwalk.debug"));
|
||||
|
||||
static <T> StackFrameTraverser<T>
|
||||
makeStackTraverser(StackWalker walker, Function<? super Stream<StackFrame>, ? extends T> function)
|
||||
@ -988,11 +989,4 @@ final class StackStreamFactory {
|
||||
c.getName().startsWith("java.lang.invoke.LambdaForm");
|
||||
}
|
||||
|
||||
private static boolean getProperty(String key, boolean value) {
|
||||
String s = GetPropertyAction.getProperty(key);
|
||||
if (s != null) {
|
||||
return Boolean.parseBoolean(s);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,6 @@ import jdk.internal.logger.LazyLoggers;
|
||||
import jdk.internal.logger.LocalizedLoggerWrapper;
|
||||
|
||||
import jdk.internal.module.ModuleBootstrap;
|
||||
import jdk.internal.module.Modules;
|
||||
import jdk.internal.module.ServicesCatalog;
|
||||
|
||||
/**
|
||||
@ -1924,10 +1923,6 @@ public final class System {
|
||||
// initialize the module system
|
||||
System.bootLayer = ModuleBootstrap.boot();
|
||||
|
||||
// base module needs to be loose (CODETOOLS-7901619)
|
||||
Module base = Object.class.getModule();
|
||||
Modules.addReads(base, null);
|
||||
|
||||
// module system initialized
|
||||
VM.initLevel(2);
|
||||
}
|
||||
|
@ -33,8 +33,6 @@ import sun.invoke.util.VerifyType;
|
||||
import sun.invoke.util.Wrapper;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
|
@ -88,7 +88,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
static {
|
||||
final String key = "jdk.internal.lambda.dumpProxyClasses";
|
||||
String path = GetPropertyAction.getProperty(key);
|
||||
String path = GetPropertyAction.privilegedGetProperty(key);
|
||||
dumper = (null == path) ? null : ProxyClassesDumper.getInstance(path);
|
||||
}
|
||||
|
||||
|
@ -396,7 +396,7 @@ class Invokers {
|
||||
LambdaForm lform = new LambdaForm(name + ":VarHandle_invoke_MT_" + shortenSignature(basicTypeSignature(mtype)),
|
||||
ARG_LIMIT + 1, names);
|
||||
|
||||
lform.prepare();
|
||||
lform.compileToBytecode();
|
||||
return lform;
|
||||
}
|
||||
|
||||
@ -448,7 +448,7 @@ class Invokers {
|
||||
LambdaForm lform = new LambdaForm(name + ":VarHandle_exactInvoker" + shortenSignature(basicTypeSignature(mtype)),
|
||||
ARG_LIMIT, names);
|
||||
|
||||
lform.prepare();
|
||||
lform.compileToBytecode();
|
||||
return lform;
|
||||
}
|
||||
|
||||
@ -497,44 +497,33 @@ class Invokers {
|
||||
|
||||
/*non-public*/ static
|
||||
@ForceInline
|
||||
MethodHandle checkVarHandleGenericType(VarHandle vh, VarHandle.AccessDescriptor vad) {
|
||||
MethodType expected = vad.symbolicMethodType;
|
||||
MethodType actual = VarHandle.AccessType.getMethodType(vad.type, vh);
|
||||
|
||||
MemberName mn = VarHandle.AccessMode.getMemberName(vad.mode, vh.vform);
|
||||
if (mn == null)
|
||||
throw vh.unsupported();
|
||||
// TODO the following MH is not constant, cache in stable field array
|
||||
// on VarForm?
|
||||
MethodHandle mh = DirectMethodHandle.make(mn);
|
||||
if (actual == expected) {
|
||||
MethodHandle checkVarHandleGenericType(VarHandle handle, VarHandle.AccessDescriptor ad) {
|
||||
// Test for exact match on invoker types
|
||||
// TODO match with erased types and add cast of return value to lambda form
|
||||
MethodHandle mh = handle.getMethodHandle(ad.mode);
|
||||
if (mh.type() == ad.symbolicMethodTypeInvoker) {
|
||||
return mh;
|
||||
}
|
||||
else {
|
||||
// Adapt to the actual (which should never fail since mh's method
|
||||
// type is in the basic form), then to the expected (which my fail
|
||||
// if the symbolic type descriptor does not match)
|
||||
// TODO optimize for the case of actual.erased() == expected.erased()
|
||||
return mh.asType(actual.insertParameterTypes(0, VarHandle.class)).
|
||||
asType(expected.insertParameterTypes(0, VarHandle.class));
|
||||
return mh.asType(ad.symbolicMethodTypeInvoker);
|
||||
}
|
||||
}
|
||||
|
||||
/*non-public*/ static
|
||||
@ForceInline
|
||||
void checkVarHandleExactType(VarHandle vh, VarHandle.AccessDescriptor vad) {
|
||||
MethodType expected = vad.symbolicMethodType;
|
||||
MethodType actual = VarHandle.AccessType.getMethodType(vad.type, vh);
|
||||
if (actual != expected)
|
||||
throw newWrongMethodTypeException(expected, actual);
|
||||
void checkVarHandleExactType(VarHandle handle, VarHandle.AccessDescriptor ad) {
|
||||
MethodType erasedTarget = handle.vform.methodType_table[ad.type];
|
||||
MethodType erasedSymbolic = ad.symbolicMethodTypeErased;
|
||||
if (erasedTarget != erasedSymbolic)
|
||||
throw newWrongMethodTypeException(erasedTarget, erasedSymbolic);
|
||||
}
|
||||
|
||||
/*non-public*/ static
|
||||
@ForceInline
|
||||
MemberName getVarHandleMemberName(VarHandle vh, VarHandle.AccessDescriptor vad) {
|
||||
MemberName mn = VarHandle.AccessMode.getMemberName(vad.mode, vh.vform);
|
||||
MemberName getVarHandleMemberName(VarHandle handle, VarHandle.AccessDescriptor ad) {
|
||||
MemberName mn = handle.vform.memberName_table[ad.mode];
|
||||
if (mn == null) {
|
||||
throw vh.unsupported();
|
||||
throw handle.unsupported();
|
||||
}
|
||||
return mn;
|
||||
}
|
||||
|
@ -430,14 +430,14 @@ class MethodHandleNatives {
|
||||
|
||||
// If not polymorphic in the return type, such as the compareAndSet
|
||||
// methods that return boolean
|
||||
if (ak.isPolyMorphicInReturnType) {
|
||||
if (ak.returnType != mtype.returnType()) {
|
||||
if (ak.at.isMonomorphicInReturnType) {
|
||||
if (ak.at.returnType != mtype.returnType()) {
|
||||
// The caller contains a different return type than that
|
||||
// defined by the method
|
||||
throw newNoSuchMethodErrorOnVarHandle(name, mtype);
|
||||
}
|
||||
// Adjust the return type of the signature method type
|
||||
sigType = sigType.changeReturnType(ak.returnType);
|
||||
sigType = sigType.changeReturnType(ak.at.returnType);
|
||||
}
|
||||
|
||||
// Get the guard method type for linking
|
||||
@ -455,26 +455,25 @@ class MethodHandleNatives {
|
||||
MemberName linker = new MemberName(
|
||||
VarHandleGuards.class, "guard_" + getVarHandleMethodSignature(sigType),
|
||||
guardType, REF_invokeStatic);
|
||||
try {
|
||||
return MemberName.getFactory().resolveOrFail(
|
||||
REF_invokeStatic, linker, VarHandleGuards.class, ReflectiveOperationException.class);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
// Fall back to lambda form linkage if guard method is not available
|
||||
// TODO Optionally log fallback ?
|
||||
|
||||
linker = MemberName.getFactory().resolveOrNull(REF_invokeStatic, linker,
|
||||
VarHandleGuards.class);
|
||||
if (linker != null) {
|
||||
return linker;
|
||||
}
|
||||
// Fall back to lambda form linkage if guard method is not available
|
||||
// TODO Optionally log fallback ?
|
||||
}
|
||||
return Invokers.varHandleInvokeLinkerMethod(name, mtype);
|
||||
}
|
||||
static String getVarHandleMethodSignature(MethodType mt) {
|
||||
StringBuilder sb = new StringBuilder(mt.parameterCount() + 1);
|
||||
StringBuilder sb = new StringBuilder(mt.parameterCount() + 2);
|
||||
|
||||
for (int i = 0; i < mt.parameterCount(); i++) {
|
||||
Class<?> pt = mt.parameterType(i);
|
||||
sb.append(getCharType(pt));
|
||||
}
|
||||
|
||||
sb.append('_').append(getCharType(mt.returnType()));
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
static char getCharType(Class<?> pt) {
|
||||
|
@ -53,7 +53,7 @@ import sun.security.action.GetPropertyAction;
|
||||
static final boolean VAR_HANDLE_GUARDS;
|
||||
|
||||
static {
|
||||
Properties props = GetPropertyAction.getProperties();
|
||||
Properties props = GetPropertyAction.privilegedGetProperties();
|
||||
DEBUG_METHOD_HANDLE_NAMES = Boolean.parseBoolean(
|
||||
props.getProperty("java.lang.invoke.MethodHandle.DEBUG_NAMES"));
|
||||
DUMP_CLASS_FILES = Boolean.parseBoolean(
|
||||
|
@ -197,7 +197,7 @@ public final class StringConcatFactory {
|
||||
// DEBUG = false; // implied
|
||||
// DUMPER = null; // implied
|
||||
|
||||
Properties props = GetPropertyAction.getProperties();
|
||||
Properties props = GetPropertyAction.privilegedGetProperties();
|
||||
final String strategy =
|
||||
props.getProperty("java.lang.invoke.stringConcat");
|
||||
CACHE_ENABLE = Boolean.parseBoolean(
|
||||
|
@ -24,42 +24,102 @@
|
||||
*/
|
||||
package java.lang.invoke;
|
||||
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
|
||||
import java.lang.invoke.VarHandle.AccessMode;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A var handle form containing a set of member name, one for each operation.
|
||||
* Each member characterizes a static method.
|
||||
*/
|
||||
class VarForm {
|
||||
final class VarForm {
|
||||
|
||||
// Holds VarForm for VarHandle implementation classes
|
||||
private static final ClassValue<VarForm> VFORMS
|
||||
= new ClassValue<>() {
|
||||
@Override
|
||||
protected VarForm computeValue(Class<?> impl) {
|
||||
return new VarForm(linkFromStatic(impl));
|
||||
final @Stable MethodType[] methodType_table;
|
||||
|
||||
final @Stable MemberName[] memberName_table;
|
||||
|
||||
VarForm(Class<?> implClass, Class<?> receiver, Class<?> value, Class<?>... intermediate) {
|
||||
this.methodType_table = new MethodType[VarHandle.AccessType.values().length];
|
||||
|
||||
// TODO lazily calculate
|
||||
this.memberName_table = linkFromStatic(implClass);
|
||||
|
||||
// (Receiver, <Intermediates>)
|
||||
List<Class<?>> l = new ArrayList<>();
|
||||
if (receiver != null)
|
||||
l.add(receiver);
|
||||
l.addAll(Arrays.asList(intermediate));
|
||||
|
||||
// (Receiver, <Intermediates>)Value
|
||||
methodType_table[VarHandle.AccessType.GET.ordinal()] =
|
||||
MethodType.methodType(value, l).erase();
|
||||
|
||||
// (Receiver, <Intermediates>, Value)void
|
||||
l.add(value);
|
||||
methodType_table[VarHandle.AccessType.SET.ordinal()] =
|
||||
MethodType.methodType(void.class, l).erase();
|
||||
|
||||
// (Receiver, <Intermediates>, Value)Value
|
||||
methodType_table[VarHandle.AccessType.GET_AND_UPDATE.ordinal()] =
|
||||
MethodType.methodType(value, l).erase();
|
||||
|
||||
// (Receiver, <Intermediates>, Value, Value)boolean
|
||||
l.add(value);
|
||||
methodType_table[VarHandle.AccessType.COMPARE_AND_SWAP.ordinal()] =
|
||||
MethodType.methodType(boolean.class, l).erase();
|
||||
|
||||
// (Receiver, <Intermediates>, Value, Value)Value
|
||||
methodType_table[VarHandle.AccessType.COMPARE_AND_EXCHANGE.ordinal()] =
|
||||
MethodType.methodType(value, l).erase();
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
final MethodType getMethodType(int type) {
|
||||
return methodType_table[type];
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
final MemberName getMemberName(int mode) {
|
||||
// TODO calculate lazily
|
||||
MemberName mn = memberName_table[mode];
|
||||
if (mn == null) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
|
||||
final @Stable MemberName[] table;
|
||||
|
||||
VarForm(MemberName[] table) {
|
||||
this.table = table;
|
||||
return mn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a var form given an VarHandle implementation class.
|
||||
* Each signature polymorphic method is linked to a static method of the
|
||||
* same name on the implementation class or a super class.
|
||||
*/
|
||||
static VarForm createFromStatic(Class<? extends VarHandle> impl) {
|
||||
return VFORMS.get(impl);
|
||||
|
||||
@Stable
|
||||
MethodType[] methodType_V_table;
|
||||
|
||||
@ForceInline
|
||||
final MethodType[] getMethodType_V_init() {
|
||||
MethodType[] table = new MethodType[VarHandle.AccessType.values().length];
|
||||
for (int i = 0; i < methodType_table.length; i++) {
|
||||
MethodType mt = methodType_table[i];
|
||||
// TODO only adjust for sig-poly methods returning Object
|
||||
table[i] = mt.changeReturnType(void.class);
|
||||
}
|
||||
methodType_V_table = table;
|
||||
return table;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
final MethodType getMethodType_V(int type) {
|
||||
MethodType[] table = methodType_V_table;
|
||||
if (table == null) {
|
||||
table = getMethodType_V_init();
|
||||
}
|
||||
return table[type];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Link all signature polymorphic methods.
|
||||
*/
|
||||
|
@ -27,10 +27,9 @@ package java.lang.invoke;
|
||||
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -406,42 +405,10 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError;
|
||||
* @since 9
|
||||
*/
|
||||
public abstract class VarHandle {
|
||||
// Use explicit final fields rather than an @Stable array as
|
||||
// this can reduce the memory per handle
|
||||
// e.g. by 24 bytes on 64 bit architectures
|
||||
final MethodType typeGet;
|
||||
final MethodType typeSet;
|
||||
final MethodType typeCompareSwap;
|
||||
final MethodType typeCompareExchange;
|
||||
final MethodType typeGetAndUpdate;
|
||||
|
||||
final VarForm vform;
|
||||
|
||||
VarHandle(VarForm vform, Class<?> receiver, Class<?> value, Class<?>... intermediate) {
|
||||
VarHandle(VarForm vform) {
|
||||
this.vform = vform;
|
||||
|
||||
// (Receiver, <Intermediates>)
|
||||
List<Class<?>> l = new ArrayList<>();
|
||||
if (receiver != null)
|
||||
l.add(receiver);
|
||||
l.addAll(Arrays.asList(intermediate));
|
||||
|
||||
// (Receiver, <Intermediates>)Value
|
||||
this.typeGet = MethodType.methodType(value, l);
|
||||
|
||||
// (Receiver, <Intermediates>, Value)void
|
||||
l.add(value);
|
||||
this.typeSet = MethodType.methodType(void.class, l);
|
||||
|
||||
// (Receiver, <Intermediates>, Value)Value
|
||||
this.typeGetAndUpdate = MethodType.methodType(value, l);
|
||||
|
||||
// (Receiver, <Intermediates>, Value, Value)boolean
|
||||
l.add(value);
|
||||
this.typeCompareSwap = MethodType.methodType(boolean.class, l);
|
||||
|
||||
// (Receiver, <Intermediates>, Value, Value)Value
|
||||
this.typeCompareExchange = MethodType.methodType(value, l);
|
||||
}
|
||||
|
||||
RuntimeException unsupported() {
|
||||
@ -1090,36 +1057,83 @@ public abstract class VarHandle {
|
||||
Object addAndGet(Object... args);
|
||||
|
||||
enum AccessType {
|
||||
GET, // 0
|
||||
SET, // 1
|
||||
COMPARE_AND_SWAP, // 2
|
||||
COMPARE_AND_EXCHANGE, // 3
|
||||
GET_AND_UPDATE; // 4
|
||||
GET(Object.class) {
|
||||
@Override
|
||||
MethodType accessModeType(Class<?> receiver, Class<?> value,
|
||||
Class<?>... intermediate) {
|
||||
Class<?>[] ps = allocateParameters(0, receiver, intermediate);
|
||||
fillParameters(ps, receiver, intermediate);
|
||||
return MethodType.methodType(value, ps);
|
||||
}
|
||||
},
|
||||
SET(void.class) {
|
||||
@Override
|
||||
MethodType accessModeType(Class<?> receiver, Class<?> value,
|
||||
Class<?>... intermediate) {
|
||||
Class<?>[] ps = allocateParameters(1, receiver, intermediate);
|
||||
int i = fillParameters(ps, receiver, intermediate);
|
||||
ps[i] = value;
|
||||
return MethodType.methodType(void.class, ps);
|
||||
}
|
||||
},
|
||||
COMPARE_AND_SWAP(boolean.class) {
|
||||
@Override
|
||||
MethodType accessModeType(Class<?> receiver, Class<?> value,
|
||||
Class<?>... intermediate) {
|
||||
Class<?>[] ps = allocateParameters(2, receiver, intermediate);
|
||||
int i = fillParameters(ps, receiver, intermediate);
|
||||
ps[i++] = value;
|
||||
ps[i] = value;
|
||||
return MethodType.methodType(boolean.class, ps);
|
||||
}
|
||||
},
|
||||
COMPARE_AND_EXCHANGE(Object.class) {
|
||||
@Override
|
||||
MethodType accessModeType(Class<?> receiver, Class<?> value,
|
||||
Class<?>... intermediate) {
|
||||
Class<?>[] ps = allocateParameters(2, receiver, intermediate);
|
||||
int i = fillParameters(ps, receiver, intermediate);
|
||||
ps[i++] = value;
|
||||
ps[i] = value;
|
||||
return MethodType.methodType(value, ps);
|
||||
}
|
||||
},
|
||||
GET_AND_UPDATE(Object.class) {
|
||||
@Override
|
||||
MethodType accessModeType(Class<?> receiver, Class<?> value,
|
||||
Class<?>... intermediate) {
|
||||
Class<?>[] ps = allocateParameters(1, receiver, intermediate);
|
||||
int i = fillParameters(ps, receiver, intermediate);
|
||||
ps[i] = value;
|
||||
return MethodType.methodType(value, ps);
|
||||
}
|
||||
};
|
||||
|
||||
MethodType getMethodType(VarHandle vh) {
|
||||
return getMethodType(this.ordinal(), vh);
|
||||
final Class<?> returnType;
|
||||
final boolean isMonomorphicInReturnType;
|
||||
|
||||
AccessType(Class<?> returnType) {
|
||||
this.returnType = returnType;
|
||||
isMonomorphicInReturnType = returnType != Object.class;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static MethodType getMethodType(int ordinal, VarHandle vh) {
|
||||
if (ordinal == 0) {
|
||||
return vh.typeGet;
|
||||
}
|
||||
else if (ordinal == 1) {
|
||||
return vh.typeSet;
|
||||
}
|
||||
else if (ordinal == 2) {
|
||||
return vh.typeCompareSwap;
|
||||
}
|
||||
else if (ordinal == 3) {
|
||||
return vh.typeCompareExchange;
|
||||
}
|
||||
else if (ordinal == 4) {
|
||||
return vh.typeGetAndUpdate;
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Illegal access type: " + ordinal);
|
||||
}
|
||||
abstract MethodType accessModeType(Class<?> receiver, Class<?> value,
|
||||
Class<?>... intermediate);
|
||||
|
||||
private static Class<?>[] allocateParameters(int values,
|
||||
Class<?> receiver, Class<?>... intermediate) {
|
||||
int size = ((receiver != null) ? 1 : 0) + intermediate.length + values;
|
||||
return new Class<?>[size];
|
||||
}
|
||||
|
||||
private static int fillParameters(Class<?>[] ps,
|
||||
Class<?> receiver, Class<?>... intermediate) {
|
||||
int i = 0;
|
||||
if (receiver != null)
|
||||
ps[i++] = receiver;
|
||||
for (int j = 0; j < intermediate.length; j++)
|
||||
ps[i++] = intermediate[j];
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1133,115 +1147,115 @@ public abstract class VarHandle {
|
||||
* method
|
||||
* {@link VarHandle#get VarHandle.get}
|
||||
*/
|
||||
GET("get", AccessType.GET, Object.class),
|
||||
GET("get", AccessType.GET),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#set VarHandle.set}
|
||||
*/
|
||||
SET("set", AccessType.SET, void.class),
|
||||
SET("set", AccessType.SET),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#getVolatile VarHandle.getVolatile}
|
||||
*/
|
||||
GET_VOLATILE("getVolatile", AccessType.GET, Object.class),
|
||||
GET_VOLATILE("getVolatile", AccessType.GET),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#setVolatile VarHandle.setVolatile}
|
||||
*/
|
||||
SET_VOLATILE("setVolatile", AccessType.SET, void.class),
|
||||
SET_VOLATILE("setVolatile", AccessType.SET),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#getAcquire VarHandle.getAcquire}
|
||||
*/
|
||||
GET_ACQUIRE("getAcquire", AccessType.GET, Object.class),
|
||||
GET_ACQUIRE("getAcquire", AccessType.GET),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#setRelease VarHandle.setRelease}
|
||||
*/
|
||||
SET_RELEASE("setRelease", AccessType.SET, void.class),
|
||||
SET_RELEASE("setRelease", AccessType.SET),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#getOpaque VarHandle.getOpaque}
|
||||
*/
|
||||
GET_OPAQUE("getOpaque", AccessType.GET, Object.class),
|
||||
GET_OPAQUE("getOpaque", AccessType.GET),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#setOpaque VarHandle.setOpaque}
|
||||
*/
|
||||
SET_OPAQUE("setOpaque", AccessType.SET, void.class),
|
||||
SET_OPAQUE("setOpaque", AccessType.SET),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#compareAndSet VarHandle.compareAndSet}
|
||||
*/
|
||||
COMPARE_AND_SET("compareAndSet", AccessType.COMPARE_AND_SWAP, boolean.class),
|
||||
COMPARE_AND_SET("compareAndSet", AccessType.COMPARE_AND_SWAP),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#compareAndExchangeVolatile VarHandle.compareAndExchangeVolatile}
|
||||
*/
|
||||
COMPARE_AND_EXCHANGE_VOLATILE("compareAndExchangeVolatile", AccessType.COMPARE_AND_EXCHANGE, Object.class),
|
||||
COMPARE_AND_EXCHANGE_VOLATILE("compareAndExchangeVolatile", AccessType.COMPARE_AND_EXCHANGE),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#compareAndExchangeAcquire VarHandle.compareAndExchangeAcquire}
|
||||
*/
|
||||
COMPARE_AND_EXCHANGE_ACQUIRE("compareAndExchangeAcquire", AccessType.COMPARE_AND_EXCHANGE, Object.class),
|
||||
COMPARE_AND_EXCHANGE_ACQUIRE("compareAndExchangeAcquire", AccessType.COMPARE_AND_EXCHANGE),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#compareAndExchangeRelease VarHandle.compareAndExchangeRelease}
|
||||
*/
|
||||
COMPARE_AND_EXCHANGE_RELEASE("compareAndExchangeRelease", AccessType.COMPARE_AND_EXCHANGE, Object.class),
|
||||
COMPARE_AND_EXCHANGE_RELEASE("compareAndExchangeRelease", AccessType.COMPARE_AND_EXCHANGE),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#weakCompareAndSet VarHandle.weakCompareAndSet}
|
||||
*/
|
||||
WEAK_COMPARE_AND_SET("weakCompareAndSet", AccessType.COMPARE_AND_SWAP, boolean.class),
|
||||
WEAK_COMPARE_AND_SET("weakCompareAndSet", AccessType.COMPARE_AND_SWAP),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#weakCompareAndSetVolatile VarHandle.weakCompareAndSetVolatile}
|
||||
*/
|
||||
WEAK_COMPARE_AND_SET_VOLATILE("weakCompareAndSetVolatile", AccessType.COMPARE_AND_SWAP, boolean.class),
|
||||
WEAK_COMPARE_AND_SET_VOLATILE("weakCompareAndSetVolatile", AccessType.COMPARE_AND_SWAP),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#weakCompareAndSetAcquire VarHandle.weakCompareAndSetAcquire}
|
||||
*/
|
||||
WEAK_COMPARE_AND_SET_ACQUIRE("weakCompareAndSetAcquire", AccessType.COMPARE_AND_SWAP, boolean.class),
|
||||
WEAK_COMPARE_AND_SET_ACQUIRE("weakCompareAndSetAcquire", AccessType.COMPARE_AND_SWAP),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#weakCompareAndSetRelease VarHandle.weakCompareAndSetRelease}
|
||||
*/
|
||||
WEAK_COMPARE_AND_SET_RELEASE("weakCompareAndSetRelease", AccessType.COMPARE_AND_SWAP, boolean.class),
|
||||
WEAK_COMPARE_AND_SET_RELEASE("weakCompareAndSetRelease", AccessType.COMPARE_AND_SWAP),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#getAndSet VarHandle.getAndSet}
|
||||
*/
|
||||
GET_AND_SET("getAndSet", AccessType.GET_AND_UPDATE, Object.class),
|
||||
GET_AND_SET("getAndSet", AccessType.GET_AND_UPDATE),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#getAndAdd VarHandle.getAndAdd}
|
||||
*/
|
||||
GET_AND_ADD("getAndAdd", AccessType.GET_AND_UPDATE, Object.class),
|
||||
GET_AND_ADD("getAndAdd", AccessType.GET_AND_UPDATE),
|
||||
/**
|
||||
* The access mode whose access is specified by the corresponding
|
||||
* method
|
||||
* {@link VarHandle#addAndGet VarHandle.addAndGet}
|
||||
*/
|
||||
ADD_AND_GET("addAndGet", AccessType.GET_AND_UPDATE, Object.class),
|
||||
ADD_AND_GET("addAndGet", AccessType.GET_AND_UPDATE),
|
||||
;
|
||||
|
||||
static final Map<String, AccessMode> methodNameToAccessMode;
|
||||
@ -1256,10 +1270,8 @@ public abstract class VarHandle {
|
||||
|
||||
final String methodName;
|
||||
final AccessType at;
|
||||
final boolean isPolyMorphicInReturnType;
|
||||
final Class<?> returnType;
|
||||
|
||||
AccessMode(final String methodName, AccessType at, Class<?> returnType) {
|
||||
AccessMode(final String methodName, AccessType at) {
|
||||
this.methodName = methodName;
|
||||
this.at = at;
|
||||
|
||||
@ -1267,10 +1279,7 @@ public abstract class VarHandle {
|
||||
assert methodName.equals(toMethodName(name()));
|
||||
// Assert that return type is correct
|
||||
// Otherwise, when disabled avoid using reflection
|
||||
assert returnType == getReturnType(methodName);
|
||||
|
||||
this.returnType = returnType;
|
||||
isPolyMorphicInReturnType = returnType != Object.class;
|
||||
assert at.returnType == getReturnType(methodName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1324,17 +1333,21 @@ public abstract class VarHandle {
|
||||
|
||||
@ForceInline
|
||||
static MemberName getMemberName(int ordinal, VarForm vform) {
|
||||
return vform.table[ordinal];
|
||||
return vform.memberName_table[ordinal];
|
||||
}
|
||||
}
|
||||
|
||||
static final class AccessDescriptor {
|
||||
final MethodType symbolicMethodType;
|
||||
final MethodType symbolicMethodTypeErased;
|
||||
final MethodType symbolicMethodTypeInvoker;
|
||||
final Class<?> returnType;
|
||||
final int type;
|
||||
final int mode;
|
||||
|
||||
public AccessDescriptor(MethodType symbolicMethodType, int type, int mode) {
|
||||
this.symbolicMethodType = symbolicMethodType;
|
||||
this.symbolicMethodTypeErased = symbolicMethodType.erase();
|
||||
this.symbolicMethodTypeInvoker = symbolicMethodType.insertParameterTypes(0, VarHandle.class);
|
||||
this.returnType = symbolicMethodType.returnType();
|
||||
this.type = type;
|
||||
this.mode = mode;
|
||||
}
|
||||
@ -1346,6 +1359,7 @@ public abstract class VarHandle {
|
||||
* @return the variable type of variables referenced by this VarHandle
|
||||
*/
|
||||
public final Class<?> varType() {
|
||||
MethodType typeSet = accessModeType(AccessMode.SET);
|
||||
return typeSet.parameterType(typeSet.parameterCount() - 1);
|
||||
}
|
||||
|
||||
@ -1356,6 +1370,7 @@ public abstract class VarHandle {
|
||||
* list is unmodifiable
|
||||
*/
|
||||
public final List<Class<?>> coordinateTypes() {
|
||||
MethodType typeGet = accessModeType(AccessMode.GET);
|
||||
return typeGet.parameterList();
|
||||
}
|
||||
|
||||
@ -1374,9 +1389,15 @@ public abstract class VarHandle {
|
||||
* @return the access mode type for the given access mode
|
||||
*/
|
||||
public final MethodType accessModeType(AccessMode accessMode) {
|
||||
return accessMode.at.getMethodType(this);
|
||||
TypesAndInvokers tis = getTypesAndInvokers();
|
||||
MethodType mt = tis.methodType_table[accessMode.at.ordinal()];
|
||||
if (mt == null) {
|
||||
mt = tis.methodType_table[accessMode.at.ordinal()] =
|
||||
accessModeTypeUncached(accessMode);
|
||||
}
|
||||
return mt;
|
||||
}
|
||||
|
||||
abstract MethodType accessModeTypeUncached(AccessMode accessMode);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the given access mode is supported, otherwise
|
||||
@ -1417,9 +1438,8 @@ public abstract class VarHandle {
|
||||
public final MethodHandle toMethodHandle(AccessMode accessMode) {
|
||||
MemberName mn = AccessMode.getMemberName(accessMode.ordinal(), vform);
|
||||
if (mn != null) {
|
||||
return DirectMethodHandle.make(mn).
|
||||
bindTo(this).
|
||||
asType(accessMode.at.getMethodType(this));
|
||||
MethodHandle mh = getMethodHandle(accessMode.ordinal());
|
||||
return mh.bindTo(this);
|
||||
}
|
||||
else {
|
||||
// Ensure an UnsupportedOperationException is thrown
|
||||
@ -1428,6 +1448,51 @@ public abstract class VarHandle {
|
||||
}
|
||||
}
|
||||
|
||||
@Stable
|
||||
TypesAndInvokers typesAndInvokers;
|
||||
|
||||
static class TypesAndInvokers {
|
||||
final @Stable
|
||||
MethodType[] methodType_table =
|
||||
new MethodType[VarHandle.AccessType.values().length];
|
||||
|
||||
final @Stable
|
||||
MethodHandle[] methodHandle_table =
|
||||
new MethodHandle[AccessMode.values().length];
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
private final TypesAndInvokers getTypesAndInvokers() {
|
||||
TypesAndInvokers tis = typesAndInvokers;
|
||||
if (tis == null) {
|
||||
tis = typesAndInvokers = new TypesAndInvokers();
|
||||
}
|
||||
return tis;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
final MethodHandle getMethodHandle(int mode) {
|
||||
TypesAndInvokers tis = getTypesAndInvokers();
|
||||
MethodHandle mh = tis.methodHandle_table[mode];
|
||||
if (mh == null) {
|
||||
mh = tis.methodHandle_table[mode] = getMethodHandleUncached(tis, mode);
|
||||
}
|
||||
return mh;
|
||||
}
|
||||
private final MethodHandle getMethodHandleUncached(TypesAndInvokers tis, int mode) {
|
||||
MethodType mt = accessModeType(AccessMode.values()[mode]).
|
||||
insertParameterTypes(0, VarHandle.class);
|
||||
MemberName mn = vform.getMemberName(mode);
|
||||
DirectMethodHandle dmh = DirectMethodHandle.make(mn);
|
||||
// Such a method handle must not be publically exposed directly
|
||||
// otherwise it can be cracked, it must be transformed or rebound
|
||||
// before exposure
|
||||
MethodHandle mh = dmh.copyWith(mt, dmh.form);
|
||||
assert mh.type().erase() == mn.getMethodType().erase();
|
||||
return mh;
|
||||
}
|
||||
|
||||
|
||||
/*non-public*/
|
||||
final void updateVarForm(VarForm newVForm) {
|
||||
if (vform == newVForm) return;
|
||||
@ -1453,6 +1518,10 @@ public abstract class VarHandle {
|
||||
catch (ReflectiveOperationException e) {
|
||||
throw newInternalError(e);
|
||||
}
|
||||
|
||||
// The VarHandleGuards must be initialized to ensure correct
|
||||
// compilation of the guard methods
|
||||
UNSAFE.ensureClassInitialized(VarHandleGuards.class);
|
||||
}
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -280,28 +280,29 @@ final class VarHandles {
|
||||
// "@ForceInline\n" +
|
||||
// "@LambdaForm.Compiled\n" +
|
||||
// "final static <METHOD> throws Throwable {\n" +
|
||||
// " MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);\n" +
|
||||
// " MethodType symbolic = ad.symbolicMethodType;\n" +
|
||||
// " if (target == symbolic) {\n" +
|
||||
// " <RETURN>MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);\n" +
|
||||
// " }\n" +
|
||||
// " else if (target.erase() == symbolic.erase()) {\n" +
|
||||
// " if (handle.vform.methodType_table[ad.type] == ad.symbolicMethodType) {\n" +
|
||||
// " <RESULT_ERASED>MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);<RETURN_ERASED>\n" +
|
||||
// " }\n" +
|
||||
// " else {\n" +
|
||||
// " MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);\n" +
|
||||
// " <RETURN>vh_invoker.invokeBasic(<LINK_TO_INVOKER_ARGS>);\n" +
|
||||
// " MethodHandle mh = handle.getMethodHandle(ad.mode);\n" +
|
||||
// " <RETURN>mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(<LINK_TO_INVOKER_ARGS>);\n" +
|
||||
// " }\n" +
|
||||
// "}";
|
||||
//
|
||||
// static final String GET_MEMBER_NAME_METHOD =
|
||||
// static final String GUARD_METHOD_TEMPLATE_V =
|
||||
// "@ForceInline\n" +
|
||||
// "final static MemberName getMemberName(VarHandle handle, VarHandle.AccessDescriptor ad) {\n" +
|
||||
// " MemberName mn = VarHandle.AccessMode.getMemberName(ad.mode, handle.vform);\n" +
|
||||
// " if (mn == null) {\n" +
|
||||
// " throw handle.unsupported();\n" +
|
||||
// "@LambdaForm.Compiled\n" +
|
||||
// "final static <METHOD> throws Throwable {\n" +
|
||||
// " if (handle.vform.methodType_table[ad.type] == ad.symbolicMethodType) {\n" +
|
||||
// " MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);\n" +
|
||||
// " }\n" +
|
||||
// " else if (handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodType) {\n" +
|
||||
// " MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);\n" +
|
||||
// " }\n" +
|
||||
// " else {\n" +
|
||||
// " MethodHandle mh = handle.getMethodHandle(ad.mode);\n" +
|
||||
// " mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(<LINK_TO_INVOKER_ARGS>);\n" +
|
||||
// " }\n" +
|
||||
// " return mn;\n" +
|
||||
// "}";
|
||||
//
|
||||
// // A template for deriving the operations
|
||||
@ -345,8 +346,6 @@ final class VarHandles {
|
||||
// System.out.println("final class VarHandleGuards {");
|
||||
//
|
||||
// System.out.println();
|
||||
// System.out.println(GET_MEMBER_NAME_METHOD);
|
||||
// System.out.println();
|
||||
//
|
||||
// // Declare the stream of shapes
|
||||
// Stream<HandleType> hts = Stream.of(
|
||||
@ -445,7 +444,10 @@ final class VarHandles {
|
||||
//
|
||||
// List<String> LINK_TO_STATIC_ARGS = params.keySet().stream().
|
||||
// collect(toList());
|
||||
// LINK_TO_STATIC_ARGS.add("getMemberName(handle, ad)");
|
||||
// LINK_TO_STATIC_ARGS.add("handle.vform.getMemberName(ad.mode)");
|
||||
// List<String> LINK_TO_STATIC_ARGS_V = params.keySet().stream().
|
||||
// collect(toList());
|
||||
// LINK_TO_STATIC_ARGS_V.add("handle.vform.getMemberName_V(ad.mode)");
|
||||
//
|
||||
// List<String> LINK_TO_INVOKER_ARGS = params.keySet().stream().
|
||||
// collect(toList());
|
||||
@ -464,9 +466,12 @@ final class VarHandles {
|
||||
//
|
||||
// String RETURN_ERASED = returnType != Object.class
|
||||
// ? ""
|
||||
// : " return symbolic.returnType().cast(r);";
|
||||
// : " return ad.returnType.cast(r);";
|
||||
//
|
||||
// return GUARD_METHOD_TEMPLATE.
|
||||
// String template = returnType == void.class
|
||||
// ? GUARD_METHOD_TEMPLATE_V
|
||||
// : GUARD_METHOD_TEMPLATE;
|
||||
// return template.
|
||||
// replace("<METHOD>", METHOD).
|
||||
// replace("<NAME>", NAME).
|
||||
// replaceAll("<RETURN>", RETURN).
|
||||
@ -474,6 +479,8 @@ final class VarHandles {
|
||||
// replace("<RETURN_ERASED>", RETURN_ERASED).
|
||||
// replaceAll("<LINK_TO_STATIC_ARGS>", LINK_TO_STATIC_ARGS.stream().
|
||||
// collect(joining(", "))).
|
||||
// replaceAll("<LINK_TO_STATIC_ARGS_V>", LINK_TO_STATIC_ARGS_V.stream().
|
||||
// collect(joining(", "))).
|
||||
// replace("<LINK_TO_INVOKER_ARGS>", LINK_TO_INVOKER_ARGS.stream().
|
||||
// collect(joining(", ")))
|
||||
// ;
|
||||
|
@ -41,12 +41,12 @@ final class VarHandle$Type$s {
|
||||
#end[Object]
|
||||
|
||||
FieldInstanceReadOnly(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
|
||||
this(receiverType, fieldOffset{#if[Object]?, fieldType}, FieldInstanceReadOnly.class);
|
||||
this(receiverType, fieldOffset{#if[Object]?, fieldType}, FieldInstanceReadOnly.FORM);
|
||||
}
|
||||
|
||||
protected FieldInstanceReadOnly(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType},
|
||||
Class<? extends FieldInstanceReadOnly> handle) {
|
||||
super(VarForm.createFromStatic(handle), receiverType, {#if[Object]?fieldType:$type$.class});
|
||||
VarForm form) {
|
||||
super(form);
|
||||
this.fieldOffset = fieldOffset;
|
||||
this.receiverType = receiverType;
|
||||
#if[Object]
|
||||
@ -54,6 +54,11 @@ final class VarHandle$Type$s {
|
||||
#end[Object]
|
||||
}
|
||||
|
||||
@Override
|
||||
final MethodType accessModeTypeUncached(AccessMode accessMode) {
|
||||
return accessMode.at.accessModeType(receiverType, {#if[Object]?fieldType:$type$.class});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ get(FieldInstanceReadOnly handle, Object holder) {
|
||||
return UNSAFE.get$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
@ -77,12 +82,14 @@ final class VarHandle$Type$s {
|
||||
return UNSAFE.get$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset);
|
||||
}
|
||||
|
||||
static final VarForm FORM = new VarForm(FieldInstanceReadOnly.class, Object.class, $type$.class);
|
||||
}
|
||||
|
||||
static class FieldInstanceReadWrite extends FieldInstanceReadOnly {
|
||||
static final class FieldInstanceReadWrite extends FieldInstanceReadOnly {
|
||||
|
||||
FieldInstanceReadWrite(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
|
||||
super(receiverType, fieldOffset{#if[Object]?, fieldType}, FieldInstanceReadWrite.class);
|
||||
super(receiverType, fieldOffset{#if[Object]?, fieldType}, FieldInstanceReadWrite.FORM);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
@ -202,6 +209,8 @@ final class VarHandle$Type$s {
|
||||
value) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
|
||||
static final VarForm FORM = new VarForm(FieldInstanceReadWrite.class, Object.class, $type$.class);
|
||||
}
|
||||
|
||||
|
||||
@ -213,12 +222,12 @@ final class VarHandle$Type$s {
|
||||
#end[Object]
|
||||
|
||||
FieldStaticReadOnly(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
|
||||
this(base, fieldOffset{#if[Object]?, fieldType}, FieldStaticReadOnly.class);
|
||||
this(base, fieldOffset{#if[Object]?, fieldType}, FieldStaticReadOnly.FORM);
|
||||
}
|
||||
|
||||
protected FieldStaticReadOnly(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType},
|
||||
Class<? extends FieldStaticReadOnly> handle) {
|
||||
super(VarForm.createFromStatic(handle), null, {#if[Object]?fieldType:$type$.class});
|
||||
VarForm form) {
|
||||
super(form);
|
||||
this.base = base;
|
||||
this.fieldOffset = fieldOffset;
|
||||
#if[Object]
|
||||
@ -226,6 +235,11 @@ final class VarHandle$Type$s {
|
||||
#end[Object]
|
||||
}
|
||||
|
||||
@Override
|
||||
final MethodType accessModeTypeUncached(AccessMode accessMode) {
|
||||
return accessMode.at.accessModeType(null, {#if[Object]?fieldType:$type$.class});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ get(FieldStaticReadOnly handle) {
|
||||
return UNSAFE.get$Type$(handle.base,
|
||||
@ -249,12 +263,14 @@ final class VarHandle$Type$s {
|
||||
return UNSAFE.get$Type$Acquire(handle.base,
|
||||
handle.fieldOffset);
|
||||
}
|
||||
|
||||
static final VarForm FORM = new VarForm(FieldStaticReadOnly.class, null, $type$.class);
|
||||
}
|
||||
|
||||
static class FieldStaticReadWrite extends FieldStaticReadOnly {
|
||||
static final class FieldStaticReadWrite extends FieldStaticReadOnly {
|
||||
|
||||
FieldStaticReadWrite(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
|
||||
super(base, fieldOffset{#if[Object]?, fieldType}, FieldStaticReadWrite.class);
|
||||
super(base, fieldOffset{#if[Object]?, fieldType}, FieldStaticReadWrite.FORM);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
@ -375,6 +391,8 @@ final class VarHandle$Type$s {
|
||||
value) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
|
||||
static final VarForm FORM = new VarForm(FieldStaticReadWrite.class, null, $type$.class);
|
||||
}
|
||||
|
||||
|
||||
@ -387,8 +405,7 @@ final class VarHandle$Type$s {
|
||||
#end[Object]
|
||||
|
||||
Array(int abase, int ashift{#if[Object]?, Class<?> arrayType}) {
|
||||
super(VarForm.createFromStatic(Array.class),
|
||||
{#if[Object]?arrayType:$type$[].class}, {#if[Object]?arrayType.getComponentType():$type$.class}, int.class);
|
||||
super(Array.FORM);
|
||||
this.abase = abase;
|
||||
this.ashift = ashift;
|
||||
#if[Object]
|
||||
@ -397,6 +414,11 @@ final class VarHandle$Type$s {
|
||||
#end[Object]
|
||||
}
|
||||
|
||||
@Override
|
||||
final MethodType accessModeTypeUncached(AccessMode accessMode) {
|
||||
return accessMode.at.accessModeType({#if[Object]?arrayType:$type$[].class}, {#if[Object]?arrayType.getComponentType():$type$.class}, int.class);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ get(Array handle, Object oarray, int index) {
|
||||
#if[Object]
|
||||
@ -630,5 +652,7 @@ final class VarHandle$Type$s {
|
||||
value) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
|
||||
static final VarForm FORM = new VarForm(Array.class, {#if[Object]?Object[].class:$type$[].class}, {#if[Object]?Object.class:$type$.class}, int.class);
|
||||
}
|
||||
}
|
||||
|
@ -59,13 +59,11 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
|
||||
#end[floatingPoint]
|
||||
|
||||
|
||||
private static class ByteArrayViewVarHandle extends VarHandle {
|
||||
private static abstract class ByteArrayViewVarHandle extends VarHandle {
|
||||
final boolean be;
|
||||
|
||||
ByteArrayViewVarHandle(Class<? extends ByteArrayViewVarHandle> implSubType,
|
||||
Class<?> arrayType, Class<?> component, boolean be) {
|
||||
super(VarForm.createFromStatic(implSubType),
|
||||
arrayType, component, int.class);
|
||||
ByteArrayViewVarHandle(VarForm form, boolean be) {
|
||||
super(form);
|
||||
this.be = be;
|
||||
}
|
||||
}
|
||||
@ -73,7 +71,12 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
|
||||
static final class ArrayHandle extends ByteArrayViewVarHandle {
|
||||
|
||||
ArrayHandle(boolean be) {
|
||||
super(ArrayHandle.class, byte[].class, $type$.class, be);
|
||||
super(ArrayHandle.FORM, be);
|
||||
}
|
||||
|
||||
@Override
|
||||
final MethodType accessModeTypeUncached(AccessMode accessMode) {
|
||||
return accessMode.at.accessModeType(byte[].class, $type$.class, int.class);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
@ -286,13 +289,20 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
|
||||
convEndian(handle.be, value))) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
|
||||
static final VarForm FORM = new VarForm(ArrayHandle.class, byte[].class, $type$.class, int.class);
|
||||
}
|
||||
|
||||
|
||||
static final class ByteBufferHandle extends ByteArrayViewVarHandle {
|
||||
|
||||
ByteBufferHandle(boolean be) {
|
||||
super(ByteBufferHandle.class, ByteBuffer.class, $type$.class, be);
|
||||
super(ByteBufferHandle.FORM, be);
|
||||
}
|
||||
|
||||
@Override
|
||||
final MethodType accessModeTypeUncached(AccessMode accessMode) {
|
||||
return accessMode.at.accessModeType(ByteBuffer.class, $type$.class, int.class);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
@ -513,5 +523,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
|
||||
convEndian(handle.be, value))) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
|
||||
static final VarForm FORM = new VarForm(ByteBufferHandle.class, ByteBuffer.class, $type$.class, int.class);
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package java.lang.module;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@ -183,17 +184,20 @@ public final class Configuration {
|
||||
this.nameToModule = Collections.emptyMap();
|
||||
}
|
||||
|
||||
private Configuration(Configuration parent, Resolver resolver) {
|
||||
Map<ResolvedModule, Set<ResolvedModule>> graph = resolver.finish(this);
|
||||
private Configuration(Configuration parent,
|
||||
Resolver resolver,
|
||||
boolean check)
|
||||
{
|
||||
Map<ResolvedModule, Set<ResolvedModule>> g = resolver.finish(this, check);
|
||||
|
||||
Map<String, ResolvedModule> nameToModule = new HashMap<>();
|
||||
for (ResolvedModule resolvedModule : graph.keySet()) {
|
||||
for (ResolvedModule resolvedModule : g.keySet()) {
|
||||
nameToModule.put(resolvedModule.name(), resolvedModule);
|
||||
}
|
||||
|
||||
this.parent = parent;
|
||||
this.graph = graph;
|
||||
this.modules = Collections.unmodifiableSet(graph.keySet());
|
||||
this.graph = g;
|
||||
this.modules = Collections.unmodifiableSet(g.keySet());
|
||||
this.nameToModule = Collections.unmodifiableMap(nameToModule);
|
||||
}
|
||||
|
||||
@ -283,10 +287,10 @@ public final class Configuration {
|
||||
Objects.requireNonNull(after);
|
||||
Objects.requireNonNull(roots);
|
||||
|
||||
Resolver resolver = new Resolver(before, this, after);
|
||||
Resolver resolver = new Resolver(before, this, after, null);
|
||||
resolver.resolveRequires(roots);
|
||||
|
||||
return new Configuration(this, resolver);
|
||||
return new Configuration(this, resolver, true);
|
||||
}
|
||||
|
||||
|
||||
@ -340,10 +344,32 @@ public final class Configuration {
|
||||
Objects.requireNonNull(after);
|
||||
Objects.requireNonNull(roots);
|
||||
|
||||
Resolver resolver = new Resolver(before, this, after);
|
||||
Resolver resolver = new Resolver(before, this, after, null);
|
||||
resolver.resolveRequires(roots).resolveUses();
|
||||
|
||||
return new Configuration(this, resolver);
|
||||
return new Configuration(this, resolver, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resolves a collection of root modules, with service binding, and with
|
||||
* the empty configuration as its parent. The post resolution checks
|
||||
* are optionally run.
|
||||
*
|
||||
* This method is used to create the configuration for the boot layer.
|
||||
*/
|
||||
static Configuration resolveRequiresAndUses(ModuleFinder finder,
|
||||
Collection<String> roots,
|
||||
boolean check,
|
||||
PrintStream traceOutput)
|
||||
{
|
||||
Configuration parent = empty();
|
||||
|
||||
Resolver resolver
|
||||
= new Resolver(finder, parent, ModuleFinder.empty(), traceOutput);
|
||||
resolver.resolveRequires(roots).resolveUses();
|
||||
|
||||
return new Configuration(parent, resolver, check);
|
||||
}
|
||||
|
||||
|
||||
|
@ -27,13 +27,17 @@ package java.lang.module;
|
||||
|
||||
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.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
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;
|
||||
@ -45,7 +49,7 @@ import static jdk.internal.module.Checks.*;
|
||||
import static java.util.Objects.*;
|
||||
|
||||
import jdk.internal.module.Checks;
|
||||
import jdk.internal.module.Hasher.DependencyHashes;
|
||||
import jdk.internal.module.ModuleHashes;
|
||||
|
||||
|
||||
/**
|
||||
@ -372,8 +376,9 @@ public class ModuleDescriptor
|
||||
|
||||
private Provides(String service, Set<String> providers, boolean check) {
|
||||
this.service = check ? requireServiceTypeName(service) : service;
|
||||
providers = check ? Collections.unmodifiableSet(new HashSet<>(providers))
|
||||
: Collections.unmodifiableSet(providers);
|
||||
providers = check
|
||||
? Collections.unmodifiableSet(new LinkedHashSet<>(providers))
|
||||
: Collections.unmodifiableSet(providers);
|
||||
if (providers.isEmpty())
|
||||
throw new IllegalArgumentException("Empty providers set");
|
||||
if (check)
|
||||
@ -787,7 +792,7 @@ public class ModuleDescriptor
|
||||
private final String osVersion;
|
||||
private final Set<String> conceals;
|
||||
private final Set<String> packages;
|
||||
private final DependencyHashes hashes;
|
||||
private final ModuleHashes hashes;
|
||||
|
||||
private ModuleDescriptor(String name,
|
||||
boolean automatic,
|
||||
@ -802,7 +807,7 @@ public class ModuleDescriptor
|
||||
String osArch,
|
||||
String osVersion,
|
||||
Set<String> conceals,
|
||||
DependencyHashes hashes)
|
||||
ModuleHashes hashes)
|
||||
{
|
||||
|
||||
this.name = name;
|
||||
@ -878,7 +883,8 @@ public class ModuleDescriptor
|
||||
String osArch,
|
||||
String osVersion,
|
||||
Set<String> conceals,
|
||||
Set<String> packages) {
|
||||
Set<String> packages,
|
||||
ModuleHashes hashes) {
|
||||
this.name = name;
|
||||
this.automatic = automatic;
|
||||
this.synthetic = synthetic;
|
||||
@ -894,7 +900,7 @@ public class ModuleDescriptor
|
||||
this.osName = osName;
|
||||
this.osArch = osArch;
|
||||
this.osVersion = osVersion;
|
||||
this.hashes = null;
|
||||
this.hashes = hashes;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1063,9 +1069,9 @@ public class ModuleDescriptor
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object with the hashes of the dependences.
|
||||
* Returns the object with the hashes of other modules
|
||||
*/
|
||||
Optional<DependencyHashes> hashes() {
|
||||
Optional<ModuleHashes> hashes() {
|
||||
return Optional.ofNullable(hashes);
|
||||
}
|
||||
|
||||
@ -1103,7 +1109,7 @@ public class ModuleDescriptor
|
||||
String osArch;
|
||||
String osVersion;
|
||||
String mainClass;
|
||||
DependencyHashes hashes;
|
||||
ModuleHashes hashes;
|
||||
|
||||
/**
|
||||
* Initializes a new builder with the given module name.
|
||||
@ -1580,7 +1586,7 @@ public class ModuleDescriptor
|
||||
return this;
|
||||
}
|
||||
|
||||
/* package */ Builder hashes(DependencyHashes hashes) {
|
||||
/* package */ Builder hashes(ModuleHashes hashes) {
|
||||
this.hashes = hashes;
|
||||
return this;
|
||||
}
|
||||
@ -1719,7 +1725,9 @@ public class ModuleDescriptor
|
||||
hc = hc * 43 + Objects.hashCode(osVersion);
|
||||
hc = hc * 43 + Objects.hashCode(conceals);
|
||||
hc = hc * 43 + Objects.hashCode(hashes);
|
||||
if (hc != 0) hash = hc;
|
||||
if (hc == 0)
|
||||
hc = -1;
|
||||
hash = hc;
|
||||
}
|
||||
return hc;
|
||||
}
|
||||
@ -1925,11 +1933,12 @@ public class ModuleDescriptor
|
||||
|
||||
static {
|
||||
/**
|
||||
* Setup the shared secret to allow code in other packages create
|
||||
* ModuleDescriptor and associated objects directly.
|
||||
* Setup the shared secret to allow code in other packages access
|
||||
* private package methods in java.lang.module.
|
||||
*/
|
||||
jdk.internal.misc.SharedSecrets
|
||||
.setJavaLangModuleAccess(new jdk.internal.misc.JavaLangModuleAccess() {
|
||||
|
||||
@Override
|
||||
public Requires newRequires(Set<Requires.Modifier> ms, String mn) {
|
||||
return new Requires(ms, mn, false);
|
||||
@ -1974,7 +1983,8 @@ public class ModuleDescriptor
|
||||
String osArch,
|
||||
String osVersion,
|
||||
Set<String> conceals,
|
||||
Set<String> packages) {
|
||||
Set<String> packages,
|
||||
ModuleHashes hashes) {
|
||||
return new ModuleDescriptor(name,
|
||||
automatic,
|
||||
synthetic,
|
||||
@ -1988,7 +1998,29 @@ public class ModuleDescriptor
|
||||
osArch,
|
||||
osVersion,
|
||||
conceals,
|
||||
packages);
|
||||
packages,
|
||||
hashes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Configuration resolveRequiresAndUses(ModuleFinder finder,
|
||||
Collection<String> roots,
|
||||
boolean check,
|
||||
PrintStream traceOutput)
|
||||
{
|
||||
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 Optional<ModuleHashes> hashes(ModuleDescriptor descriptor) {
|
||||
return descriptor.hashes();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -37,11 +37,12 @@ import java.nio.BufferUnderflowException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import jdk.internal.module.Hasher.DependencyHashes;
|
||||
import jdk.internal.module.ModuleHashes;
|
||||
|
||||
import static jdk.internal.module.ClassFileConstants.*;
|
||||
|
||||
@ -337,7 +338,7 @@ final class ModuleInfo {
|
||||
// computeIfAbsent
|
||||
Set<String> providers = pm.get(sn);
|
||||
if (providers == null) {
|
||||
providers = new HashSet<>();
|
||||
providers = new LinkedHashSet<>(); // preserve order
|
||||
pm.put(sn, providers);
|
||||
}
|
||||
providers.add(cn);
|
||||
@ -425,7 +426,7 @@ final class ModuleInfo {
|
||||
map.put(dn, hash);
|
||||
}
|
||||
|
||||
builder.hashes(new DependencyHashes(algorithm, map));
|
||||
builder.hashes(new ModuleHashes(algorithm, map));
|
||||
}
|
||||
|
||||
|
||||
|
@ -40,7 +40,7 @@ import java.nio.file.Path;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
@ -52,7 +52,6 @@ import java.util.jar.Manifest;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
@ -190,18 +189,16 @@ class ModulePath implements ConfigurableModuleFinder {
|
||||
}
|
||||
}
|
||||
|
||||
if (attrs.isRegularFile() || attrs.isDirectory()) {
|
||||
// packaged or exploded module
|
||||
ModuleReference mref = readModule(entry, attrs);
|
||||
if (mref != null) {
|
||||
String name = mref.descriptor().name();
|
||||
return Collections.singletonMap(name, mref);
|
||||
}
|
||||
// packaged or exploded module
|
||||
ModuleReference mref = readModule(entry, attrs);
|
||||
if (mref != null) {
|
||||
String name = mref.descriptor().name();
|
||||
return Collections.singletonMap(name, mref);
|
||||
} else {
|
||||
// skipped
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
// not recognized
|
||||
throw new FindException("Unrecognized module: " + entry);
|
||||
|
||||
} catch (IOException ioe) {
|
||||
throw new FindException(ioe);
|
||||
}
|
||||
@ -238,16 +235,13 @@ class ModulePath implements ConfigurableModuleFinder {
|
||||
|
||||
// module found
|
||||
if (mref != null) {
|
||||
|
||||
// can have at most one version of a module in the directory
|
||||
String name = mref.descriptor().name();
|
||||
if (nameToReference.put(name, mref) != null) {
|
||||
throw new FindException("Two versions of module "
|
||||
+ name + " found in " + dir);
|
||||
+ name + " found in " + dir);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,28 +251,40 @@ class ModulePath implements ConfigurableModuleFinder {
|
||||
|
||||
/**
|
||||
* Locates a packaged or exploded module, returning a {@code ModuleReference}
|
||||
* to the module. Returns {@code null} if the module is not recognized
|
||||
* as a packaged or exploded module.
|
||||
* to the module. Returns {@code null} if the entry is skipped because it is
|
||||
* to a directory that does not contain a module-info.class or it's a hidden
|
||||
* file.
|
||||
*
|
||||
* @throws IOException if an I/O error occurs
|
||||
* @throws FindException if an error occurs parsing the module descriptor
|
||||
* @throws FindException if the file is not recognized as a module or an
|
||||
* error occurs parsing its module descriptor
|
||||
*/
|
||||
private ModuleReference readModule(Path entry, BasicFileAttributes attrs)
|
||||
throws IOException
|
||||
{
|
||||
try {
|
||||
|
||||
ModuleReference mref = null;
|
||||
if (attrs.isDirectory()) {
|
||||
mref = readExplodedModule(entry);
|
||||
} if (attrs.isRegularFile()) {
|
||||
if (entry.toString().endsWith(".jar")) {
|
||||
mref = readJar(entry);
|
||||
} else if (isLinkPhase && entry.toString().endsWith(".jmod")) {
|
||||
mref = readJMod(entry);
|
||||
return readExplodedModule(entry); // may return null
|
||||
}
|
||||
|
||||
String fn = entry.getFileName().toString();
|
||||
if (attrs.isRegularFile()) {
|
||||
if (fn.endsWith(".jar")) {
|
||||
return readJar(entry);
|
||||
} else if (fn.endsWith(".jmod")) {
|
||||
if (isLinkPhase)
|
||||
return readJMod(entry);
|
||||
throw new FindException("JMOD files not supported: " + entry);
|
||||
}
|
||||
}
|
||||
return mref;
|
||||
|
||||
// skip hidden files
|
||||
if (fn.startsWith(".") || Files.isHidden(entry)) {
|
||||
return null;
|
||||
} else {
|
||||
throw new FindException("Unrecognized module: " + entry);
|
||||
}
|
||||
|
||||
} catch (InvalidModuleDescriptorException e) {
|
||||
throw new FindException("Error reading module: " + entry, e);
|
||||
@ -292,15 +298,17 @@ class ModulePath implements ConfigurableModuleFinder {
|
||||
return zf.stream()
|
||||
.filter(e -> e.getName().startsWith("classes/") &&
|
||||
e.getName().endsWith(".class"))
|
||||
.map(e -> toPackageName(e))
|
||||
.map(e -> toPackageName(e.getName().substring(8)))
|
||||
.filter(pkg -> pkg.length() > 0) // module-info
|
||||
.distinct()
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code ModuleReference} to a module in jmod file on the
|
||||
* file system.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws InvalidModuleDescriptorException
|
||||
*/
|
||||
private ModuleReference readJMod(Path file) throws IOException {
|
||||
try (ZipFile zf = new ZipFile(file.toString())) {
|
||||
@ -419,13 +427,12 @@ class ModulePath implements ConfigurableModuleFinder {
|
||||
|
||||
// scan the entries in the JAR file to locate the .class and service
|
||||
// configuration file
|
||||
Stream<String> stream = jf.stream()
|
||||
.map(e -> e.getName())
|
||||
.filter(e -> (e.endsWith(".class") || e.startsWith(SERVICES_PREFIX)))
|
||||
.distinct();
|
||||
Map<Boolean, Set<String>> map
|
||||
= stream.collect(Collectors.partitioningBy(s -> s.endsWith(".class"),
|
||||
Collectors.toSet()));
|
||||
Map<Boolean, Set<String>> map =
|
||||
jf.stream()
|
||||
.map(JarEntry::getName)
|
||||
.filter(s -> (s.endsWith(".class") ^ s.startsWith(SERVICES_PREFIX)))
|
||||
.collect(Collectors.partitioningBy(s -> s.endsWith(".class"),
|
||||
Collectors.toSet()));
|
||||
Set<String> classFiles = map.get(Boolean.TRUE);
|
||||
Set<String> configFiles = map.get(Boolean.FALSE);
|
||||
|
||||
@ -433,19 +440,18 @@ class ModulePath implements ConfigurableModuleFinder {
|
||||
classFiles.stream()
|
||||
.map(c -> toPackageName(c))
|
||||
.distinct()
|
||||
.forEach(p -> builder.exports(p));
|
||||
.forEach(builder::exports);
|
||||
|
||||
// map names of service configuration files to service names
|
||||
Set<String> serviceNames = configFiles.stream()
|
||||
.map(this::toServiceName)
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
.flatMap(Optional::stream)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// parse each service configuration file
|
||||
for (String sn : serviceNames) {
|
||||
JarEntry entry = jf.getJarEntry(SERVICES_PREFIX + sn);
|
||||
Set<String> providerClasses = new HashSet<>();
|
||||
Set<String> providerClasses = new LinkedHashSet<>();
|
||||
try (InputStream in = jf.getInputStream(entry)) {
|
||||
BufferedReader reader
|
||||
= new BufferedReader(new InputStreamReader(in, "UTF-8"));
|
||||
@ -475,19 +481,25 @@ class ModulePath implements ConfigurableModuleFinder {
|
||||
private Set<String> jarPackages(JarFile jf) {
|
||||
return jf.stream()
|
||||
.filter(e -> e.getName().endsWith(".class"))
|
||||
.map(e -> toPackageName(e))
|
||||
.map(e -> toPackageName(e.getName()))
|
||||
.filter(pkg -> pkg.length() > 0) // module-info
|
||||
.distinct()
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code ModuleReference} to a module in modular JAR file on
|
||||
* the file system.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws FindException
|
||||
* @throws InvalidModuleDescriptorException
|
||||
*/
|
||||
private ModuleReference readJar(Path file) throws IOException {
|
||||
try (JarFile jf = new JarFile(file.toString())) {
|
||||
|
||||
try (JarFile jf = new JarFile(file.toFile(),
|
||||
true, // verify
|
||||
ZipFile.OPEN_READ,
|
||||
JarFile.Release.RUNTIME))
|
||||
{
|
||||
ModuleDescriptor md;
|
||||
JarEntry entry = jf.getJarEntry(MODULE_INFO);
|
||||
if (entry == null) {
|
||||
@ -520,7 +532,6 @@ class ModulePath implements ConfigurableModuleFinder {
|
||||
path.toString().endsWith(".class")))
|
||||
.map(path -> toPackageName(dir.relativize(path)))
|
||||
.filter(pkg -> pkg.length() > 0) // module-info
|
||||
.distinct()
|
||||
.collect(Collectors.toSet());
|
||||
} catch (IOException x) {
|
||||
throw new UncheckedIOException(x);
|
||||
@ -530,6 +541,9 @@ class ModulePath implements ConfigurableModuleFinder {
|
||||
/**
|
||||
* Returns a {@code ModuleReference} to an exploded module on the file
|
||||
* system or {@code null} if {@code module-info.class} not found.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws InvalidModuleDescriptorException
|
||||
*/
|
||||
private ModuleReference readExplodedModule(Path dir) throws IOException {
|
||||
Path mi = dir.resolve(MODULE_INFO);
|
||||
@ -559,19 +573,6 @@ class ModulePath implements ConfigurableModuleFinder {
|
||||
}
|
||||
}
|
||||
|
||||
private String toPackageName(ZipEntry entry) {
|
||||
String name = entry.getName();
|
||||
assert name.endsWith(".class");
|
||||
// jmod classes in classes/, jar in /
|
||||
int start = name.startsWith("classes/") ? 8 : 0;
|
||||
int index = name.lastIndexOf("/");
|
||||
if (index > start) {
|
||||
return name.substring(start, index).replace('/', '.');
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private String toPackageName(Path path) {
|
||||
String name = path.toString();
|
||||
assert name.endsWith(".class");
|
||||
|
@ -142,10 +142,11 @@ public interface ModuleReader extends Closeable {
|
||||
* @see ClassLoader#defineClass(String, ByteBuffer, java.security.ProtectionDomain)
|
||||
*/
|
||||
default Optional<ByteBuffer> read(String name) throws IOException {
|
||||
Optional<InputStream> in = open(name);
|
||||
if (in.isPresent()) {
|
||||
byte[] bytes = in.get().readAllBytes();
|
||||
return Optional.of(ByteBuffer.wrap(bytes));
|
||||
Optional<InputStream> oin = open(name);
|
||||
if (oin.isPresent()) {
|
||||
try (InputStream in = oin.get()) {
|
||||
return Optional.of(ByteBuffer.wrap(in.readAllBytes()));
|
||||
}
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2015, 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
|
||||
@ -32,7 +32,7 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import jdk.internal.module.Hasher.HashSupplier;
|
||||
import jdk.internal.module.ModuleHashes.HashSupplier;
|
||||
|
||||
|
||||
/**
|
||||
@ -54,12 +54,33 @@ public final class ModuleReference {
|
||||
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 string to avoid needing to compute it many times
|
||||
private String 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.
|
||||
*/
|
||||
@ -67,11 +88,9 @@ public final class ModuleReference {
|
||||
URI location,
|
||||
Supplier<ModuleReader> readerSupplier,
|
||||
HashSupplier hasher)
|
||||
|
||||
{
|
||||
this.descriptor = Objects.requireNonNull(descriptor);
|
||||
this.location = location;
|
||||
this.readerSupplier = Objects.requireNonNull(readerSupplier);
|
||||
this.hasher = hasher;
|
||||
this(descriptor, location, readerSupplier, false, hasher);
|
||||
}
|
||||
|
||||
|
||||
@ -96,10 +115,9 @@ public final class ModuleReference {
|
||||
URI location,
|
||||
Supplier<ModuleReader> readerSupplier)
|
||||
{
|
||||
this(descriptor, location, readerSupplier, null);
|
||||
this(descriptor, location, readerSupplier, false, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the module descriptor.
|
||||
*
|
||||
@ -150,6 +168,20 @@ public final class ModuleReference {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this module has been patched via -Xpatch.
|
||||
*/
|
||||
boolean isPatched() {
|
||||
return patched;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hash supplier for this module.
|
||||
*/
|
||||
HashSupplier hasher() {
|
||||
return hasher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the hash of this module, returning it as a hex string.
|
||||
* Returns {@code null} if the hash cannot be computed.
|
||||
@ -166,8 +198,6 @@ public final class ModuleReference {
|
||||
return result;
|
||||
}
|
||||
|
||||
private int hash;
|
||||
|
||||
/**
|
||||
* Computes a hash code for this module reference.
|
||||
*
|
||||
@ -181,12 +211,17 @@ public final class ModuleReference {
|
||||
public int hashCode() {
|
||||
int hc = hash;
|
||||
if (hc == 0) {
|
||||
hc = Objects.hash(descriptor, location, readerSupplier, hasher);
|
||||
if (hc != 0) hash = hc;
|
||||
hc = Objects.hash(descriptor, location, readerSupplier, hasher,
|
||||
Boolean.valueOf(patched));
|
||||
if (hc == 0)
|
||||
hc = -1;
|
||||
hash = hc;
|
||||
}
|
||||
return hc;
|
||||
}
|
||||
|
||||
private int hash;
|
||||
|
||||
/**
|
||||
* Tests this module reference for equality with the given object.
|
||||
*
|
||||
@ -214,7 +249,8 @@ public final class ModuleReference {
|
||||
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);
|
||||
&& Objects.equals(this.hasher, that.hasher)
|
||||
&& this.patched == that.patched;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,8 +48,8 @@ import java.util.zip.ZipFile;
|
||||
|
||||
import jdk.internal.misc.JavaLangAccess;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import jdk.internal.module.Hasher;
|
||||
import jdk.internal.module.Hasher.HashSupplier;
|
||||
import jdk.internal.module.ModuleHashes;
|
||||
import jdk.internal.module.ModuleHashes.HashSupplier;
|
||||
import jdk.internal.module.ModulePatcher;
|
||||
import sun.net.www.ParseUtil;
|
||||
|
||||
@ -89,7 +89,7 @@ class ModuleReferences {
|
||||
static ModuleReference newJarModule(ModuleDescriptor md, Path file) {
|
||||
URI uri = file.toUri();
|
||||
Supplier<ModuleReader> supplier = () -> new JarModuleReader(file, uri);
|
||||
HashSupplier hasher = (algorithm) -> Hasher.generate(file, algorithm);
|
||||
HashSupplier hasher = (a) -> ModuleHashes.computeHashAsString(file, a);
|
||||
return newModule(md, uri, supplier, hasher);
|
||||
}
|
||||
|
||||
@ -99,7 +99,7 @@ class ModuleReferences {
|
||||
static ModuleReference newJModModule(ModuleDescriptor md, Path file) {
|
||||
URI uri = file.toUri();
|
||||
Supplier<ModuleReader> supplier = () -> new JModModuleReader(file, uri);
|
||||
HashSupplier hasher = (algorithm) -> Hasher.generate(file, algorithm);
|
||||
HashSupplier hasher = (a) -> ModuleHashes.computeHashAsString(file, a);
|
||||
return newModule(md, file.toUri(), supplier, hasher);
|
||||
}
|
||||
|
||||
@ -122,7 +122,7 @@ class ModuleReferences {
|
||||
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
private final Lock readLock = lock.readLock();
|
||||
private final Lock writeLock = lock.writeLock();
|
||||
private volatile boolean closed;
|
||||
private boolean closed;
|
||||
|
||||
SafeCloseModuleReader() { }
|
||||
|
||||
@ -198,7 +198,10 @@ class ModuleReferences {
|
||||
|
||||
static JarFile newJarFile(Path path) {
|
||||
try {
|
||||
return new JarFile(path.toFile());
|
||||
return new JarFile(path.toFile(),
|
||||
true, // verify
|
||||
ZipFile.OPEN_READ,
|
||||
JarFile.Release.RUNTIME);
|
||||
} catch (IOException ioe) {
|
||||
throw new UncheckedIOException(ioe);
|
||||
}
|
||||
@ -219,6 +222,8 @@ class ModuleReferences {
|
||||
if (je != null) {
|
||||
String encodedPath = ParseUtil.encodePath(name, false);
|
||||
String uris = "jar:" + uri + "!/" + encodedPath;
|
||||
if (jf.isMultiRelease())
|
||||
uris += "#runtime";
|
||||
return Optional.of(URI.create(uris));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
|
@ -25,8 +25,8 @@
|
||||
|
||||
package java.lang.module;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.lang.module.ModuleDescriptor.Requires.Modifier;
|
||||
import java.lang.reflect.Layer;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@ -43,7 +43,7 @@ import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jdk.internal.module.Hasher;
|
||||
import jdk.internal.module.ModuleHashes;
|
||||
|
||||
/**
|
||||
* The resolver used by {@link Configuration#resolveRequires} and
|
||||
@ -55,6 +55,7 @@ final class Resolver {
|
||||
private final ModuleFinder beforeFinder;
|
||||
private final Configuration parent;
|
||||
private final ModuleFinder afterFinder;
|
||||
private final PrintStream traceOutput;
|
||||
|
||||
// maps module name to module reference
|
||||
private final Map<String, ModuleReference> nameToReference = new HashMap<>();
|
||||
@ -62,10 +63,12 @@ final class Resolver {
|
||||
|
||||
Resolver(ModuleFinder beforeFinder,
|
||||
Configuration parent,
|
||||
ModuleFinder afterFinder) {
|
||||
ModuleFinder afterFinder,
|
||||
PrintStream traceOutput) {
|
||||
this.beforeFinder = beforeFinder;
|
||||
this.parent = parent;
|
||||
this.afterFinder = afterFinder;
|
||||
this.traceOutput = traceOutput;
|
||||
}
|
||||
|
||||
|
||||
@ -76,8 +79,6 @@ final class Resolver {
|
||||
*/
|
||||
Resolver resolveRequires(Collection<String> roots) {
|
||||
|
||||
long start = trace_start("Resolve");
|
||||
|
||||
// create the visit stack to get us started
|
||||
Deque<ModuleDescriptor> q = new ArrayDeque<>();
|
||||
for (String root : roots) {
|
||||
@ -95,10 +96,9 @@ final class Resolver {
|
||||
}
|
||||
}
|
||||
|
||||
if (TRACE) {
|
||||
if (isTracing()) {
|
||||
trace("Root module %s located", root);
|
||||
if (mref.location().isPresent())
|
||||
trace(" (%s)", mref.location().get());
|
||||
mref.location().ifPresent(uri -> trace(" (%s)", uri));
|
||||
}
|
||||
|
||||
assert mref.descriptor().name().equals(root);
|
||||
@ -108,13 +108,6 @@ final class Resolver {
|
||||
|
||||
resolve(q);
|
||||
|
||||
if (TRACE) {
|
||||
long duration = System.currentTimeMillis() - start;
|
||||
Set<String> names = nameToReference.keySet();
|
||||
trace("Resolver completed in %s ms", duration);
|
||||
names.stream().sorted().forEach(name -> trace(" %s", name));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -153,11 +146,10 @@ final class Resolver {
|
||||
q.offer(mref.descriptor());
|
||||
resolved.add(mref.descriptor());
|
||||
|
||||
if (TRACE) {
|
||||
if (isTracing()) {
|
||||
trace("Module %s located, required by %s",
|
||||
dn, descriptor.name());
|
||||
if (mref.location().isPresent())
|
||||
trace(" (%s)", mref.location().get());
|
||||
mref.location().ifPresent(uri -> trace(" (%s)", uri));
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,8 +167,6 @@ final class Resolver {
|
||||
*/
|
||||
Resolver resolveUses() {
|
||||
|
||||
long start = trace_start("Bind");
|
||||
|
||||
// Scan the finders for all available service provider modules. As
|
||||
// java.base uses services then then module finders will be scanned
|
||||
// anyway.
|
||||
@ -230,10 +220,10 @@ final class Resolver {
|
||||
|
||||
String pn = provider.name();
|
||||
if (!nameToReference.containsKey(pn)) {
|
||||
|
||||
if (TRACE && mref.location().isPresent())
|
||||
trace(" (%s)", mref.location().get());
|
||||
|
||||
if (isTracing()) {
|
||||
mref.location()
|
||||
.ifPresent(uri -> trace(" (%s)", uri));
|
||||
}
|
||||
nameToReference.put(pn, mref);
|
||||
q.push(provider);
|
||||
}
|
||||
@ -248,14 +238,6 @@ final class Resolver {
|
||||
|
||||
} while (!candidateConsumers.isEmpty());
|
||||
|
||||
|
||||
if (TRACE) {
|
||||
long duration = System.currentTimeMillis() - start;
|
||||
Set<String> names = nameToReference.keySet();
|
||||
trace("Bind completed in %s ms", duration);
|
||||
names.stream().sorted().forEach(name -> trace(" %s", name));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -264,23 +246,33 @@ final class Resolver {
|
||||
* Execute post-resolution checks and returns the module graph of resolved
|
||||
* modules as {@code Map}. The resolved modules will be in the given
|
||||
* configuration.
|
||||
*
|
||||
* @param check {@true} to execute the post resolution checks
|
||||
*/
|
||||
Map<ResolvedModule, Set<ResolvedModule>> finish(Configuration cf) {
|
||||
Map<ResolvedModule, Set<ResolvedModule>> finish(Configuration cf,
|
||||
boolean check)
|
||||
{
|
||||
if (isTracing()) {
|
||||
trace("Result:");
|
||||
Set<String> names = nameToReference.keySet();
|
||||
names.stream().sorted().forEach(name -> trace(" %s", name));
|
||||
}
|
||||
|
||||
detectCycles();
|
||||
|
||||
checkPlatformConstraints();
|
||||
|
||||
checkHashes();
|
||||
if (check) {
|
||||
detectCycles();
|
||||
checkPlatformConstraints();
|
||||
checkHashes();
|
||||
}
|
||||
|
||||
Map<ResolvedModule, Set<ResolvedModule>> graph = makeGraph(cf);
|
||||
|
||||
checkExportSuppliers(graph);
|
||||
if (check) {
|
||||
checkExportSuppliers(graph);
|
||||
}
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks the given module graph for cycles.
|
||||
*
|
||||
@ -420,52 +412,44 @@ final class Resolver {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks the hashes in the module descriptor to ensure that they match
|
||||
* the hash of the dependency's module reference.
|
||||
* any recorded hashes.
|
||||
*/
|
||||
private void checkHashes() {
|
||||
|
||||
for (ModuleReference mref : nameToReference.values()) {
|
||||
ModuleDescriptor descriptor = mref.descriptor();
|
||||
|
||||
// get map of module names to hash
|
||||
Optional<Hasher.DependencyHashes> ohashes = descriptor.hashes();
|
||||
// get map of module hashes
|
||||
Optional<ModuleHashes> ohashes = descriptor.hashes();
|
||||
if (!ohashes.isPresent())
|
||||
continue;
|
||||
Hasher.DependencyHashes hashes = ohashes.get();
|
||||
|
||||
// check dependences
|
||||
for (ModuleDescriptor.Requires d : descriptor.requires()) {
|
||||
String dn = d.name();
|
||||
String recordedHash = hashes.hashFor(dn);
|
||||
|
||||
if (recordedHash != null) {
|
||||
|
||||
ModuleReference other = nameToReference.get(dn);
|
||||
if (other == null) {
|
||||
other = parent.findModule(dn)
|
||||
.map(ResolvedModule::reference)
|
||||
.orElse(null);
|
||||
}
|
||||
if (other == null)
|
||||
throw new InternalError(dn + " not found");
|
||||
|
||||
String actualHash = other.computeHash(hashes.algorithm());
|
||||
if (actualHash == null)
|
||||
fail("Unable to compute the hash of module %s", dn);
|
||||
|
||||
if (!recordedHash.equals(actualHash)) {
|
||||
fail("Hash of %s (%s) differs to expected hash (%s)",
|
||||
dn, actualHash, recordedHash);
|
||||
}
|
||||
ModuleHashes hashes = ohashes.get();
|
||||
|
||||
String algorithm = hashes.algorithm();
|
||||
for (String dn : hashes.names()) {
|
||||
ModuleReference other = nameToReference.get(dn);
|
||||
if (other == null) {
|
||||
other = parent.findModule(dn)
|
||||
.map(ResolvedModule::reference)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
// skip checking the hash if the module has been patched
|
||||
if (other != null && !other.isPatched()) {
|
||||
String recordedHash = hashes.hashFor(dn);
|
||||
String actualHash = other.computeHash(algorithm);
|
||||
if (actualHash == null)
|
||||
fail("Unable to compute the hash of module %s", dn);
|
||||
if (!recordedHash.equals(actualHash)) {
|
||||
fail("Hash of %s (%s) differs to expected hash (%s)" +
|
||||
" recorded in %s", dn, actualHash, recordedHash,
|
||||
descriptor.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -666,7 +650,7 @@ final class Resolver {
|
||||
// source is exported to descriptor2
|
||||
String source = export.source();
|
||||
ModuleDescriptor other
|
||||
= packageToExporter.put(source, descriptor2);
|
||||
= packageToExporter.put(source, descriptor2);
|
||||
|
||||
if (other != null && other != descriptor2) {
|
||||
// package might be local to descriptor1
|
||||
@ -690,33 +674,38 @@ final class Resolver {
|
||||
}
|
||||
}
|
||||
|
||||
// uses S
|
||||
for (String service : descriptor1.uses()) {
|
||||
String pn = packageName(service);
|
||||
if (!packageToExporter.containsKey(pn)) {
|
||||
fail("Module %s does not read a module that exports %s",
|
||||
descriptor1.name(), pn);
|
||||
}
|
||||
}
|
||||
// uses/provides checks not applicable to automatic modules
|
||||
if (!descriptor1.isAutomatic()) {
|
||||
|
||||
// provides S
|
||||
for (Map.Entry<String, ModuleDescriptor.Provides> entry :
|
||||
descriptor1.provides().entrySet()) {
|
||||
String service = entry.getKey();
|
||||
ModuleDescriptor.Provides provides = entry.getValue();
|
||||
|
||||
String pn = packageName(service);
|
||||
if (!packageToExporter.containsKey(pn)) {
|
||||
fail("Module %s does not read a module that exports %s",
|
||||
descriptor1.name(), pn);
|
||||
}
|
||||
|
||||
for (String provider : provides.providers()) {
|
||||
if (!packages.contains(packageName(provider))) {
|
||||
fail("Provider %s not in module %s",
|
||||
provider, descriptor1.name());
|
||||
// uses S
|
||||
for (String service : descriptor1.uses()) {
|
||||
String pn = packageName(service);
|
||||
if (!packageToExporter.containsKey(pn)) {
|
||||
fail("Module %s does not read a module that exports %s",
|
||||
descriptor1.name(), pn);
|
||||
}
|
||||
}
|
||||
|
||||
// provides S
|
||||
for (Map.Entry<String, ModuleDescriptor.Provides> entry :
|
||||
descriptor1.provides().entrySet()) {
|
||||
String service = entry.getKey();
|
||||
ModuleDescriptor.Provides provides = entry.getValue();
|
||||
|
||||
String pn = packageName(service);
|
||||
if (!packageToExporter.containsKey(pn)) {
|
||||
fail("Module %s does not read a module that exports %s",
|
||||
descriptor1.name(), pn);
|
||||
}
|
||||
|
||||
for (String provider : provides.providers()) {
|
||||
if (!packages.contains(packageName(provider))) {
|
||||
fail("Provider %s not in module %s",
|
||||
provider, descriptor1.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -796,27 +785,18 @@ final class Resolver {
|
||||
throw new ResolutionException(msg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tracing support, limited to boot layer for now.
|
||||
* Tracing support
|
||||
*/
|
||||
|
||||
private final static boolean TRACE
|
||||
= Boolean.getBoolean("jdk.launcher.traceResolver")
|
||||
&& (Layer.boot() == null);
|
||||
|
||||
private String op;
|
||||
|
||||
private long trace_start(String op) {
|
||||
this.op = op;
|
||||
return System.currentTimeMillis();
|
||||
private boolean isTracing() {
|
||||
return traceOutput != null;
|
||||
}
|
||||
|
||||
private void trace(String fmt, Object ... args) {
|
||||
if (TRACE) {
|
||||
System.out.print("[" + op + "] ");
|
||||
System.out.format(fmt, args);
|
||||
System.out.println();
|
||||
if (traceOutput != null) {
|
||||
traceOutput.format("[Resolver] " + fmt, args);
|
||||
traceOutput.println();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,7 @@ import java.util.function.Supplier;
|
||||
import jdk.internal.jimage.ImageLocation;
|
||||
import jdk.internal.jimage.ImageReader;
|
||||
import jdk.internal.jimage.ImageReaderFactory;
|
||||
import jdk.internal.module.ModuleHashes;
|
||||
import jdk.internal.module.SystemModules;
|
||||
import jdk.internal.module.ModulePatcher;
|
||||
import jdk.internal.perf.PerfCounter;
|
||||
@ -101,13 +102,16 @@ class SystemModuleFinder implements ModuleFinder {
|
||||
for (int i = 0; i < n; i++) {
|
||||
String mn = moduleNames[i];
|
||||
ModuleDescriptor md;
|
||||
String hash;
|
||||
if (fastLoad) {
|
||||
md = descriptors[i];
|
||||
hash = SystemModules.MODULES_TO_HASH[i];
|
||||
} else {
|
||||
// fallback to read module-info.class
|
||||
// if fast loading of ModuleDescriptors is disabled
|
||||
ImageLocation location = imageReader.findLocation(mn, "module-info.class");
|
||||
md = ModuleDescriptor.read(imageReader.getResourceBuffer(location));
|
||||
hash = null;
|
||||
}
|
||||
if (!md.name().equals(mn))
|
||||
throw new InternalError();
|
||||
@ -123,7 +127,8 @@ class SystemModuleFinder implements ModuleFinder {
|
||||
}
|
||||
};
|
||||
|
||||
ModuleReference mref = new ModuleReference(md, uri, readerSupplier);
|
||||
ModuleReference mref =
|
||||
new ModuleReference(md, uri, readerSupplier, hashSupplier(hash));
|
||||
|
||||
// may need a reference to a patched module if -Xpatch specified
|
||||
mref = ModulePatcher.interposeIfNeeded(mref);
|
||||
@ -142,6 +147,18 @@ class SystemModuleFinder implements ModuleFinder {
|
||||
initTime.addElapsedTimeFrom(t0);
|
||||
}
|
||||
|
||||
private static ModuleHashes.HashSupplier hashSupplier(String hash) {
|
||||
if (hash == null)
|
||||
return null;
|
||||
|
||||
return new ModuleHashes.HashSupplier() {
|
||||
@Override
|
||||
public String generate(String algorithm) {
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
SystemModuleFinder() { }
|
||||
|
||||
@Override
|
||||
|
@ -27,6 +27,7 @@ package java.lang.reflect;
|
||||
|
||||
import java.lang.module.Configuration;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleDescriptor.Provides;
|
||||
import java.lang.module.ResolvedModule;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@ -41,6 +42,8 @@ import java.util.stream.Collectors;
|
||||
import jdk.internal.loader.Loader;
|
||||
import jdk.internal.loader.LoaderPool;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import jdk.internal.module.ServicesCatalog;
|
||||
import jdk.internal.module.ServicesCatalog.ServiceProvider;
|
||||
import sun.security.util.SecurityConstants;
|
||||
|
||||
|
||||
@ -549,4 +552,55 @@ public final class Layer {
|
||||
public static Layer boot() {
|
||||
return SharedSecrets.getJavaLangAccess().getBootLayer();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the ServicesCatalog for this Layer, creating it if not
|
||||
* already created.
|
||||
*/
|
||||
ServicesCatalog getServicesCatalog() {
|
||||
ServicesCatalog servicesCatalog = this.servicesCatalog;
|
||||
if (servicesCatalog != null)
|
||||
return servicesCatalog;
|
||||
|
||||
Map<String, Set<ServiceProvider>> map = new HashMap<>();
|
||||
for (Module m : nameToModule.values()) {
|
||||
ModuleDescriptor descriptor = m.getDescriptor();
|
||||
for (Provides provides : descriptor.provides().values()) {
|
||||
String service = provides.service();
|
||||
Set<ServiceProvider> providers
|
||||
= map.computeIfAbsent(service, k -> new HashSet<>());
|
||||
for (String pn : provides.providers()) {
|
||||
providers.add(new ServiceProvider(m, pn));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ServicesCatalog catalog = new ServicesCatalog() {
|
||||
@Override
|
||||
public void register(Module module) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
@Override
|
||||
public Set<ServiceProvider> findServices(String service) {
|
||||
Set<ServiceProvider> providers = map.get(service);
|
||||
if (providers == null) {
|
||||
return Collections.emptySet();
|
||||
} else {
|
||||
return Collections.unmodifiableSet(providers);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
synchronized (this) {
|
||||
servicesCatalog = this.servicesCatalog;
|
||||
if (servicesCatalog == null) {
|
||||
this.servicesCatalog = servicesCatalog = catalog;
|
||||
}
|
||||
}
|
||||
|
||||
return servicesCatalog;
|
||||
}
|
||||
|
||||
private volatile ServicesCatalog servicesCatalog;
|
||||
}
|
||||
|
@ -43,11 +43,7 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@ -142,9 +138,6 @@ public final class Module {
|
||||
this.name = null;
|
||||
this.loader = loader;
|
||||
this.descriptor = null;
|
||||
|
||||
// unnamed modules are loose
|
||||
this.loose = true;
|
||||
}
|
||||
|
||||
|
||||
@ -245,17 +238,27 @@ public final class Module {
|
||||
}
|
||||
|
||||
|
||||
// -- readability --
|
||||
// --
|
||||
|
||||
// true if this module reads all unnamed modules (a.k.a. loose module)
|
||||
private volatile boolean loose;
|
||||
// the special Module to mean reads or exported to "all unnamed modules"
|
||||
private static final Module ALL_UNNAMED_MODULE = new Module(null);
|
||||
|
||||
// special Module to mean exported to "everyone"
|
||||
private static final Module EVERYONE_MODULE = new Module(null);
|
||||
|
||||
// exported to all modules
|
||||
private static final Set<Module> EVERYONE = Collections.singleton(EVERYONE_MODULE);
|
||||
|
||||
|
||||
// -- readability --
|
||||
|
||||
// the modules that this module permanently reads
|
||||
// (will be final when the modules are defined in reverse topology order)
|
||||
private volatile Set<Module> reads;
|
||||
|
||||
// created lazily, additional modules that this module reflectively reads
|
||||
private volatile WeakSet<Module> transientReads;
|
||||
// additional module (2nd key) that some module (1st key) reflectively reads
|
||||
private static final WeakPairMap<Module, Module, Boolean> transientReads
|
||||
= new WeakPairMap<>();
|
||||
|
||||
|
||||
/**
|
||||
@ -284,22 +287,19 @@ public final class Module {
|
||||
|
||||
// check if this module reads other
|
||||
if (other.isNamed()) {
|
||||
|
||||
Set<Module> reads = this.reads; // volatile read
|
||||
if (reads != null && reads.contains(other))
|
||||
return true;
|
||||
|
||||
} else {
|
||||
|
||||
// loose modules read all unnamed modules
|
||||
if (this.loose)
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// check if this module reads the other module reflectively
|
||||
WeakSet<Module> tr = this.transientReads; // volatile read
|
||||
if (tr != null && tr.contains(other))
|
||||
if (transientReads.containsKeyPair(this, other))
|
||||
return true;
|
||||
|
||||
// if other is an unnamed module then check if this module reads
|
||||
// all unnamed modules
|
||||
if (!other.isNamed()
|
||||
&& transientReads.containsKeyPair(this, ALL_UNNAMED_MODULE))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -346,8 +346,7 @@ public final class Module {
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the given {@code Module} readable to this module without
|
||||
* notifying the VM.
|
||||
* Updates this module to read another module without notifying the VM.
|
||||
*
|
||||
* @apiNote This method is for VM white-box testing.
|
||||
*/
|
||||
@ -361,40 +360,28 @@ public final class Module {
|
||||
* If {@code syncVM} is {@code true} then the VM is notified.
|
||||
*/
|
||||
private void implAddReads(Module other, boolean syncVM) {
|
||||
Objects.requireNonNull(other);
|
||||
|
||||
// nothing to do
|
||||
if (other == this || !this.isNamed())
|
||||
return;
|
||||
|
||||
// if the other is null then change this module to be loose.
|
||||
if (other == null) {
|
||||
if (syncVM)
|
||||
addReads0(this, null);
|
||||
this.loose = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// check if we already read this module
|
||||
Set<Module> reads = this.reads;
|
||||
if (reads != null && reads.contains(other))
|
||||
return;
|
||||
|
||||
// update VM first, just in case it fails
|
||||
if (syncVM)
|
||||
addReads0(this, other);
|
||||
|
||||
// add reflective read
|
||||
WeakSet<Module> tr = this.transientReads;
|
||||
if (tr == null) {
|
||||
synchronized (this) {
|
||||
tr = this.transientReads;
|
||||
if (tr == null) {
|
||||
tr = new WeakSet<>();
|
||||
this.transientReads = tr;
|
||||
}
|
||||
if (syncVM) {
|
||||
if (other == ALL_UNNAMED_MODULE) {
|
||||
addReads0(this, null);
|
||||
} else {
|
||||
addReads0(this, other);
|
||||
}
|
||||
}
|
||||
tr.add(other);
|
||||
|
||||
// add reflective read
|
||||
transientReads.putIfAbsent(this, other, Boolean.TRUE);
|
||||
}
|
||||
|
||||
|
||||
@ -404,15 +391,10 @@ public final class Module {
|
||||
// (will be final when the modules are defined in reverse topology order)
|
||||
private volatile Map<String, Set<Module>> exports;
|
||||
|
||||
// created lazily, additional exports added at run-time
|
||||
private volatile Map<String, WeakSet<Module>> transientExports;
|
||||
|
||||
// the special Module to mean exported to all modules
|
||||
private static final Module EVERYONE_MODULE = new Module(null);
|
||||
private static final Set<Module> EVERYONE = Collections.singleton(EVERYONE_MODULE);
|
||||
|
||||
// the special Module to mean exported to all unnamed modules
|
||||
private static final Module ALL_UNNAMED_MODULE = new Module(null);
|
||||
// additional exports added at run-time
|
||||
// this module (1st key), other module (2nd key), exported packages (value)
|
||||
private static final WeakPairMap<Module, Module, Map<String, Boolean>>
|
||||
transientExports = new WeakPairMap<>();
|
||||
|
||||
|
||||
/**
|
||||
@ -489,23 +471,9 @@ public final class Module {
|
||||
if (exports != null) {
|
||||
Set<Module> targets = exports.get(pn);
|
||||
|
||||
if (targets != null) {
|
||||
|
||||
// exported to all modules
|
||||
if (targets.contains(EVERYONE_MODULE))
|
||||
return true;
|
||||
|
||||
if (other != EVERYONE_MODULE) {
|
||||
// exported to other
|
||||
if (targets.contains(other))
|
||||
return true;
|
||||
|
||||
// other is an unnamed module && exported to all unnamed
|
||||
if (!other.isNamed() && targets.contains(ALL_UNNAMED_MODULE))
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
if ((targets != null)
|
||||
&& (targets.contains(other) || targets.contains(EVERYONE_MODULE)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -515,29 +483,27 @@ public final class Module {
|
||||
* package package to the given module.
|
||||
*/
|
||||
private boolean isExportedReflectively(String pn, Module other) {
|
||||
Map<String, WeakSet<Module>> te = this.transientExports;
|
||||
if (te != null) {
|
||||
WeakSet<Module> targets = te.get(pn);
|
||||
// exported to all modules
|
||||
Map<String, ?> exports = transientExports.get(this, EVERYONE_MODULE);
|
||||
if (exports != null && exports.containsKey(pn))
|
||||
return true;
|
||||
|
||||
if (targets != null) {
|
||||
if (other != EVERYONE_MODULE) {
|
||||
|
||||
// exported to all modules
|
||||
if (targets.contains(EVERYONE_MODULE))
|
||||
// exported to other
|
||||
exports = transientExports.get(this, other);
|
||||
if (exports != null && exports.containsKey(pn))
|
||||
return true;
|
||||
|
||||
// other is an unnamed module && exported to all unnamed
|
||||
if (!other.isNamed()) {
|
||||
exports = transientExports.get(this, ALL_UNNAMED_MODULE);
|
||||
if (exports != null && exports.containsKey(pn))
|
||||
return true;
|
||||
|
||||
if (other != EVERYONE_MODULE) {
|
||||
|
||||
// exported to other
|
||||
if (targets.contains(other))
|
||||
return true;
|
||||
|
||||
// other is an unnamed module && exported to all unnamed
|
||||
if (!other.isNamed() && targets.contains(ALL_UNNAMED_MODULE))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -638,34 +604,19 @@ public final class Module {
|
||||
}
|
||||
}
|
||||
|
||||
// create transientExports if needed
|
||||
Map<String, WeakSet<Module>> te = this.transientExports; // read
|
||||
if (te == null) {
|
||||
synchronized (this) {
|
||||
te = this.transientExports;
|
||||
if (te == null) {
|
||||
te = new ConcurrentHashMap<>();
|
||||
this.transientExports = te; // volatile write
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add package name to transientExports if absent
|
||||
WeakSet<Module> s = te.get(pn);
|
||||
if (s == null) {
|
||||
s = new WeakSet<>();
|
||||
WeakSet<Module> prev = te.putIfAbsent(pn, s);
|
||||
if (prev != null)
|
||||
s = prev;
|
||||
}
|
||||
s.add(other);
|
||||
transientExports
|
||||
.computeIfAbsent(this, other,
|
||||
(_this, _other) -> new ConcurrentHashMap<>())
|
||||
.putIfAbsent(pn, Boolean.TRUE);
|
||||
}
|
||||
|
||||
|
||||
// -- services --
|
||||
|
||||
// created lazily, additional service types that this module uses
|
||||
private volatile WeakSet<Class<?>> transientUses;
|
||||
// additional service type (2nd key) that some module (1st key) uses
|
||||
private static final WeakPairMap<Module, Class<?>, Boolean> transientUses
|
||||
= new WeakPairMap<>();
|
||||
|
||||
/**
|
||||
* If the caller's module is this module then update this module to add a
|
||||
@ -702,17 +653,7 @@ public final class Module {
|
||||
}
|
||||
|
||||
if (!canUse(st)) {
|
||||
WeakSet<Class<?>> uses = this.transientUses;
|
||||
if (uses == null) {
|
||||
synchronized (this) {
|
||||
uses = this.transientUses;
|
||||
if (uses == null) {
|
||||
uses = new WeakSet<>();
|
||||
this.transientUses = uses;
|
||||
}
|
||||
}
|
||||
}
|
||||
uses.add(st);
|
||||
transientUses.putIfAbsent(this, st, Boolean.TRUE);
|
||||
}
|
||||
|
||||
}
|
||||
@ -746,11 +687,7 @@ public final class Module {
|
||||
return true;
|
||||
|
||||
// uses added via addUses
|
||||
WeakSet<Class<?>> uses = this.transientUses;
|
||||
if (uses != null && uses.contains(st))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return transientUses.containsKeyPair(this, st);
|
||||
}
|
||||
|
||||
|
||||
@ -885,7 +822,7 @@ public final class Module {
|
||||
// -- creating Module objects --
|
||||
|
||||
/**
|
||||
* Find the runtime Module corresponding to the given ReadDependence
|
||||
* Find the runtime Module corresponding to the given ResolvedModule
|
||||
* in the given parent Layer (or its parents).
|
||||
*/
|
||||
private static Module find(ResolvedModule resolvedModule, Layer layer) {
|
||||
@ -969,7 +906,7 @@ public final class Module {
|
||||
|
||||
// automatic modules reads all unnamed modules
|
||||
if (descriptor.isAutomatic()) {
|
||||
m.implAddReads(null, true);
|
||||
m.implAddReads(ALL_UNNAMED_MODULE, true);
|
||||
}
|
||||
|
||||
// exports
|
||||
@ -1097,7 +1034,7 @@ public final class Module {
|
||||
* the representation is the string {@code "module"}, followed by a space,
|
||||
* and then the module name. For an unnamed module, the representation is
|
||||
* the string {@code "unnamed module"}, followed by a space, and then an
|
||||
* implementation specific identifier for the unnamed module.
|
||||
* implementation specific string that identifies the unnamed module.
|
||||
*
|
||||
* @return The string representation of this module
|
||||
*/
|
||||
@ -1112,46 +1049,6 @@ public final class Module {
|
||||
}
|
||||
|
||||
|
||||
// -- supporting classes --
|
||||
|
||||
|
||||
/**
|
||||
* A "not-a-Set" set of weakly referenced objects that supports concurrent
|
||||
* access.
|
||||
*/
|
||||
private static class WeakSet<E> {
|
||||
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
private final Lock readLock = lock.readLock();
|
||||
private final Lock writeLock = lock.writeLock();
|
||||
|
||||
private final WeakHashMap<E, Boolean> map = new WeakHashMap<>();
|
||||
|
||||
/**
|
||||
* Adds the specified element to the set.
|
||||
*/
|
||||
void add(E e) {
|
||||
writeLock.lock();
|
||||
try {
|
||||
map.put(e, Boolean.TRUE);
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this set contains the specified element.
|
||||
*/
|
||||
boolean contains(E e) {
|
||||
readLock.lock();
|
||||
try {
|
||||
return map.containsKey(e);
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -- native methods --
|
||||
|
||||
// JVM_DefineModule
|
||||
@ -1196,8 +1093,12 @@ public final class Module {
|
||||
m1.implAddReads(m2, true);
|
||||
}
|
||||
@Override
|
||||
public void addReadsAllUnnamed(Module m) {
|
||||
m.implAddReads(Module.ALL_UNNAMED_MODULE);
|
||||
}
|
||||
@Override
|
||||
public void addExports(Module m, String pn, Module other) {
|
||||
m.implAddExports(pn, Objects.requireNonNull(other), true);
|
||||
m.implAddExports(pn, other, true);
|
||||
}
|
||||
@Override
|
||||
public void addExportsToAll(Module m, String pn) {
|
||||
@ -1211,6 +1112,10 @@ public final class Module {
|
||||
public void addPackage(Module m, String pn) {
|
||||
m.implAddPackage(pn, true);
|
||||
}
|
||||
@Override
|
||||
public ServicesCatalog getServicesCatalog(Layer layer) {
|
||||
return layer.getServicesCatalog();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -582,7 +582,7 @@ public class Proxy implements java.io.Serializable {
|
||||
}
|
||||
|
||||
private static final String DEBUG =
|
||||
GetPropertyAction.getProperty("jdk.proxy.debug", "");
|
||||
GetPropertyAction.privilegedGetProperty("jdk.proxy.debug", "");
|
||||
|
||||
private static boolean isDebug() {
|
||||
return !DEBUG.isEmpty();
|
||||
|
@ -0,0 +1,354 @@
|
||||
/*
|
||||
* 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 java.lang.reflect;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* A WeakHashMap-like data structure that uses a pair of weakly-referenced keys
|
||||
* with identity equality semantics to associate a strongly-referenced value.
|
||||
* Unlike WeakHashMap, this data structure is thread-safe.
|
||||
*
|
||||
* @param <K1> the type of 1st key in key pair
|
||||
* @param <K2> the type of 2nd key in key pair
|
||||
* @param <V> the type of value
|
||||
* @author Peter Levart
|
||||
*/
|
||||
final class WeakPairMap<K1, K2, V> {
|
||||
|
||||
private final ConcurrentHashMap<Pair<K1, K2>, V> map = new ConcurrentHashMap<>();
|
||||
private final ReferenceQueue<Object> queue = new ReferenceQueue<>();
|
||||
|
||||
/**
|
||||
* Tests if the specified pair of keys are associated with a value
|
||||
* in the WeakPairMap.
|
||||
*
|
||||
* @param k1 the 1st of the pair of keys
|
||||
* @param k2 the 2nd of the pair of keys
|
||||
* @return true if and only if the specified key pair is in this WeakPairMap,
|
||||
* as determined by the identity comparison; false otherwise
|
||||
* @throws NullPointerException if any of the specified keys is null
|
||||
*/
|
||||
public boolean containsKeyPair(K1 k1, K2 k2) {
|
||||
expungeStaleAssociations();
|
||||
return map.containsKey(Pair.lookup(k1, k2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value to which the specified pair of keys is mapped, or null
|
||||
* if this WeakPairMap contains no mapping for the key pair.
|
||||
* <p>More formally, if this WeakPairMap contains a mapping from a key pair
|
||||
* {@code (_k1, _k2)} to a value {@code v} such that
|
||||
* {@code k1 == _k1 && k2 == _k2}, then this method returns {@code v};
|
||||
* otherwise it returns {@code null}.
|
||||
* (There can be at most one such mapping.)
|
||||
*
|
||||
* @param k1 the 1st of the pair of keys for which the mapped value is to
|
||||
* be returned
|
||||
* @param k2 the 2nd of the pair of keys for which the mapped value is to
|
||||
* be returned
|
||||
* @return the value to which the specified key pair is mapped, or null if
|
||||
* this map contains no mapping for the key pair
|
||||
* @throws NullPointerException if any of the specified keys is null
|
||||
*/
|
||||
public V get(K1 k1, K2 k2) {
|
||||
expungeStaleAssociations();
|
||||
return map.get(Pair.lookup(k1, k2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the specified key pair to the specified value in this WeakPairMap.
|
||||
* Neither the keys nor the value can be null.
|
||||
* <p>The value can be retrieved by calling the {@link #get} method
|
||||
* with the the same keys (compared by identity).
|
||||
*
|
||||
* @param k1 the 1st of the pair of keys with which the specified value is to
|
||||
* be associated
|
||||
* @param k2 the 2nd of the pair of keys with which the specified value is to
|
||||
* be associated
|
||||
* @param v value to be associated with the specified key pair
|
||||
* @return the previous value associated with key pair, or {@code null} if
|
||||
* there was no mapping for key pair
|
||||
* @throws NullPointerException if any of the specified keys or value is null
|
||||
*/
|
||||
public V put(K1 k1, K2 k2, V v) {
|
||||
expungeStaleAssociations();
|
||||
return map.put(Pair.weak(k1, k2, queue), v);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the specified key pair is not already associated with a value,
|
||||
* associates it with the given value and returns {@code null}, else does
|
||||
* nothing and returns the currently associated value.
|
||||
*
|
||||
* @param k1 the 1st of the pair of keys with which the specified value is to
|
||||
* be associated
|
||||
* @param k2 the 2nd of the pair of keys with which the specified value is to
|
||||
* be associated
|
||||
* @param v value to be associated with the specified key pair
|
||||
* @return the previous value associated with key pair, or {@code null} if
|
||||
* there was no mapping for key pair
|
||||
* @throws NullPointerException if any of the specified keys or value is null
|
||||
*/
|
||||
public V putIfAbsent(K1 k1, K2 k2, V v) {
|
||||
expungeStaleAssociations();
|
||||
return map.putIfAbsent(Pair.weak(k1, k2, queue), v);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the specified key pair is not already associated with a value,
|
||||
* attempts to compute its value using the given mapping function
|
||||
* and enters it into this WeakPairMap unless {@code null}. The entire
|
||||
* method invocation is performed atomically, so the function is
|
||||
* applied at most once per key pair. Some attempted update operations
|
||||
* on this WeakPairMap by other threads may be blocked while computation
|
||||
* is in progress, so the computation should be short and simple,
|
||||
* and must not attempt to update any other mappings of this WeakPairMap.
|
||||
*
|
||||
* @param k1 the 1st of the pair of keys with which the
|
||||
* computed value is to be associated
|
||||
* @param k2 the 2nd of the pair of keys with which the
|
||||
* computed value is to be associated
|
||||
* @param mappingFunction the function to compute a value
|
||||
* @return the current (existing or computed) value associated with
|
||||
* the specified key pair, or null if the computed value is null
|
||||
* @throws NullPointerException if any of the specified keys or
|
||||
* mappingFunction is null
|
||||
* @throws IllegalStateException if the computation detectably
|
||||
* attempts a recursive update to this map
|
||||
* that would otherwise never complete
|
||||
* @throws RuntimeException or Error if the mappingFunction does so, in
|
||||
* which case the mapping is left unestablished
|
||||
*/
|
||||
public V computeIfAbsent(K1 k1, K2 k2,
|
||||
BiFunction<? super K1, ? super K2, ? extends V>
|
||||
mappingFunction) {
|
||||
expungeStaleAssociations();
|
||||
try {
|
||||
return map.computeIfAbsent(
|
||||
Pair.weak(k1, k2, queue),
|
||||
pair -> mappingFunction.apply(pair.first(), pair.second()));
|
||||
} finally {
|
||||
Reference.reachabilityFence(k1);
|
||||
Reference.reachabilityFence(k2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Collection} view of the values contained in this
|
||||
* WeakPairMap. The collection is backed by the WeakPairMap, so changes to
|
||||
* the map are reflected in the collection, and vice-versa. The collection
|
||||
* supports element removal, which removes the corresponding
|
||||
* mapping from this map, via the {@code Iterator.remove},
|
||||
* {@code Collection.remove}, {@code removeAll},
|
||||
* {@code retainAll}, and {@code clear} operations. It does not
|
||||
* support the {@code add} or {@code addAll} operations.
|
||||
*
|
||||
* @return the collection view
|
||||
*/
|
||||
public Collection<V> values() {
|
||||
expungeStaleAssociations();
|
||||
return map.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes associations from this WeakPairMap for which at least one of the
|
||||
* keys in key pair has been found weakly-reachable and corresponding
|
||||
* WeakRefPeer(s) enqueued. Called as part of each public operation.
|
||||
*/
|
||||
private void expungeStaleAssociations() {
|
||||
WeakRefPeer<?> peer;
|
||||
while ((peer = (WeakRefPeer<?>) queue.poll()) != null) {
|
||||
map.remove(peer.weakPair());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Common interface of both {@link Weak} and {@link Lookup} key pairs.
|
||||
*/
|
||||
private interface Pair<K1, K2> {
|
||||
|
||||
static <K1, K2> Pair<K1, K2> weak(K1 k1, K2 k2,
|
||||
ReferenceQueue<Object> queue) {
|
||||
return new Weak<>(k1, k2, queue);
|
||||
}
|
||||
|
||||
static <K1, K2> Pair<K1, K2> lookup(K1 k1, K2 k2) {
|
||||
return new Lookup<>(k1, k2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The 1st of the pair of keys (may be null for {@link Weak}
|
||||
* when it gets cleared)
|
||||
*/
|
||||
K1 first();
|
||||
|
||||
/**
|
||||
* @return The 2nd of the pair of keys (may be null for {@link Weak}
|
||||
* when it gets cleared)
|
||||
*/
|
||||
K2 second();
|
||||
|
||||
static int hashCode(Object first, Object second) {
|
||||
// assert first != null && second != null;
|
||||
return System.identityHashCode(first) ^
|
||||
System.identityHashCode(second);
|
||||
}
|
||||
|
||||
static boolean equals(Object first, Object second, Pair<?, ?> p) {
|
||||
return first != null && second != null &&
|
||||
first == p.first() && second == p.second();
|
||||
}
|
||||
|
||||
/**
|
||||
* A Pair where both keys are weakly-referenced.
|
||||
* It is composed of two instances of {@link WeakRefPeer}s:
|
||||
* <pre>{@code
|
||||
*
|
||||
* +-referent-> [K1] +-referent-> [K2]
|
||||
* | |
|
||||
* +----------------+ +----------------+
|
||||
* | Pair.Weak <: |-----peer----->| (anonymous) <: |
|
||||
* | WeakRefPeer, | | WeakRefPeer |
|
||||
* | Pair |<--weakPair()--| |
|
||||
* +----------------+ +----------------+
|
||||
* | ^
|
||||
* | |
|
||||
* +-weakPair()-+
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* Pair.Weak is used for CHM keys. Both peers are associated with the
|
||||
* same {@link ReferenceQueue} so when either of their referents
|
||||
* becomes weakly-reachable, the corresponding entries can be
|
||||
* {@link #expungeStaleAssociations() expunged} from the map.
|
||||
*/
|
||||
final class Weak<K1, K2> extends WeakRefPeer<K1> implements Pair<K1, K2> {
|
||||
|
||||
// saved hash so it can be retrieved after the reference is cleared
|
||||
private final int hash;
|
||||
// link to <K2> peer
|
||||
private final WeakRefPeer<K2> peer;
|
||||
|
||||
Weak(K1 k1, K2 k2, ReferenceQueue<Object> queue) {
|
||||
super(k1, queue);
|
||||
hash = Pair.hashCode(k1, k2);
|
||||
peer = new WeakRefPeer<>(k2, queue) {
|
||||
// link back to <K1> peer
|
||||
@Override
|
||||
Weak<?, ?> weakPair() { return Weak.this; }
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
Weak<?, ?> weakPair() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public K1 first() {
|
||||
return get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public K2 second() {
|
||||
return peer.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return this == obj ||
|
||||
(obj instanceof Pair &&
|
||||
Pair.equals(first(), second(), (Pair<?, ?>) obj));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimized lookup Pair, used as lookup key in methods like
|
||||
* {@link java.util.Map#get(Object)} or
|
||||
* {@link java.util.Map#containsKey(Object)}) where
|
||||
* there is a great chance its allocation is eliminated
|
||||
* by escape analysis when such lookups are inlined by JIT.
|
||||
* All its methods are purposely designed so that 'this' is never
|
||||
* passed to any other method or used as identity.
|
||||
*/
|
||||
final class Lookup<K1, K2> implements Pair<K1, K2> {
|
||||
private final K1 k1;
|
||||
private final K2 k2;
|
||||
|
||||
Lookup(K1 k1, K2 k2) {
|
||||
this.k1 = Objects.requireNonNull(k1);
|
||||
this.k2 = Objects.requireNonNull(k2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public K1 first() {
|
||||
return k1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public K2 second() {
|
||||
return k2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Pair.hashCode(k1, k2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof Pair &&
|
||||
Pair.equals(k1, k2, (Pair<?, ?>) obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Common abstract supertype of a pair of WeakReference peers.
|
||||
*/
|
||||
private static abstract class WeakRefPeer<K> extends WeakReference<K> {
|
||||
|
||||
WeakRefPeer(K k, ReferenceQueue<Object> queue) {
|
||||
super(Objects.requireNonNull(k), queue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link Pair.Weak} side of the pair of peers.
|
||||
*/
|
||||
abstract Pair.Weak<?, ?> weakPair();
|
||||
}
|
||||
}
|
@ -1536,7 +1536,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
* be performed to generate a result with the specified scale, the
|
||||
* specified rounding mode is applied.
|
||||
*
|
||||
* <p>The new {@link #divide(BigDecimal, int, RoundingMode)} method
|
||||
* @deprecated The method {@link #divide(BigDecimal, int, RoundingMode)}
|
||||
* should be used in preference to this legacy method.
|
||||
*
|
||||
* @param divisor value by which this {@code BigDecimal} is to be divided.
|
||||
@ -1558,6 +1558,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
* @see #ROUND_HALF_EVEN
|
||||
* @see #ROUND_UNNECESSARY
|
||||
*/
|
||||
@Deprecated(since="9")
|
||||
public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) {
|
||||
if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY)
|
||||
throw new IllegalArgumentException("Invalid rounding mode");
|
||||
@ -1602,7 +1603,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
* rounding must be performed to generate a result with the given
|
||||
* scale, the specified rounding mode is applied.
|
||||
*
|
||||
* <p>The new {@link #divide(BigDecimal, RoundingMode)} method
|
||||
* @deprecated The method {@link #divide(BigDecimal, RoundingMode)}
|
||||
* should be used in preference to this legacy method.
|
||||
*
|
||||
* @param divisor value by which this {@code BigDecimal} is to be divided.
|
||||
@ -1623,6 +1624,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
* @see #ROUND_HALF_EVEN
|
||||
* @see #ROUND_UNNECESSARY
|
||||
*/
|
||||
@Deprecated(since="9")
|
||||
public BigDecimal divide(BigDecimal divisor, int roundingMode) {
|
||||
return this.divide(divisor, scale, roundingMode);
|
||||
}
|
||||
@ -2267,14 +2269,20 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
* Rounding mode to round away from zero. Always increments the
|
||||
* digit prior to a nonzero discarded fraction. Note that this rounding
|
||||
* mode never decreases the magnitude of the calculated value.
|
||||
*
|
||||
* @deprecated Use {@link RoundingMode#UP} instead.
|
||||
*/
|
||||
@Deprecated(since="9")
|
||||
public static final int ROUND_UP = 0;
|
||||
|
||||
/**
|
||||
* Rounding mode to round towards zero. Never increments the digit
|
||||
* prior to a discarded fraction (i.e., truncates). Note that this
|
||||
* rounding mode never increases the magnitude of the calculated value.
|
||||
*
|
||||
* @deprecated Use {@link RoundingMode#DOWN} instead.
|
||||
*/
|
||||
@Deprecated(since="9")
|
||||
public static final int ROUND_DOWN = 1;
|
||||
|
||||
/**
|
||||
@ -2283,7 +2291,10 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
* {@code ROUND_UP}; if negative, behaves as for
|
||||
* {@code ROUND_DOWN}. Note that this rounding mode never
|
||||
* decreases the calculated value.
|
||||
*
|
||||
* @deprecated Use {@link RoundingMode#CEILING} instead.
|
||||
*/
|
||||
@Deprecated(since="9")
|
||||
public static final int ROUND_CEILING = 2;
|
||||
|
||||
/**
|
||||
@ -2292,7 +2303,10 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
* {@code ROUND_DOWN}; if negative, behave as for
|
||||
* {@code ROUND_UP}. Note that this rounding mode never
|
||||
* increases the calculated value.
|
||||
*
|
||||
* @deprecated Use {@link RoundingMode#FLOOR} instead.
|
||||
*/
|
||||
@Deprecated(since="9")
|
||||
public static final int ROUND_FLOOR = 3;
|
||||
|
||||
/**
|
||||
@ -2302,7 +2316,10 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
* ≥ 0.5; otherwise, behaves as for {@code ROUND_DOWN}. Note
|
||||
* that this is the rounding mode that most of us were taught in
|
||||
* grade school.
|
||||
*
|
||||
* @deprecated Use {@link RoundingMode#HALF_UP} instead.
|
||||
*/
|
||||
@Deprecated(since="9")
|
||||
public static final int ROUND_HALF_UP = 4;
|
||||
|
||||
/**
|
||||
@ -2311,7 +2328,10 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
* down. Behaves as for {@code ROUND_UP} if the discarded
|
||||
* fraction is {@literal >} 0.5; otherwise, behaves as for
|
||||
* {@code ROUND_DOWN}.
|
||||
*
|
||||
* @deprecated Use {@link RoundingMode#HALF_DOWN} instead.
|
||||
*/
|
||||
@Deprecated(since="9")
|
||||
public static final int ROUND_HALF_DOWN = 5;
|
||||
|
||||
/**
|
||||
@ -2323,7 +2343,10 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
* {@code ROUND_HALF_DOWN} if it's even. Note that this is the
|
||||
* rounding mode that minimizes cumulative error when applied
|
||||
* repeatedly over a sequence of calculations.
|
||||
*
|
||||
* @deprecated Use {@link RoundingMode#HALF_EVEN} instead.
|
||||
*/
|
||||
@Deprecated(since="9")
|
||||
public static final int ROUND_HALF_EVEN = 6;
|
||||
|
||||
/**
|
||||
@ -2331,7 +2354,10 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
* result, hence no rounding is necessary. If this rounding mode is
|
||||
* specified on an operation that yields an inexact result, an
|
||||
* {@code ArithmeticException} is thrown.
|
||||
*
|
||||
* @deprecated Use {@link RoundingMode#UNNECESSARY} instead.
|
||||
*/
|
||||
@Deprecated(since="9")
|
||||
public static final int ROUND_UNNECESSARY = 7;
|
||||
|
||||
|
||||
@ -2408,7 +2434,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
* Instead, {@code setScale} returns an object with the proper
|
||||
* scale; the returned object may or may not be newly allocated.
|
||||
*
|
||||
* <p>The new {@link #setScale(int, RoundingMode)} method should
|
||||
* @deprecated The method {@link #setScale(int, RoundingMode)} should
|
||||
* be used in preference to this legacy method.
|
||||
*
|
||||
* @param newScale scale of the {@code BigDecimal} value to be returned.
|
||||
@ -2431,6 +2457,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
* @see #ROUND_HALF_EVEN
|
||||
* @see #ROUND_UNNECESSARY
|
||||
*/
|
||||
@Deprecated(since="9")
|
||||
public BigDecimal setScale(int newScale, int roundingMode) {
|
||||
if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY)
|
||||
throw new IllegalArgumentException("Invalid rounding mode");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013, 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
|
||||
@ -90,6 +90,7 @@ package java.math;
|
||||
* @author Joseph D. Darcy
|
||||
* @since 1.5
|
||||
*/
|
||||
@SuppressWarnings("deprecation") // Legacy rounding mode constants in BigDecimal
|
||||
public enum RoundingMode {
|
||||
|
||||
/**
|
||||
|
@ -52,7 +52,8 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
|
||||
protected InetAddress connectedAddress = null;
|
||||
private int connectedPort = -1;
|
||||
|
||||
private static final String os = GetPropertyAction.getProperty("os.name");
|
||||
private static final String os =
|
||||
GetPropertyAction.privilegedGetProperty("os.name");
|
||||
|
||||
/**
|
||||
* flag set if the native connect() call not to be used
|
||||
|
@ -1124,7 +1124,7 @@ class InetAddress implements java.io.Serializable {
|
||||
private static NameService createNameService() {
|
||||
|
||||
String hostsFileName =
|
||||
GetPropertyAction.getProperty("jdk.net.hosts.file");
|
||||
GetPropertyAction.privilegedGetProperty("jdk.net.hosts.file");
|
||||
NameService theNameService;
|
||||
if (hostsFileName != null) {
|
||||
theNameService = new HostsFileNameService(hostsFileName);
|
||||
@ -1643,9 +1643,11 @@ class InetAddress implements java.io.Serializable {
|
||||
* property can vary across implementations of the java.
|
||||
* classes. The default is an empty String "".
|
||||
*/
|
||||
String prefix = GetPropertyAction.getProperty("impl.prefix", "");
|
||||
String prefix = GetPropertyAction.privilegedGetProperty("impl.prefix", "");
|
||||
try {
|
||||
impl = Class.forName("java.net." + prefix + implName).newInstance();
|
||||
@SuppressWarnings("deprecation")
|
||||
Object tmp = Class.forName("java.net." + prefix + implName).newInstance();
|
||||
impl = tmp;
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.err.println("Class not found: java.net." + prefix +
|
||||
implName + ":\ncheck impl.prefix property " +
|
||||
@ -1662,7 +1664,9 @@ class InetAddress implements java.io.Serializable {
|
||||
|
||||
if (impl == null) {
|
||||
try {
|
||||
impl = Class.forName(implName).newInstance();
|
||||
@SuppressWarnings("deprecation")
|
||||
Object tmp = Class.forName(implName).newInstance();
|
||||
impl = tmp;
|
||||
} catch (Exception e) {
|
||||
throw new Error("System property impl.prefix incorrect");
|
||||
}
|
||||
|
@ -71,7 +71,9 @@ public abstract class ProxySelector {
|
||||
try {
|
||||
Class<?> c = Class.forName("sun.net.spi.DefaultProxySelector");
|
||||
if (c != null && ProxySelector.class.isAssignableFrom(c)) {
|
||||
theProxySelector = (ProxySelector) c.newInstance();
|
||||
@SuppressWarnings("deprecation")
|
||||
ProxySelector tmp = (ProxySelector) c.newInstance();
|
||||
theProxySelector = tmp;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
theProxySelector = null;
|
||||
|
@ -178,7 +178,7 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts {
|
||||
userName = pw.getUserName();
|
||||
password = new String(pw.getPassword());
|
||||
} else {
|
||||
userName = GetPropertyAction.getProperty("user.name");
|
||||
userName = GetPropertyAction.privilegedGetProperty("user.name");
|
||||
}
|
||||
if (userName == null)
|
||||
return false;
|
||||
@ -1088,7 +1088,7 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts {
|
||||
userName = System.getProperty("user.name");
|
||||
} catch (SecurityException se) { /* swallow Exception */ }
|
||||
} else {
|
||||
userName = GetPropertyAction.getProperty("user.name");
|
||||
userName = GetPropertyAction.privilegedGetProperty("user.name");
|
||||
}
|
||||
return userName;
|
||||
}
|
||||
|
@ -1198,8 +1198,9 @@ public final class URL implements java.io.Serializable {
|
||||
public URLStreamHandler createURLStreamHandler(String protocol) {
|
||||
String name = PREFIX + "." + protocol + ".Handler";
|
||||
try {
|
||||
Class<?> c = Class.forName(name);
|
||||
return (URLStreamHandler)c.newInstance();
|
||||
@SuppressWarnings("deprecation")
|
||||
Object o = Class.forName(name).newInstance();
|
||||
return (URLStreamHandler)o;
|
||||
} catch (ClassNotFoundException x) {
|
||||
// ignore
|
||||
} catch (Exception e) {
|
||||
@ -1212,7 +1213,7 @@ public final class URL implements java.io.Serializable {
|
||||
|
||||
private static URLStreamHandler lookupViaProperty(String protocol) {
|
||||
String packagePrefixList =
|
||||
GetPropertyAction.getProperty(protocolPathProp);
|
||||
GetPropertyAction.privilegedGetProperty(protocolPathProp);
|
||||
if (packagePrefixList == null) {
|
||||
// not set
|
||||
return null;
|
||||
@ -1234,7 +1235,9 @@ public final class URL implements java.io.Serializable {
|
||||
}
|
||||
}
|
||||
if (cls != null) {
|
||||
handler = (URLStreamHandler)cls.newInstance();
|
||||
@SuppressWarnings("deprecation")
|
||||
Object tmp = cls.newInstance();
|
||||
handler = (URLStreamHandler)tmp;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// any number of exceptions can get thrown here
|
||||
|
@ -1323,7 +1323,9 @@ public abstract class URLConnection {
|
||||
}
|
||||
}
|
||||
if (cls != null) {
|
||||
return (ContentHandler) cls.newInstance();
|
||||
@SuppressWarnings("deprecation")
|
||||
Object tmp = cls.newInstance();
|
||||
return (ContentHandler) tmp;
|
||||
}
|
||||
} catch(Exception ignored) { }
|
||||
}
|
||||
@ -1397,7 +1399,7 @@ public abstract class URLConnection {
|
||||
*/
|
||||
private String getContentHandlerPkgPrefixes() {
|
||||
String packagePrefixList =
|
||||
GetPropertyAction.getProperty(contentPathProp, "");
|
||||
GetPropertyAction.privilegedGetProperty(contentPathProp, "");
|
||||
|
||||
if (packagePrefixList != "") {
|
||||
packagePrefixList += "|";
|
||||
|
@ -133,7 +133,7 @@ public class URLEncoder {
|
||||
dontNeedEncoding.set('.');
|
||||
dontNeedEncoding.set('*');
|
||||
|
||||
dfltEncName = GetPropertyAction.getProperty("file.encoding");
|
||||
dfltEncName = GetPropertyAction.privilegedGetProperty("file.encoding");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,9 +94,10 @@ public abstract class AsynchronousChannelProvider {
|
||||
if (cn == null)
|
||||
return null;
|
||||
try {
|
||||
Class<?> c = Class.forName(cn, true,
|
||||
ClassLoader.getSystemClassLoader());
|
||||
return (AsynchronousChannelProvider)c.newInstance();
|
||||
@SuppressWarnings("deprecation")
|
||||
Object tmp = Class.forName(cn, true,
|
||||
ClassLoader.getSystemClassLoader()).newInstance();
|
||||
return (AsynchronousChannelProvider)tmp;
|
||||
} catch (ClassNotFoundException x) {
|
||||
throw new ServiceConfigurationError(null, x);
|
||||
} catch (IllegalAccessException x) {
|
||||
|
@ -95,9 +95,10 @@ public abstract class SelectorProvider {
|
||||
if (cn == null)
|
||||
return false;
|
||||
try {
|
||||
Class<?> c = Class.forName(cn, true,
|
||||
ClassLoader.getSystemClassLoader());
|
||||
provider = (SelectorProvider)c.newInstance();
|
||||
@SuppressWarnings("deprecation")
|
||||
Object tmp = Class.forName(cn, true,
|
||||
ClassLoader.getSystemClassLoader()).newInstance();
|
||||
provider = (SelectorProvider)tmp;
|
||||
return true;
|
||||
} catch (ClassNotFoundException x) {
|
||||
throw new ServiceConfigurationError(null, x);
|
||||
|
@ -283,8 +283,8 @@ public abstract class Charset
|
||||
if (level == null) {
|
||||
if (!VM.isBooted())
|
||||
return false;
|
||||
bugLevel = level =
|
||||
GetPropertyAction.getProperty("sun.nio.cs.bugLevel", "");
|
||||
bugLevel = level = GetPropertyAction
|
||||
.privilegedGetProperty("sun.nio.cs.bugLevel", "");
|
||||
}
|
||||
return level.equals(bl);
|
||||
}
|
||||
@ -609,7 +609,8 @@ public abstract class Charset
|
||||
public static Charset defaultCharset() {
|
||||
if (defaultCharset == null) {
|
||||
synchronized (Charset.class) {
|
||||
String csn = GetPropertyAction.getProperty("file.encoding");
|
||||
String csn = GetPropertyAction
|
||||
.privilegedGetProperty("file.encoding");
|
||||
Charset cs = lookup(csn);
|
||||
if (cs != null)
|
||||
defaultCharset = cs;
|
||||
|
@ -46,7 +46,7 @@ class TempFileHelper {
|
||||
|
||||
// temporary directory location
|
||||
private static final Path tmpdir =
|
||||
Paths.get(GetPropertyAction.getProperty("java.io.tmpdir"));
|
||||
Paths.get(GetPropertyAction.privilegedGetProperty("java.io.tmpdir"));
|
||||
|
||||
private static final boolean isPosix =
|
||||
FileSystems.getDefault().supportedFileAttributeViews().contains("posix");
|
||||
|
@ -222,8 +222,9 @@ public abstract class Policy {
|
||||
public Policy run() {
|
||||
try {
|
||||
ClassLoader scl = ClassLoader.getSystemClassLoader();
|
||||
Class<?> c = Class.forName(policyProvider, true, scl);
|
||||
return (Policy)c.newInstance();
|
||||
@SuppressWarnings("deprecation")
|
||||
Object o = Class.forName(policyProvider, true, scl).newInstance();
|
||||
return (Policy)o;
|
||||
} catch (Exception e) {
|
||||
if (debug != null) {
|
||||
debug.println("policy provider " + policyProvider +
|
||||
|
@ -147,6 +147,7 @@ public abstract class ZoneRulesProvider {
|
||||
if (prop != null) {
|
||||
try {
|
||||
Class<?> c = Class.forName(prop, true, ClassLoader.getSystemClassLoader());
|
||||
@SuppressWarnings("deprecation")
|
||||
ZoneRulesProvider provider = ZoneRulesProvider.class.cast(c.newInstance());
|
||||
registerProvider(provider);
|
||||
loaded.add(provider);
|
||||
|
@ -858,7 +858,7 @@ public final class Locale implements Cloneable, Serializable {
|
||||
|
||||
private static Locale initDefault() {
|
||||
String language, region, script, country, variant;
|
||||
Properties props = GetPropertyAction.getProperties();
|
||||
Properties props = GetPropertyAction.privilegedGetProperties();
|
||||
language = props.getProperty("user.language", "en");
|
||||
// for compatibility, check for old user.region property
|
||||
region = props.getProperty("user.region");
|
||||
@ -883,7 +883,7 @@ public final class Locale implements Cloneable, Serializable {
|
||||
}
|
||||
|
||||
private static Locale initDefault(Locale.Category category) {
|
||||
Properties props = GetPropertyAction.getProperties();
|
||||
Properties props = GetPropertyAction.privilegedGetProperties();
|
||||
return getInstance(
|
||||
props.getProperty(category.languageKey,
|
||||
defaultLocale.getLanguage()),
|
||||
|
@ -140,9 +140,8 @@ public class PropertyResourceBundle extends ResourceBundle {
|
||||
|
||||
// Check whether the strict encoding is specified.
|
||||
// The possible encoding is either "ISO-8859-1" or "UTF-8".
|
||||
private static final String encoding =
|
||||
GetPropertyAction
|
||||
.getProperty("java.util.PropertyResourceBundle.encoding", "")
|
||||
private static final String encoding = GetPropertyAction
|
||||
.privilegedGetProperty("java.util.PropertyResourceBundle.encoding", "")
|
||||
.toUpperCase(Locale.ROOT);
|
||||
|
||||
/**
|
||||
|
@ -29,8 +29,6 @@ import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleDescriptor.Provides;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Layer;
|
||||
@ -85,7 +83,7 @@ import jdk.internal.reflect.Reflection;
|
||||
* and deployed as a named module must have an appropriate <i>uses</i> clause
|
||||
* in its <i>module descriptor</i> to declare that the module uses
|
||||
* implementations of the service. A corresponding requirement is that a
|
||||
* provider deployed as a named modules must have an appropriate
|
||||
* provider deployed as a named module must have an appropriate
|
||||
* <i>provides</i> clause in its module descriptor to declare that the module
|
||||
* provides an implementation of the service. The <i>uses</i> and
|
||||
* <i>provides</i> allow consumers of a service to be <i>linked</i> to
|
||||
@ -550,35 +548,29 @@ public final class ServiceLoader<S>
|
||||
/**
|
||||
* Implements lazy service provider lookup of service providers that
|
||||
* are provided by modules in a module Layer.
|
||||
*
|
||||
* For now, this iterator examines all modules in each Layer. This will
|
||||
* be replaced once we decide on how the service-use graph is exposed
|
||||
* in the module API.
|
||||
*/
|
||||
private class LayerLookupIterator
|
||||
extends RestrictedIterator<S>
|
||||
{
|
||||
final String serviceName;
|
||||
Layer currentLayer;
|
||||
Iterator<ModuleDescriptor> descriptorIterator;
|
||||
Iterator<String> providersIterator;
|
||||
|
||||
Module nextModule;
|
||||
String nextProvider;
|
||||
Iterator<ServiceProvider> iterator;
|
||||
ServiceProvider nextProvider;
|
||||
|
||||
LayerLookupIterator() {
|
||||
serviceName = service.getName();
|
||||
currentLayer = layer;
|
||||
|
||||
// need to get us started
|
||||
descriptorIterator = descriptors(layer, serviceName);
|
||||
iterator = providers(currentLayer, serviceName);
|
||||
}
|
||||
|
||||
Iterator<ModuleDescriptor> descriptors(Layer layer, String service) {
|
||||
return layer.modules().stream()
|
||||
.map(Module::getDescriptor)
|
||||
.filter(d -> d.provides().get(service) != null)
|
||||
.iterator();
|
||||
Iterator<ServiceProvider> providers(Layer layer, String service) {
|
||||
ServicesCatalog catalog = SharedSecrets
|
||||
.getJavaLangReflectModuleAccess()
|
||||
.getServicesCatalog(layer);
|
||||
|
||||
return catalog.findServices(serviceName).iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -591,30 +583,18 @@ public final class ServiceLoader<S>
|
||||
while (true) {
|
||||
|
||||
// next provider
|
||||
if (providersIterator != null && providersIterator.hasNext()) {
|
||||
nextProvider = providersIterator.next();
|
||||
if (iterator != null && iterator.hasNext()) {
|
||||
nextProvider = iterator.next();
|
||||
return true;
|
||||
}
|
||||
|
||||
// next descriptor
|
||||
if (descriptorIterator.hasNext()) {
|
||||
ModuleDescriptor descriptor = descriptorIterator.next();
|
||||
|
||||
nextModule = currentLayer.findModule(descriptor.name()).get();
|
||||
|
||||
Provides provides = descriptor.provides().get(serviceName);
|
||||
providersIterator = provides.providers().iterator();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// next layer
|
||||
Layer parent = currentLayer.parent().orElse(null);
|
||||
if (parent == null)
|
||||
return false;
|
||||
|
||||
currentLayer = parent;
|
||||
descriptorIterator = descriptors(currentLayer, serviceName);
|
||||
iterator = providers(currentLayer, serviceName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -623,13 +603,14 @@ public final class ServiceLoader<S>
|
||||
if (!hasNextService())
|
||||
throw new NoSuchElementException();
|
||||
|
||||
assert nextModule != null && nextProvider != null;
|
||||
|
||||
String cn = nextProvider;
|
||||
ServiceProvider provider = nextProvider;
|
||||
nextProvider = null;
|
||||
|
||||
Module module = provider.module();
|
||||
String cn = provider.providerName();
|
||||
|
||||
// attempt to load the provider
|
||||
Class<?> c = loadClassInModule(nextModule, cn);
|
||||
Class<?> c = loadClassInModule(module, cn);
|
||||
if (c == null)
|
||||
fail(service, "Provider " + cn + " not found");
|
||||
if (!service.isAssignableFrom(c))
|
||||
@ -830,7 +811,9 @@ public final class ServiceLoader<S>
|
||||
}
|
||||
S p = null;
|
||||
try {
|
||||
p = service.cast(c.newInstance());
|
||||
@SuppressWarnings("deprecation")
|
||||
Object tmp = c.newInstance();
|
||||
p = service.cast(tmp);
|
||||
} catch (Throwable x) {
|
||||
fail(service,
|
||||
"Provider " + cn + " could not be instantiated",
|
||||
|
@ -42,6 +42,7 @@ import java.io.Serializable;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Properties;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
import sun.util.calendar.ZoneInfo;
|
||||
import sun.util.calendar.ZoneInfoFile;
|
||||
@ -660,12 +661,13 @@ public abstract class TimeZone implements Serializable, Cloneable {
|
||||
private static synchronized TimeZone setDefaultZone() {
|
||||
TimeZone tz;
|
||||
// get the time zone ID from the system properties
|
||||
String zoneID = GetPropertyAction.getProperty("user.timezone");
|
||||
Properties props = GetPropertyAction.privilegedGetProperties();
|
||||
String zoneID = props.getProperty("user.timezone");
|
||||
|
||||
// if the time zone ID is not set (yet), perform the
|
||||
// platform to Java time zone ID mapping.
|
||||
if (zoneID == null || zoneID.isEmpty()) {
|
||||
String javaHome = GetPropertyAction.getProperty("java.home");
|
||||
String javaHome = props.getProperty("java.home");
|
||||
try {
|
||||
zoneID = getSystemTimeZoneID(javaHome);
|
||||
if (zoneID == null) {
|
||||
@ -693,13 +695,7 @@ public abstract class TimeZone implements Serializable, Cloneable {
|
||||
assert tz != null;
|
||||
|
||||
final String id = zoneID;
|
||||
AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||
@Override
|
||||
public Void run() {
|
||||
System.setProperty("user.timezone", id);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
props.setProperty("user.timezone", id);
|
||||
|
||||
defaultTimeZone = tz;
|
||||
return tz;
|
||||
|
@ -3507,6 +3507,7 @@ public class ForkJoinPool extends AbstractExecutorService {
|
||||
* Creates and returns the common pool, respecting user settings
|
||||
* specified via system properties.
|
||||
*/
|
||||
@SuppressWarnings("deprecation") // Class.newInstance
|
||||
static ForkJoinPool makeCommonPool() {
|
||||
int parallelism = -1;
|
||||
ForkJoinWorkerThreadFactory factory = null;
|
||||
|
@ -155,7 +155,7 @@ class JarFile extends ZipFile {
|
||||
BASE_VERSION = 8; // one less than lowest version for versioned entries
|
||||
int runtimeVersion = jdk.Version.current().major();
|
||||
String jarVersion =
|
||||
GetPropertyAction.getProperty("jdk.util.jar.version");
|
||||
GetPropertyAction.privilegedGetProperty("jdk.util.jar.version");
|
||||
if (jarVersion != null) {
|
||||
int jarVer = Integer.parseInt(jarVersion);
|
||||
runtimeVersion = (jarVer > runtimeVersion)
|
||||
@ -163,7 +163,7 @@ class JarFile extends ZipFile {
|
||||
}
|
||||
RUNTIME_VERSION = runtimeVersion;
|
||||
String enableMultiRelease = GetPropertyAction
|
||||
.getProperty("jdk.util.jar.enableMultiRelease", "true");
|
||||
.privilegedGetProperty("jdk.util.jar.enableMultiRelease", "true");
|
||||
switch (enableMultiRelease) {
|
||||
case "true":
|
||||
default:
|
||||
@ -658,6 +658,28 @@ class JarFile extends ZipFile {
|
||||
return vze == null ? ze : vze;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the real name of a {@code JarEntry}. If this {@code JarFile} is
|
||||
* a multi-release jar file and is configured to be processed as such, the
|
||||
* name returned by this method is the path name of the versioned entry
|
||||
* that the {@code JarEntry} represents, rather than the path name of the
|
||||
* base entry that {@link JarEntry#getName()} returns. If the
|
||||
* {@code JarEntry} does not represent a versioned entry, or the
|
||||
* jar file is not a multi-release jar file or {@code JarFile} is not
|
||||
* configured for processing a multi-release jar file, this method returns
|
||||
* the same name that {@link JarEntry#getName()} returns.
|
||||
*
|
||||
* @param entry the JarEntry
|
||||
* @return the real name of the JarEntry
|
||||
* @since 9
|
||||
*/
|
||||
String getRealName(JarEntry entry) {
|
||||
if (entry instanceof JarFileEntry) {
|
||||
return ((JarFileEntry)entry).realName();
|
||||
}
|
||||
return entry.getName();
|
||||
}
|
||||
|
||||
private class JarFileEntry extends JarEntry {
|
||||
final private String name;
|
||||
|
||||
@ -684,7 +706,7 @@ class JarFile extends ZipFile {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (certs == null && jv != null) {
|
||||
certs = jv.getCerts(JarFile.this, reifiedEntry());
|
||||
certs = jv.getCerts(JarFile.this, realEntry());
|
||||
}
|
||||
return certs == null ? null : certs.clone();
|
||||
}
|
||||
@ -695,17 +717,20 @@ class JarFile extends ZipFile {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (signers == null && jv != null) {
|
||||
signers = jv.getCodeSigners(JarFile.this, reifiedEntry());
|
||||
signers = jv.getCodeSigners(JarFile.this, realEntry());
|
||||
}
|
||||
return signers == null ? null : signers.clone();
|
||||
}
|
||||
JarFileEntry reifiedEntry() {
|
||||
JarFileEntry realEntry() {
|
||||
if (isMultiRelease()) {
|
||||
String entryName = super.getName();
|
||||
return entryName.equals(this.name) ? this : new JarFileEntry(entryName, this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
String realName() {
|
||||
return super.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
@ -876,11 +901,11 @@ class JarFile extends ZipFile {
|
||||
private JarEntry verifiableEntry(ZipEntry ze) {
|
||||
if (ze instanceof JarFileEntry) {
|
||||
// assure the name and entry match for verification
|
||||
return ((JarFileEntry)ze).reifiedEntry();
|
||||
return ((JarFileEntry)ze).realEntry();
|
||||
}
|
||||
ze = getJarEntry(ze.getName());
|
||||
if (ze instanceof JarFileEntry) {
|
||||
return ((JarFileEntry)ze).reifiedEntry();
|
||||
return ((JarFileEntry)ze).realEntry();
|
||||
}
|
||||
return (JarEntry)ze;
|
||||
}
|
||||
|
@ -60,4 +60,8 @@ class JavaUtilJarAccessImpl implements JavaUtilJarAccess {
|
||||
public List<Object> getManifestDigests(JarFile jar) {
|
||||
return jar.getManifestDigests();
|
||||
}
|
||||
|
||||
public String getRealName(JarFile jar, JarEntry entry) {
|
||||
return jar.getRealName(entry);
|
||||
}
|
||||
}
|
||||
|
@ -695,7 +695,7 @@ public abstract class Pack200 {
|
||||
Class<?> impl = (PACK_PROVIDER.equals(prop))? packerImpl: unpackerImpl;
|
||||
if (impl == null) {
|
||||
// The first time, we must decide which class to use.
|
||||
implName = GetPropertyAction.getProperty(prop,"");
|
||||
implName = GetPropertyAction.privilegedGetProperty(prop,"");
|
||||
if (implName != null && !implName.equals(""))
|
||||
impl = Class.forName(implName);
|
||||
else if (PACK_PROVIDER.equals(prop))
|
||||
@ -704,7 +704,9 @@ public abstract class Pack200 {
|
||||
impl = com.sun.java.util.jar.pack.UnpackerImpl.class;
|
||||
}
|
||||
// We have a class. Now instantiate it.
|
||||
return impl.newInstance();
|
||||
@SuppressWarnings("deprecation")
|
||||
Object result = impl.newInstance();
|
||||
return result;
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new Error("Class not found: " + implName +
|
||||
":\ncheck property " + prop +
|
||||
|
@ -94,7 +94,7 @@ public class PatternSyntaxException
|
||||
}
|
||||
|
||||
private static final String nl =
|
||||
GetPropertyAction.getProperty("line.separator");
|
||||
GetPropertyAction.privilegedGetProperty("line.separator");
|
||||
|
||||
/**
|
||||
* Returns a multi-line string containing the description of the syntax
|
||||
|
@ -55,7 +55,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
*/
|
||||
private static final boolean inhibitZip64 =
|
||||
Boolean.parseBoolean(
|
||||
GetPropertyAction.getProperty("jdk.util.zip.inhibitZip64"));
|
||||
GetPropertyAction.privilegedGetProperty("jdk.util.zip.inhibitZip64"));
|
||||
|
||||
private static class XEntry {
|
||||
final ZipEntry entry;
|
||||
|
@ -97,6 +97,7 @@ public abstract class SSLServerSocketFactory extends ServerSocketFactory
|
||||
}
|
||||
}
|
||||
log("class " + clsName + " is loaded");
|
||||
@SuppressWarnings("deprecation")
|
||||
SSLServerSocketFactory fac = (SSLServerSocketFactory)cls.newInstance();
|
||||
log("instantiated an instance of class " + clsName);
|
||||
theFactory = fac;
|
||||
|
@ -51,7 +51,7 @@ public abstract class SSLSocketFactory extends SocketFactory
|
||||
static final boolean DEBUG;
|
||||
|
||||
static {
|
||||
String s = GetPropertyAction.getProperty("javax.net.debug", "")
|
||||
String s = GetPropertyAction.privilegedGetProperty("javax.net.debug", "")
|
||||
.toLowerCase(Locale.ENGLISH);
|
||||
|
||||
DEBUG = s.contains("all") || s.contains("ssl");
|
||||
@ -106,6 +106,7 @@ public abstract class SSLSocketFactory extends SocketFactory
|
||||
}
|
||||
}
|
||||
log("class " + clsName + " is loaded");
|
||||
@SuppressWarnings("deprecation")
|
||||
SSLSocketFactory fac = (SSLSocketFactory)cls.newInstance();
|
||||
log("instantiated an instance of class " + clsName);
|
||||
theFactory = fac;
|
||||
|
@ -250,7 +250,9 @@ public abstract class Configuration {
|
||||
finalClass, false,
|
||||
Thread.currentThread().getContextClassLoader()
|
||||
).asSubclass(Configuration.class);
|
||||
return implClass.newInstance();
|
||||
@SuppressWarnings("deprecation")
|
||||
Configuration result = implClass.newInstance();
|
||||
return result;
|
||||
}
|
||||
});
|
||||
AccessController.doPrivileged(
|
||||
|
@ -304,7 +304,9 @@ public class LoginContext {
|
||||
Class<? extends CallbackHandler> c = Class.forName(
|
||||
defaultHandler, true,
|
||||
finalLoader).asSubclass(CallbackHandler.class);
|
||||
return c.newInstance();
|
||||
@SuppressWarnings("deprecation")
|
||||
CallbackHandler result = c.newInstance();
|
||||
return result;
|
||||
}
|
||||
});
|
||||
} catch (java.security.PrivilegedActionException pae) {
|
||||
@ -697,8 +699,9 @@ public class LoginContext {
|
||||
|
||||
if (moduleStack[i].module == null) {
|
||||
try {
|
||||
moduleStack[i].module = (LoginModule) Class.forName(
|
||||
name, false, contextClassLoader).newInstance();
|
||||
@SuppressWarnings("deprecation")
|
||||
Object tmp = Class.forName(name, false, contextClassLoader).newInstance();
|
||||
moduleStack[i].module = (LoginModule) tmp;
|
||||
if (debug != null) {
|
||||
debug.println(name + " loaded via reflection");
|
||||
}
|
||||
|
@ -273,7 +273,8 @@ public final class Version
|
||||
*/
|
||||
public static Version current() {
|
||||
if (current == null) {
|
||||
current = parse(GetPropertyAction.getProperty("java.version"));
|
||||
current = parse(
|
||||
GetPropertyAction.privilegedGetProperty("java.version"));
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
@ -124,7 +124,9 @@ public final class JrtFileSystemProvider extends FileSystemProvider {
|
||||
ClassLoader cl = newJrtFsLoader(jrtfs);
|
||||
try {
|
||||
Class<?> c = Class.forName(JrtFileSystemProvider.class.getName(), false, cl);
|
||||
return ((FileSystemProvider)c.newInstance()).newFileSystem(uri, newEnv);
|
||||
@SuppressWarnings("deprecation")
|
||||
Object tmp = c.newInstance();
|
||||
return ((FileSystemProvider)tmp).newFileSystem(uri, newEnv);
|
||||
} catch (ClassNotFoundException |
|
||||
IllegalAccessException |
|
||||
InstantiationException e) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 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
|
||||
@ -68,7 +68,7 @@ public class BootLoader {
|
||||
}
|
||||
|
||||
// ServiceCatalog for the boot class loader
|
||||
private static final ServicesCatalog SERVICES_CATALOG = new ServicesCatalog();
|
||||
private static final ServicesCatalog SERVICES_CATALOG = ServicesCatalog.create();
|
||||
|
||||
// ClassLoaderValue map for boot class loader
|
||||
private static final ConcurrentHashMap<?, ?> CLASS_LOADER_VALUE_MAP =
|
||||
|
@ -104,7 +104,7 @@ public class BuiltinClassLoader
|
||||
* A module defined/loaded by a built-in class loader.
|
||||
*
|
||||
* A LoadedModule encapsulates a ModuleReference along with its CodeSource
|
||||
* URL to avoid needing to create this URL when define classes.
|
||||
* URL to avoid needing to create this URL when defining classes.
|
||||
*/
|
||||
private static class LoadedModule {
|
||||
private final BuiltinClassLoader loader;
|
||||
|
@ -85,7 +85,7 @@ public class URLClassPath {
|
||||
private static final boolean DISABLE_JAR_CHECKING;
|
||||
|
||||
static {
|
||||
Properties props = GetPropertyAction.getProperties();
|
||||
Properties props = GetPropertyAction.privilegedGetProperties();
|
||||
JAVA_VERSION = props.getProperty("java.version");
|
||||
DEBUG = (props.getProperty("sun.misc.URLClassPath.debug") != null);
|
||||
String p = props.getProperty("sun.misc.URLClassPath.disableJarChecking");
|
||||
@ -372,9 +372,15 @@ public class URLClassPath {
|
||||
return java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedExceptionAction<>() {
|
||||
public Loader run() throws IOException {
|
||||
String protocol = url.getProtocol(); // lower cased in URL
|
||||
String file = url.getFile();
|
||||
if (file != null && file.endsWith("/")) {
|
||||
if ("file".equals(url.getProtocol())) {
|
||||
if ("jar".equals(protocol)
|
||||
&& file != null && (file.indexOf("!/") == file.length() - 2)) {
|
||||
// extract the nested URL
|
||||
URL nestedUrl = new URL(file.substring(0, file.length() - 2));
|
||||
return new JarLoader(nestedUrl, jarHandler, lmap);
|
||||
} else if (file != null && file.endsWith("/")) {
|
||||
if ("file".equals(protocol)) {
|
||||
return new FileLoader(url);
|
||||
} else {
|
||||
return new Loader(url);
|
||||
@ -718,13 +724,13 @@ public class URLClassPath {
|
||||
|
||||
final URL url;
|
||||
try {
|
||||
String nm;
|
||||
if (jar.isMultiRelease()) {
|
||||
// add #runtime fragment to tell JarURLConnection to use
|
||||
// runtime versioning if the underlying jar file is multi-release
|
||||
url = new URL(getBaseURL(), ParseUtil.encodePath(name, false) + "#runtime");
|
||||
nm = SharedSecrets.javaUtilJarAccess().getRealName(jar, entry);
|
||||
} else {
|
||||
url = new URL(getBaseURL(), ParseUtil.encodePath(name, false));
|
||||
nm = name;
|
||||
}
|
||||
url = new URL(getBaseURL(), ParseUtil.encodePath(nm, false));
|
||||
if (check) {
|
||||
URLClassPath.check(url);
|
||||
}
|
||||
@ -940,7 +946,8 @@ public class URLClassPath {
|
||||
|
||||
ensureOpen();
|
||||
|
||||
if (SharedSecrets.javaUtilJarAccess().jarFileHasClassPathAttribute(jar)) { // Only get manifest when necessary
|
||||
// Only get manifest when necessary
|
||||
if (SharedSecrets.javaUtilJarAccess().jarFileHasClassPathAttribute(jar)) {
|
||||
Manifest man = jar.getManifest();
|
||||
if (man != null) {
|
||||
Attributes attr = man.getMainAttributes();
|
||||
|
@ -81,7 +81,7 @@ public final class LoggerFinderLoader {
|
||||
// Get configuration error policy
|
||||
private static ErrorPolicy configurationErrorPolicy() {
|
||||
String errorPolicy =
|
||||
GetPropertyAction.getProperty("jdk.logger.finder.error");
|
||||
GetPropertyAction.privilegedGetProperty("jdk.logger.finder.error");
|
||||
if (errorPolicy == null || errorPolicy.isEmpty()) {
|
||||
return ErrorPolicy.WARNING;
|
||||
}
|
||||
@ -96,7 +96,7 @@ public final class LoggerFinderLoader {
|
||||
// This is further submitted to the configuration error policy.
|
||||
private static boolean ensureSingletonProvider() {
|
||||
return Boolean.parseBoolean(
|
||||
GetPropertyAction.getProperty("jdk.logger.finder.singleton"));
|
||||
GetPropertyAction.privilegedGetProperty("jdk.logger.finder.singleton"));
|
||||
}
|
||||
|
||||
private static Iterator<System.LoggerFinder> findLoggerFinderProviders() {
|
||||
|
@ -56,7 +56,7 @@ public class SimpleConsoleLogger extends LoggerConfiguration
|
||||
|
||||
static Level getDefaultLevel() {
|
||||
String levelName = GetPropertyAction
|
||||
.getProperty("jdk.system.logger.level", "INFO");
|
||||
.privilegedGetProperty("jdk.system.logger.level", "INFO");
|
||||
try {
|
||||
return Level.valueOf(levelName);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
@ -426,7 +426,7 @@ public class SimpleConsoleLogger extends LoggerConfiguration
|
||||
static private final String[] skips;
|
||||
static {
|
||||
String additionalPkgs =
|
||||
GetPropertyAction.getProperty("jdk.logger.packages");
|
||||
GetPropertyAction.privilegedGetProperty("jdk.logger.packages");
|
||||
skips = additionalPkgs == null ? new String[0] : additionalPkgs.split(",");
|
||||
}
|
||||
|
||||
@ -485,7 +485,7 @@ public class SimpleConsoleLogger extends LoggerConfiguration
|
||||
// jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java
|
||||
// to fail - because that test has a testcase which somehow references
|
||||
// PlatformLogger and counts the number of generated lambda classes.
|
||||
String format = GetPropertyAction.getProperty(key);
|
||||
String format = GetPropertyAction.privilegedGetProperty(key);
|
||||
|
||||
if (format == null && defaultPropertyGetter != null) {
|
||||
format = defaultPropertyGetter.apply(key);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 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
|
||||
@ -25,13 +25,24 @@
|
||||
|
||||
package jdk.internal.misc;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.lang.module.Configuration;
|
||||
import jdk.internal.module.ModuleHashes;
|
||||
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleDescriptor.Exports;
|
||||
import java.lang.module.ModuleDescriptor.Requires;
|
||||
import java.lang.module.ModuleDescriptor.Provides;
|
||||
import java.lang.module.ModuleDescriptor.Version;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.util.Collection;
|
||||
import java.lang.module.ModuleReader;
|
||||
import java.lang.module.ModuleReference;
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Provides access to non-public methods in java.lang.module.
|
||||
@ -89,5 +100,29 @@ public interface JavaLangModuleAccess {
|
||||
String osArch,
|
||||
String osVersion,
|
||||
Set<String> conceals,
|
||||
Set<String> packages);
|
||||
Set<String> packages,
|
||||
ModuleHashes hashes);
|
||||
|
||||
/**
|
||||
* Resolves a collection of root modules, with service binding
|
||||
* and the empty configuration as the parent. The post resolution
|
||||
* checks are optionally run.
|
||||
*/
|
||||
Configuration resolveRequiresAndUses(ModuleFinder finder,
|
||||
Collection<String> roots,
|
||||
boolean check,
|
||||
PrintStream traceOutput);
|
||||
|
||||
/**
|
||||
* Creates a ModuleReference to a "patched" module.
|
||||
*/
|
||||
ModuleReference newPatchedModule(ModuleDescriptor descriptor,
|
||||
URI location,
|
||||
Supplier<ModuleReader> readerSupplier);
|
||||
|
||||
/**
|
||||
* Returns the object with the hashes of other modules
|
||||
*/
|
||||
Optional<ModuleHashes> hashes(ModuleDescriptor descriptor);
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
@ -26,9 +26,12 @@
|
||||
package jdk.internal.misc;
|
||||
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.reflect.Layer;
|
||||
import java.lang.reflect.Module;
|
||||
import java.net.URI;
|
||||
|
||||
import jdk.internal.module.ServicesCatalog;
|
||||
|
||||
/**
|
||||
* Provides access to non-public methods in java.lang.reflect.Module
|
||||
*/
|
||||
@ -56,6 +59,11 @@ public interface JavaLangReflectModuleAccess {
|
||||
*/
|
||||
void addReads(Module m1, Module m2);
|
||||
|
||||
/**
|
||||
* Updates module m to read all unnamed modules.
|
||||
*/
|
||||
void addReadsAllUnnamed(Module m);
|
||||
|
||||
/**
|
||||
* Updates module m1 to export a package to module m2. The export does
|
||||
* not result in a strong reference to m2 (m2 can be GC'ed).
|
||||
@ -76,4 +84,10 @@ public interface JavaLangReflectModuleAccess {
|
||||
* Add a package to the given module.
|
||||
*/
|
||||
void addPackage(Module m, String pkg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ServicesCatalog for the given Layer.
|
||||
*/
|
||||
ServicesCatalog getServicesCatalog(Layer layer);
|
||||
|
||||
}
|
@ -41,4 +41,5 @@ public interface JavaUtilJarAccess {
|
||||
public Enumeration<JarEntry> entries2(JarFile jar);
|
||||
public void setEagerValidation(JarFile jar, boolean eager);
|
||||
public List<Object> getManifestDigests(JarFile jar);
|
||||
public String getRealName(JarFile jar, JarEntry entry);
|
||||
}
|
||||
|
@ -74,6 +74,8 @@ final class Builder {
|
||||
String osName;
|
||||
String osArch;
|
||||
String osVersion;
|
||||
String algorithm;
|
||||
Map<String, String> hashes;
|
||||
|
||||
Builder(String name, int reqs, int exports,
|
||||
int provides, int conceals, int packages) {
|
||||
@ -251,6 +253,25 @@ 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, String hash) {
|
||||
if (hashes == null)
|
||||
hashes = new HashMap<>();
|
||||
|
||||
hashes.put(mn, hash);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of packages that is the union of the exported and
|
||||
* concealed packages.
|
||||
@ -273,6 +294,9 @@ final class Builder {
|
||||
public ModuleDescriptor build() {
|
||||
assert name != null;
|
||||
|
||||
ModuleHashes moduleHashes =
|
||||
hashes != null ? new ModuleHashes(algorithm, hashes) : null;
|
||||
|
||||
return jlma.newModuleDescriptor(name,
|
||||
false, // automatic
|
||||
false, // assume not synthetic for now
|
||||
@ -286,6 +310,7 @@ final class Builder {
|
||||
osArch,
|
||||
osVersion,
|
||||
conceals,
|
||||
computePackages(exports, conceals));
|
||||
computePackages(exports, conceals),
|
||||
moduleHashes);
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import java.lang.module.ModuleDescriptor.Version;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@ -42,7 +43,6 @@ import jdk.internal.org.objectweb.asm.ByteVector;
|
||||
import jdk.internal.org.objectweb.asm.ClassReader;
|
||||
import jdk.internal.org.objectweb.asm.ClassWriter;
|
||||
import jdk.internal.org.objectweb.asm.Label;
|
||||
import jdk.internal.module.Hasher.DependencyHashes;
|
||||
import static jdk.internal.module.ClassFileConstants.*;
|
||||
|
||||
|
||||
@ -148,7 +148,7 @@ class ClassFileAttributes {
|
||||
for (int i=0; i<provides_count; i++) {
|
||||
String sn = cr.readClass(off, buf).replace('/', '.');
|
||||
String cn = cr.readClass(off + 2, buf).replace('/', '.');
|
||||
provides.computeIfAbsent(sn, k -> new HashSet<>()).add(cn);
|
||||
provides.computeIfAbsent(sn, k -> new LinkedHashSet<>()).add(cn);
|
||||
off += 4;
|
||||
}
|
||||
provides.entrySet().forEach(e -> builder.provides(e.getKey(),
|
||||
@ -281,10 +281,10 @@ class ClassFileAttributes {
|
||||
* u4 attribute_length;
|
||||
*
|
||||
* // the number of entries in the packages table
|
||||
* u2 package_count;
|
||||
* u2 packages_count;
|
||||
* { // index to CONSTANT_CONSTANT_utf8_info structure with the package name
|
||||
* u2 package_index
|
||||
* } package[package_count];
|
||||
* } packages[package_count];
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@ -579,9 +579,9 @@ class ClassFileAttributes {
|
||||
* alternative is to store it as an array of u1.
|
||||
*/
|
||||
static class HashesAttribute extends Attribute {
|
||||
private final DependencyHashes hashes;
|
||||
private final ModuleHashes hashes;
|
||||
|
||||
HashesAttribute(DependencyHashes hashes) {
|
||||
HashesAttribute(ModuleHashes hashes) {
|
||||
super(HASHES);
|
||||
this.hashes = hashes;
|
||||
}
|
||||
@ -613,7 +613,7 @@ class ClassFileAttributes {
|
||||
map.put(dn, hash);
|
||||
}
|
||||
|
||||
DependencyHashes hashes = new DependencyHashes(algorithm, map);
|
||||
ModuleHashes hashes = new ModuleHashes(algorithm, map);
|
||||
|
||||
return new HashesAttribute(hashes);
|
||||
}
|
||||
|
@ -26,12 +26,15 @@
|
||||
package jdk.internal.module;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.module.Configuration;
|
||||
import java.lang.module.ModuleReference;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.lang.module.ModuleReference;
|
||||
import java.lang.module.ResolvedModule;
|
||||
import java.lang.reflect.Layer;
|
||||
import java.lang.reflect.Module;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
@ -41,10 +44,10 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jdk.internal.loader.BootLoader;
|
||||
import jdk.internal.loader.BuiltinClassLoader;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import jdk.internal.perf.PerfCounter;
|
||||
|
||||
/**
|
||||
@ -54,10 +57,9 @@ import jdk.internal.perf.PerfCounter;
|
||||
* the module system. In summary, the boot method creates a Configuration by
|
||||
* resolving a set of module names specified via the launcher (or equivalent)
|
||||
* -m and -addmods options. The modules are located on a module path that is
|
||||
* constructed from the upgrade, system and application module paths. The
|
||||
* Configuration is reified by creating the boot Layer with each module in the
|
||||
* the configuration defined to one of the built-in class loaders. The mapping
|
||||
* of modules to class loaders is statically mapped in a helper class.
|
||||
* constructed from the upgrade module path, system modules, and application
|
||||
* module path. The Configuration is instantiated as the boot Layer with each
|
||||
* module in the the configuration defined to one of the built-in class loaders.
|
||||
*/
|
||||
|
||||
public final class ModuleBootstrap {
|
||||
@ -65,6 +67,11 @@ public final class ModuleBootstrap {
|
||||
|
||||
private static final String JAVA_BASE = "java.base";
|
||||
|
||||
private static final String JAVA_SE = "java.se";
|
||||
|
||||
// the token for "all default modules"
|
||||
private static final String ALL_DEFAULT = "ALL-DEFAULT";
|
||||
|
||||
// the token for "all unnamed modules"
|
||||
private static final String ALL_UNNAMED = "ALL-UNNAMED";
|
||||
|
||||
@ -94,47 +101,65 @@ public final class ModuleBootstrap {
|
||||
|
||||
long t0 = System.nanoTime();
|
||||
|
||||
// system module path
|
||||
ModuleFinder systemModulePath = ModuleFinder.ofSystem();
|
||||
// system modules
|
||||
ModuleFinder systemModules = ModuleFinder.ofSystem();
|
||||
|
||||
// Once we have the system module path then we define the base module.
|
||||
// We do this here so that java.base is defined to the VM as early as
|
||||
PerfCounters.systemModulesTime.addElapsedTimeFrom(t0);
|
||||
|
||||
|
||||
long t1 = System.nanoTime();
|
||||
|
||||
// Once we have the system modules then we define the base module to
|
||||
// the VM. We do this here so that java.base is defined as early as
|
||||
// possible and also that resources in the base module can be located
|
||||
// for error messages that may happen from here on.
|
||||
Optional<ModuleReference> obase = systemModulePath.find(JAVA_BASE);
|
||||
if (!obase.isPresent())
|
||||
ModuleReference base = systemModules.find(JAVA_BASE).orElse(null);
|
||||
if (base == null)
|
||||
throw new InternalError(JAVA_BASE + " not found");
|
||||
ModuleReference base = obase.get();
|
||||
URI baseUri = base.location().orElse(null);
|
||||
if (baseUri == null)
|
||||
throw new InternalError(JAVA_BASE + " does not have a location");
|
||||
BootLoader.loadModule(base);
|
||||
Modules.defineModule(null, base.descriptor(), base.location().orElse(null));
|
||||
Modules.defineModule(null, base.descriptor(), baseUri);
|
||||
|
||||
PerfCounters.defineBaseTime.addElapsedTimeFrom(t1);
|
||||
|
||||
|
||||
long t2 = System.nanoTime();
|
||||
|
||||
// -upgrademodulepath option specified to launcher
|
||||
ModuleFinder upgradeModulePath
|
||||
= createModulePathFinder("jdk.upgrade.module.path");
|
||||
if (upgradeModulePath != null)
|
||||
systemModules = ModuleFinder.compose(upgradeModulePath, systemModules);
|
||||
|
||||
// -modulepath option specified to the launcher
|
||||
ModuleFinder appModulePath = createModulePathFinder("jdk.module.path");
|
||||
|
||||
// The module finder: [-upgrademodulepath] system-module-path [-modulepath]
|
||||
ModuleFinder finder = systemModulePath;
|
||||
if (upgradeModulePath != null)
|
||||
finder = ModuleFinder.compose(upgradeModulePath, finder);
|
||||
// The module finder: [-upgrademodulepath] system [-modulepath]
|
||||
ModuleFinder finder = systemModules;
|
||||
if (appModulePath != null)
|
||||
finder = ModuleFinder.compose(finder, appModulePath);
|
||||
|
||||
// launcher -m option to specify the initial module
|
||||
// The root modules to resolve
|
||||
Set<String> roots = new HashSet<>();
|
||||
|
||||
// launcher -m option to specify the main/initial module
|
||||
String mainModule = System.getProperty("jdk.module.main");
|
||||
if (mainModule != null)
|
||||
roots.add(mainModule);
|
||||
|
||||
// additional module(s) specified by -addmods
|
||||
boolean addAllDefaultModules = false;
|
||||
boolean addAllSystemModules = false;
|
||||
boolean addAllApplicationModules = false;
|
||||
Set<String> addModules = null;
|
||||
String propValue = System.getProperty("jdk.launcher.addmods");
|
||||
if (propValue != null) {
|
||||
addModules = new HashSet<>();
|
||||
for (String mod: propValue.split(",")) {
|
||||
switch (mod) {
|
||||
case ALL_DEFAULT:
|
||||
addAllDefaultModules = true;
|
||||
break;
|
||||
case ALL_SYSTEM:
|
||||
addAllSystemModules = true;
|
||||
break;
|
||||
@ -142,28 +167,12 @@ public final class ModuleBootstrap {
|
||||
addAllApplicationModules = true;
|
||||
break;
|
||||
default :
|
||||
addModules.add(mod);
|
||||
roots.add(mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The root modules to resolve
|
||||
Set<String> roots = new HashSet<>();
|
||||
|
||||
// main/initial module
|
||||
if (mainModule != null) {
|
||||
roots.add(mainModule);
|
||||
if (addAllApplicationModules)
|
||||
fail(ALL_MODULE_PATH + " not allowed with initial module");
|
||||
}
|
||||
|
||||
// If -addmods is specified then those modules need to be resolved
|
||||
if (addModules != null)
|
||||
roots.addAll(addModules);
|
||||
|
||||
|
||||
// -limitmods
|
||||
boolean limitmods = false;
|
||||
propValue = System.getProperty("jdk.launcher.limitmods");
|
||||
if (propValue != null) {
|
||||
Set<String> mods = new HashSet<>();
|
||||
@ -171,62 +180,101 @@ public final class ModuleBootstrap {
|
||||
mods.add(mod);
|
||||
}
|
||||
finder = limitFinder(finder, mods, roots);
|
||||
limitmods = true;
|
||||
}
|
||||
|
||||
|
||||
// If there is no initial module specified then assume that the
|
||||
// initial module is the unnamed module of the application class
|
||||
// loader. By convention, and for compatibility, this is
|
||||
// implemented by putting the names of all modules on the system
|
||||
// module path into the set of modules to resolve.
|
||||
//
|
||||
// If `-addmods ALL-SYSTEM` is used then all modules on the system
|
||||
// module path will be resolved, irrespective of whether an initial
|
||||
// module is specified.
|
||||
//
|
||||
// If `-addmods ALL-MODULE-PATH` is used, and no initial module is
|
||||
// specified, then all modules on the application module path will
|
||||
// be resolved.
|
||||
//
|
||||
if (mainModule == null || addAllSystemModules) {
|
||||
Set<ModuleReference> mrefs;
|
||||
if (addAllApplicationModules) {
|
||||
assert mainModule == null;
|
||||
mrefs = finder.findAll();
|
||||
} else {
|
||||
mrefs = systemModulePath.findAll();
|
||||
if (limitmods) {
|
||||
ModuleFinder f = finder;
|
||||
mrefs = mrefs.stream()
|
||||
.filter(m -> f.find(m.descriptor().name()).isPresent())
|
||||
.collect(Collectors.toSet());
|
||||
// If there is no initial module specified then assume that the initial
|
||||
// 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.
|
||||
if (mainModule == null || addAllDefaultModules) {
|
||||
boolean hasJava = false;
|
||||
if (systemModules.find(JAVA_SE).isPresent()) {
|
||||
// java.se is a system module
|
||||
if (finder == systemModules || finder.find(JAVA_SE).isPresent()) {
|
||||
// java.se is observable
|
||||
hasJava = true;
|
||||
roots.add(JAVA_SE);
|
||||
}
|
||||
}
|
||||
// map to module names
|
||||
for (ModuleReference mref : mrefs) {
|
||||
roots.add(mref.descriptor().name());
|
||||
|
||||
for (ModuleReference mref : systemModules.findAll()) {
|
||||
String mn = mref.descriptor().name();
|
||||
if (hasJava && mn.startsWith("java."))
|
||||
continue;
|
||||
|
||||
// add as root if observable and exports at least one package
|
||||
if ((finder == systemModules || finder.find(mn).isPresent())) {
|
||||
ModuleDescriptor descriptor = mref.descriptor();
|
||||
for (ModuleDescriptor.Exports e : descriptor.exports()) {
|
||||
if (!e.isQualified()) {
|
||||
roots.add(mn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long t1 = System.nanoTime();
|
||||
// If `-addmods ALL-SYSTEM` is specified then all observable system
|
||||
// modules will be resolved.
|
||||
if (addAllSystemModules) {
|
||||
ModuleFinder f = finder; // observable modules
|
||||
systemModules.findAll()
|
||||
.stream()
|
||||
.map(ModuleReference::descriptor)
|
||||
.map(ModuleDescriptor::name)
|
||||
.filter(mn -> f.find(mn).isPresent()) // observable
|
||||
.forEach(mn -> roots.add(mn));
|
||||
}
|
||||
|
||||
// If `-addmods ALL-MODULE-PATH` is specified then all observable
|
||||
// modules on the application module path will be resolved.
|
||||
if (appModulePath != null && addAllApplicationModules) {
|
||||
ModuleFinder f = finder; // observable modules
|
||||
appModulePath.findAll()
|
||||
.stream()
|
||||
.map(ModuleReference::descriptor)
|
||||
.map(ModuleDescriptor::name)
|
||||
.filter(mn -> f.find(mn).isPresent()) // observable
|
||||
.forEach(mn -> roots.add(mn));
|
||||
}
|
||||
|
||||
PerfCounters.optionsAndRootsTime.addElapsedTimeFrom(t2);
|
||||
|
||||
|
||||
long t3 = System.nanoTime();
|
||||
|
||||
// determine if post resolution checks are needed
|
||||
boolean needPostResolutionChecks = true;
|
||||
if (baseUri.getScheme().equals("jrt") // toLowerCase not needed here
|
||||
&& (upgradeModulePath == null)
|
||||
&& (appModulePath == null)
|
||||
&& (System.getProperty("jdk.launcher.patch.0") == null)) {
|
||||
needPostResolutionChecks = false;
|
||||
}
|
||||
|
||||
PrintStream traceOutput = null;
|
||||
if (Boolean.getBoolean("jdk.launcher.traceResolver"))
|
||||
traceOutput = System.out;
|
||||
|
||||
// run the resolver to create the configuration
|
||||
|
||||
Configuration cf = Configuration.empty()
|
||||
Configuration cf = SharedSecrets.getJavaLangModuleAccess()
|
||||
.resolveRequiresAndUses(finder,
|
||||
ModuleFinder.empty(),
|
||||
roots);
|
||||
roots,
|
||||
needPostResolutionChecks,
|
||||
traceOutput);
|
||||
|
||||
// time to create configuration
|
||||
PerfCounters.resolveTime.addElapsedTimeFrom(t1);
|
||||
PerfCounters.resolveTime.addElapsedTimeFrom(t3);
|
||||
|
||||
|
||||
// mapping of modules to class loaders
|
||||
Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
|
||||
|
||||
// check that all modules to be mapped to the boot loader will be
|
||||
// loaded from the system module path
|
||||
if (finder != systemModulePath) {
|
||||
// loaded from the runtime image
|
||||
if (needPostResolutionChecks) {
|
||||
for (ResolvedModule resolvedModule : cf.modules()) {
|
||||
ModuleReference mref = resolvedModule.reference();
|
||||
String name = mref.descriptor().name();
|
||||
@ -237,20 +285,22 @@ public final class ModuleBootstrap {
|
||||
&& upgradeModulePath.find(name).isPresent())
|
||||
fail(name + ": cannot be loaded from upgrade module path");
|
||||
|
||||
if (!systemModulePath.find(name).isPresent())
|
||||
if (!systemModules.find(name).isPresent())
|
||||
fail(name + ": cannot be loaded from application module path");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long t2 = System.nanoTime();
|
||||
|
||||
long t4 = System.nanoTime();
|
||||
|
||||
// define modules to VM/runtime
|
||||
Layer bootLayer = Layer.empty().defineModules(cf, clf);
|
||||
|
||||
PerfCounters.layerCreateTime.addElapsedTimeFrom(t2);
|
||||
PerfCounters.layerCreateTime.addElapsedTimeFrom(t4);
|
||||
|
||||
long t3 = System.nanoTime();
|
||||
|
||||
long t5 = System.nanoTime();
|
||||
|
||||
// define the module to its class loader, except java.base
|
||||
for (ResolvedModule resolvedModule : cf.modules()) {
|
||||
@ -264,7 +314,8 @@ public final class ModuleBootstrap {
|
||||
}
|
||||
}
|
||||
|
||||
PerfCounters.loadModulesTime.addElapsedTimeFrom(t3);
|
||||
PerfCounters.loadModulesTime.addElapsedTimeFrom(t5);
|
||||
|
||||
|
||||
// -XaddReads and -XaddExports
|
||||
addExtraReads(bootLayer);
|
||||
@ -295,25 +346,21 @@ public final class ModuleBootstrap {
|
||||
|
||||
// module name -> reference
|
||||
Map<String, ModuleReference> map = new HashMap<>();
|
||||
|
||||
// root modules and their transitive dependences
|
||||
cf.modules().stream()
|
||||
.map(ResolvedModule::reference)
|
||||
.forEach(mref -> map.put(mref.descriptor().name(), mref));
|
||||
|
||||
// additional modules
|
||||
otherMods.stream()
|
||||
.map(finder::find)
|
||||
.flatMap(Optional::stream)
|
||||
.forEach(mref -> map.putIfAbsent(mref.descriptor().name(), mref));
|
||||
|
||||
// set of modules that are observable
|
||||
Set<ModuleReference> mrefs = new HashSet<>(map.values());
|
||||
|
||||
// add the other modules
|
||||
for (String mod : otherMods) {
|
||||
Optional<ModuleReference> omref = finder.find(mod);
|
||||
if (omref.isPresent()) {
|
||||
ModuleReference mref = omref.get();
|
||||
map.putIfAbsent(mod, mref);
|
||||
mrefs.add(mref);
|
||||
} else {
|
||||
// no need to fail
|
||||
}
|
||||
}
|
||||
|
||||
return new ModuleFinder() {
|
||||
@Override
|
||||
public Optional<ModuleReference> find(String name) {
|
||||
@ -369,15 +416,15 @@ public final class ModuleBootstrap {
|
||||
|
||||
Module other;
|
||||
if (ALL_UNNAMED.equals(name)) {
|
||||
other = null; // loose
|
||||
Modules.addReadsAllUnnamed(m);
|
||||
} else {
|
||||
om = bootLayer.findModule(name);
|
||||
if (!om.isPresent())
|
||||
fail("Unknown module: " + name);
|
||||
other = om.get();
|
||||
Modules.addReads(m, other);
|
||||
}
|
||||
|
||||
Modules.addReads(m, other);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -439,10 +486,6 @@ public final class ModuleBootstrap {
|
||||
* Decodes the values of -XaddReads or -XaddExports options
|
||||
*
|
||||
* The format of the options is: $KEY=$MODULE(,$MODULE)*
|
||||
*
|
||||
* For transition purposes, this method allows the first usage to be
|
||||
* $KEY=$MODULE(,$KEY=$MODULE)
|
||||
* This format will eventually be removed.
|
||||
*/
|
||||
private static Map<String, Set<String>> decode(String prefix) {
|
||||
int index = 0;
|
||||
@ -467,42 +510,15 @@ public final class ModuleBootstrap {
|
||||
if (rhs.isEmpty())
|
||||
fail("Unable to parse: " + value);
|
||||
|
||||
// new format $MODULE(,$MODULE)* or old format $(MODULE)=...
|
||||
pos = rhs.indexOf('=');
|
||||
|
||||
// old format only allowed in first -X option
|
||||
if (pos >= 0 && index > 0)
|
||||
fail("Unable to parse: " + value);
|
||||
// value is <module>(,<module>)*
|
||||
if (map.containsKey(key))
|
||||
fail(key + " specified more than once");
|
||||
|
||||
if (pos == -1) {
|
||||
|
||||
// new format: $KEY=$MODULE(,$MODULE)*
|
||||
|
||||
Set<String> values = map.get(key);
|
||||
if (values != null)
|
||||
fail(key + " specified more than once");
|
||||
|
||||
values = new HashSet<>();
|
||||
map.put(key, values);
|
||||
for (String s : rhs.split(",")) {
|
||||
if (s.length() > 0) values.add(s);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// old format: $KEY=$MODULE(,$KEY=$MODULE)*
|
||||
|
||||
assert index == 0; // old format only allowed in first usage
|
||||
|
||||
for (String expr : value.split(",")) {
|
||||
if (expr.length() > 0) {
|
||||
String[] s = expr.split("=");
|
||||
if (s.length != 2)
|
||||
fail("Unable to parse: " + expr);
|
||||
|
||||
map.computeIfAbsent(s[0], k -> new HashSet<>()).add(s[1]);
|
||||
}
|
||||
}
|
||||
Set<String> values = new HashSet<>();
|
||||
map.put(key, values);
|
||||
for (String s : rhs.split(",")) {
|
||||
if (s.length() > 0) values.add(s);
|
||||
}
|
||||
|
||||
index++;
|
||||
@ -521,6 +537,13 @@ public final class ModuleBootstrap {
|
||||
}
|
||||
|
||||
static class PerfCounters {
|
||||
|
||||
static PerfCounter systemModulesTime
|
||||
= PerfCounter.newPerfCounter("jdk.module.bootstrap.systemModulesTime");
|
||||
static PerfCounter defineBaseTime
|
||||
= PerfCounter.newPerfCounter("jdk.module.bootstrap.defineBaseTime");
|
||||
static PerfCounter optionsAndRootsTime
|
||||
= PerfCounter.newPerfCounter("jdk.module.bootstrap.optionsAndRootsTime");
|
||||
static PerfCounter resolveTime
|
||||
= PerfCounter.newPerfCounter("jdk.module.bootstrap.resolveTime");
|
||||
static PerfCounter layerCreateTime
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 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,6 +22,7 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.internal.module;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -32,17 +33,16 @@ import java.nio.file.Path;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Supporting class for computing, encoding and decoding hashes (message
|
||||
* digests).
|
||||
* The result of hashing the contents of a number of module artifacts.
|
||||
*/
|
||||
|
||||
public class Hasher {
|
||||
private Hasher() { }
|
||||
public final class ModuleHashes {
|
||||
|
||||
/**
|
||||
* A supplier of an encoded message digest.
|
||||
@ -51,43 +51,49 @@ public class Hasher {
|
||||
String generate(String algorithm);
|
||||
}
|
||||
|
||||
|
||||
private final String algorithm;
|
||||
private final Map<String, String> nameToHash;
|
||||
|
||||
/**
|
||||
* Encapsulates the result of hashing the contents of a number of module
|
||||
* artifacts.
|
||||
* Creates a {@code ModuleHashes}.
|
||||
*
|
||||
* @param algorithm the algorithm used to create the hashes
|
||||
* @param nameToHash the map of module name to hash value (in string form)
|
||||
*/
|
||||
public static class DependencyHashes {
|
||||
private final String algorithm;
|
||||
private final Map<String, String> nameToHash;
|
||||
|
||||
public DependencyHashes(String algorithm, Map<String, String> nameToHash) {
|
||||
this.algorithm = algorithm;
|
||||
this.nameToHash = nameToHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the algorithm used to hash the dependences ("SHA-256" or
|
||||
* "MD5" for example).
|
||||
*/
|
||||
public String algorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of module names for which hashes are recorded.
|
||||
*/
|
||||
public Set<String> names() {
|
||||
return nameToHash.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retruns the hash string for the given module name, {@code null}
|
||||
* if there is no hash recorded for the module.
|
||||
*/
|
||||
public String hashFor(String dn) {
|
||||
return nameToHash.get(dn);
|
||||
}
|
||||
public ModuleHashes(String algorithm, Map<String, String> nameToHash) {
|
||||
this.algorithm = algorithm;
|
||||
this.nameToHash = Collections.unmodifiableMap(nameToHash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the algorithm used to hash the modules ("SHA-256" for example).
|
||||
*/
|
||||
public String algorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of module names for which hashes are recorded.
|
||||
*/
|
||||
public Set<String> names() {
|
||||
return nameToHash.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hash string for the given module name, {@code null}
|
||||
* if there is no hash recorded for the module.
|
||||
*/
|
||||
public String hashFor(String mn) {
|
||||
return nameToHash.get(mn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns unmodifiable map of module name to hash string.
|
||||
*/
|
||||
public Map<String, String> hashes() {
|
||||
return nameToHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the hash for the given file with the given message digest
|
||||
@ -96,7 +102,7 @@ public class Hasher {
|
||||
* @throws UncheckedIOException if an I/O error occurs
|
||||
* @throws RuntimeException if the algorithm is not available
|
||||
*/
|
||||
public static String generate(Path file, String algorithm) {
|
||||
public static String computeHashAsString(Path file, String algorithm) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance(algorithm);
|
||||
|
||||
@ -104,8 +110,7 @@ public class Hasher {
|
||||
// memory when jlink is running concurrently on very large jmods
|
||||
try (FileChannel fc = FileChannel.open(file)) {
|
||||
ByteBuffer bb = ByteBuffer.allocate(32*1024);
|
||||
int nread;
|
||||
while ((nread = fc.read(bb)) > 0) {
|
||||
while (fc.read(bb) > 0) {
|
||||
bb.flip();
|
||||
md.update(bb);
|
||||
assert bb.remaining() == 0;
|
||||
@ -124,19 +129,19 @@ public class Hasher {
|
||||
|
||||
/**
|
||||
* Computes the hash for every entry in the given map, returning a
|
||||
* {@code DependencyHashes} to encapsulate the result. The map key is
|
||||
* {@code ModuleHashes} to encapsulate the result. The map key is
|
||||
* the entry name, typically the module name. The map value is the file
|
||||
* path to the entry (module artifact).
|
||||
*
|
||||
* @return DependencyHashes encapsulate the hashes
|
||||
* @return ModuleHashes encapsulate the hashes
|
||||
*/
|
||||
public static DependencyHashes generate(Map<String, Path> map, String algorithm) {
|
||||
public static ModuleHashes generate(Map<String, Path> map, String algorithm) {
|
||||
Map<String, String> nameToHash = new HashMap<>();
|
||||
for (Map.Entry<String, Path> entry: map.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
Path path = entry.getValue();
|
||||
nameToHash.put(name, generate(path, algorithm));
|
||||
nameToHash.put(name, computeHashAsString(path, algorithm));
|
||||
}
|
||||
return new DependencyHashes(algorithm, nameToHash);
|
||||
return new ModuleHashes(algorithm, nameToHash);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2015, 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
|
||||
@ -41,7 +41,6 @@ import jdk.internal.org.objectweb.asm.ClassReader;
|
||||
import jdk.internal.org.objectweb.asm.ClassVisitor;
|
||||
import jdk.internal.org.objectweb.asm.ClassWriter;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
import jdk.internal.module.Hasher.DependencyHashes;
|
||||
|
||||
import static jdk.internal.module.ClassFileAttributes.*;
|
||||
|
||||
@ -69,7 +68,7 @@ public final class ModuleInfoExtender {
|
||||
private String osVersion;
|
||||
|
||||
// the hashes for the Hashes attribute
|
||||
private DependencyHashes hashes;
|
||||
private ModuleHashes hashes;
|
||||
|
||||
private ModuleInfoExtender(InputStream in) {
|
||||
this.in = in;
|
||||
@ -113,10 +112,10 @@ public final class ModuleInfoExtender {
|
||||
|
||||
/**
|
||||
* The Hashes attribute will be emitted to the module-info with
|
||||
* the hashes encapsulated in the given {@code DependencyHashes}
|
||||
* the hashes encapsulated in the given {@code ModuleHashes}
|
||||
* object.
|
||||
*/
|
||||
public ModuleInfoExtender hashes(DependencyHashes hashes) {
|
||||
public ModuleInfoExtender hashes(ModuleHashes hashes) {
|
||||
this.hashes = hashes;
|
||||
return this;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 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
|
||||
@ -49,28 +49,22 @@ public final class ModuleInfoWriter {
|
||||
* Writes the given module descriptor to a module-info.class file,
|
||||
* returning it in a byte array.
|
||||
*/
|
||||
private static byte[] toModuleInfo(ModuleDescriptor descriptor) {
|
||||
private static byte[] toModuleInfo(ModuleDescriptor md) {
|
||||
|
||||
ClassWriter cw = new ClassWriter(0);
|
||||
|
||||
String name = descriptor.name().replace('.', '/') + "/module-info";
|
||||
String name = md.name().replace('.', '/') + "/module-info";
|
||||
cw.visit(Opcodes.V1_8, ACC_MODULE, name, null, null, null);
|
||||
|
||||
cw.visitAttribute(new ModuleAttribute(descriptor));
|
||||
cw.visitAttribute(new ConcealedPackagesAttribute(descriptor.conceals()));
|
||||
|
||||
Optional<Version> oversion = descriptor.version();
|
||||
if (oversion.isPresent())
|
||||
cw.visitAttribute(new VersionAttribute(oversion.get()));
|
||||
|
||||
Optional<String> omain = descriptor.mainClass();
|
||||
if (omain.isPresent())
|
||||
cw.visitAttribute(new MainClassAttribute(omain.get()));
|
||||
cw.visitAttribute(new ModuleAttribute(md));
|
||||
cw.visitAttribute(new ConcealedPackagesAttribute(md.conceals()));
|
||||
md.version().ifPresent(v -> cw.visitAttribute(new VersionAttribute(v)));
|
||||
md.mainClass().ifPresent(mc -> cw.visitAttribute(new MainClassAttribute(mc)));
|
||||
|
||||
// write the TargetPlatform attribute if have any of OS name/arch/version
|
||||
String osName = descriptor.osName().orElse(null);
|
||||
String osArch = descriptor.osArch().orElse(null);
|
||||
String osVersion = descriptor.osVersion().orElse(null);
|
||||
String osName = md.osName().orElse(null);
|
||||
String osArch = md.osArch().orElse(null);
|
||||
String osVersion = md.osVersion().orElse(null);
|
||||
if (osName != null || osArch != null || osVersion != null) {
|
||||
cw.visitAttribute(new TargetPlatformAttribute(osName,
|
||||
osArch,
|
||||
|
@ -91,56 +91,29 @@ public final class ModulePatcher {
|
||||
|
||||
Map<String, List<Path>> map = new HashMap<>();
|
||||
while (value != null) {
|
||||
|
||||
// <module>=<file>(:<file>)*
|
||||
|
||||
int pos = value.indexOf('=');
|
||||
|
||||
if (pos == -1 && index > 0)
|
||||
if (pos == -1)
|
||||
throwIAE("Unable to parse: " + value);
|
||||
|
||||
if (pos == 0)
|
||||
throwIAE("Missing module name: " + value);
|
||||
|
||||
if (pos > 0) {
|
||||
String mn = value.substring(0, pos);
|
||||
List<Path> list = map.get(mn);
|
||||
if (list != null)
|
||||
throwIAE("Module " + mn + " specified more than once");
|
||||
list = new ArrayList<>();
|
||||
map.put(mn, list);
|
||||
|
||||
// new format: <module>=<file>(:<file>)*
|
||||
|
||||
String mn = value.substring(0, pos);
|
||||
List<Path> list = map.get(mn);
|
||||
if (list != null)
|
||||
throwIAE("Module " + mn + " specified more than once");
|
||||
list = new ArrayList<>();
|
||||
map.put(mn, list);
|
||||
|
||||
String paths = value.substring(pos+1);
|
||||
for (String path : paths.split(File.pathSeparator)) {
|
||||
if (!path.isEmpty()) {
|
||||
list.add(Paths.get(path));
|
||||
}
|
||||
String paths = value.substring(pos+1);
|
||||
for (String path : paths.split(File.pathSeparator)) {
|
||||
if (!path.isEmpty()) {
|
||||
list.add(Paths.get(path));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// old format: <dir>(:<dir>)*
|
||||
|
||||
assert index == 0; // old format only allowed in first -Xpatch
|
||||
|
||||
String[] dirs = value.split(File.pathSeparator);
|
||||
for (String d : dirs) {
|
||||
if (d.length() > 0) {
|
||||
Path top = Paths.get(d);
|
||||
try {
|
||||
Files.list(top).forEach(e -> {
|
||||
String mn = e.getFileName().toString();
|
||||
Path dir = top.resolve(mn);
|
||||
map.computeIfAbsent(mn, k -> new ArrayList<>())
|
||||
.add(dir);
|
||||
});
|
||||
} catch (IOException ignore) { }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
index++;
|
||||
value = System.getProperty(PATCH_PROPERTY_PREFIX + index);
|
||||
}
|
||||
@ -175,7 +148,8 @@ public final class ModulePatcher {
|
||||
for (Path file : paths) {
|
||||
if (Files.isRegularFile(file)) {
|
||||
|
||||
// JAR file
|
||||
// JAR file - do not open as a multi-release JAR as this
|
||||
// is not supported by the boot class loader
|
||||
try (JarFile jf = new JarFile(file.toFile())) {
|
||||
jf.stream()
|
||||
.filter(e -> e.getName().endsWith(".class"))
|
||||
@ -209,10 +183,11 @@ public final class ModulePatcher {
|
||||
descriptor = JLMA.newModuleDescriptor(descriptor, packages);
|
||||
}
|
||||
|
||||
// return a new module reference
|
||||
// return a module reference to the patched module
|
||||
URI location = mref.location().orElse(null);
|
||||
return new ModuleReference(descriptor, location,
|
||||
() -> new PatchedModuleReader(paths, mref));
|
||||
return JLMA.newPatchedModule(descriptor,
|
||||
location,
|
||||
() -> new PatchedModuleReader(paths, mref));
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 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
|
||||
@ -58,7 +58,7 @@ public class Modules {
|
||||
* Creates a new Module. The module has the given ModuleDescriptor and
|
||||
* is defined to the given class loader.
|
||||
*
|
||||
* The resulting Module is in a larva state in that it does not not read
|
||||
* The resulting Module is in a larval state in that it does not not read
|
||||
* any other module and does not have any exports.
|
||||
*
|
||||
* The URI is for information purposes only.
|
||||
@ -74,7 +74,7 @@ public class Modules {
|
||||
* Define a new module to the VM. The module has the given set of
|
||||
* concealed packages and is defined to the given class loader.
|
||||
*
|
||||
* The resulting Module is in a larva state in that it does not not read
|
||||
* The resulting Module is in a larval state in that it does not not read
|
||||
* any other module and does not have any exports.
|
||||
*/
|
||||
public static Module defineModule(ClassLoader loader,
|
||||
@ -95,6 +95,13 @@ public class Modules {
|
||||
JLRMA.addReads(m1, m2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update module {@code m} to read all unnamed modules.
|
||||
*/
|
||||
public static void addReadsAllUnnamed(Module m) {
|
||||
JLRMA.addReadsAllUnnamed(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates module m1 to export a package to module m2.
|
||||
* Same as m1.addExports(pkg, m2) but without a caller check.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2015, 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
|
||||
@ -29,94 +29,105 @@ import java.lang.reflect.Module;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleDescriptor.Provides;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* A services catalog. Each {@code ClassLoader} has an optional {@code
|
||||
* ServicesCatalog} for modules that provide services. This is to support
|
||||
* ClassLoader centric ServiceLoader.load methods.
|
||||
* A <em>services catalog</em>. Each {@code ClassLoader} and {@code Layer} has
|
||||
* an optional {@code ServicesCatalog} for modules that provide services.
|
||||
*
|
||||
* @see java.util.ServiceLoader
|
||||
*/
|
||||
public class ServicesCatalog {
|
||||
|
||||
// use RW locks as register is rare
|
||||
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
private final Lock readLock = lock.readLock();
|
||||
private final Lock writeLock = lock.writeLock();
|
||||
public interface ServicesCatalog {
|
||||
|
||||
/**
|
||||
* Represents a service provider in the services catalog.
|
||||
*/
|
||||
public class ServiceProvider {
|
||||
public final class ServiceProvider {
|
||||
private final Module module;
|
||||
private final String providerName;
|
||||
ServiceProvider(Module module, String providerName) {
|
||||
|
||||
public ServiceProvider(Module module, String providerName) {
|
||||
this.module = module;
|
||||
this.providerName = providerName;
|
||||
}
|
||||
|
||||
public Module module() {
|
||||
return module;
|
||||
}
|
||||
|
||||
public String providerName() {
|
||||
return providerName;
|
||||
}
|
||||
}
|
||||
|
||||
// service providers
|
||||
private final Map<String, Set<ServiceProvider>> loaderServices = new HashMap<>();
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(module, providerName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new module catalog.
|
||||
*/
|
||||
public ServicesCatalog() { }
|
||||
|
||||
/**
|
||||
* Registers the module in this module catalog.
|
||||
*/
|
||||
public void register(Module m) {
|
||||
ModuleDescriptor descriptor = m.getDescriptor();
|
||||
|
||||
writeLock.lock();
|
||||
try {
|
||||
// extend the services map
|
||||
for (Provides ps : descriptor.provides().values()) {
|
||||
String service = ps.service();
|
||||
Set<String> providerNames = ps.providers();
|
||||
|
||||
// create a new set to replace the existing
|
||||
Set<ServiceProvider> result = new HashSet<>();
|
||||
Set<ServiceProvider> providers = loaderServices.get(service);
|
||||
if (providers != null) {
|
||||
result.addAll(providers);
|
||||
}
|
||||
for (String pn : providerNames) {
|
||||
result.add(new ServiceProvider(m, pn));
|
||||
}
|
||||
loaderServices.put(service, Collections.unmodifiableSet(result));
|
||||
}
|
||||
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
@Override
|
||||
public boolean equals(Object ob) {
|
||||
if (!(ob instanceof ServiceProvider))
|
||||
return false;
|
||||
ServiceProvider that = (ServiceProvider)ob;
|
||||
return Objects.equals(this.module, that.module)
|
||||
&& Objects.equals(this.providerName, that.providerName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the providers in the given module in this services catalog.
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If this services catalog is immutable
|
||||
*/
|
||||
void register(Module module);
|
||||
|
||||
/**
|
||||
* Returns the (possibly empty) set of service providers that implement the
|
||||
* given service type.
|
||||
*
|
||||
* @see java.util.ServiceLoader
|
||||
*/
|
||||
public Set<ServiceProvider> findServices(String service) {
|
||||
readLock.lock();
|
||||
try {
|
||||
return loaderServices.getOrDefault(service, Collections.emptySet());
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
Set<ServiceProvider> findServices(String service);
|
||||
|
||||
/**
|
||||
* Creates a ServicesCatalog that supports concurrent registration and
|
||||
* and lookup.
|
||||
*/
|
||||
static ServicesCatalog create() {
|
||||
return new ServicesCatalog() {
|
||||
|
||||
private Map<String, Set<ServiceProvider>> map = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void register(Module m) {
|
||||
ModuleDescriptor descriptor = m.getDescriptor();
|
||||
|
||||
for (Provides provides : descriptor.provides().values()) {
|
||||
String service = provides.service();
|
||||
Set<String> providerNames = provides.providers();
|
||||
|
||||
// create a new set to replace the existing
|
||||
Set<ServiceProvider> result = new HashSet<>();
|
||||
Set<ServiceProvider> providers = map.get(service);
|
||||
if (providers != null) {
|
||||
result.addAll(providers);
|
||||
}
|
||||
for (String pn : providerNames) {
|
||||
result.add(new ServiceProvider(m, pn));
|
||||
}
|
||||
map.put(service, Collections.unmodifiableSet(result));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ServiceProvider> findServices(String service) {
|
||||
return map.getOrDefault(service, Collections.emptySet());
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -40,21 +40,26 @@ import java.lang.module.ModuleDescriptor;
|
||||
*/
|
||||
public final class SystemModules {
|
||||
/**
|
||||
* Name of the installed modules.
|
||||
* Name of the system modules.
|
||||
*
|
||||
* This array provides a way for InstalledModuleFinder to fallback
|
||||
* This array provides a way for SystemModuleFinder to fallback
|
||||
* and read module-info.class from the run-time image instead of
|
||||
* the fastpath.
|
||||
*/
|
||||
public static final String[] MODULE_NAMES = new String[1];
|
||||
|
||||
/**
|
||||
* Hash of system modules.
|
||||
*/
|
||||
public static String[] MODULES_TO_HASH = new String[1];
|
||||
|
||||
/**
|
||||
* Number of packages in the boot layer from the installed modules.
|
||||
*
|
||||
* Don't make it final to avoid inlining during compile time as
|
||||
* the value will be changed at jlink time.
|
||||
*/
|
||||
public static final int PACKAGES_IN_BOOT_LAYER = 1024;
|
||||
public static int PACKAGES_IN_BOOT_LAYER = 1024;
|
||||
|
||||
/**
|
||||
* Returns a non-empty array of ModuleDescriptors in the run-time image.
|
||||
@ -64,4 +69,5 @@ public final class SystemModules {
|
||||
public static ModuleDescriptor[] modules() {
|
||||
return new ModuleDescriptor[0];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -392,6 +392,7 @@ class MethodAccessorGenerator extends AccessorGenerator {
|
||||
// matter.
|
||||
return AccessController.doPrivileged(
|
||||
new PrivilegedAction<MagicAccessorImpl>() {
|
||||
@SuppressWarnings("deprecation") // Class.newInstance
|
||||
public MagicAccessorImpl run() {
|
||||
try {
|
||||
return (MagicAccessorImpl)
|
||||
|
@ -343,8 +343,8 @@ public class Reflection {
|
||||
|
||||
private static void printStackTraceIfNeeded(Throwable e) {
|
||||
if (!printStackWhenAccessFailsSet && VM.initLevel() >= 1) {
|
||||
String s = GetPropertyAction
|
||||
.getProperty("sun.reflect.debugModuleAccessChecks");
|
||||
String s = GetPropertyAction.privilegedGetProperty(
|
||||
"sun.reflect.debugModuleAccessChecks");
|
||||
printStackWhenAccessFails =
|
||||
(s != null && !s.equalsIgnoreCase("false"));
|
||||
printStackWhenAccessFailsSet = true;
|
||||
|
@ -398,7 +398,7 @@ public class ReflectionFactory {
|
||||
return;
|
||||
}
|
||||
|
||||
Properties props = GetPropertyAction.getProperties();
|
||||
Properties props = GetPropertyAction.privilegedGetProperties();
|
||||
String val = props.getProperty("sun.reflect.noInflation");
|
||||
if (val != null && val.equals("true")) {
|
||||
noInflation = true;
|
||||
|
@ -166,6 +166,8 @@ module java.base {
|
||||
java.sql,
|
||||
java.xml,
|
||||
jdk.charsets,
|
||||
jdk.jartool,
|
||||
jdk.jlink,
|
||||
jdk.net,
|
||||
jdk.scripting.nashorn,
|
||||
jdk.unsupported,
|
||||
|
@ -84,8 +84,10 @@ import java.util.jar.Manifest;
|
||||
import jdk.internal.misc.VM;
|
||||
|
||||
|
||||
public enum LauncherHelper {
|
||||
INSTANCE;
|
||||
public final class LauncherHelper {
|
||||
|
||||
// No instantiation
|
||||
private LauncherHelper() {}
|
||||
|
||||
// used to identify JavaFX applications
|
||||
private static final String JAVAFX_APPLICATION_MARKER =
|
||||
|
@ -27,7 +27,7 @@
|
||||
java.launcher.opt.header = Usage: {0} [options] class [args...]\n\
|
||||
\ (to execute a class)\n or {0} [options] -jar jarfile [args...]\n\
|
||||
\ (to execute a jar file)\n\
|
||||
\ or {0} [-options] -mp <modulepath> -m <modulename> | <modulename>/<mainclass>\n\
|
||||
\ or {0} [options] -mp <modulepath> -m <modulename>[/<mainclass>] [args...]\n\
|
||||
\ (to execute the main class in a module)\n\
|
||||
where options include:\n
|
||||
|
||||
@ -51,8 +51,9 @@ java.launcher.opt.footer =\ -cp <class search path of directories and zip
|
||||
\ A {0} separated list of directories, each directory\n\
|
||||
\ is a directory of modules that replace upgradeable\n\
|
||||
\ modules in the runtime image\n\
|
||||
\ -m <modulename> | <modulename>/<mainclass>\n\
|
||||
\ the initial or main module to resolve\n\
|
||||
\ -m <modulename>[/<mainclass>]\n\
|
||||
\ the initial module to resolve, and the name of the main class\n\
|
||||
\ to execute if not specified by the module\n\
|
||||
\ -addmods <modulename>[,<modulename>...]\n\
|
||||
\ root modules to resolve in addition to the initial module\n\
|
||||
\ -limitmods <modulename>[,<modulename>...]\n\
|
||||
|
@ -53,8 +53,8 @@ public class ResourceManager {
|
||||
private static final AtomicInteger numSockets;
|
||||
|
||||
static {
|
||||
String prop =
|
||||
GetPropertyAction.getProperty("sun.net.maxDatagramSockets");
|
||||
String prop = GetPropertyAction
|
||||
.privilegedGetProperty("sun.net.maxDatagramSockets");
|
||||
int defmax = DEFAULT_MAX_SOCKETS;
|
||||
try {
|
||||
if (prop != null) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user