Merge
This commit is contained in:
commit
43568d8cc0
jdk
make
GenerateModuleSummary.gmkModuleTools.gmkTools.gmk
copy
gendata
launcher
Launcher-java.desktop.gmkLauncher-java.scripting.gmkLauncher-jdk.compiler.gmkLauncher-jdk.javadoc.gmkLauncher-jdk.jlink.gmkLauncher-jdk.scripting.nashorn.shell.gmk
src/classes/build/tools/jigsaw
src
java.base/share
classes
java
io
lang
jdk/internal
module-info.javasun
invoke/util
launcher
security
lib/security
native/libjli
java.desktop/unix/native
java.httpclient/share/classes/java/net/http
java.security.jgss/share/classes/sun/security/jgss/krb5
jdk.jartool/share/classes/sun/tools/jar
jdk.jlink/share/classes/jdk/tools
jimage
jlink
internal
resources
jmod
test
ProblemList.txtTEST.ROOT
com/sun
corba
5036554
7130985
se/impl
jdi
jndi/cosnaming
management/HotSpotDiagnosticMXBean
java
awt
Gtk/GtkVersionTest
Toolkit/Headless/WrappedToolkitTest
xembed/server
beans/XMLDecoder/8028054
io
lang
Class
forName/modules
getDeclaredField
getResource
ClassLoader/getResource/modules
SecurityManager/modules
String/concat
instrument
invoke/modules
reflect
net/Authenticator
@ -42,6 +42,6 @@ $(GENGRAPHS_DIR)/technology-summary.html: $(TOOLS_MODULE_SRCDIR)/technology-summ
|
||||
|
||||
$(GENGRAPHS_DIR)/module-summary.html: $(BUILD_JIGSAW_TOOLS) $(GENGRAPHS_DIR)/technology-summary.html
|
||||
$(MKDIR) -p $(@D)
|
||||
$(TOOL_MODULESUMMARY) -o $@ -mp $(IMAGES_OUTPUTDIR)/jmods
|
||||
$(TOOL_MODULESUMMARY) -o $@ --module-path $(IMAGES_OUTPUTDIR)/jmods
|
||||
|
||||
all: $(GENGRAPHS_DIR)/jdk.dot $(GENGRAPHS_DIR)/module-summary.html
|
||||
|
@ -36,12 +36,12 @@ $(eval $(call SetupJavaCompilation,BUILD_JIGSAW_TOOLS, \
|
||||
INCLUDES := build/tools/deps \
|
||||
build/tools/jigsaw, \
|
||||
BIN := $(TOOLS_CLASSES_DIR), \
|
||||
ADD_JAVAC_FLAGS := -XaddExports:jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED ))
|
||||
ADD_JAVAC_FLAGS := --add-exports jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED ))
|
||||
|
||||
|
||||
TOOL_GENGRAPHS := $(BUILD_JAVA) -esa -ea -cp $(TOOLS_CLASSES_DIR) \
|
||||
build.tools.jigsaw.GenGraphs
|
||||
|
||||
TOOL_MODULESUMMARY := $(BUILD_JAVA) -esa -ea -cp $(TOOLS_CLASSES_DIR) \
|
||||
-XaddExports:jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED \
|
||||
--add-exports jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED \
|
||||
build.tools.jigsaw.ModuleSummary
|
||||
|
@ -38,7 +38,7 @@ BUILD_TOOLS_JDK := $(call SetupJavaCompilationCompileTarget, \
|
||||
################################################################################
|
||||
|
||||
ifeq ($(BOOT_JDK_MODULAR), true)
|
||||
COMPILEFONTCONFIG_ADD_EXPORTS := -XaddExports:java.desktop/sun.awt=ALL-UNNAMED
|
||||
COMPILEFONTCONFIG_ADD_EXPORTS := --add-exports java.desktop/sun.awt=ALL-UNNAMED
|
||||
endif
|
||||
|
||||
TOOL_COMPILEFONTCONFIG = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
|
||||
@ -94,7 +94,7 @@ TOOL_SPP = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes build.too
|
||||
# Nimbus is used somewhere in the swing build.
|
||||
|
||||
ifeq ($(BOOT_JDK_MODULAR), true)
|
||||
COMPILENIMBUS_ADD_MODS := -addmods java.xml.bind
|
||||
COMPILENIMBUS_ADD_MODS := --add-modules java.xml.bind
|
||||
endif
|
||||
|
||||
TOOL_GENERATENIMBUS = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
|
||||
|
@ -203,7 +203,7 @@ TARGETS += $(DEF_POLICY_DST)
|
||||
################################################################################
|
||||
|
||||
ifeq ($(CACERTS_FILE), )
|
||||
CACERTS_FILE := $(JDK_TOPDIR)/src/java.base/share/conf/security/cacerts
|
||||
CACERTS_FILE := $(JDK_TOPDIR)/src/java.base/share/lib/security/cacerts
|
||||
endif
|
||||
|
||||
CACERTS_DST := $(LIB_DST_DIR)/security/cacerts
|
||||
|
@ -63,11 +63,11 @@ $(eval $(call SetupJavaCompilation,BUILD_BREAKITERATOR_LD, \
|
||||
|
||||
ifeq ($(BOOT_JDK_MODULAR), true)
|
||||
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 \
|
||||
--patch-module java.base=$(BREAK_ITERATOR_CLASSES)/java.base \
|
||||
--patch-module jdk.localedata=$(BREAK_ITERATOR_CLASSES)/jdk.localedata \
|
||||
--add-exports java.base/sun.text=ALL-UNNAMED \
|
||||
--add-exports java.base/sun.text.resources=ALL-UNNAMED \
|
||||
--add-exports jdk.localedata/sun.text.resources.ext=ALL-UNNAMED \
|
||||
#
|
||||
else
|
||||
BREAK_ITERATOR_BOOTCLASSPATH := -Xbootclasspath/p:$(call PathList, \
|
||||
|
@ -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-DEFAULT, \
|
||||
JAVA_ARGS := --add-modules ALL-DEFAULT, \
|
||||
LIBS_unix := $(X_LIBS), \
|
||||
))
|
||||
endif
|
||||
|
@ -27,5 +27,5 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jrunscript, \
|
||||
MAIN_CLASS := com.sun.tools.script.shell.Main, \
|
||||
JAVA_ARGS := -addmods ALL-DEFAULT, \
|
||||
JAVA_ARGS := --add-modules ALL-DEFAULT, \
|
||||
))
|
||||
|
@ -27,7 +27,7 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, javac, \
|
||||
MAIN_CLASS := com.sun.tools.javac.Main, \
|
||||
JAVA_ARGS := -addmods ALL-DEFAULT, \
|
||||
JAVA_ARGS := --add-modules ALL-DEFAULT, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
|
||||
-DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
|
||||
))
|
||||
|
@ -27,7 +27,7 @@ include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, javadoc, \
|
||||
MAIN_CLASS := jdk.javadoc.internal.tool.Main, \
|
||||
JAVA_ARGS := -addmods ALL-DEFAULT, \
|
||||
JAVA_ARGS := --add-modules ALL-DEFAULT, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
|
||||
-DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
|
||||
))
|
||||
|
@ -32,7 +32,7 @@ $(eval $(call SetupBuildLauncher, jimage,\
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jlink,\
|
||||
MAIN_CLASS := jdk.tools.jlink.internal.Main, \
|
||||
JAVA_ARGS := -addmods ALL-DEFAULT, \
|
||||
JAVA_ARGS := --add-modules 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-DEFAULT, \
|
||||
JAVA_ARGS := --add-modules ALL-DEFAULT, \
|
||||
CFLAGS := -DENABLE_ARG_FILES, \
|
||||
))
|
||||
|
@ -51,7 +51,7 @@ import static build.tools.jigsaw.ModuleSummary.HtmlDocument.Selector.*;
|
||||
import static build.tools.jigsaw.ModuleSummary.HtmlDocument.Division.*;
|
||||
|
||||
public class ModuleSummary {
|
||||
private static final String USAGE = "Usage: ModuleSummary -mp <dir> -o <outfile> [-root mn]*";
|
||||
private static final String USAGE = "Usage: ModuleSummary --module-path <dir> -o <outfile> [--root mn]*";
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int i=0;
|
||||
@ -61,13 +61,13 @@ public class ModuleSummary {
|
||||
while (i < args.length && args[i].startsWith("-")) {
|
||||
String arg = args[i++];
|
||||
switch (arg) {
|
||||
case "-mp":
|
||||
case "--module-path":
|
||||
modpath = Paths.get(args[i++]);
|
||||
break;
|
||||
case "-o":
|
||||
outfile = Paths.get(args[i++]);
|
||||
break;
|
||||
case "-root":
|
||||
case "--root":
|
||||
roots.add(args[i++]);
|
||||
default:
|
||||
System.err.println(USAGE);
|
||||
|
@ -131,8 +131,10 @@ public class CharArrayReader extends Reader {
|
||||
if (pos >= count) {
|
||||
return -1;
|
||||
}
|
||||
if (pos + len > count) {
|
||||
len = count - pos;
|
||||
|
||||
int avail = count - pos;
|
||||
if (len > avail) {
|
||||
len = avail;
|
||||
}
|
||||
if (len <= 0) {
|
||||
return 0;
|
||||
@ -158,8 +160,10 @@ public class CharArrayReader extends Reader {
|
||||
public long skip(long n) throws IOException {
|
||||
synchronized (lock) {
|
||||
ensureOpen();
|
||||
if (pos + n > count) {
|
||||
n = count - pos;
|
||||
|
||||
long avail = count - pos;
|
||||
if (n > avail) {
|
||||
n = avail;
|
||||
}
|
||||
if (n < 0) {
|
||||
return 0;
|
||||
|
@ -118,8 +118,10 @@ class StringBufferInputStream extends InputStream {
|
||||
if (pos >= count) {
|
||||
return -1;
|
||||
}
|
||||
if (pos + len > count) {
|
||||
len = count - pos;
|
||||
|
||||
int avail = count - pos;
|
||||
if (len > avail) {
|
||||
len = avail;
|
||||
}
|
||||
if (len <= 0) {
|
||||
return 0;
|
||||
|
@ -644,23 +644,20 @@ public final class System {
|
||||
* <code>getProperties</code> operation, it may choose to permit the
|
||||
* {@link #getProperty(String)} operation.
|
||||
*
|
||||
* @implNote In addition to the standard system properties, the {@code
|
||||
* java} launcher may create the Java Virtual Machine with system
|
||||
* properties that have the following keys:
|
||||
* @implNote In addition to the standard system properties, the system
|
||||
* properties may include the following keys:
|
||||
* <table summary="Shows property keys and associated values">
|
||||
* <tr><th>Key</th>
|
||||
* <th>Description of Associated Value</th></tr>
|
||||
* <tr><td>{@code jdk.module.path}</td>
|
||||
* <td>Application module path</td></tr>
|
||||
* <tr><td>{@code jdk.upgrade.module.path}</td>
|
||||
* <td>The application module path</td></tr>
|
||||
* <tr><td>{@code jdk.module.upgrade.path}</td>
|
||||
* <td>The upgrade module path</td></tr>
|
||||
* <tr><td>{@code jdk.module.main}</td>
|
||||
* <td>The module name of the initial/main module</td></tr>
|
||||
* <tr><td>{@code jdk.module.main.class}</td>
|
||||
* <td>The main class name of the initial module</td></tr>
|
||||
* </table>
|
||||
* These properties may also be set by custom launchers that use the JNI
|
||||
* invocation API to create the Java Virtual Machine.
|
||||
*
|
||||
* @return the system properties
|
||||
* @exception SecurityException if a security manager exists and its
|
||||
|
@ -587,26 +587,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||
return bmhClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @implNote this method is used by GenerateBMHClassesPlugin to enable
|
||||
* ahead-of-time generation of BMH classes at link time. It does
|
||||
* added validation since this string may be user provided.
|
||||
*/
|
||||
static Map.Entry<String, byte[]> generateConcreteBMHClassBytes(
|
||||
final String types) {
|
||||
for (char c : types.toCharArray()) {
|
||||
if ("LIJFD".indexOf(c) < 0) {
|
||||
throw new IllegalArgumentException("All characters must "
|
||||
+ "correspond to a basic field type: LIJFD");
|
||||
}
|
||||
}
|
||||
String shortTypes = LambdaForm.shortenSignature(types);
|
||||
final String className = speciesInternalClassName(shortTypes);
|
||||
return Map.entry(className,
|
||||
generateConcreteBMHClassBytes(shortTypes, types, className));
|
||||
}
|
||||
|
||||
private static String speciesInternalClassName(String shortTypes) {
|
||||
static String speciesInternalClassName(String shortTypes) {
|
||||
return SPECIES_PREFIX_PATH + shortTypes;
|
||||
}
|
||||
|
||||
|
@ -186,7 +186,7 @@ class DirectMethodHandle extends MethodHandle {
|
||||
return mtype.form().setCachedLambdaForm(which, lform);
|
||||
}
|
||||
|
||||
private static LambdaForm makePreparedLambdaForm(MethodType mtype, int which) {
|
||||
static LambdaForm makePreparedLambdaForm(MethodType mtype, int which) {
|
||||
boolean needsInit = (which == LF_INVSTATIC_INIT);
|
||||
boolean doesAlloc = (which == LF_NEWINVSPECIAL);
|
||||
String linkerName, lambdaName;
|
||||
@ -248,20 +248,6 @@ class DirectMethodHandle extends MethodHandle {
|
||||
return lform;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: This method acts as an API hook for use by the
|
||||
* GenerateJLIClassesPlugin to generate a class wrapping DirectMethodHandle
|
||||
* methods for an array of method types.
|
||||
*/
|
||||
static byte[] generateDMHClassBytes(String className, MethodType[] methodTypes, int[] types) {
|
||||
LambdaForm[] forms = new LambdaForm[methodTypes.length];
|
||||
for (int i = 0; i < forms.length; i++) {
|
||||
forms[i] = makePreparedLambdaForm(methodTypes[i], types[i]);
|
||||
methodTypes[i] = forms[i].methodType();
|
||||
}
|
||||
return InvokerBytecodeGenerator.generateCodeBytesForMultiple(className, forms, methodTypes);
|
||||
}
|
||||
|
||||
static Object findDirectMethodHandle(Name name) {
|
||||
if (name.function == NF_internalMemberName ||
|
||||
name.function == NF_internalMemberNameEnsureInit ||
|
||||
@ -515,7 +501,7 @@ class DirectMethodHandle extends MethodHandle {
|
||||
// Enumerate the different field kinds using Wrapper,
|
||||
// with an extra case added for checked references.
|
||||
private static final int
|
||||
FT_LAST_WRAPPER = Wrapper.values().length-1,
|
||||
FT_LAST_WRAPPER = Wrapper.COUNT-1,
|
||||
FT_UNCHECKED_REF = Wrapper.OBJECT.ordinal(),
|
||||
FT_CHECKED_REF = FT_LAST_WRAPPER+1,
|
||||
FT_LIMIT = FT_LAST_WRAPPER+2;
|
||||
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.invoke;
|
||||
|
||||
import java.util.Map;
|
||||
import jdk.internal.org.objectweb.asm.ClassWriter;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
||||
/**
|
||||
* Helper class to assist the GenerateJLIClassesPlugin to get access to
|
||||
* generate classes ahead of time.
|
||||
*/
|
||||
class GenerateJLIClassesHelper {
|
||||
|
||||
static byte[] generateDMHClassBytes(String className,
|
||||
MethodType[] methodTypes, int[] types) {
|
||||
LambdaForm[] forms = new LambdaForm[methodTypes.length];
|
||||
for (int i = 0; i < forms.length; i++) {
|
||||
forms[i] = DirectMethodHandle.makePreparedLambdaForm(methodTypes[i],
|
||||
types[i]);
|
||||
methodTypes[i] = forms[i].methodType();
|
||||
}
|
||||
return generateCodeBytesForLFs(className, forms, methodTypes);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate customized code for a set of LambdaForms of specified types into
|
||||
* a class with a specified name.
|
||||
*/
|
||||
private static byte[] generateCodeBytesForLFs(String className,
|
||||
LambdaForm[] forms, MethodType[] types) {
|
||||
assert(forms.length == types.length);
|
||||
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
|
||||
cw.visit(Opcodes.V1_8, Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER,
|
||||
className, null, InvokerBytecodeGenerator.INVOKER_SUPER_NAME, null);
|
||||
cw.visitSource(className.substring(className.lastIndexOf('/') + 1), null);
|
||||
for (int i = 0; i < forms.length; i++) {
|
||||
InvokerBytecodeGenerator g
|
||||
= new InvokerBytecodeGenerator(className, forms[i], types[i]);
|
||||
g.setClassWriter(cw);
|
||||
g.addMethod();
|
||||
}
|
||||
return cw.toByteArray();
|
||||
}
|
||||
|
||||
static Map.Entry<String, byte[]> generateConcreteBMHClassBytes(
|
||||
final String types) {
|
||||
for (char c : types.toCharArray()) {
|
||||
if ("LIJFD".indexOf(c) < 0) {
|
||||
throw new IllegalArgumentException("All characters must "
|
||||
+ "correspond to a basic field type: LIJFD");
|
||||
}
|
||||
}
|
||||
String shortTypes = LambdaForm.shortenSignature(types);
|
||||
final String className =
|
||||
BoundMethodHandle.Factory.speciesInternalClassName(shortTypes);
|
||||
return Map.entry(className,
|
||||
BoundMethodHandle.Factory.generateConcreteBMHClassBytes(
|
||||
shortTypes, types, className));
|
||||
}
|
||||
}
|
@ -70,7 +70,7 @@ class InvokerBytecodeGenerator {
|
||||
private static final String LLV_SIG = "(L" + OBJ + ";L" + OBJ + ";)V";
|
||||
|
||||
/** Name of its super class*/
|
||||
private static final String INVOKER_SUPER_NAME = OBJ;
|
||||
static final String INVOKER_SUPER_NAME = OBJ;
|
||||
|
||||
/** Name of new class */
|
||||
private final String className;
|
||||
@ -124,7 +124,7 @@ class InvokerBytecodeGenerator {
|
||||
}
|
||||
|
||||
/** For generating customized code for a single LambdaForm. */
|
||||
private InvokerBytecodeGenerator(String className, LambdaForm form, MethodType invokerType) {
|
||||
InvokerBytecodeGenerator(String className, LambdaForm form, MethodType invokerType) {
|
||||
this(form, form.names.length,
|
||||
className, form.debugName, invokerType);
|
||||
// Create an array to map name indexes to locals indexes.
|
||||
@ -655,35 +655,11 @@ class InvokerBytecodeGenerator {
|
||||
return classFile;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: This is used from GenerateJLIClassesPlugin via
|
||||
* DirectMethodHandle::generateDMHClassBytes.
|
||||
*
|
||||
* Generate customized code for a set of LambdaForms of specified types into
|
||||
* a class with a specified name.
|
||||
*/
|
||||
static byte[] generateCodeBytesForMultiple(String className,
|
||||
LambdaForm[] forms, MethodType[] types) {
|
||||
assert(forms.length == types.length);
|
||||
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
|
||||
cw.visit(Opcodes.V1_8, Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER,
|
||||
className, null, INVOKER_SUPER_NAME, null);
|
||||
cw.visitSource(className.substring(className.lastIndexOf('/') + 1), null);
|
||||
for (int i = 0; i < forms.length; i++) {
|
||||
InvokerBytecodeGenerator g
|
||||
= new InvokerBytecodeGenerator(className, forms[i], types[i]);
|
||||
g.setClassWriter(cw);
|
||||
g.addMethod();
|
||||
}
|
||||
return cw.toByteArray();
|
||||
}
|
||||
|
||||
private void setClassWriter(ClassWriter cw) {
|
||||
void setClassWriter(ClassWriter cw) {
|
||||
this.cw = cw;
|
||||
}
|
||||
|
||||
private void addMethod() {
|
||||
void addMethod() {
|
||||
methodPrologue();
|
||||
|
||||
// Suppress this method in backtraces displayed to the user.
|
||||
|
@ -60,7 +60,7 @@ class LambdaFormEditor {
|
||||
}
|
||||
|
||||
/** A description of a cached transform, possibly associated with the result of the transform.
|
||||
* The logical content is a sequence of byte values, starting with a Kind.ordinal value.
|
||||
* The logical content is a sequence of byte values, starting with a kind value.
|
||||
* The sequence is unterminated, ending with an indefinite number of zero bytes.
|
||||
* Sequences that are simple (short enough and with small enough values) pack into a 64-bit long.
|
||||
*/
|
||||
@ -68,17 +68,22 @@ class LambdaFormEditor {
|
||||
final long packedBytes;
|
||||
final byte[] fullBytes;
|
||||
|
||||
private enum Kind {
|
||||
NO_KIND, // necessary because ordinal must be greater than zero
|
||||
BIND_ARG, ADD_ARG, DUP_ARG,
|
||||
SPREAD_ARGS,
|
||||
FILTER_ARG, FILTER_RETURN, FILTER_RETURN_TO_ZERO,
|
||||
COLLECT_ARGS, COLLECT_ARGS_TO_VOID, COLLECT_ARGS_TO_ARRAY,
|
||||
FOLD_ARGS, FOLD_ARGS_TO_VOID,
|
||||
PERMUTE_ARGS,
|
||||
LOCAL_TYPES
|
||||
//maybe add more for guard with test, catch exception, pointwise type conversions
|
||||
}
|
||||
// maybe add more for guard with test, catch exception, pointwise type conversions
|
||||
private static final byte
|
||||
BIND_ARG = 1,
|
||||
ADD_ARG = 2,
|
||||
DUP_ARG = 3,
|
||||
SPREAD_ARGS = 4,
|
||||
FILTER_ARG = 5,
|
||||
FILTER_RETURN = 6,
|
||||
FILTER_RETURN_TO_ZERO = 7,
|
||||
COLLECT_ARGS = 8,
|
||||
COLLECT_ARGS_TO_VOID = 9,
|
||||
COLLECT_ARGS_TO_ARRAY = 10,
|
||||
FOLD_ARGS = 11,
|
||||
FOLD_ARGS_TO_VOID = 12,
|
||||
PERMUTE_ARGS = 13,
|
||||
LOCAL_TYPES = 14;
|
||||
|
||||
private static final boolean STRESS_TEST = false; // turn on to disable most packing
|
||||
private static final int
|
||||
@ -131,20 +136,6 @@ class LambdaFormEditor {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private byte byteAt(int i) {
|
||||
long pb = packedBytes;
|
||||
if (pb == 0) {
|
||||
if (i >= fullBytes.length) return 0;
|
||||
return fullBytes[i];
|
||||
}
|
||||
assert(fullBytes == null);
|
||||
if (i > PACKED_BYTE_MAX_LENGTH) return 0;
|
||||
int pos = (i * PACKED_BYTE_SIZE);
|
||||
return (byte)((pb >>> pos) & PACKED_BYTE_MASK);
|
||||
}
|
||||
|
||||
Kind kind() { return Kind.values()[byteAt(0)]; }
|
||||
|
||||
private Transform(long packedBytes, byte[] fullBytes, LambdaForm result) {
|
||||
super(result);
|
||||
this.packedBytes = packedBytes;
|
||||
@ -162,44 +153,39 @@ class LambdaFormEditor {
|
||||
assert((b & 0xFF) == b); // incoming value must fit in *unsigned* byte
|
||||
return (byte)b;
|
||||
}
|
||||
private static byte bval(Kind k) {
|
||||
return bval(k.ordinal());
|
||||
}
|
||||
static Transform of(Kind k, int b1) {
|
||||
static Transform of(byte k, int b1) {
|
||||
byte b0 = bval(k);
|
||||
if (inRange(b0 | b1))
|
||||
return new Transform(packedBytes(b0, b1));
|
||||
else
|
||||
return new Transform(fullBytes(b0, b1));
|
||||
}
|
||||
static Transform of(Kind k, int b1, int b2) {
|
||||
byte b0 = (byte) k.ordinal();
|
||||
static Transform of(byte b0, int b1, int b2) {
|
||||
if (inRange(b0 | b1 | b2))
|
||||
return new Transform(packedBytes(b0, b1, b2));
|
||||
else
|
||||
return new Transform(fullBytes(b0, b1, b2));
|
||||
}
|
||||
static Transform of(Kind k, int b1, int b2, int b3) {
|
||||
byte b0 = (byte) k.ordinal();
|
||||
static Transform of(byte b0, int b1, int b2, int b3) {
|
||||
if (inRange(b0 | b1 | b2 | b3))
|
||||
return new Transform(packedBytes(b0, b1, b2, b3));
|
||||
else
|
||||
return new Transform(fullBytes(b0, b1, b2, b3));
|
||||
}
|
||||
private static final byte[] NO_BYTES = {};
|
||||
static Transform of(Kind k, int... b123) {
|
||||
return ofBothArrays(k, b123, NO_BYTES);
|
||||
static Transform of(byte kind, int... b123) {
|
||||
return ofBothArrays(kind, b123, NO_BYTES);
|
||||
}
|
||||
static Transform of(Kind k, int b1, byte[] b234) {
|
||||
return ofBothArrays(k, new int[]{ b1 }, b234);
|
||||
static Transform of(byte kind, int b1, byte[] b234) {
|
||||
return ofBothArrays(kind, new int[]{ b1 }, b234);
|
||||
}
|
||||
static Transform of(Kind k, int b1, int b2, byte[] b345) {
|
||||
return ofBothArrays(k, new int[]{ b1, b2 }, b345);
|
||||
static Transform of(byte kind, int b1, int b2, byte[] b345) {
|
||||
return ofBothArrays(kind, new int[]{ b1, b2 }, b345);
|
||||
}
|
||||
private static Transform ofBothArrays(Kind k, int[] b123, byte[] b456) {
|
||||
private static Transform ofBothArrays(byte kind, int[] b123, byte[] b456) {
|
||||
byte[] fullBytes = new byte[1 + b123.length + b456.length];
|
||||
int i = 0;
|
||||
fullBytes[i++] = bval(k);
|
||||
fullBytes[i++] = bval(kind);
|
||||
for (int bv : b123) {
|
||||
fullBytes[i++] = bval(bv);
|
||||
}
|
||||
@ -449,7 +435,7 @@ class LambdaFormEditor {
|
||||
// Each editing method can (potentially) cache the edited LF so that it can be reused later.
|
||||
|
||||
LambdaForm bindArgumentForm(int pos) {
|
||||
Transform key = Transform.of(Transform.Kind.BIND_ARG, pos);
|
||||
Transform key = Transform.of(Transform.BIND_ARG, pos);
|
||||
LambdaForm form = getInCache(key);
|
||||
if (form != null) {
|
||||
assert(form.parameterConstraint(0) == newSpeciesData(lambdaForm.parameterType(pos)));
|
||||
@ -484,7 +470,7 @@ class LambdaFormEditor {
|
||||
}
|
||||
|
||||
LambdaForm addArgumentForm(int pos, BasicType type) {
|
||||
Transform key = Transform.of(Transform.Kind.ADD_ARG, pos, type.ordinal());
|
||||
Transform key = Transform.of(Transform.ADD_ARG, pos, type.ordinal());
|
||||
LambdaForm form = getInCache(key);
|
||||
if (form != null) {
|
||||
assert(form.arity == lambdaForm.arity+1);
|
||||
@ -501,7 +487,7 @@ class LambdaFormEditor {
|
||||
}
|
||||
|
||||
LambdaForm dupArgumentForm(int srcPos, int dstPos) {
|
||||
Transform key = Transform.of(Transform.Kind.DUP_ARG, srcPos, dstPos);
|
||||
Transform key = Transform.of(Transform.DUP_ARG, srcPos, dstPos);
|
||||
LambdaForm form = getInCache(key);
|
||||
if (form != null) {
|
||||
assert(form.arity == lambdaForm.arity-1);
|
||||
@ -530,7 +516,7 @@ class LambdaFormEditor {
|
||||
elementTypeKey = TYPE_LIMIT + Wrapper.forPrimitiveType(elementType).ordinal();
|
||||
}
|
||||
}
|
||||
Transform key = Transform.of(Transform.Kind.SPREAD_ARGS, pos, elementTypeKey, arrayLength);
|
||||
Transform key = Transform.of(Transform.SPREAD_ARGS, pos, elementTypeKey, arrayLength);
|
||||
LambdaForm form = getInCache(key);
|
||||
if (form != null) {
|
||||
assert(form.arity == lambdaForm.arity - arrayLength + 1);
|
||||
@ -569,9 +555,9 @@ class LambdaFormEditor {
|
||||
return filterArgumentForm(pos, basicType(collectorType.parameterType(0)));
|
||||
}
|
||||
byte[] newTypes = BasicType.basicTypesOrd(collectorType.parameterArray());
|
||||
Transform.Kind kind = (dropResult
|
||||
? Transform.Kind.COLLECT_ARGS_TO_VOID
|
||||
: Transform.Kind.COLLECT_ARGS);
|
||||
byte kind = (dropResult
|
||||
? Transform.COLLECT_ARGS_TO_VOID
|
||||
: Transform.COLLECT_ARGS);
|
||||
if (dropResult && collectorArity == 0) pos = 1; // pure side effect
|
||||
Transform key = Transform.of(kind, pos, collectorArity, newTypes);
|
||||
LambdaForm form = getInCache(key);
|
||||
@ -598,7 +584,7 @@ class LambdaFormEditor {
|
||||
argTypeKey = TYPE_LIMIT + Wrapper.forPrimitiveType(elementType).ordinal();
|
||||
}
|
||||
assert(collectorType.parameterList().equals(Collections.nCopies(collectorArity, elementType)));
|
||||
Transform.Kind kind = Transform.Kind.COLLECT_ARGS_TO_ARRAY;
|
||||
byte kind = Transform.COLLECT_ARGS_TO_ARRAY;
|
||||
Transform key = Transform.of(kind, pos, collectorArity, argTypeKey);
|
||||
LambdaForm form = getInCache(key);
|
||||
if (form != null) {
|
||||
@ -634,7 +620,7 @@ class LambdaFormEditor {
|
||||
}
|
||||
|
||||
LambdaForm filterArgumentForm(int pos, BasicType newType) {
|
||||
Transform key = Transform.of(Transform.Kind.FILTER_ARG, pos, newType.ordinal());
|
||||
Transform key = Transform.of(Transform.FILTER_ARG, pos, newType.ordinal());
|
||||
LambdaForm form = getInCache(key);
|
||||
if (form != null) {
|
||||
assert(form.arity == lambdaForm.arity);
|
||||
@ -710,7 +696,7 @@ class LambdaFormEditor {
|
||||
}
|
||||
|
||||
LambdaForm filterReturnForm(BasicType newType, boolean constantZero) {
|
||||
Transform.Kind kind = (constantZero ? Transform.Kind.FILTER_RETURN_TO_ZERO : Transform.Kind.FILTER_RETURN);
|
||||
byte kind = (constantZero ? Transform.FILTER_RETURN_TO_ZERO : Transform.FILTER_RETURN);
|
||||
Transform key = Transform.of(kind, newType.ordinal());
|
||||
LambdaForm form = getInCache(key);
|
||||
if (form != null) {
|
||||
@ -762,11 +748,11 @@ class LambdaFormEditor {
|
||||
|
||||
LambdaForm foldArgumentsForm(int foldPos, boolean dropResult, MethodType combinerType) {
|
||||
int combinerArity = combinerType.parameterCount();
|
||||
Transform.Kind kind = (dropResult ? Transform.Kind.FOLD_ARGS_TO_VOID : Transform.Kind.FOLD_ARGS);
|
||||
byte kind = (dropResult ? Transform.FOLD_ARGS_TO_VOID : Transform.FOLD_ARGS);
|
||||
Transform key = Transform.of(kind, foldPos, combinerArity);
|
||||
LambdaForm form = getInCache(key);
|
||||
if (form != null) {
|
||||
assert(form.arity == lambdaForm.arity - (kind == Transform.Kind.FOLD_ARGS ? 1 : 0));
|
||||
assert(form.arity == lambdaForm.arity - (kind == Transform.FOLD_ARGS ? 1 : 0));
|
||||
return form;
|
||||
}
|
||||
form = makeArgumentCombinationForm(foldPos, combinerType, true, dropResult);
|
||||
@ -786,7 +772,7 @@ class LambdaFormEditor {
|
||||
}
|
||||
assert(skip + reorder.length == lambdaForm.arity);
|
||||
if (nullPerm) return lambdaForm; // do not bother to cache
|
||||
Transform key = Transform.of(Transform.Kind.PERMUTE_ARGS, reorder);
|
||||
Transform key = Transform.of(Transform.PERMUTE_ARGS, reorder);
|
||||
LambdaForm form = getInCache(key);
|
||||
if (form != null) {
|
||||
assert(form.arity == skip+inTypes) : form;
|
||||
@ -855,7 +841,7 @@ class LambdaFormEditor {
|
||||
int[] desc = BasicType.basicTypeOrds(localTypes);
|
||||
desc = Arrays.copyOf(desc, desc.length + 1);
|
||||
desc[desc.length - 1] = pos;
|
||||
Transform key = Transform.of(Transform.Kind.LOCAL_TYPES, desc);
|
||||
Transform key = Transform.of(Transform.LOCAL_TYPES, desc);
|
||||
LambdaForm form = getInCache(key);
|
||||
if (form != null) {
|
||||
return form;
|
||||
|
@ -25,8 +25,6 @@
|
||||
|
||||
package java.lang.invoke;
|
||||
|
||||
import jdk.internal.misc.JavaLangInvokeAccess;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import sun.invoke.util.BytecodeDescriptor;
|
||||
import sun.invoke.util.VerifyAccess;
|
||||
|
||||
@ -37,7 +35,6 @@ import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Module;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@ -1002,7 +999,9 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError;
|
||||
Collections.addAll(result, buf0);
|
||||
}
|
||||
}
|
||||
result.addAll(Arrays.asList(buf).subList(0, bufCount));
|
||||
for (int i = 0; i < bufCount; i++) {
|
||||
result.add(buf[i]);
|
||||
}
|
||||
// Signature matching is not the same as type matching, since
|
||||
// one signature might correspond to several types.
|
||||
// So if matchType is a Class or MethodType, refilter the results.
|
||||
@ -1150,27 +1149,4 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError;
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
// StackFrameInfo stores Member and this provides the shared secrets
|
||||
// for stack walker to access MemberName information.
|
||||
SharedSecrets.setJavaLangInvokeAccess(new JavaLangInvokeAccess() {
|
||||
@Override
|
||||
public Object newMemberName() {
|
||||
return new MemberName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(Object mname) {
|
||||
MemberName memberName = (MemberName)mname;
|
||||
return memberName.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNative(Object mname) {
|
||||
MemberName memberName = (MemberName)mname;
|
||||
return memberName.isNative();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,8 @@
|
||||
|
||||
package java.lang.invoke;
|
||||
|
||||
import jdk.internal.misc.JavaLangInvokeAccess;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
|
||||
import jdk.internal.org.objectweb.asm.ClassWriter;
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
@ -44,6 +46,7 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@ -1710,6 +1713,39 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw newInternalError(ex);
|
||||
}
|
||||
|
||||
SharedSecrets.setJavaLangInvokeAccess(new JavaLangInvokeAccess() {
|
||||
@Override
|
||||
public Object newMemberName() {
|
||||
return new MemberName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(Object mname) {
|
||||
MemberName memberName = (MemberName)mname;
|
||||
return memberName.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNative(Object mname) {
|
||||
MemberName memberName = (MemberName)mname;
|
||||
return memberName.isNative();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] generateDMHClassBytes(String className,
|
||||
MethodType[] methodTypes, int[] types) {
|
||||
return GenerateJLIClassesHelper
|
||||
.generateDMHClassBytes(className, methodTypes, types);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map.Entry<String, byte[]> generateConcreteBMHClassBytes(
|
||||
final String types) {
|
||||
return GenerateJLIClassesHelper
|
||||
.generateConcreteBMHClassBytes(types);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore(). */
|
||||
|
@ -3115,7 +3115,7 @@ assert((int)twice.invokeExact(21) == 42);
|
||||
return dropArguments(zero(type.returnType()), 0, type.parameterList());
|
||||
}
|
||||
|
||||
private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.values().length];
|
||||
private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.COUNT];
|
||||
private static MethodHandle makeIdentity(Class<?> ptype) {
|
||||
MethodType mtype = methodType(ptype, ptype);
|
||||
LambdaForm lform = LambdaForm.identityForm(BasicType.basicType(ptype));
|
||||
@ -3133,7 +3133,7 @@ assert((int)twice.invokeExact(21) == 42);
|
||||
assert(btw == Wrapper.OBJECT);
|
||||
return makeZero(rtype);
|
||||
}
|
||||
private static final MethodHandle[] ZERO_MHS = new MethodHandle[Wrapper.values().length];
|
||||
private static final MethodHandle[] ZERO_MHS = new MethodHandle[Wrapper.COUNT];
|
||||
private static MethodHandle makeZero(Class<?> rtype) {
|
||||
MethodType mtype = methodType(rtype);
|
||||
LambdaForm lform = LambdaForm.zeroForm(BasicType.basicType(rtype));
|
||||
|
@ -281,8 +281,7 @@ public final class StringConcatFactory {
|
||||
if (c == TAG_CONST) {
|
||||
Object cnst = constants[constC++];
|
||||
el.add(new RecipeElement(cnst));
|
||||
}
|
||||
if (c == TAG_ARG) {
|
||||
} else if (c == TAG_ARG) {
|
||||
el.add(new RecipeElement(argC++));
|
||||
}
|
||||
} else {
|
||||
@ -322,32 +321,30 @@ public final class StringConcatFactory {
|
||||
private static final class RecipeElement {
|
||||
private final Object value;
|
||||
private final int argPos;
|
||||
private final Tag tag;
|
||||
|
||||
public RecipeElement(Object cnst) {
|
||||
this.value = Objects.requireNonNull(cnst);
|
||||
this.argPos = -1;
|
||||
this.tag = Tag.CONST;
|
||||
}
|
||||
|
||||
public RecipeElement(int arg) {
|
||||
this.value = null;
|
||||
assert (arg >= 0);
|
||||
this.argPos = arg;
|
||||
this.tag = Tag.ARG;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
assert (tag == Tag.CONST);
|
||||
assert (isConst());
|
||||
return value;
|
||||
}
|
||||
|
||||
public int getArgPos() {
|
||||
assert (tag == Tag.ARG);
|
||||
assert (!isConst());
|
||||
return argPos;
|
||||
}
|
||||
|
||||
public Tag getTag() {
|
||||
return tag;
|
||||
public boolean isConst() {
|
||||
return argPos == -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -357,22 +354,19 @@ public final class StringConcatFactory {
|
||||
|
||||
RecipeElement that = (RecipeElement) o;
|
||||
|
||||
if (tag != that.tag) return false;
|
||||
if (tag == Tag.CONST && (!value.equals(that.value))) return false;
|
||||
if (tag == Tag.ARG && (argPos != that.argPos)) return false;
|
||||
boolean isConst = isConst();
|
||||
if (isConst != that.isConst()) return false;
|
||||
if (isConst && (!value.equals(that.value))) return false;
|
||||
if (!isConst && (argPos != that.argPos)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return tag.hashCode();
|
||||
return argPos;
|
||||
}
|
||||
}
|
||||
|
||||
private enum Tag {
|
||||
CONST, ARG
|
||||
}
|
||||
|
||||
/**
|
||||
* Facilitates the creation of optimized String concatenation methods, that
|
||||
* can be used to efficiently concatenate a known number of arguments of
|
||||
@ -880,31 +874,24 @@ public final class StringConcatFactory {
|
||||
|
||||
int off = 0;
|
||||
for (RecipeElement el : recipe.getElements()) {
|
||||
switch (el.getTag()) {
|
||||
case CONST: {
|
||||
// Guaranteed non-null, no null check required.
|
||||
break;
|
||||
if (el.isConst()) {
|
||||
// Guaranteed non-null, no null check required.
|
||||
} else {
|
||||
// Null-checks are needed only for String arguments, and when a previous stage
|
||||
// did not do implicit null-checks. If a String is null, we eagerly replace it
|
||||
// with "null" constant. Note, we omit Objects here, because we don't call
|
||||
// .length() on them down below.
|
||||
int ac = el.getArgPos();
|
||||
Class<?> cl = arr[ac];
|
||||
if (cl == String.class && !guaranteedNonNull[ac]) {
|
||||
Label l0 = new Label();
|
||||
mv.visitIntInsn(ALOAD, off);
|
||||
mv.visitJumpInsn(IFNONNULL, l0);
|
||||
mv.visitLdcInsn("null");
|
||||
mv.visitIntInsn(ASTORE, off);
|
||||
mv.visitLabel(l0);
|
||||
}
|
||||
case ARG: {
|
||||
// Null-checks are needed only for String arguments, and when a previous stage
|
||||
// did not do implicit null-checks. If a String is null, we eagerly replace it
|
||||
// with "null" constant. Note, we omit Objects here, because we don't call
|
||||
// .length() on them down below.
|
||||
int ac = el.getArgPos();
|
||||
Class<?> cl = arr[ac];
|
||||
if (cl == String.class && !guaranteedNonNull[ac]) {
|
||||
Label l0 = new Label();
|
||||
mv.visitIntInsn(ALOAD, off);
|
||||
mv.visitJumpInsn(IFNONNULL, l0);
|
||||
mv.visitLdcInsn("null");
|
||||
mv.visitIntInsn(ASTORE, off);
|
||||
mv.visitLabel(l0);
|
||||
}
|
||||
off += getParameterSize(cl);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new StringConcatException("Unhandled tag: " + el.getTag());
|
||||
off += getParameterSize(cl);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -925,37 +912,30 @@ public final class StringConcatFactory {
|
||||
mv.visitInsn(ICONST_0);
|
||||
|
||||
for (RecipeElement el : recipe.getElements()) {
|
||||
switch (el.getTag()) {
|
||||
case CONST: {
|
||||
Object cnst = el.getValue();
|
||||
len += cnst.toString().length();
|
||||
break;
|
||||
if (el.isConst()) {
|
||||
Object cnst = el.getValue();
|
||||
len += cnst.toString().length();
|
||||
} else {
|
||||
/*
|
||||
If an argument is String, then we can call .length() on it. Sized/Exact modes have
|
||||
converted arguments for us. If an argument is primitive, we can provide a guess
|
||||
for its String representation size.
|
||||
*/
|
||||
Class<?> cl = arr[el.getArgPos()];
|
||||
if (cl == String.class) {
|
||||
mv.visitIntInsn(ALOAD, off);
|
||||
mv.visitMethodInsn(
|
||||
INVOKEVIRTUAL,
|
||||
"java/lang/String",
|
||||
"length",
|
||||
"()I",
|
||||
false
|
||||
);
|
||||
mv.visitInsn(IADD);
|
||||
} else if (cl.isPrimitive()) {
|
||||
len += estimateSize(cl);
|
||||
}
|
||||
case ARG: {
|
||||
/*
|
||||
If an argument is String, then we can call .length() on it. Sized/Exact modes have
|
||||
converted arguments for us. If an argument is primitive, we can provide a guess
|
||||
for its String representation size.
|
||||
*/
|
||||
Class<?> cl = arr[el.getArgPos()];
|
||||
if (cl == String.class) {
|
||||
mv.visitIntInsn(ALOAD, off);
|
||||
mv.visitMethodInsn(
|
||||
INVOKEVIRTUAL,
|
||||
"java/lang/String",
|
||||
"length",
|
||||
"()I",
|
||||
false
|
||||
);
|
||||
mv.visitInsn(IADD);
|
||||
} else if (cl.isPrimitive()) {
|
||||
len += estimateSize(cl);
|
||||
}
|
||||
off += getParameterSize(cl);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new StringConcatException("Unhandled tag: " + el.getTag());
|
||||
off += getParameterSize(cl);
|
||||
}
|
||||
}
|
||||
|
||||
@ -987,23 +967,17 @@ public final class StringConcatFactory {
|
||||
int off = 0;
|
||||
for (RecipeElement el : recipe.getElements()) {
|
||||
String desc;
|
||||
switch (el.getTag()) {
|
||||
case CONST: {
|
||||
Object cnst = el.getValue();
|
||||
mv.visitLdcInsn(cnst);
|
||||
desc = getSBAppendDesc(cnst.getClass());
|
||||
break;
|
||||
}
|
||||
case ARG: {
|
||||
Class<?> cl = arr[el.getArgPos()];
|
||||
mv.visitVarInsn(getLoadOpcode(cl), off);
|
||||
off += getParameterSize(cl);
|
||||
desc = getSBAppendDesc(cl);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new StringConcatException("Unhandled tag: " + el.getTag());
|
||||
if (el.isConst()) {
|
||||
Object cnst = el.getValue();
|
||||
mv.visitLdcInsn(cnst);
|
||||
desc = getSBAppendDesc(cnst.getClass());
|
||||
} else {
|
||||
Class<?> cl = arr[el.getArgPos()];
|
||||
mv.visitVarInsn(getLoadOpcode(cl), off);
|
||||
off += getParameterSize(cl);
|
||||
desc = getSBAppendDesc(cl);
|
||||
}
|
||||
|
||||
mv.visitMethodInsn(
|
||||
INVOKEVIRTUAL,
|
||||
"java/lang/StringBuilder",
|
||||
@ -1279,26 +1253,19 @@ public final class StringConcatFactory {
|
||||
// call the usual String.length(). Primitive values string sizes can be estimated.
|
||||
int initial = 0;
|
||||
for (RecipeElement el : recipe.getElements()) {
|
||||
switch (el.getTag()) {
|
||||
case CONST: {
|
||||
Object cnst = el.getValue();
|
||||
initial += cnst.toString().length();
|
||||
break;
|
||||
if (el.isConst()) {
|
||||
Object cnst = el.getValue();
|
||||
initial += cnst.toString().length();
|
||||
} else {
|
||||
final int i = el.getArgPos();
|
||||
Class<?> type = ptypesList.get(i);
|
||||
if (type.isPrimitive()) {
|
||||
MethodHandle est = MethodHandles.constant(int.class, estimateSize(type));
|
||||
est = MethodHandles.dropArguments(est, 0, type);
|
||||
lengthers[i] = est;
|
||||
} else {
|
||||
lengthers[i] = STRING_LENGTH;
|
||||
}
|
||||
case ARG: {
|
||||
final int i = el.getArgPos();
|
||||
Class<?> type = ptypesList.get(i);
|
||||
if (type.isPrimitive()) {
|
||||
MethodHandle est = MethodHandles.constant(int.class, estimateSize(type));
|
||||
est = MethodHandles.dropArguments(est, 0, type);
|
||||
lengthers[i] = est;
|
||||
} else {
|
||||
lengthers[i] = STRING_LENGTH;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new StringConcatException("Unhandled tag: " + el.getTag());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1311,26 +1278,19 @@ public final class StringConcatFactory {
|
||||
for (int i = elements.size() - 1; i >= 0; i--) {
|
||||
RecipeElement el = elements.get(i);
|
||||
MethodHandle appender;
|
||||
switch (el.getTag()) {
|
||||
case CONST: {
|
||||
Object constant = el.getValue();
|
||||
MethodHandle mh = appender(adaptToStringBuilder(constant.getClass()));
|
||||
appender = MethodHandles.insertArguments(mh, 1, constant);
|
||||
break;
|
||||
}
|
||||
case ARG: {
|
||||
int ac = el.getArgPos();
|
||||
appender = appender(ptypesList.get(ac));
|
||||
if (el.isConst()) {
|
||||
Object constant = el.getValue();
|
||||
MethodHandle mh = appender(adaptToStringBuilder(constant.getClass()));
|
||||
appender = MethodHandles.insertArguments(mh, 1, constant);
|
||||
} else {
|
||||
int ac = el.getArgPos();
|
||||
appender = appender(ptypesList.get(ac));
|
||||
|
||||
// Insert dummy arguments to match the prefix in the signature.
|
||||
// The actual appender argument will be the ac-ith argument.
|
||||
if (ac != 0) {
|
||||
appender = MethodHandles.dropArguments(appender, 1, ptypesList.subList(0, ac));
|
||||
}
|
||||
break;
|
||||
// Insert dummy arguments to match the prefix in the signature.
|
||||
// The actual appender argument will be the ac-ith argument.
|
||||
if (ac != 0) {
|
||||
appender = MethodHandles.dropArguments(appender, 1, ptypesList.subList(0, ac));
|
||||
}
|
||||
default:
|
||||
throw new StringConcatException("Unhandled tag: " + el.getTag());
|
||||
}
|
||||
builder = MethodHandles.foldArguments(builder, appender);
|
||||
}
|
||||
@ -1521,19 +1481,12 @@ public final class StringConcatFactory {
|
||||
// *ending* index.
|
||||
for (RecipeElement el : recipe.getElements()) {
|
||||
MethodHandle prepender;
|
||||
switch (el.getTag()) {
|
||||
case CONST: {
|
||||
Object cnst = el.getValue();
|
||||
prepender = MethodHandles.insertArguments(prepender(cnst.getClass()), 3, cnst);
|
||||
break;
|
||||
}
|
||||
case ARG: {
|
||||
int pos = el.getArgPos();
|
||||
prepender = selectArgument(prepender(ptypesList.get(pos)), 3, ptypesList, pos);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new StringConcatException("Unhandled tag: " + el.getTag());
|
||||
if (el.isConst()) {
|
||||
Object cnst = el.getValue();
|
||||
prepender = MethodHandles.insertArguments(prepender(cnst.getClass()), 3, cnst);
|
||||
} else {
|
||||
int pos = el.getArgPos();
|
||||
prepender = selectArgument(prepender(ptypesList.get(pos)), 3, ptypesList, pos);
|
||||
}
|
||||
|
||||
// Remove "old" index from arguments
|
||||
@ -1573,43 +1526,36 @@ public final class StringConcatFactory {
|
||||
byte initialCoder = INITIAL_CODER;
|
||||
int initialLen = 0; // initial length, in characters
|
||||
for (RecipeElement el : recipe.getElements()) {
|
||||
switch (el.getTag()) {
|
||||
case CONST: {
|
||||
Object constant = el.getValue();
|
||||
String s = constant.toString();
|
||||
initialCoder = (byte) coderMixer(String.class).invoke(initialCoder, s);
|
||||
initialLen += s.length();
|
||||
break;
|
||||
}
|
||||
case ARG: {
|
||||
int ac = el.getArgPos();
|
||||
if (el.isConst()) {
|
||||
Object constant = el.getValue();
|
||||
String s = constant.toString();
|
||||
initialCoder = (byte) coderMixer(String.class).invoke(initialCoder, s);
|
||||
initialLen += s.length();
|
||||
} else {
|
||||
int ac = el.getArgPos();
|
||||
|
||||
Class<?> argClass = ptypesList.get(ac);
|
||||
MethodHandle lm = selectArgument(lengthMixer(argClass), 1, ptypesList, ac);
|
||||
lm = MethodHandles.dropArguments(lm, 0, byte.class); // (*)
|
||||
lm = MethodHandles.dropArguments(lm, 2, byte.class);
|
||||
Class<?> argClass = ptypesList.get(ac);
|
||||
MethodHandle lm = selectArgument(lengthMixer(argClass), 1, ptypesList, ac);
|
||||
lm = MethodHandles.dropArguments(lm, 0, byte.class); // (*)
|
||||
lm = MethodHandles.dropArguments(lm, 2, byte.class);
|
||||
|
||||
MethodHandle cm = selectArgument(coderMixer(argClass), 1, ptypesList, ac);
|
||||
cm = MethodHandles.dropArguments(cm, 0, int.class); // (**)
|
||||
MethodHandle cm = selectArgument(coderMixer(argClass), 1, ptypesList, ac);
|
||||
cm = MethodHandles.dropArguments(cm, 0, int.class); // (**)
|
||||
|
||||
// Read this bottom up:
|
||||
// Read this bottom up:
|
||||
|
||||
// 4. Drop old index and coder, producing ("new-index", "new-coder", <args>)
|
||||
mh = MethodHandles.dropArguments(mh, 2, int.class, byte.class);
|
||||
// 4. Drop old index and coder, producing ("new-index", "new-coder", <args>)
|
||||
mh = MethodHandles.dropArguments(mh, 2, int.class, byte.class);
|
||||
|
||||
// 3. Compute "new-index", producing ("new-index", "new-coder", "old-index", "old-coder", <args>)
|
||||
// Length mixer ignores both "new-coder" and "old-coder" due to dropArguments above (*)
|
||||
mh = MethodHandles.foldArguments(mh, lm);
|
||||
// 3. Compute "new-index", producing ("new-index", "new-coder", "old-index", "old-coder", <args>)
|
||||
// Length mixer ignores both "new-coder" and "old-coder" due to dropArguments above (*)
|
||||
mh = MethodHandles.foldArguments(mh, lm);
|
||||
|
||||
// 2. Compute "new-coder", producing ("new-coder", "old-index", "old-coder", <args>)
|
||||
// Coder mixer ignores the "old-index" arg due to dropArguments above (**)
|
||||
mh = MethodHandles.foldArguments(mh, cm);
|
||||
// 2. Compute "new-coder", producing ("new-coder", "old-index", "old-coder", <args>)
|
||||
// Coder mixer ignores the "old-index" arg due to dropArguments above (**)
|
||||
mh = MethodHandles.foldArguments(mh, cm);
|
||||
|
||||
// 1. The mh shape here is ("old-index", "old-coder", <args>)
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new StringConcatException("Unhandled tag: " + el.getTag());
|
||||
// 1. The mh shape here is ("old-index", "old-coder", <args>)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ class TypeConvertingMethodAdapter extends MethodVisitor {
|
||||
super(Opcodes.ASM5, mv);
|
||||
}
|
||||
|
||||
private static final int NUM_WRAPPERS = Wrapper.values().length;
|
||||
private static final int NUM_WRAPPERS = Wrapper.COUNT;
|
||||
|
||||
private static final String NAME_OBJECT = "java/lang/Object";
|
||||
private static final String WRAPPER_PREFIX = "Ljava/lang/";
|
||||
|
@ -1057,57 +1057,11 @@ public abstract class VarHandle {
|
||||
Object addAndGet(Object... args);
|
||||
|
||||
enum AccessType {
|
||||
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);
|
||||
}
|
||||
};
|
||||
GET(Object.class),
|
||||
SET(void.class),
|
||||
COMPARE_AND_SWAP(boolean.class),
|
||||
COMPARE_AND_EXCHANGE(Object.class),
|
||||
GET_AND_UPDATE(Object.class);
|
||||
|
||||
final Class<?> returnType;
|
||||
final boolean isMonomorphicInReturnType;
|
||||
@ -1117,8 +1071,41 @@ public abstract class VarHandle {
|
||||
isMonomorphicInReturnType = returnType != Object.class;
|
||||
}
|
||||
|
||||
abstract MethodType accessModeType(Class<?> receiver, Class<?> value,
|
||||
Class<?>... intermediate);
|
||||
MethodType accessModeType(Class<?> receiver, Class<?> value,
|
||||
Class<?>... intermediate) {
|
||||
Class<?>[] ps;
|
||||
int i;
|
||||
switch (this) {
|
||||
case GET:
|
||||
ps = allocateParameters(0, receiver, intermediate);
|
||||
fillParameters(ps, receiver, intermediate);
|
||||
return MethodType.methodType(value, ps);
|
||||
case SET:
|
||||
ps = allocateParameters(1, receiver, intermediate);
|
||||
i = fillParameters(ps, receiver, intermediate);
|
||||
ps[i] = value;
|
||||
return MethodType.methodType(void.class, ps);
|
||||
case COMPARE_AND_SWAP:
|
||||
ps = allocateParameters(2, receiver, intermediate);
|
||||
i = fillParameters(ps, receiver, intermediate);
|
||||
ps[i++] = value;
|
||||
ps[i] = value;
|
||||
return MethodType.methodType(boolean.class, ps);
|
||||
case COMPARE_AND_EXCHANGE:
|
||||
ps = allocateParameters(2, receiver, intermediate);
|
||||
i = fillParameters(ps, receiver, intermediate);
|
||||
ps[i++] = value;
|
||||
ps[i] = value;
|
||||
return MethodType.methodType(value, ps);
|
||||
case GET_AND_UPDATE:
|
||||
ps = allocateParameters(1, receiver, intermediate);
|
||||
i = fillParameters(ps, receiver, intermediate);
|
||||
ps[i] = value;
|
||||
return MethodType.methodType(value, ps);
|
||||
default:
|
||||
throw new InternalError("Unknown AccessType");
|
||||
}
|
||||
}
|
||||
|
||||
private static Class<?>[] allocateParameters(int values,
|
||||
Class<?> receiver, Class<?>... intermediate) {
|
||||
|
@ -169,7 +169,7 @@ public final class ModuleReference {
|
||||
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this module has been patched via -Xpatch.
|
||||
* Returns {@code true} if this module has been patched via --patch-module.
|
||||
*/
|
||||
boolean isPatched() {
|
||||
return patched;
|
||||
|
@ -68,7 +68,7 @@ class ModuleReferences {
|
||||
|
||||
/**
|
||||
* Creates a ModuleReference to a module or to patched module when
|
||||
* creating modules for the boot Layer and -Xpatch is specified.
|
||||
* creating modules for the boot Layer and --patch-module is specified.
|
||||
*/
|
||||
private static ModuleReference newModule(ModuleDescriptor md,
|
||||
URI uri,
|
||||
|
@ -178,7 +178,7 @@ class SystemModuleFinder implements ModuleFinder {
|
||||
ModuleReference mref =
|
||||
new ModuleReference(md, uri, readerSupplier, hash);
|
||||
|
||||
// may need a reference to a patched module if -Xpatch specified
|
||||
// may need a reference to a patched module if --patch-module specified
|
||||
mref = ModulePatcher.interposeIfNeeded(mref);
|
||||
|
||||
return mref;
|
||||
|
@ -25,19 +25,42 @@
|
||||
|
||||
package jdk.internal.misc;
|
||||
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.Map;
|
||||
|
||||
public interface JavaLangInvokeAccess {
|
||||
/**
|
||||
* Create a new MemberName instance
|
||||
* Create a new MemberName instance. Used by {@see StackFrameInfo}.
|
||||
*/
|
||||
Object newMemberName();
|
||||
|
||||
/**
|
||||
* Returns the name for the given MemberName
|
||||
* Returns the name for the given MemberName. Used by {@see StackFrameInfo}.
|
||||
*/
|
||||
String getName(Object mname);
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the given MemberName is a native method
|
||||
* Returns {@code true} if the given MemberName is a native method. Used by
|
||||
* {@see StackFrameInfo}.
|
||||
*/
|
||||
boolean isNative(Object mname);
|
||||
|
||||
/**
|
||||
* Returns a {@code byte[]} containing the bytecode for a class implementing
|
||||
* DirectMethodHandle of each pairwise combination of {@code MethodType} and
|
||||
* an {@code int} representing method type. Used by
|
||||
* GenerateJLIClassesPlugin to generate such a class during the jlink phase.
|
||||
*/
|
||||
byte[] generateDMHClassBytes(String className, MethodType[] methodTypes,
|
||||
int[] types);
|
||||
|
||||
/**
|
||||
* Returns a {@code byte[]} containing the bytecode for a BoundMethodHandle
|
||||
* species class implementing the signature defined by {@code types}. Used
|
||||
* by GenerateBMHClassesPlugin to enable generation of such classes during
|
||||
* the jlink phase. Should do some added validation since this string may be
|
||||
* user provided.
|
||||
*/
|
||||
Map.Entry<String, byte[]> generateConcreteBMHClassBytes(
|
||||
final String types);
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ public class SharedSecrets {
|
||||
public static JavaLangInvokeAccess getJavaLangInvokeAccess() {
|
||||
if (javaLangInvokeAccess == null) {
|
||||
try {
|
||||
Class<?> c = Class.forName("java.lang.invoke.MemberName");
|
||||
Class<?> c = Class.forName("java.lang.invoke.MethodHandleImpl");
|
||||
unsafe.ensureClassInitialized(c);
|
||||
} catch (ClassNotFoundException e) {};
|
||||
}
|
||||
|
@ -56,8 +56,8 @@ import jdk.internal.perf.PerfCounter;
|
||||
* The {@link #boot() boot} method is called early in the startup to initialize
|
||||
* 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 module path, system modules, and application
|
||||
* -m and --add-modules options. The modules are located on a module path that
|
||||
* is 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.
|
||||
*/
|
||||
@ -127,16 +127,16 @@ public final class ModuleBootstrap {
|
||||
|
||||
long t2 = System.nanoTime();
|
||||
|
||||
// -upgrademodulepath option specified to launcher
|
||||
// --upgrade-module-path option specified to launcher
|
||||
ModuleFinder upgradeModulePath
|
||||
= createModulePathFinder("jdk.upgrade.module.path");
|
||||
= createModulePathFinder("jdk.module.upgrade.path");
|
||||
if (upgradeModulePath != null)
|
||||
systemModules = ModuleFinder.compose(upgradeModulePath, systemModules);
|
||||
|
||||
// -modulepath option specified to the launcher
|
||||
// --module-path option specified to the launcher
|
||||
ModuleFinder appModulePath = createModulePathFinder("jdk.module.path");
|
||||
|
||||
// The module finder: [-upgrademodulepath] system [-modulepath]
|
||||
// The module finder: [--upgrade-module-path] system [--module-path]
|
||||
ModuleFinder finder = systemModules;
|
||||
if (appModulePath != null)
|
||||
finder = ModuleFinder.compose(finder, appModulePath);
|
||||
@ -149,11 +149,11 @@ public final class ModuleBootstrap {
|
||||
if (mainModule != null)
|
||||
roots.add(mainModule);
|
||||
|
||||
// additional module(s) specified by -addmods
|
||||
// additional module(s) specified by --add-modules
|
||||
boolean addAllDefaultModules = false;
|
||||
boolean addAllSystemModules = false;
|
||||
boolean addAllApplicationModules = false;
|
||||
String propValue = System.getProperty("jdk.launcher.addmods");
|
||||
String propValue = getAndRemoveProperty("jdk.module.addmods");
|
||||
if (propValue != null) {
|
||||
for (String mod: propValue.split(",")) {
|
||||
switch (mod) {
|
||||
@ -172,8 +172,8 @@ public final class ModuleBootstrap {
|
||||
}
|
||||
}
|
||||
|
||||
// -limitmods
|
||||
propValue = System.getProperty("jdk.launcher.limitmods");
|
||||
// --limit-modules
|
||||
propValue = getAndRemoveProperty("jdk.module.limitmods");
|
||||
if (propValue != null) {
|
||||
Set<String> mods = new HashSet<>();
|
||||
for (String mod: propValue.split(",")) {
|
||||
@ -216,7 +216,7 @@ public final class ModuleBootstrap {
|
||||
}
|
||||
}
|
||||
|
||||
// If `-addmods ALL-SYSTEM` is specified then all observable system
|
||||
// If `--add-modules ALL-SYSTEM` is specified then all observable system
|
||||
// modules will be resolved.
|
||||
if (addAllSystemModules) {
|
||||
ModuleFinder f = finder; // observable modules
|
||||
@ -228,9 +228,9 @@ public final class ModuleBootstrap {
|
||||
.forEach(mn -> roots.add(mn));
|
||||
}
|
||||
|
||||
// If `-addmods ALL-MODULE-PATH` is specified then all observable
|
||||
// If `--add-modules ALL-MODULE-PATH` is specified then all observable
|
||||
// modules on the application module path will be resolved.
|
||||
if (appModulePath != null && addAllApplicationModules) {
|
||||
if (appModulePath != null && addAllApplicationModules) {
|
||||
ModuleFinder f = finder; // observable modules
|
||||
appModulePath.findAll()
|
||||
.stream()
|
||||
@ -250,7 +250,7 @@ public final class ModuleBootstrap {
|
||||
if (baseUri.getScheme().equals("jrt") // toLowerCase not needed here
|
||||
&& (upgradeModulePath == null)
|
||||
&& (appModulePath == null)
|
||||
&& (System.getProperty("jdk.launcher.patch.0") == null)) {
|
||||
&& (!ModulePatcher.isBootLayerPatched())) {
|
||||
needPostResolutionChecks = false;
|
||||
}
|
||||
|
||||
@ -317,7 +317,7 @@ public final class ModuleBootstrap {
|
||||
PerfCounters.loadModulesTime.addElapsedTimeFrom(t5);
|
||||
|
||||
|
||||
// -XaddReads and -XaddExports
|
||||
// --add-reads and --add-exports
|
||||
addExtraReads(bootLayer);
|
||||
addExtraExports(bootLayer);
|
||||
|
||||
@ -394,13 +394,13 @@ public final class ModuleBootstrap {
|
||||
|
||||
|
||||
/**
|
||||
* Process the -XaddReads options to add any additional read edges that
|
||||
* Process the --add-reads options to add any additional read edges that
|
||||
* are specified on the command-line.
|
||||
*/
|
||||
private static void addExtraReads(Layer bootLayer) {
|
||||
|
||||
// decode the command line options
|
||||
Map<String, Set<String>> map = decode("jdk.launcher.addreads.");
|
||||
Map<String, Set<String>> map = decode("jdk.module.addreads.");
|
||||
|
||||
for (Map.Entry<String, Set<String>> e : map.entrySet()) {
|
||||
|
||||
@ -431,13 +431,13 @@ public final class ModuleBootstrap {
|
||||
|
||||
|
||||
/**
|
||||
* Process the -XaddExports options to add any additional read edges that
|
||||
* Process the --add-exports options to add any additional read edges that
|
||||
* are specified on the command-line.
|
||||
*/
|
||||
private static void addExtraExports(Layer bootLayer) {
|
||||
|
||||
// decode the command line options
|
||||
Map<String, Set<String>> map = decode("jdk.launcher.addexports.");
|
||||
Map<String, Set<String>> map = decode("jdk.module.addexports.");
|
||||
|
||||
for (Map.Entry<String, Set<String>> e : map.entrySet()) {
|
||||
|
||||
@ -483,13 +483,14 @@ public final class ModuleBootstrap {
|
||||
|
||||
|
||||
/**
|
||||
* Decodes the values of -XaddReads or -XaddExports options
|
||||
* Decodes the values of --add-reads or --add-exports options
|
||||
*
|
||||
* The format of the options is: $KEY=$MODULE(,$MODULE)*
|
||||
*/
|
||||
private static Map<String, Set<String>> decode(String prefix) {
|
||||
int index = 0;
|
||||
String value = System.getProperty(prefix + index);
|
||||
// the system property is removed after decoding
|
||||
String value = getAndRemoveProperty(prefix + index);
|
||||
if (value == null)
|
||||
return Collections.emptyMap();
|
||||
|
||||
@ -522,12 +523,18 @@ public final class ModuleBootstrap {
|
||||
}
|
||||
|
||||
index++;
|
||||
value = System.getProperty(prefix + index);
|
||||
value = getAndRemoveProperty(prefix + index);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets and remove the named system property
|
||||
*/
|
||||
private static String getAndRemoveProperty(String key) {
|
||||
return (String)System.getProperties().remove(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws a RuntimeException with the given message
|
||||
|
@ -58,7 +58,7 @@ import sun.net.www.ParseUtil;
|
||||
|
||||
|
||||
/**
|
||||
* Provides support for patching modules in the boot layer with -Xpatch.
|
||||
* Provides support for patching modules in the boot layer with --patch-module.
|
||||
*/
|
||||
|
||||
public final class ModulePatcher {
|
||||
@ -66,28 +66,27 @@ public final class ModulePatcher {
|
||||
private static final JavaLangModuleAccess JLMA
|
||||
= SharedSecrets.getJavaLangModuleAccess();
|
||||
|
||||
// the prefix of the system properties that encode the value of -Xpatch
|
||||
private static final String PATCH_PROPERTY_PREFIX = "jdk.launcher.patch.";
|
||||
// the prefix of the system properties that encode the value of --patch-module
|
||||
private static final String PATCH_PROPERTY_PREFIX = "jdk.module.patch.";
|
||||
|
||||
// module name -> sequence of patches (directories or JAR files)
|
||||
private static final Map<String, List<Path>> PATCH_MAP = decodeProperties();
|
||||
|
||||
private ModulePatcher() { }
|
||||
|
||||
|
||||
/**
|
||||
* Decodes the values of -Xpatch options, returning a Map of module name to
|
||||
* list of file paths.
|
||||
* Decodes the values of --patch-module options, returning a Map of module
|
||||
* name to list of file paths.
|
||||
*
|
||||
* @throws IllegalArgumentException if the the module name is missing or
|
||||
* -Xpatch is used more than once to patch the same module
|
||||
* --patch-module is used more than once to patch the same module
|
||||
*/
|
||||
private static Map<String, List<Path>> decodeProperties() {
|
||||
|
||||
int index = 0;
|
||||
String value = System.getProperty(PATCH_PROPERTY_PREFIX + index);
|
||||
String value = getAndRemoveProperty(PATCH_PROPERTY_PREFIX + index);
|
||||
if (value == null)
|
||||
return Collections.emptyMap(); // -Xpatch not specified
|
||||
return Collections.emptyMap(); // --patch-module not specified
|
||||
|
||||
Map<String, List<Path>> map = new HashMap<>();
|
||||
while (value != null) {
|
||||
@ -115,13 +114,21 @@ public final class ModulePatcher {
|
||||
}
|
||||
|
||||
index++;
|
||||
value = System.getProperty(PATCH_PROPERTY_PREFIX + index);
|
||||
value = getAndRemoveProperty(PATCH_PROPERTY_PREFIX + index);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns {@code true} is --patch-module is specified to patch modules
|
||||
* in the boot layer.
|
||||
*/
|
||||
static boolean isBootLayerPatched() {
|
||||
return !PATCH_MAP.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a module reference that interposes on the given module if
|
||||
* needed. If there are no patches for the given module then the module
|
||||
@ -536,6 +543,13 @@ public final class ModulePatcher {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets and remove the named system property
|
||||
*/
|
||||
private static String getAndRemoveProperty(String key) {
|
||||
return (String)System.getProperties().remove(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives a package name from the name of an entry in a JAR file.
|
||||
*/
|
||||
|
@ -128,6 +128,7 @@ module java.base {
|
||||
exports jdk.internal.logger to
|
||||
java.logging;
|
||||
exports jdk.internal.org.objectweb.asm to
|
||||
jdk.jartool,
|
||||
jdk.jlink,
|
||||
jdk.scripting.nashorn,
|
||||
jdk.vm.ci;
|
||||
|
@ -29,27 +29,32 @@ import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.EnumMap;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
|
||||
public class ValueConversions {
|
||||
private static final Class<?> THIS_CLASS = ValueConversions.class;
|
||||
private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
|
||||
|
||||
/** Thread-safe canonicalized mapping from Wrapper to MethodHandle
|
||||
/**
|
||||
* Thread-safe canonicalized mapping from Wrapper to MethodHandle
|
||||
* with unsynchronized reads and synchronized writes.
|
||||
* It's safe to publish MethodHandles by data race because they are immutable. */
|
||||
* It's safe to publish MethodHandles by data race because they are immutable.
|
||||
*/
|
||||
private static class WrapperCache {
|
||||
/** EnumMap uses preconstructed array internally, which is constant during it's lifetime. */
|
||||
private final EnumMap<Wrapper, MethodHandle> map = new EnumMap<>(Wrapper.class);
|
||||
@Stable
|
||||
private final MethodHandle[] map = new MethodHandle[Wrapper.COUNT];
|
||||
|
||||
public MethodHandle get(Wrapper w) {
|
||||
return map.get(w);
|
||||
return map[w.ordinal()];
|
||||
}
|
||||
public synchronized MethodHandle put(final Wrapper w, final MethodHandle mh) {
|
||||
// Simulate CAS to avoid racy duplication
|
||||
MethodHandle prev = map.putIfAbsent(w, mh);
|
||||
if (prev != null) return prev;
|
||||
return mh;
|
||||
MethodHandle prev = map[w.ordinal()];
|
||||
if (prev != null) {
|
||||
return prev;
|
||||
} else {
|
||||
map[w.ordinal()] = mh;
|
||||
return mh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -623,7 +628,7 @@ public class ValueConversions {
|
||||
return (x ? (byte)1 : (byte)0);
|
||||
}
|
||||
|
||||
private static final WrapperCache[] CONVERT_PRIMITIVE_FUNCTIONS = newWrapperCaches(Wrapper.values().length);
|
||||
private static final WrapperCache[] CONVERT_PRIMITIVE_FUNCTIONS = newWrapperCaches(Wrapper.COUNT);
|
||||
|
||||
public static MethodHandle convertPrimitive(Wrapper wsrc, Wrapper wdst) {
|
||||
WrapperCache cache = CONVERT_PRIMITIVE_FUNCTIONS[wsrc.ordinal()];
|
||||
|
@ -42,6 +42,8 @@ public enum Wrapper {
|
||||
VOID ( Void.class, void.class, 'V', null, Format.other( 0)),
|
||||
;
|
||||
|
||||
public static final int COUNT = 10;
|
||||
|
||||
private final Class<?> wrapperType;
|
||||
private final Class<?> primitiveType;
|
||||
private final char basicTypeChar;
|
||||
@ -160,7 +162,10 @@ public enum Wrapper {
|
||||
return true;
|
||||
}
|
||||
|
||||
static { assert(checkConvertibleFrom()); }
|
||||
static {
|
||||
assert(checkConvertibleFrom());
|
||||
assert(COUNT == Wrapper.values().length);
|
||||
}
|
||||
private static boolean checkConvertibleFrom() {
|
||||
// Check the matrix for correct classification of widening conversions.
|
||||
for (Wrapper w : values()) {
|
||||
|
@ -60,8 +60,6 @@ import java.nio.charset.Charset;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.text.Normalizer;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ResourceBundle;
|
||||
@ -905,7 +903,7 @@ public final class LauncherHelper {
|
||||
|
||||
ModuleFinder finder = jdk.internal.module.ModuleBootstrap.finder();
|
||||
|
||||
int colon = optionFlag.indexOf(':');
|
||||
int colon = optionFlag.indexOf('=');
|
||||
if (colon == -1) {
|
||||
finder.findAll().stream()
|
||||
.sorted(Comparator.comparing(ModuleReference::descriptor))
|
||||
|
@ -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>[/<mainclass>] [args...]\n\
|
||||
\ or {0} [options] -p <modulepath> -m <modulename>[/<mainclass>] [args...]\n\
|
||||
\ (to execute the main class in a module)\n\
|
||||
where options include:\n
|
||||
|
||||
@ -41,24 +41,28 @@ java.launcher.ergo.message2 =\ because you are running on a se
|
||||
# Translators please note do not translate the options themselves
|
||||
java.launcher.opt.footer =\ -cp <class search path of directories and zip/jar files>\n\
|
||||
\ -classpath <class search path of directories and zip/jar files>\n\
|
||||
\ --class-path <class search path of directories and zip/jar files>\n\
|
||||
\ A {0} separated list of directories, JAR archives,\n\
|
||||
\ and ZIP archives to search for class files.\n\
|
||||
\ -mp <module path>\n\
|
||||
\ -modulepath <module path>...\n\
|
||||
\ -p <module path>\n\
|
||||
\ --module-path <module path>...\n\
|
||||
\ A {0} separated list of directories, each directory\n\
|
||||
\ is a directory of modules.\n\
|
||||
\ -upgrademodulepath <module path>...\n\
|
||||
\ --upgrade-module-path <module path>...\n\
|
||||
\ 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>[/<mainclass>]\n\
|
||||
\ -m <module>[/<mainclass>]\n\
|
||||
\ --module <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\
|
||||
\ --add-modules <modulename>[,<modulename>...]\n\
|
||||
\ root modules to resolve in addition to the initial module.\n\
|
||||
\ <modulename> can also be ALL-DEFAULT, ALL-SYSTEM,\n\
|
||||
\ ALL-MODULE-PATH.\n\
|
||||
\ --limit-modules <modulename>[,<modulename>...]\n\
|
||||
\ limit the universe of observable modules\n\
|
||||
\ -listmods[:<modulename>[,<modulename>...]]\n\
|
||||
\ --list-modules [<modulename>[,<modulename>...]]\n\
|
||||
\ list the observable modules and exit\n\
|
||||
\ --dry-run create VM but do not execute main method.\n\
|
||||
\ This --dry-run option may be useful for validating the\n\
|
||||
@ -69,7 +73,8 @@ java.launcher.opt.footer =\ -cp <class search path of directories and zip
|
||||
\ enable verbose output\n\
|
||||
\ -version print product version and exit\n\
|
||||
\ -showversion print product version and continue\n\
|
||||
\ -? -help print this help message\n\
|
||||
\ -? -help --help\n\
|
||||
\ print this help message\n\
|
||||
\ -X print help on non-standard options\n\
|
||||
\ -ea[:<packagename>...|:<classname>]\n\
|
||||
\ -enableassertions[:<packagename>...|:<classname>]\n\
|
||||
@ -91,6 +96,8 @@ java.launcher.opt.footer =\ -cp <class search path of directories and zip
|
||||
\ -splash:<imagepath>\n\
|
||||
\ show splash screen with specified image\n\
|
||||
\ @<filepath> read options from the specified file\n\
|
||||
\To specify an argument for a long option, you can use --<name>=<value> or\n\
|
||||
\--<name> <value>.\n\
|
||||
|
||||
See http://www.oracle.com/technetwork/java/javase/documentation/index.html for more details.
|
||||
|
||||
@ -123,17 +130,21 @@ java.launcher.X.usage=\
|
||||
\ show all property settings and continue\n\
|
||||
\ -XshowSettings:locale\n\
|
||||
\ show all locale related settings and continue\n\
|
||||
\ -XaddReads:<module>=<other-module>(,<other-module>)*\n\
|
||||
\ <module> reads other modules,\n\
|
||||
\ regardless of module declaration\n\
|
||||
\ -XaddExports:<module>/<package>=<other-module>(,<other-module>)*\n\
|
||||
\ <module> exports <package> to other modules,\n\
|
||||
\ regardless of module declaration\n\
|
||||
\ -Xpatch:<module>=<file>({0}<file>)*\n\
|
||||
\ -Xdisable-@files disable further argument file expansion\n\
|
||||
\ --add-reads <module>=<target-module>(,<target-module>)*\n\
|
||||
\ updates <module> to read <target-module>, regardless\n\
|
||||
\ of module declaration. \n\
|
||||
\ <target-module> can be ALL-UNNAMED to read all unnamed\n\
|
||||
\ modules.\n\
|
||||
\ --add-exports <module>/<package>=<target-module>(,<target-module>)*\n\
|
||||
\ updates <module> to export <package> to <target-module>,\n\
|
||||
\ regardless of module declaration.\n\
|
||||
\ <target-module> can be ALL-UNNAMED to export to all\n\
|
||||
\ unnamed modules.\n\
|
||||
\ --patch-module <module>=<file>({0}<file>)*\n\
|
||||
\ Override or augment a module with classes and resources\n\
|
||||
\ in JAR files or directories\n\
|
||||
\ -Xdisable-@files disable further argument file expansion\n\n\
|
||||
The -X options are non-standard and subject to change without notice.\n
|
||||
\ in JAR files or directories.\n\n\
|
||||
These options are non-standard and subject to change without notice.\n
|
||||
|
||||
# Translators please note do not translate the options themselves
|
||||
java.launcher.X.macosx.usage=\
|
||||
|
@ -1994,7 +1994,7 @@ final class ServerHandshaker extends Handshaker {
|
||||
|
||||
private StaplingParameters processStapling(ClientHello mesg) {
|
||||
StaplingParameters params = null;
|
||||
ExtensionType ext;
|
||||
ExtensionType ext = null;
|
||||
StatusRequestType type = null;
|
||||
StatusRequest req = null;
|
||||
Map<X509Certificate, byte[]> responses;
|
||||
@ -2012,33 +2012,40 @@ final class ServerHandshaker extends Handshaker {
|
||||
CertStatusReqListV2Extension statReqExtV2 =
|
||||
(CertStatusReqListV2Extension)mesg.extensions.get(
|
||||
ExtensionType.EXT_STATUS_REQUEST_V2);
|
||||
// Keep processing only if either status_request or status_request_v2
|
||||
// has been sent in the ClientHello.
|
||||
if (statReqExt == null && statReqExtV2 == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Determine which type of stapling we are doing and assert the
|
||||
// proper extension in the server hello.
|
||||
// Favor status_request_v2 over status_request and ocsp_multi
|
||||
// over ocsp.
|
||||
// If multiple ocsp or ocsp_multi types exist, select the first
|
||||
// instance of a given type
|
||||
ext = ExtensionType.EXT_STATUS_REQUEST;
|
||||
// instance of a given type. Also since we don't support ResponderId
|
||||
// selection yet, only accept a request if the ResponderId field
|
||||
// is empty.
|
||||
if (statReqExtV2 != null) { // RFC 6961 stapling
|
||||
ext = ExtensionType.EXT_STATUS_REQUEST_V2;
|
||||
List<CertStatusReqItemV2> reqItems =
|
||||
statReqExtV2.getRequestItems();
|
||||
int ocspIdx = -1;
|
||||
int ocspMultiIdx = -1;
|
||||
for (int pos = 0; pos < reqItems.size(); pos++) {
|
||||
for (int pos = 0; (pos < reqItems.size() &&
|
||||
(ocspIdx == -1 || ocspMultiIdx == -1)); pos++) {
|
||||
CertStatusReqItemV2 item = reqItems.get(pos);
|
||||
if (ocspIdx < 0 && item.getType() ==
|
||||
StatusRequestType.OCSP) {
|
||||
ocspIdx = pos;
|
||||
} else if (ocspMultiIdx < 0 && item.getType() ==
|
||||
StatusRequestType.OCSP_MULTI) {
|
||||
ocspMultiIdx = pos;
|
||||
StatusRequestType curType = item.getType();
|
||||
if (ocspIdx < 0 && curType == StatusRequestType.OCSP) {
|
||||
OCSPStatusRequest ocspReq =
|
||||
(OCSPStatusRequest)item.getRequest();
|
||||
if (ocspReq.getResponderIds().isEmpty()) {
|
||||
ocspIdx = pos;
|
||||
}
|
||||
} else if (ocspMultiIdx < 0 &&
|
||||
curType == StatusRequestType.OCSP_MULTI) {
|
||||
// If the type is OCSP, then the request
|
||||
// is guaranteed to be OCSPStatusRequest
|
||||
OCSPStatusRequest ocspReq =
|
||||
(OCSPStatusRequest)item.getRequest();
|
||||
if (ocspReq.getResponderIds().isEmpty()) {
|
||||
ocspMultiIdx = pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ocspMultiIdx >= 0) {
|
||||
@ -2047,16 +2054,47 @@ final class ServerHandshaker extends Handshaker {
|
||||
} else if (ocspIdx >= 0) {
|
||||
type = reqItems.get(ocspIdx).getType();
|
||||
req = reqItems.get(ocspIdx).getRequest();
|
||||
} else {
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
System.out.println("Warning: No suitable request " +
|
||||
"found in the status_request_v2 extension.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only attempt to process a status_request extension if:
|
||||
// * The status_request extension is set AND
|
||||
// * either the status_request_v2 extension is not present OR
|
||||
// * none of the underlying OCSPStatusRequest structures is suitable
|
||||
// for stapling.
|
||||
// If either of the latter two bullet items is true the ext, type and
|
||||
// req variables should all be null. If any are null we will try
|
||||
// processing an asserted status_request.
|
||||
if ((statReqExt != null) &&
|
||||
(ext == null || type == null || req == null)) {
|
||||
ext = ExtensionType.EXT_STATUS_REQUEST;
|
||||
type = statReqExt.getType();
|
||||
if (type == StatusRequestType.OCSP) {
|
||||
// If the type is OCSP, then the request is guaranteed
|
||||
// to be OCSPStatusRequest
|
||||
OCSPStatusRequest ocspReq =
|
||||
(OCSPStatusRequest)statReqExt.getRequest();
|
||||
if (ocspReq.getResponderIds().isEmpty()) {
|
||||
req = ocspReq;
|
||||
} else {
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
req = null;
|
||||
System.out.println("Warning: No suitable request " +
|
||||
"found in the status_request extension.");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // RFC 6066 stapling
|
||||
type = StatusRequestType.OCSP;
|
||||
req = statReqExt.getRequest();
|
||||
}
|
||||
|
||||
// If, after walking through the extensions we were unable to
|
||||
// find a suitable StatusRequest, then stapling is disabled.
|
||||
// Both statReqType and statReqData must have been set to continue.
|
||||
if (type == null || req == null) {
|
||||
// The ext, type and req variables must have been set to continue.
|
||||
if (type == null || req == null || ext == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -63,8 +63,6 @@ public class KeyStoreUtil {
|
||||
// this class is not meant to be instantiated
|
||||
}
|
||||
|
||||
private static final String JKS = "jks";
|
||||
|
||||
private static final Collator collator = Collator.getInstance();
|
||||
static {
|
||||
// this is for case insensitive string comparisons
|
||||
@ -112,25 +110,25 @@ public class KeyStoreUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file name of the keystore with the configured CA certificates.
|
||||
*/
|
||||
public static String getCacerts() {
|
||||
String sep = File.separator;
|
||||
return System.getProperty("java.home") + sep
|
||||
+ "lib" + sep + "security" + sep
|
||||
+ "cacerts";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the keystore with the configured CA certificates.
|
||||
*/
|
||||
public static KeyStore getCacertsKeyStore()
|
||||
throws Exception
|
||||
{
|
||||
String sep = File.separator;
|
||||
File file = new File(System.getProperty("java.home") + sep
|
||||
+ "lib" + sep + "security" + sep
|
||||
+ "cacerts");
|
||||
public static KeyStore getCacertsKeyStore() throws Exception {
|
||||
File file = new File(getCacerts());
|
||||
if (!file.exists()) {
|
||||
return null;
|
||||
}
|
||||
KeyStore caks = null;
|
||||
try (FileInputStream fis = new FileInputStream(file)) {
|
||||
caks = KeyStore.getInstance(JKS);
|
||||
caks.load(fis, null);
|
||||
}
|
||||
return caks;
|
||||
return KeyStore.getInstance(file, (char[])null);
|
||||
}
|
||||
|
||||
public static char[] getPassWithModifier(String modifier, String arg,
|
||||
|
@ -153,6 +153,7 @@ public final class Main {
|
||||
private boolean trustcacerts = false;
|
||||
private boolean protectedPath = false;
|
||||
private boolean srcprotectedPath = false;
|
||||
private boolean cacerts = false;
|
||||
private CertificateFactory cf = null;
|
||||
private KeyStore caks = null; // "cacerts" keystore
|
||||
private char[] srcstorePass = null;
|
||||
@ -169,15 +170,15 @@ public final class Main {
|
||||
STOREPASS, STORETYPE, PROVIDERNAME, ADDPROVIDER,
|
||||
PROVIDERCLASS, PROVIDERPATH, V, PROTECTED),
|
||||
CHANGEALIAS("Changes.an.entry.s.alias",
|
||||
ALIAS, DESTALIAS, KEYPASS, KEYSTORE, STOREPASS,
|
||||
ALIAS, DESTALIAS, KEYPASS, KEYSTORE, CACERTS, STOREPASS,
|
||||
STORETYPE, PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS,
|
||||
PROVIDERPATH, V, PROTECTED),
|
||||
DELETE("Deletes.an.entry",
|
||||
ALIAS, KEYSTORE, STOREPASS, STORETYPE,
|
||||
ALIAS, KEYSTORE, CACERTS, STOREPASS, STORETYPE,
|
||||
PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS,
|
||||
PROVIDERPATH, V, PROTECTED),
|
||||
EXPORTCERT("Exports.certificate",
|
||||
RFC, ALIAS, FILEOUT, KEYSTORE, STOREPASS,
|
||||
RFC, ALIAS, FILEOUT, KEYSTORE, CACERTS, STOREPASS,
|
||||
STORETYPE, PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS,
|
||||
PROVIDERPATH, V, PROTECTED),
|
||||
GENKEYPAIR("Generates.a.key.pair",
|
||||
@ -196,7 +197,7 @@ public final class Main {
|
||||
PROVIDERCLASS, PROVIDERPATH, V, PROTECTED),
|
||||
IMPORTCERT("Imports.a.certificate.or.a.certificate.chain",
|
||||
NOPROMPT, TRUSTCACERTS, PROTECTED, ALIAS, FILEIN,
|
||||
KEYPASS, KEYSTORE, STOREPASS, STORETYPE,
|
||||
KEYPASS, KEYSTORE, CACERTS, STOREPASS, STORETYPE,
|
||||
PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS,
|
||||
PROVIDERPATH, V),
|
||||
IMPORTPASS("Imports.a.password",
|
||||
@ -215,7 +216,7 @@ public final class Main {
|
||||
STORETYPE, PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS,
|
||||
PROVIDERPATH, V),
|
||||
LIST("Lists.entries.in.a.keystore",
|
||||
RFC, ALIAS, KEYSTORE, STOREPASS, STORETYPE,
|
||||
RFC, ALIAS, KEYSTORE, CACERTS, STOREPASS, STORETYPE,
|
||||
PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS,
|
||||
PROVIDERPATH, V, PROTECTED),
|
||||
PRINTCERT("Prints.the.content.of.a.certificate",
|
||||
@ -225,7 +226,7 @@ public final class Main {
|
||||
PRINTCRL("Prints.the.content.of.a.CRL.file",
|
||||
FILEIN, V),
|
||||
STOREPASSWD("Changes.the.store.password.of.a.keystore",
|
||||
NEW, KEYSTORE, STOREPASS, STORETYPE, PROVIDERNAME,
|
||||
NEW, KEYSTORE, CACERTS, STOREPASS, STORETYPE, PROVIDERNAME,
|
||||
ADDPROVIDER, PROVIDERCLASS, PROVIDERPATH, V),
|
||||
|
||||
// Undocumented start here, KEYCLONE is used a marker in -help;
|
||||
@ -306,6 +307,7 @@ public final class Main {
|
||||
KEYPASS("keypass", "<arg>", "key.password"),
|
||||
KEYSIZE("keysize", "<size>", "key.bit.size"),
|
||||
KEYSTORE("keystore", "<keystore>", "keystore.name"),
|
||||
CACERTS("cacerts", null, "access.the.cacerts.keystore"),
|
||||
NEW("new", "<arg>", "new.password"),
|
||||
NOPROMPT("noprompt", null, "do.not.prompt"),
|
||||
OUTFILE("outfile", "<file>", "output.file.name"),
|
||||
@ -472,14 +474,16 @@ public final class Main {
|
||||
help = true;
|
||||
} else if (collator.compare(flags, "-conf") == 0) {
|
||||
i++;
|
||||
}
|
||||
|
||||
/*
|
||||
* specifiers
|
||||
*/
|
||||
else if (collator.compare(flags, "-keystore") == 0 ||
|
||||
collator.compare(flags, "-destkeystore") == 0) {
|
||||
} else if (collator.compare(flags, "-keystore") == 0) {
|
||||
ksfname = args[++i];
|
||||
if (new File(ksfname).getCanonicalPath().equals(
|
||||
new File(KeyStoreUtil.getCacerts()).getCanonicalPath())) {
|
||||
System.err.println(rb.getString("warning.cacerts.option"));
|
||||
}
|
||||
} else if (collator.compare(flags, "-destkeystore") == 0) {
|
||||
ksfname = args[++i];
|
||||
} else if (collator.compare(flags, "-cacerts") == 0) {
|
||||
cacerts = true;
|
||||
} else if (collator.compare(flags, "-storepass") == 0 ||
|
||||
collator.compare(flags, "-deststorepass") == 0) {
|
||||
storePass = getPass(modifier, args[++i]);
|
||||
@ -636,6 +640,15 @@ public final class Main {
|
||||
* Execute the commands.
|
||||
*/
|
||||
void doCommands(PrintStream out) throws Exception {
|
||||
|
||||
if (cacerts) {
|
||||
if (ksfname != null || storetype != null) {
|
||||
throw new IllegalArgumentException(rb.getString
|
||||
("the.keystore.or.storetype.option.cannot.be.used.with.the.cacerts.option"));
|
||||
}
|
||||
ksfname = KeyStoreUtil.getCacerts();
|
||||
}
|
||||
|
||||
if (storetype == null) {
|
||||
storetype = KeyStore.getDefaultType();
|
||||
}
|
||||
|
@ -127,6 +127,10 @@ public class Resources extends java.util.ListResourceBundle {
|
||||
"key bit size"}, //-keysize
|
||||
{"keystore.name",
|
||||
"keystore name"}, //-keystore
|
||||
{"access.the.cacerts.keystore",
|
||||
"access the cacerts keystore"}, // -cacerts
|
||||
{"warning.cacerts.option",
|
||||
"Warning: use -cacerts option to access cacerts keystore"},
|
||||
{"new.password",
|
||||
"new password"}, //-new
|
||||
{"do.not.prompt",
|
||||
@ -194,6 +198,8 @@ public class Resources extends java.util.ListResourceBundle {
|
||||
{"Command.option.flag.needs.an.argument.", "Command option {0} needs an argument."},
|
||||
{"Warning.Different.store.and.key.passwords.not.supported.for.PKCS12.KeyStores.Ignoring.user.specified.command.value.",
|
||||
"Warning: Different store and key passwords not supported for PKCS12 KeyStores. Ignoring user-specified {0} value."},
|
||||
{"the.keystore.or.storetype.option.cannot.be.used.with.the.cacerts.option",
|
||||
"The -keystore or -storetype option cannot be used with the -cacerts option"},
|
||||
{".keystore.must.be.NONE.if.storetype.is.{0}",
|
||||
"-keystore must be NONE if -storetype is {0}"},
|
||||
{"Too.many.retries.program.terminated",
|
||||
|
@ -102,24 +102,21 @@ static void checkArg(const char *arg) {
|
||||
|
||||
// All arguments arrive here must be a launcher argument,
|
||||
// ie. by now, all argfile expansions must have been performed.
|
||||
if (*arg++ == '-') {
|
||||
if (*arg == '-') {
|
||||
expectingNoDashArg = JNI_FALSE;
|
||||
if (JLI_StrCmp(arg, "cp") == 0 ||
|
||||
JLI_StrCmp(arg, "classpath") == 0 ||
|
||||
JLI_StrCmp(arg, "addmods") == 0 ||
|
||||
JLI_StrCmp(arg, "limitmods") == 0 ||
|
||||
JLI_StrCmp(arg, "mp") == 0 ||
|
||||
JLI_StrCmp(arg, "modulepath") == 0 ||
|
||||
JLI_StrCmp(arg, "upgrademodulepath") == 0) {
|
||||
if (IsWhiteSpaceOption(arg)) {
|
||||
// expect an argument
|
||||
expectingNoDashArg = JNI_TRUE;
|
||||
} else if (JLI_StrCmp(arg, "jar") == 0 ||
|
||||
JLI_StrCmp(arg, "m") == 0) {
|
||||
// This is tricky, we do expect NoDashArg
|
||||
// But that is considered main class to stop expansion
|
||||
expectingNoDashArg = JNI_FALSE;
|
||||
// We can not just update the idx here because if -jar @file
|
||||
// still need expansion of @file to get the argument for -jar
|
||||
} else if (JLI_StrCmp(arg, "Xdisable-@files") == 0) {
|
||||
|
||||
if (JLI_StrCmp(arg, "-jar") == 0 ||
|
||||
JLI_StrCmp(arg, "-m") == 0) {
|
||||
// This is tricky, we do expect NoDashArg
|
||||
// But that is considered main class to stop expansion
|
||||
expectingNoDashArg = JNI_FALSE;
|
||||
// We can not just update the idx here because if -jar @file
|
||||
// still need expansion of @file to get the argument for -jar
|
||||
}
|
||||
} else if (JLI_StrCmp(arg, "-Xdisable-@files") == 0) {
|
||||
stopExpansion = JNI_TRUE;
|
||||
}
|
||||
} else {
|
||||
|
@ -69,7 +69,7 @@ static jboolean showVersion = JNI_FALSE; /* print but continue */
|
||||
static jboolean printUsage = JNI_FALSE; /* print and exit*/
|
||||
static jboolean printXUsage = JNI_FALSE; /* print and exit*/
|
||||
static jboolean dryRun = JNI_FALSE; /* initialize VM and exit */
|
||||
static char *showSettings = NULL; /* print but continue */
|
||||
static char *showSettings = NULL; /* print but continue */
|
||||
static char *listModules = NULL;
|
||||
|
||||
static const char *_program_name;
|
||||
@ -99,17 +99,9 @@ static int numOptions, maxOptions;
|
||||
* Prototypes for functions internal to launcher.
|
||||
*/
|
||||
static void SetClassPath(const char *s);
|
||||
static void SetModulePath(const char *s);
|
||||
static void SetUpgradeModulePath(const char *s);
|
||||
static void SetMainModule(const char *s);
|
||||
static void SetAddModulesProp(const char *mods);
|
||||
static void SetLimitModulesProp(const char *mods);
|
||||
static void SetAddReadsProp(const jint n, const char *s);
|
||||
static void SetAddExportsProp(const jint n, const char *s);
|
||||
static void SetPatchProp(const jint n, const char *s);
|
||||
static void SelectVersion(int argc, char **argv, char **main_class);
|
||||
static void SetJvmEnvironment(int argc, char **argv);
|
||||
static jboolean IsWhiteSpaceOptionArgument(const char* name);
|
||||
static jboolean ParseArguments(int *pargc, char ***pargv,
|
||||
int *pmode, char **pwhat,
|
||||
int *pret, const char *jrepath);
|
||||
@ -133,6 +125,18 @@ static void SetPaths(int argc, char **argv);
|
||||
static void DumpState();
|
||||
static jboolean RemovableOption(char *option);
|
||||
|
||||
enum OptionKind {
|
||||
LAUNCHER_OPTION = 0,
|
||||
LAUNCHER_OPTION_WITH_ARGUMENT,
|
||||
LAUNCHER_MAIN_OPTION,
|
||||
VM_LONG_OPTION,
|
||||
VM_LONG_OPTION_WITH_ARGUMENT,
|
||||
VM_OPTION
|
||||
};
|
||||
|
||||
static int GetOpt(int *pargc, char ***pargv, char **poption, char **pvalue);
|
||||
static jboolean IsOptionWithArgument(int argc, char **argv);
|
||||
|
||||
/* Maximum supported entries from jvm.cfg. */
|
||||
#define INIT_MAX_KNOWN_VMS 10
|
||||
|
||||
@ -162,6 +166,19 @@ static int KnownVMIndex(const char* name);
|
||||
static void FreeKnownVMs();
|
||||
static jboolean IsWildCardEnabled();
|
||||
|
||||
/*
|
||||
* This reports error. VM will not be created and no usage is printed.
|
||||
*/
|
||||
#define REPORT_ERROR(AC_ok, AC_failure_message, AC_questionable_arg) \
|
||||
do { \
|
||||
if (!AC_ok) { \
|
||||
JLI_ReportErrorMessage(AC_failure_message, AC_questionable_arg); \
|
||||
printUsage = JNI_FALSE; \
|
||||
*pret = 1; \
|
||||
return JNI_FALSE; \
|
||||
} \
|
||||
} while (JNI_FALSE)
|
||||
|
||||
#define ARG_CHECK(AC_arg_count, AC_failure_message, AC_questionable_arg) \
|
||||
do { \
|
||||
if (AC_arg_count < 1) { \
|
||||
@ -511,17 +528,73 @@ JavaMain(void * _args)
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if the given option name has a whitespace separated argument.
|
||||
* Test if the given name is one of the class path options.
|
||||
*/
|
||||
jboolean
|
||||
IsWhiteSpaceOptionArgument(const char* name) {
|
||||
static jboolean
|
||||
IsClassPathOption(const char* name) {
|
||||
return JLI_StrCmp(name, "-classpath") == 0 ||
|
||||
JLI_StrCmp(name, "-cp") == 0 ||
|
||||
JLI_StrCmp(name, "-modulepath") == 0 ||
|
||||
JLI_StrCmp(name, "-mp") == 0 ||
|
||||
JLI_StrCmp(name, "-upgrademodulepath") == 0 ||
|
||||
JLI_StrCmp(name, "-addmods") == 0 ||
|
||||
JLI_StrCmp(name, "-limitmods") == 0;
|
||||
JLI_StrCmp(name, "--class-path") == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if the given name is a launcher option taking the main entry point.
|
||||
*/
|
||||
static jboolean
|
||||
IsLauncherMainOption(const char* name) {
|
||||
return JLI_StrCmp(name, "--module") == 0 ||
|
||||
JLI_StrCmp(name, "-m") == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if the given name is a white-space launcher option.
|
||||
*/
|
||||
static jboolean
|
||||
IsLauncherOption(const char* name) {
|
||||
return IsClassPathOption(name) ||
|
||||
IsLauncherMainOption(name) ||
|
||||
JLI_StrCmp(name, "--list-modules") == 0;
|
||||
}
|
||||
|
||||
#ifndef OLD_MODULE_OPTIONS
|
||||
/*
|
||||
* Old module options for transition
|
||||
*/
|
||||
static jboolean
|
||||
IsOldModuleOption(const char* name) {
|
||||
return JLI_StrCmp(name, "-modulepath") == 0 ||
|
||||
JLI_StrCmp(name, "-mp") == 0 ||
|
||||
JLI_StrCmp(name, "-upgrademodulepath") == 0 ||
|
||||
JLI_StrCmp(name, "-addmods") == 0 ||
|
||||
JLI_StrCmp(name, "-limitmods") == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Test if the given name is a module-system white-space option that
|
||||
* will be passed to the VM with its corresponding long-form option
|
||||
* name and "=" delimiter.
|
||||
*/
|
||||
static jboolean
|
||||
IsModuleOption(const char* name) {
|
||||
return JLI_StrCmp(name, "--module-path") == 0 ||
|
||||
JLI_StrCmp(name, "-p") == 0 ||
|
||||
JLI_StrCmp(name, "--upgrade-module-path") == 0 ||
|
||||
JLI_StrCmp(name, "--add-modules") == 0 ||
|
||||
JLI_StrCmp(name, "--limit-modules") == 0 ||
|
||||
JLI_StrCmp(name, "--add-exports") == 0 ||
|
||||
JLI_StrCmp(name, "--add-reads") == 0 ||
|
||||
JLI_StrCmp(name, "--patch-module") == 0 ||
|
||||
IsOldModuleOption(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if the given name has a white space option.
|
||||
*/
|
||||
jboolean
|
||||
IsWhiteSpaceOption(const char* name) {
|
||||
return IsModuleOption(name) ||
|
||||
IsLauncherOption(name);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -559,7 +632,7 @@ CheckJvmType(int *pargc, char ***argv, jboolean speculative) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (IsWhiteSpaceOptionArgument(arg)) {
|
||||
if (IsWhiteSpaceOption(arg)) {
|
||||
newArgv[newArgvIdx++] = arg;
|
||||
argi++;
|
||||
if (argi < argc) {
|
||||
@ -701,7 +774,7 @@ SetJvmEnvironment(int argc, char **argv) {
|
||||
if (i > 0) {
|
||||
char *prev = argv[i - 1];
|
||||
// skip non-dash arg preceded by class path specifiers
|
||||
if (*arg != '-' && IsWhiteSpaceOptionArgument(prev)) {
|
||||
if (*arg != '-' && IsWhiteSpaceOption(prev)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -709,6 +782,7 @@ SetJvmEnvironment(int argc, char **argv) {
|
||||
|| JLI_StrCmp(arg, "-version") == 0
|
||||
|| JLI_StrCmp(arg, "-fullversion") == 0
|
||||
|| JLI_StrCmp(arg, "-help") == 0
|
||||
|| JLI_StrCmp(arg, "--help") == 0
|
||||
|| JLI_StrCmp(arg, "-?") == 0
|
||||
|| JLI_StrCmp(arg, "-jar") == 0
|
||||
|| JLI_StrCmp(arg, "-X") == 0) {
|
||||
@ -882,39 +956,16 @@ SetClassPath(const char *s)
|
||||
}
|
||||
|
||||
static void
|
||||
SetModulePath(const char *s)
|
||||
AddLongFormOption(const char *option, const char *arg)
|
||||
{
|
||||
static const char format[] = "%s=%s";
|
||||
char *def;
|
||||
const char *orig = s;
|
||||
static const char format[] = "-Djdk.module.path=%s";
|
||||
if (s == NULL)
|
||||
return;
|
||||
s = JLI_WildcardExpandClasspath(s);
|
||||
def = JLI_MemAlloc(sizeof(format)
|
||||
- 2 /* strlen("%s") */
|
||||
+ JLI_StrLen(s));
|
||||
sprintf(def, format, s);
|
||||
AddOption(def, NULL);
|
||||
if (s != orig)
|
||||
JLI_MemFree((char *) s);
|
||||
}
|
||||
size_t def_len;
|
||||
|
||||
static void
|
||||
SetUpgradeModulePath(const char *s)
|
||||
{
|
||||
char *def;
|
||||
const char *orig = s;
|
||||
static const char format[] = "-Djdk.upgrade.module.path=%s";
|
||||
if (s == NULL)
|
||||
return;
|
||||
s = JLI_WildcardExpandClasspath(s);
|
||||
def = JLI_MemAlloc(sizeof(format)
|
||||
- 2 /* strlen("%s") */
|
||||
+ JLI_StrLen(s));
|
||||
sprintf(def, format, s);
|
||||
def_len = JLI_StrLen(option) + 1 + JLI_StrLen(arg) + 1;
|
||||
def = JLI_MemAlloc(def_len);
|
||||
JLI_Snprintf(def, def_len, format, option, arg);
|
||||
AddOption(def, NULL);
|
||||
if (s != orig)
|
||||
JLI_MemFree((char *) s);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -939,46 +990,6 @@ SetMainModule(const char *s)
|
||||
AddOption(def, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
SetAddModulesProp(const char *mods) {
|
||||
size_t buflen = JLI_StrLen(mods) + 40;
|
||||
char *prop = (char *)JLI_MemAlloc(buflen);
|
||||
JLI_Snprintf(prop, buflen, "-Djdk.launcher.addmods=%s", mods);
|
||||
AddOption(prop, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
SetLimitModulesProp(const char *mods) {
|
||||
size_t buflen = JLI_StrLen(mods) + 40;
|
||||
char *prop = (char *)JLI_MemAlloc(buflen);
|
||||
JLI_Snprintf(prop, buflen, "-Djdk.launcher.limitmods=%s", mods);
|
||||
AddOption(prop, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
SetAddReadsProp(const jint n, const char *s) {
|
||||
size_t buflen = JLI_StrLen(s) + 40;
|
||||
char *prop = (char *)JLI_MemAlloc(buflen);
|
||||
JLI_Snprintf(prop, buflen, "-Djdk.launcher.addreads.%d=%s", n, s);
|
||||
AddOption(prop, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
SetAddExportsProp(const jint n, const char *s) {
|
||||
size_t buflen = JLI_StrLen(s) + 40;
|
||||
char *prop = (char *)JLI_MemAlloc(buflen);
|
||||
JLI_Snprintf(prop, buflen, "-Djdk.launcher.addexports.%d=%s", n, s);
|
||||
AddOption(prop, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
SetPatchProp(const jint n, const char *s) {
|
||||
size_t buflen = JLI_StrLen(s) + 40;
|
||||
char *prop = (char *)JLI_MemAlloc(buflen);
|
||||
JLI_Snprintf(prop, buflen, "-Djdk.launcher.patch.%d=%s", n, s);
|
||||
AddOption(prop, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* The SelectVersion() routine ensures that an appropriate version of
|
||||
* the JRE is running. The specification for the appropriate version
|
||||
@ -1003,6 +1014,7 @@ SelectVersion(int argc, char **argv, char **main_class)
|
||||
char *splash_jar_name = NULL;
|
||||
char *env_in;
|
||||
int res;
|
||||
jboolean has_arg;
|
||||
|
||||
/*
|
||||
* If the version has already been selected, set *main_class
|
||||
@ -1033,9 +1045,11 @@ SelectVersion(int argc, char **argv, char **main_class)
|
||||
* This capability is no longer available with JRE versions 1.9 and later.
|
||||
* These command line options are reported as errors.
|
||||
*/
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
while ((arg = *argv) != 0 && *arg == '-') {
|
||||
has_arg = IsOptionWithArgument(argc, argv);
|
||||
if (JLI_StrCCmp(arg, "-version:") == 0) {
|
||||
JLI_ReportErrorMessage(SPC_ERROR1);
|
||||
} else if (JLI_StrCmp(arg, "-jre-restrict-search") == 0) {
|
||||
@ -1045,10 +1059,12 @@ SelectVersion(int argc, char **argv, char **main_class)
|
||||
} else {
|
||||
if (JLI_StrCmp(arg, "-jar") == 0)
|
||||
jarflag = 1;
|
||||
if (IsWhiteSpaceOptionArgument(arg) && (argc >= 2)) {
|
||||
argc--;
|
||||
argv++;
|
||||
arg = *argv;
|
||||
if (IsWhiteSpaceOption(arg)) {
|
||||
if (has_arg) {
|
||||
argc--;
|
||||
argv++;
|
||||
arg = *argv;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1139,6 +1155,108 @@ SelectVersion(int argc, char **argv, char **main_class)
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if the current argv is an option, i.e. with a leading `-`
|
||||
* and followed with an argument without a leading `-`.
|
||||
*/
|
||||
static jboolean
|
||||
IsOptionWithArgument(int argc, char** argv) {
|
||||
char* option;
|
||||
char* arg;
|
||||
|
||||
if (argc <= 1)
|
||||
return JNI_FALSE;
|
||||
|
||||
option = *argv;
|
||||
arg = *(argv+1);
|
||||
return *option == '-' && *arg != '-';
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the option, and its argument if the option has an argument.
|
||||
* It will update *pargc, **pargv to the next option.
|
||||
*/
|
||||
static int
|
||||
GetOpt(int *pargc, char ***pargv, char **poption, char **pvalue) {
|
||||
int argc = *pargc;
|
||||
char** argv = *pargv;
|
||||
char* arg = *argv;
|
||||
|
||||
char* option = arg;
|
||||
char* value = NULL;
|
||||
char* equals = NULL;
|
||||
int kind = LAUNCHER_OPTION;
|
||||
jboolean has_arg = JNI_FALSE;
|
||||
|
||||
// check if this option may be a white-space option with an argument
|
||||
has_arg = IsOptionWithArgument(argc, argv);
|
||||
|
||||
argv++; --argc;
|
||||
if (IsLauncherOption(arg)) {
|
||||
if (has_arg) {
|
||||
value = *argv;
|
||||
argv++; --argc;
|
||||
}
|
||||
kind = IsLauncherMainOption(arg) ? LAUNCHER_MAIN_OPTION
|
||||
: LAUNCHER_OPTION_WITH_ARGUMENT;
|
||||
} else if (IsModuleOption(arg)) {
|
||||
kind = VM_LONG_OPTION_WITH_ARGUMENT;
|
||||
if (has_arg) {
|
||||
value = *argv;
|
||||
argv++; --argc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Support short form alias
|
||||
*/
|
||||
if (JLI_StrCmp(arg, "-p") == 0) {
|
||||
option = "--module-path";
|
||||
}
|
||||
|
||||
} else if (JLI_StrCCmp(arg, "--") == 0 && (equals = JLI_StrChr(arg, '=')) != NULL) {
|
||||
value = equals+1;
|
||||
if (JLI_StrCCmp(arg, "--list-modules=") == 0 ||
|
||||
JLI_StrCCmp(arg, "--module=") == 0 ||
|
||||
JLI_StrCCmp(arg, "--class-path=") == 0) {
|
||||
kind = LAUNCHER_OPTION_WITH_ARGUMENT;
|
||||
} else {
|
||||
kind = VM_LONG_OPTION;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef OLD_MODULE_OPTIONS
|
||||
// for transition to support both old and new syntax
|
||||
if (JLI_StrCmp(arg, "-modulepath") == 0 ||
|
||||
JLI_StrCmp(arg, "-mp") == 0) {
|
||||
option = "--module-path";
|
||||
} else if (JLI_StrCmp(arg, "-upgrademodulepath") == 0) {
|
||||
option = "--upgrade-module-path";
|
||||
} else if (JLI_StrCmp(arg, "-addmods") == 0) {
|
||||
option = "--add-modules";
|
||||
} else if (JLI_StrCmp(arg, "-limitmods") == 0) {
|
||||
option = "--limit-modules";
|
||||
} else if (JLI_StrCCmp(arg, "-XaddExports:") == 0) {
|
||||
option = "--add-exports";
|
||||
value = arg + 13;
|
||||
kind = VM_LONG_OPTION_WITH_ARGUMENT;
|
||||
} else if (JLI_StrCCmp(arg, "-XaddReads:") == 0) {
|
||||
option = "--add-reads";
|
||||
value = arg + 11;
|
||||
kind = VM_LONG_OPTION_WITH_ARGUMENT;
|
||||
} else if (JLI_StrCCmp(arg, "-Xpatch:") == 0) {
|
||||
option = "--patch-module";
|
||||
value = arg + 8;
|
||||
kind = VM_LONG_OPTION_WITH_ARGUMENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
*pargc = argc;
|
||||
*pargv = argv;
|
||||
*poption = option;
|
||||
*pvalue = value;
|
||||
return kind;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parses command line arguments. Returns JNI_FALSE if launcher
|
||||
* should exit without starting vm, returns JNI_TRUE if vm needs
|
||||
@ -1158,52 +1276,85 @@ ParseArguments(int *pargc, char ***pargv,
|
||||
*pret = 0;
|
||||
|
||||
while ((arg = *argv) != 0 && *arg == '-') {
|
||||
argv++; --argc;
|
||||
if (JLI_StrCmp(arg, "-classpath") == 0 || JLI_StrCmp(arg, "-cp") == 0) {
|
||||
ARG_CHECK (argc, ARG_ERROR1, arg);
|
||||
SetClassPath(*argv);
|
||||
mode = LM_CLASS;
|
||||
argv++; --argc;
|
||||
} else if (JLI_StrCmp(arg, "-modulepath") == 0 || JLI_StrCmp(arg, "-mp") == 0) {
|
||||
ARG_CHECK (argc, ARG_ERROR4, arg);
|
||||
SetModulePath(*argv);
|
||||
argv++; --argc;
|
||||
} else if (JLI_StrCmp(arg, "-upgrademodulepath") == 0) {
|
||||
ARG_CHECK (argc, ARG_ERROR4, arg);
|
||||
SetUpgradeModulePath(*argv);
|
||||
argv++; --argc;
|
||||
} else if (JLI_StrCmp(arg, "-jar") == 0) {
|
||||
ARG_CHECK (argc, ARG_ERROR2, arg);
|
||||
char *option = NULL;
|
||||
char *value = NULL;
|
||||
int kind = GetOpt(&argc, &argv, &option, &value);
|
||||
jboolean has_arg = value != NULL;
|
||||
|
||||
/*
|
||||
* Option to set main entry point
|
||||
*/
|
||||
if (JLI_StrCmp(arg, "-jar") == 0) {
|
||||
ARG_CHECK(argc, ARG_ERROR2, arg);
|
||||
mode = LM_JAR;
|
||||
} else if (JLI_StrCmp(arg, "-m") == 0) {
|
||||
ARG_CHECK (argc, ARG_ERROR5, arg);
|
||||
SetMainModule(*argv);
|
||||
} else if (JLI_StrCmp(arg, "--module") == 0 ||
|
||||
JLI_StrCCmp(arg, "--module=") == 0 ||
|
||||
JLI_StrCmp(arg, "-m") == 0) {
|
||||
REPORT_ERROR (has_arg, ARG_ERROR5, arg);
|
||||
SetMainModule(value);
|
||||
mode = LM_MODULE;
|
||||
} else if (JLI_StrCmp(arg, "-addmods") == 0) {
|
||||
ARG_CHECK (argc, ARG_ERROR6, arg);
|
||||
SetAddModulesProp(*argv);
|
||||
argv++; --argc;
|
||||
} else if (JLI_StrCmp(arg, "-limitmods") == 0) {
|
||||
ARG_CHECK (argc, ARG_ERROR6, arg);
|
||||
SetLimitModulesProp(*argv);
|
||||
argv++; --argc;
|
||||
} else if (JLI_StrCmp(arg, "-listmods") == 0 ||
|
||||
JLI_StrCCmp(arg, "-listmods:") == 0) {
|
||||
if (has_arg) {
|
||||
*pwhat = value;
|
||||
break;
|
||||
}
|
||||
} else if (JLI_StrCmp(arg, "--class-path") == 0 ||
|
||||
JLI_StrCCmp(arg, "--class-path=") == 0 ||
|
||||
JLI_StrCmp(arg, "-classpath") == 0 ||
|
||||
JLI_StrCmp(arg, "-cp") == 0) {
|
||||
REPORT_ERROR (has_arg, ARG_ERROR1, arg);
|
||||
SetClassPath(value);
|
||||
mode = LM_CLASS;
|
||||
} else if (JLI_StrCmp(arg, "--list-modules") == 0 ||
|
||||
JLI_StrCCmp(arg, "--list-modules=") == 0) {
|
||||
listModules = arg;
|
||||
|
||||
// set listModules to --list-modules=<module-names> if argument is specified
|
||||
if (JLI_StrCmp(arg, "--list-modules") == 0 && has_arg) {
|
||||
static const char format[] = "%s=%s";
|
||||
size_t buflen = JLI_StrLen(option) + 2 + JLI_StrLen(value);
|
||||
listModules = JLI_MemAlloc(buflen);
|
||||
JLI_Snprintf(listModules, buflen, format, option, value);
|
||||
}
|
||||
return JNI_TRUE;
|
||||
} else if (JLI_StrCCmp(arg, "-XaddReads:") == 0) {
|
||||
static jint n;
|
||||
char *value = arg + 11;
|
||||
SetAddReadsProp(n++, value);
|
||||
} else if (JLI_StrCCmp(arg, "-XaddExports:") == 0) {
|
||||
static jint n;
|
||||
char *value = arg + 13;
|
||||
SetAddExportsProp(n++, value);
|
||||
} else if (JLI_StrCCmp(arg, "-Xpatch:") == 0) {
|
||||
static jint n;
|
||||
char *value = arg + 8;
|
||||
SetPatchProp(n++, value);
|
||||
} else if (JLI_StrCmp(arg, "-help") == 0 ||
|
||||
/*
|
||||
* Parse white-space options
|
||||
*/
|
||||
} else if (has_arg) {
|
||||
if (kind == VM_LONG_OPTION) {
|
||||
AddOption(option, NULL);
|
||||
} else if (kind == VM_LONG_OPTION_WITH_ARGUMENT) {
|
||||
AddLongFormOption(option, value);
|
||||
}
|
||||
/*
|
||||
* Error missing argument
|
||||
*/
|
||||
} else if (!has_arg && IsWhiteSpaceOption(arg)) {
|
||||
if (JLI_StrCmp(arg, "--module-path") == 0 ||
|
||||
JLI_StrCmp(arg, "-p") == 0 ||
|
||||
JLI_StrCmp(arg, "--upgrade-module-path") == 0) {
|
||||
REPORT_ERROR (has_arg, ARG_ERROR4, arg);
|
||||
} else if (JLI_StrCmp(arg, "--add-modules") == 0 ||
|
||||
JLI_StrCmp(arg, "--limit-modules") == 0 ||
|
||||
JLI_StrCmp(arg, "--add-exports") == 0 ||
|
||||
JLI_StrCmp(arg, "--add-reads") == 0 ||
|
||||
JLI_StrCmp(arg, "--patch-module") == 0) {
|
||||
REPORT_ERROR (has_arg, ARG_ERROR6, arg);
|
||||
}
|
||||
#ifndef OLD_MODULE_OPTIONS
|
||||
else if (JLI_StrCmp(arg, "-modulepath") == 0 ||
|
||||
JLI_StrCmp(arg, "-mp") == 0 ||
|
||||
JLI_StrCmp(arg, "-upgrademodulepath") == 0) {
|
||||
REPORT_ERROR (has_arg, ARG_ERROR4, arg);
|
||||
} else if (JLI_StrCmp(arg, "-addmods") == 0 ||
|
||||
JLI_StrCmp(arg, "-limitmods") == 0) {
|
||||
REPORT_ERROR (has_arg, ARG_ERROR6, arg);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* The following cases will cause the argument parsing to stop
|
||||
*/
|
||||
} else if (JLI_StrCmp(arg, "--help") == 0 ||
|
||||
JLI_StrCmp(arg, "-help") == 0 ||
|
||||
JLI_StrCmp(arg, "-h") == 0 ||
|
||||
JLI_StrCmp(arg, "-?") == 0) {
|
||||
printUsage = JNI_TRUE;
|
||||
@ -1282,7 +1433,7 @@ ParseArguments(int *pargc, char ***pargv,
|
||||
}
|
||||
}
|
||||
|
||||
if (--argc >= 0) {
|
||||
if (*pwhat == NULL && --argc >= 0) {
|
||||
*pwhat = *argv++;
|
||||
}
|
||||
|
||||
@ -1692,7 +1843,7 @@ static void
|
||||
ListModules(JNIEnv *env, char *optString)
|
||||
{
|
||||
jmethodID listModulesID;
|
||||
jstring joptString;
|
||||
jstring joptString = NULL;
|
||||
jclass cls = GetLauncherHelperClass(env);
|
||||
NULL_CHECK(cls);
|
||||
NULL_CHECK(listModulesID = (*env)->GetStaticMethodID(env, cls,
|
||||
|
@ -161,6 +161,7 @@ void SetJavaLauncherProp(void);
|
||||
jint ReadKnownVMs(const char *jvmcfg, jboolean speculative);
|
||||
char *CheckJvmType(int *argc, char ***argv, jboolean speculative);
|
||||
void AddOption(char *str, void *info);
|
||||
jboolean IsWhiteSpaceOption(const char* name);
|
||||
|
||||
enum ergo_policy {
|
||||
DEFAULT_POLICY = 0,
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
double getNativeScaleFactor();
|
||||
double getNativeScaleFactor(char *output_name);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -806,7 +806,7 @@ SplashGetScaledImageName(const char* jarName, const char* fileName,
|
||||
#ifndef __linux__
|
||||
return JNI_FALSE;
|
||||
#endif
|
||||
*scaleFactor = getNativeScaleFactor();
|
||||
*scaleFactor = getNativeScaleFactor(NULL);
|
||||
if (*scaleFactor == 2.0) {
|
||||
size_t length = 0;
|
||||
char *stringToAppend = ".java-scale2x";
|
||||
|
@ -31,7 +31,7 @@ import java.nio.ByteBuffer;
|
||||
/*
|
||||
* I/O abstraction used to implement WebSocket.
|
||||
*/
|
||||
public interface RawChannel {
|
||||
interface RawChannel {
|
||||
|
||||
interface RawEvent {
|
||||
|
||||
|
@ -235,8 +235,11 @@ public class Krb5InitCredential
|
||||
*/
|
||||
public int getInitLifetime() throws GSSException {
|
||||
int retVal = 0;
|
||||
retVal = (int)(getEndTime().getTime()
|
||||
- (new Date().getTime()));
|
||||
Date d = getEndTime();
|
||||
if (d == null) {
|
||||
return 0;
|
||||
}
|
||||
retVal = (int)(d.getTime() - (new Date().getTime()));
|
||||
|
||||
return retVal/1000;
|
||||
}
|
||||
|
324
jdk/src/jdk.jartool/share/classes/sun/tools/jar/FingerPrint.java
Normal file
324
jdk/src/jdk.jartool/share/classes/sun/tools/jar/FingerPrint.java
Normal file
@ -0,0 +1,324 @@
|
||||
/*
|
||||
* 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 sun.tools.jar;
|
||||
|
||||
import jdk.internal.org.objectweb.asm.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A FingerPrint is an abstract representation of a JarFile entry that contains
|
||||
* information to determine if the entry represents a class or a
|
||||
* resource, and whether two entries are identical. If the FingerPrint represents
|
||||
* a class, it also contains information to (1) describe the public API;
|
||||
* (2) compare the public API of this class with another class; (3) determine
|
||||
* whether or not it's a nested class and, if so, the name of the associated
|
||||
* top level class; and (4) for an canonically ordered set of classes determine
|
||||
* if the class versions are compatible. A set of classes is canonically
|
||||
* ordered if the classes in the set have the same name, and the base class
|
||||
* precedes the versioned classes and if each versioned class with version
|
||||
* {@code n} precedes classes with versions {@code > n} for all versions
|
||||
* {@code n}.
|
||||
*/
|
||||
final class FingerPrint {
|
||||
private static final MessageDigest MD;
|
||||
|
||||
private final byte[] sha1;
|
||||
private final ClassAttributes attrs;
|
||||
private final boolean isClassEntry;
|
||||
private final String entryName;
|
||||
|
||||
static {
|
||||
try {
|
||||
MD = MessageDigest.getInstance("SHA-1");
|
||||
} catch (NoSuchAlgorithmException x) {
|
||||
// log big problem?
|
||||
throw new RuntimeException(x);
|
||||
}
|
||||
}
|
||||
|
||||
public FingerPrint(String entryName,byte[] bytes) throws IOException {
|
||||
this.entryName = entryName;
|
||||
if (entryName.endsWith(".class") && isCafeBabe(bytes)) {
|
||||
isClassEntry = true;
|
||||
sha1 = sha1(bytes, 8); // skip magic number and major/minor version
|
||||
attrs = getClassAttributes(bytes);
|
||||
} else {
|
||||
isClassEntry = false;
|
||||
sha1 = sha1(bytes);
|
||||
attrs = new ClassAttributes(); // empty class
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isClass() {
|
||||
return isClassEntry;
|
||||
}
|
||||
|
||||
public boolean isNestedClass() {
|
||||
return attrs.nestedClass;
|
||||
}
|
||||
|
||||
public boolean isPublicClass() {
|
||||
return attrs.publicClass;
|
||||
}
|
||||
|
||||
public boolean isIdentical(FingerPrint that) {
|
||||
if (that == null) return false;
|
||||
if (this == that) return true;
|
||||
return isEqual(this.sha1, that.sha1);
|
||||
}
|
||||
|
||||
public boolean isCompatibleVersion(FingerPrint that) {
|
||||
return attrs.version >= that.attrs.version;
|
||||
}
|
||||
|
||||
public boolean isSameAPI(FingerPrint that) {
|
||||
if (that == null) return false;
|
||||
return attrs.equals(that.attrs);
|
||||
}
|
||||
|
||||
public String name() {
|
||||
String name = attrs.name;
|
||||
return name == null ? entryName : name;
|
||||
}
|
||||
|
||||
public String topLevelName() {
|
||||
String name = attrs.topLevelName;
|
||||
return name == null ? name() : name;
|
||||
}
|
||||
|
||||
private byte[] sha1(byte[] entry) {
|
||||
MD.update(entry);
|
||||
return MD.digest();
|
||||
}
|
||||
|
||||
private byte[] sha1(byte[] entry, int offset) {
|
||||
MD.update(entry, offset, entry.length - offset);
|
||||
return MD.digest();
|
||||
}
|
||||
|
||||
private boolean isEqual(byte[] sha1_1, byte[] sha1_2) {
|
||||
return MessageDigest.isEqual(sha1_1, sha1_2);
|
||||
}
|
||||
|
||||
private static final byte[] cafeBabe = {(byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe};
|
||||
|
||||
private boolean isCafeBabe(byte[] bytes) {
|
||||
if (bytes.length < 4) return false;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (bytes[i] != cafeBabe[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private ClassAttributes getClassAttributes(byte[] bytes) {
|
||||
ClassReader rdr = new ClassReader(bytes);
|
||||
ClassAttributes attrs = new ClassAttributes();
|
||||
rdr.accept(attrs, 0);
|
||||
return attrs;
|
||||
}
|
||||
|
||||
private static final class Field {
|
||||
private final int access;
|
||||
private final String name;
|
||||
private final String desc;
|
||||
|
||||
Field(int access, String name, String desc) {
|
||||
this.access = access;
|
||||
this.name = name;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object that) {
|
||||
if (that == null) return false;
|
||||
if (this == that) return true;
|
||||
if (!(that instanceof Field)) return false;
|
||||
Field field = (Field)that;
|
||||
return (access == field.access) && name.equals(field.name)
|
||||
&& desc.equals(field.desc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 17;
|
||||
result = 37 * result + access;
|
||||
result = 37 * result + name.hashCode();
|
||||
result = 37 * result + desc.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Method {
|
||||
private final int access;
|
||||
private final String name;
|
||||
private final String desc;
|
||||
private final Set<String> exceptions;
|
||||
|
||||
Method(int access, String name, String desc, Set<String> exceptions) {
|
||||
this.access = access;
|
||||
this.name = name;
|
||||
this.desc = desc;
|
||||
this.exceptions = exceptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object that) {
|
||||
if (that == null) return false;
|
||||
if (this == that) return true;
|
||||
if (!(that instanceof Method)) return false;
|
||||
Method method = (Method)that;
|
||||
return (access == method.access) && name.equals(method.name)
|
||||
&& desc.equals(method.desc)
|
||||
&& exceptions.equals(method.exceptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 17;
|
||||
result = 37 * result + access;
|
||||
result = 37 * result + name.hashCode();
|
||||
result = 37 * result + desc.hashCode();
|
||||
result = 37 * result + exceptions.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ClassAttributes extends ClassVisitor {
|
||||
private String name;
|
||||
private String topLevelName;
|
||||
private String superName;
|
||||
private int version;
|
||||
private int access;
|
||||
private boolean publicClass;
|
||||
private boolean nestedClass;
|
||||
private final Set<Field> fields = new HashSet<>();
|
||||
private final Set<Method> methods = new HashSet<>();
|
||||
|
||||
public ClassAttributes() {
|
||||
super(Opcodes.ASM5);
|
||||
}
|
||||
|
||||
private boolean isPublic(int access) {
|
||||
return ((access & Opcodes.ACC_PUBLIC) == Opcodes.ACC_PUBLIC)
|
||||
|| ((access & Opcodes.ACC_PROTECTED) == Opcodes.ACC_PROTECTED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(int version, int access, String name, String signature,
|
||||
String superName, String[] interfaces) {
|
||||
this.version = version;
|
||||
this.access = access;
|
||||
this.name = name;
|
||||
this.nestedClass = name.contains("$");
|
||||
this.superName = superName;
|
||||
this.publicClass = isPublic(access);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOuterClass(String owner, String name, String desc) {
|
||||
if (!this.nestedClass) return;
|
||||
this.topLevelName = owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(String name, String outerName, String innerName,
|
||||
int access) {
|
||||
if (!this.nestedClass) return;
|
||||
if (outerName == null) return;
|
||||
if (!this.name.equals(name)) return;
|
||||
if (this.topLevelName == null) this.topLevelName = outerName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldVisitor visitField(int access, String name, String desc,
|
||||
String signature, Object value) {
|
||||
if (isPublic(access)) {
|
||||
fields.add(new Field(access, name, desc));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String desc,
|
||||
String signature, String[] exceptions) {
|
||||
if (isPublic(access)) {
|
||||
Set<String> exceptionSet = new HashSet<>();
|
||||
if (exceptions != null) {
|
||||
for (String e : exceptions) {
|
||||
exceptionSet.add(e);
|
||||
}
|
||||
}
|
||||
// treat type descriptor as a proxy for signature because signature
|
||||
// is usually null, need to strip off the return type though
|
||||
int n;
|
||||
if (desc != null && (n = desc.lastIndexOf(')')) != -1) {
|
||||
desc = desc.substring(0, n + 1);
|
||||
methods.add(new Method(access, name, desc, exceptionSet));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
this.nestedClass = this.topLevelName != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object that) {
|
||||
if (that == null) return false;
|
||||
if (this == that) return true;
|
||||
if (!(that instanceof ClassAttributes)) return false;
|
||||
ClassAttributes clsAttrs = (ClassAttributes)that;
|
||||
boolean superNameOkay = superName != null
|
||||
? superName.equals(clsAttrs.superName) : true;
|
||||
return access == clsAttrs.access
|
||||
&& superNameOkay
|
||||
&& fields.equals(clsAttrs.fields)
|
||||
&& methods.equals(clsAttrs.methods);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 17;
|
||||
result = 37 * result + access;
|
||||
result = 37 * result + superName != null ? superName.hashCode() : 0;
|
||||
result = 37 * result + fields.hashCode();
|
||||
result = 37 * result + methods.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
@ -91,7 +91,7 @@ class GNUStyleOptions {
|
||||
tool.xflag = true;
|
||||
}
|
||||
},
|
||||
new Option(false, OptionType.MAIN_OPERATION, "--print-module-descriptor", "-p") {
|
||||
new Option(false, OptionType.MAIN_OPERATION, "--print-module-descriptor", "-d") {
|
||||
void process(Main tool, String opt, String arg) throws BadArgs {
|
||||
if (tool.cflag || tool.iflag || tool.tflag || tool.uflag || tool.xflag)
|
||||
throw new BadArgs("error.multiple.main.operations").showUsage(true);
|
||||
@ -145,7 +145,7 @@ class GNUStyleOptions {
|
||||
}
|
||||
}
|
||||
},
|
||||
new Option(true, OptionType.CREATE_UPDATE, "--modulepath", "--mp") {
|
||||
new Option(true, OptionType.CREATE_UPDATE, "--module-path", "-p") {
|
||||
void process(Main jartool, String opt, String arg) {
|
||||
String[] dirs = arg.split(File.pathSeparator);
|
||||
Path[] paths = new Path[dirs.length];
|
||||
|
@ -42,6 +42,7 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
@ -278,23 +279,20 @@ class Main {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cflag) {
|
||||
Manifest manifest = null;
|
||||
InputStream in = null;
|
||||
|
||||
if (!Mflag) {
|
||||
if (mname != null) {
|
||||
in = new FileInputStream(mname);
|
||||
manifest = new Manifest(new BufferedInputStream(in));
|
||||
try (InputStream in = new FileInputStream(mname)) {
|
||||
manifest = new Manifest(new BufferedInputStream(in));
|
||||
}
|
||||
} else {
|
||||
manifest = new Manifest();
|
||||
}
|
||||
addVersion(manifest);
|
||||
addCreatedBy(manifest);
|
||||
if (isAmbiguousMainClass(manifest)) {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (ename != null) {
|
||||
@ -304,11 +302,13 @@ class Main {
|
||||
addMultiRelease(manifest);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String,Path> moduleInfoPaths = new HashMap<>();
|
||||
for (int version : filesMap.keySet()) {
|
||||
String[] files = filesMap.get(version);
|
||||
expand(null, files, false, moduleInfoPaths, version);
|
||||
}
|
||||
|
||||
Map<String,byte[]> moduleInfos = new LinkedHashMap<>();
|
||||
if (!moduleInfoPaths.isEmpty()) {
|
||||
if (!checkModuleInfos(moduleInfoPaths))
|
||||
@ -332,84 +332,61 @@ class Main {
|
||||
return false;
|
||||
}
|
||||
|
||||
OutputStream out;
|
||||
if (fname != null) {
|
||||
out = new FileOutputStream(fname);
|
||||
} else {
|
||||
out = new FileOutputStream(FileDescriptor.out);
|
||||
if (vflag) {
|
||||
// Disable verbose output so that it does not appear
|
||||
// on stdout along with file data
|
||||
// error("Warning: -v option ignored");
|
||||
vflag = false;
|
||||
}
|
||||
if (vflag && fname == null) {
|
||||
// Disable verbose output so that it does not appear
|
||||
// on stdout along with file data
|
||||
// error("Warning: -v option ignored");
|
||||
vflag = false;
|
||||
}
|
||||
File tmpfile = null;
|
||||
final OutputStream finalout = out;
|
||||
|
||||
final String tmpbase = (fname == null)
|
||||
? "tmpjar"
|
||||
: fname.substring(fname.indexOf(File.separatorChar) + 1);
|
||||
if (nflag) {
|
||||
tmpfile = createTemporaryFile(tmpbase, ".jar");
|
||||
out = new FileOutputStream(tmpfile);
|
||||
}
|
||||
create(new BufferedOutputStream(out, 4096), manifest, moduleInfos);
|
||||
File tmpfile = createTemporaryFile(tmpbase, ".jar");
|
||||
|
||||
if (in != null) {
|
||||
in.close();
|
||||
try (OutputStream out = new FileOutputStream(tmpfile)) {
|
||||
create(new BufferedOutputStream(out, 4096), manifest, moduleInfos);
|
||||
}
|
||||
out.close();
|
||||
|
||||
if (nflag) {
|
||||
JarFile jarFile = null;
|
||||
File packFile = null;
|
||||
JarOutputStream jos = null;
|
||||
File packFile = createTemporaryFile(tmpbase, ".pack");
|
||||
try {
|
||||
Packer packer = Pack200.newPacker();
|
||||
Map<String, String> p = packer.properties();
|
||||
p.put(Packer.EFFORT, "1"); // Minimal effort to conserve CPU
|
||||
jarFile = new JarFile(tmpfile.getCanonicalPath());
|
||||
packFile = createTemporaryFile(tmpbase, ".pack");
|
||||
out = new FileOutputStream(packFile);
|
||||
packer.pack(jarFile, out);
|
||||
jos = new JarOutputStream(finalout);
|
||||
Unpacker unpacker = Pack200.newUnpacker();
|
||||
unpacker.unpack(packFile, jos);
|
||||
} catch (IOException ioe) {
|
||||
fatalError(ioe);
|
||||
} finally {
|
||||
if (jarFile != null) {
|
||||
jarFile.close();
|
||||
try (
|
||||
JarFile jarFile = new JarFile(tmpfile.getCanonicalPath());
|
||||
OutputStream pack = new FileOutputStream(packFile)
|
||||
) {
|
||||
packer.pack(jarFile, pack);
|
||||
}
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
if (jos != null) {
|
||||
jos.close();
|
||||
}
|
||||
if (tmpfile != null && tmpfile.exists()) {
|
||||
if (tmpfile.exists()) {
|
||||
tmpfile.delete();
|
||||
}
|
||||
if (packFile != null && packFile.exists()) {
|
||||
packFile.delete();
|
||||
tmpfile = createTemporaryFile(tmpbase, ".jar");
|
||||
try (
|
||||
OutputStream out = new FileOutputStream(tmpfile);
|
||||
JarOutputStream jos = new JarOutputStream(out)
|
||||
) {
|
||||
Unpacker unpacker = Pack200.newUnpacker();
|
||||
unpacker.unpack(packFile, jos);
|
||||
}
|
||||
} finally {
|
||||
Files.deleteIfExists(packFile.toPath());
|
||||
}
|
||||
}
|
||||
|
||||
validateAndClose(tmpfile);
|
||||
|
||||
} else if (uflag) {
|
||||
File inputFile = null, tmpFile = null;
|
||||
FileInputStream in;
|
||||
FileOutputStream out;
|
||||
if (fname != null) {
|
||||
inputFile = new File(fname);
|
||||
tmpFile = createTempFileInSameDirectoryAs(inputFile);
|
||||
in = new FileInputStream(inputFile);
|
||||
out = new FileOutputStream(tmpFile);
|
||||
} else {
|
||||
in = new FileInputStream(FileDescriptor.in);
|
||||
out = new FileOutputStream(FileDescriptor.out);
|
||||
vflag = false;
|
||||
tmpFile = createTemporaryFile("tmpjar", ".jar");
|
||||
}
|
||||
InputStream manifest = (!Mflag && (mname != null)) ?
|
||||
(new FileInputStream(mname)) : null;
|
||||
|
||||
Map<String,Path> moduleInfoPaths = new HashMap<>();
|
||||
for (int version : filesMap.keySet()) {
|
||||
@ -421,8 +398,19 @@ class Main {
|
||||
for (Map.Entry<String,Path> e : moduleInfoPaths.entrySet())
|
||||
moduleInfos.put(e.getKey(), readModuleInfo(e.getValue()));
|
||||
|
||||
boolean updateOk = update(in, new BufferedOutputStream(out),
|
||||
manifest, moduleInfos, null);
|
||||
try (
|
||||
FileInputStream in = (fname != null) ? new FileInputStream(inputFile)
|
||||
: new FileInputStream(FileDescriptor.in);
|
||||
FileOutputStream out = new FileOutputStream(tmpFile);
|
||||
InputStream manifest = (!Mflag && (mname != null)) ?
|
||||
(new FileInputStream(mname)) : null;
|
||||
) {
|
||||
boolean updateOk = update(in, new BufferedOutputStream(out),
|
||||
manifest, moduleInfos, null);
|
||||
if (ok) {
|
||||
ok = updateOk;
|
||||
}
|
||||
}
|
||||
|
||||
// Consistency checks for modular jars.
|
||||
if (!moduleInfos.isEmpty()) {
|
||||
@ -430,23 +418,8 @@ class Main {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
ok = updateOk;
|
||||
}
|
||||
in.close();
|
||||
out.close();
|
||||
if (manifest != null) {
|
||||
manifest.close();
|
||||
}
|
||||
if (ok && fname != null) {
|
||||
// on Win32, we need this delete
|
||||
inputFile.delete();
|
||||
if (!tmpFile.renameTo(inputFile)) {
|
||||
tmpFile.delete();
|
||||
throw new IOException(getMsg("error.write.file"));
|
||||
}
|
||||
tmpFile.delete();
|
||||
}
|
||||
validateAndClose(tmpFile);
|
||||
|
||||
} else if (tflag) {
|
||||
replaceFSC(filesMap);
|
||||
// For the "list table contents" action, access using the
|
||||
@ -520,6 +493,28 @@ class Main {
|
||||
return ok;
|
||||
}
|
||||
|
||||
private void validateAndClose(File tmpfile) throws IOException {
|
||||
if (ok && isMultiRelease) {
|
||||
ok = validate(tmpfile.getCanonicalPath());
|
||||
if (!ok) {
|
||||
error(formatMsg("error.validator.jarfile.invalid", fname));
|
||||
}
|
||||
}
|
||||
|
||||
Path path = tmpfile.toPath();
|
||||
try {
|
||||
if (ok) {
|
||||
if (fname != null) {
|
||||
Files.move(path, Paths.get(fname), StandardCopyOption.REPLACE_EXISTING);
|
||||
} else {
|
||||
Files.copy(path, new FileOutputStream(FileDescriptor.out));
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Files.deleteIfExists(path);
|
||||
}
|
||||
}
|
||||
|
||||
private String[] filesMapToFiles(Map<Integer,String[]> filesMap) {
|
||||
if (filesMap.isEmpty()) return null;
|
||||
return filesMap.entrySet()
|
||||
@ -534,6 +529,76 @@ class Main {
|
||||
.map(f -> (new EntryName(f, version)).entryName);
|
||||
}
|
||||
|
||||
// sort base entries before versioned entries, and sort entry classes with
|
||||
// nested classes so that the top level class appears before the associated
|
||||
// nested class
|
||||
private Comparator<JarEntry> entryComparator = (je1, je2) -> {
|
||||
String s1 = je1.getName();
|
||||
String s2 = je2.getName();
|
||||
if (s1.equals(s2)) return 0;
|
||||
boolean b1 = s1.startsWith(VERSIONS_DIR);
|
||||
boolean b2 = s2.startsWith(VERSIONS_DIR);
|
||||
if (b1 && !b2) return 1;
|
||||
if (!b1 && b2) return -1;
|
||||
int n = 0; // starting char for String compare
|
||||
if (b1 && b2) {
|
||||
// normally strings would be sorted so "10" goes before "9", but
|
||||
// version number strings need to be sorted numerically
|
||||
n = VERSIONS_DIR.length(); // skip the common prefix
|
||||
int i1 = s1.indexOf('/', n);
|
||||
int i2 = s1.indexOf('/', n);
|
||||
if (i1 == -1) throw new InvalidJarException(s1);
|
||||
if (i2 == -1) throw new InvalidJarException(s2);
|
||||
// shorter version numbers go first
|
||||
if (i1 != i2) return i1 - i2;
|
||||
// otherwise, handle equal length numbers below
|
||||
}
|
||||
int l1 = s1.length();
|
||||
int l2 = s2.length();
|
||||
int lim = Math.min(l1, l2);
|
||||
for (int k = n; k < lim; k++) {
|
||||
char c1 = s1.charAt(k);
|
||||
char c2 = s2.charAt(k);
|
||||
if (c1 != c2) {
|
||||
// change natural ordering so '.' comes before '$'
|
||||
// i.e. top level classes come before nested classes
|
||||
if (c1 == '$' && c2 == '.') return 1;
|
||||
if (c1 == '.' && c2 == '$') return -1;
|
||||
return c1 - c2;
|
||||
}
|
||||
}
|
||||
return l1 - l2;
|
||||
};
|
||||
|
||||
private boolean validate(String fname) {
|
||||
boolean valid;
|
||||
|
||||
try (JarFile jf = new JarFile(fname)) {
|
||||
Validator validator = new Validator(this, jf);
|
||||
jf.stream()
|
||||
.filter(e -> !e.isDirectory())
|
||||
.filter(e -> !e.getName().equals(MANIFEST_NAME))
|
||||
.filter(e -> !e.getName().endsWith(MODULE_INFO))
|
||||
.sorted(entryComparator)
|
||||
.forEachOrdered(validator);
|
||||
valid = validator.isValid();
|
||||
} catch (IOException e) {
|
||||
error(formatMsg2("error.validator.jarfile.exception", fname, e.getMessage()));
|
||||
valid = false;
|
||||
} catch (InvalidJarException e) {
|
||||
error(formatMsg("error.validator.bad.entry.name", e.getMessage()));
|
||||
valid = false;
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
private static class InvalidJarException extends RuntimeException {
|
||||
private static final long serialVersionUID = -3642329147299217726L;
|
||||
InvalidJarException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses command line arguments.
|
||||
*/
|
||||
|
242
jdk/src/jdk.jartool/share/classes/sun/tools/jar/Validator.java
Normal file
242
jdk/src/jdk.jartool/share/classes/sun/tools/jar/Validator.java
Normal file
@ -0,0 +1,242 @@
|
||||
/*
|
||||
* 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 sun.tools.jar;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
final class Validator implements Consumer<JarEntry> {
|
||||
private final static boolean DEBUG = Boolean.getBoolean("jar.debug");
|
||||
private final Map<String,FingerPrint> fps = new HashMap<>();
|
||||
private final int vdlen = Main.VERSIONS_DIR.length();
|
||||
private final Main main;
|
||||
private final JarFile jf;
|
||||
private int oldVersion = -1;
|
||||
private String currentTopLevelName;
|
||||
private boolean isValid = true;
|
||||
|
||||
Validator(Main main, JarFile jf) {
|
||||
this.main = main;
|
||||
this.jf = jf;
|
||||
}
|
||||
|
||||
boolean isValid() {
|
||||
return isValid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validator has state and assumes entries provided to accept are ordered
|
||||
* from base entries first and then through the versioned entries in
|
||||
* ascending version order. Also, to find isolated nested classes,
|
||||
* classes must be ordered so that the top level class is before the associated
|
||||
* nested class(es).
|
||||
*/
|
||||
public void accept(JarEntry je) {
|
||||
String entryName = je.getName();
|
||||
|
||||
// directories are always accepted
|
||||
if (entryName.endsWith("/")) {
|
||||
debug("%s is a directory", entryName);
|
||||
return;
|
||||
}
|
||||
|
||||
// figure out the version and basename from the JarEntry
|
||||
int version;
|
||||
String basename;
|
||||
if (entryName.startsWith(Main.VERSIONS_DIR)) {
|
||||
int n = entryName.indexOf("/", vdlen);
|
||||
if (n == -1) {
|
||||
main.error(Main.formatMsg("error.validator.version.notnumber", entryName));
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
String v = entryName.substring(vdlen, n);
|
||||
try {
|
||||
version = Integer.parseInt(v);
|
||||
} catch (NumberFormatException x) {
|
||||
main.error(Main.formatMsg("error.validator.version.notnumber", entryName));
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
if (n == entryName.length()) {
|
||||
main.error(Main.formatMsg("error.validator.entryname.tooshort", entryName));
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
basename = entryName.substring(n + 1);
|
||||
} else {
|
||||
version = 0;
|
||||
basename = entryName;
|
||||
}
|
||||
debug("\n===================\nversion %d %s", version, entryName);
|
||||
|
||||
if (oldVersion != version) {
|
||||
oldVersion = version;
|
||||
currentTopLevelName = null;
|
||||
}
|
||||
|
||||
// analyze the entry, keeping key attributes
|
||||
FingerPrint fp;
|
||||
try (InputStream is = jf.getInputStream(je)) {
|
||||
fp = new FingerPrint(basename, is.readAllBytes());
|
||||
} catch (IOException x) {
|
||||
main.error(x.getMessage());
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
String internalName = fp.name();
|
||||
|
||||
// process a base entry paying attention to nested classes
|
||||
if (version == 0) {
|
||||
debug("base entry found");
|
||||
if (fp.isNestedClass()) {
|
||||
debug("nested class found");
|
||||
if (fp.topLevelName().equals(currentTopLevelName)) {
|
||||
fps.put(internalName, fp);
|
||||
return;
|
||||
}
|
||||
main.error(Main.formatMsg("error.validator.isolated.nested.class", entryName));
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
// top level class or resource entry
|
||||
if (fp.isClass()) {
|
||||
currentTopLevelName = fp.topLevelName();
|
||||
if (!checkInternalName(entryName, basename, internalName)) {
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
fps.put(internalName, fp);
|
||||
return;
|
||||
}
|
||||
|
||||
// process a versioned entry, look for previous entry with same name
|
||||
FingerPrint matchFp = fps.get(internalName);
|
||||
debug("looking for match");
|
||||
if (matchFp == null) {
|
||||
debug("no match found");
|
||||
if (fp.isClass()) {
|
||||
if (fp.isNestedClass()) {
|
||||
if (!checkNestedClass(version, entryName, internalName, fp)) {
|
||||
isValid = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (fp.isPublicClass()) {
|
||||
main.error(Main.formatMsg("error.validator.new.public.class", entryName));
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
debug("%s is a non-public class entry", entryName);
|
||||
fps.put(internalName, fp);
|
||||
currentTopLevelName = fp.topLevelName();
|
||||
return;
|
||||
}
|
||||
debug("%s is a resource entry");
|
||||
fps.put(internalName, fp);
|
||||
return;
|
||||
}
|
||||
debug("match found");
|
||||
|
||||
// are the two classes/resources identical?
|
||||
if (fp.isIdentical(matchFp)) {
|
||||
main.error(Main.formatMsg("error.validator.identical.entry", entryName));
|
||||
return; // it's okay, just takes up room
|
||||
}
|
||||
debug("sha1 not equal -- different bytes");
|
||||
|
||||
// ok, not identical, check for compatible class version and api
|
||||
if (fp.isClass()) {
|
||||
if (fp.isNestedClass()) {
|
||||
if (!checkNestedClass(version, entryName, internalName, fp)) {
|
||||
isValid = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
debug("%s is a class entry", entryName);
|
||||
if (!fp.isCompatibleVersion(matchFp)) {
|
||||
main.error(Main.formatMsg("error.validator.incompatible.class.version", entryName));
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
if (!fp.isSameAPI(matchFp)) {
|
||||
main.error(Main.formatMsg("error.validator.different.api", entryName));
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
if (!checkInternalName(entryName, basename, internalName)) {
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
debug("fingerprints same -- same api");
|
||||
fps.put(internalName, fp);
|
||||
currentTopLevelName = fp.topLevelName();
|
||||
return;
|
||||
}
|
||||
debug("%s is a resource", entryName);
|
||||
|
||||
main.error(Main.formatMsg("error.validator.resources.with.same.name", entryName));
|
||||
fps.put(internalName, fp);
|
||||
return;
|
||||
}
|
||||
|
||||
private boolean checkInternalName(String entryName, String basename, String internalName) {
|
||||
String className = className(basename);
|
||||
if (internalName.equals(className)) {
|
||||
return true;
|
||||
}
|
||||
main.error(Main.formatMsg2("error.validator.names.mismatch",
|
||||
entryName, internalName.replace("/", ".")));
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkNestedClass(int version, String entryName, String internalName, FingerPrint fp) {
|
||||
debug("%s is a nested class entry in top level class %s", entryName, fp.topLevelName());
|
||||
if (fp.topLevelName().equals(currentTopLevelName)) {
|
||||
debug("%s (top level class) was accepted", fp.topLevelName());
|
||||
fps.put(internalName, fp);
|
||||
return true;
|
||||
}
|
||||
debug("top level class was not accepted");
|
||||
main.error(Main.formatMsg("error.validator.isolated.nested.class", entryName));
|
||||
return false;
|
||||
}
|
||||
|
||||
private String className(String entryName) {
|
||||
return entryName.endsWith(".class") ? entryName.substring(0, entryName.length() - 6) : null;
|
||||
}
|
||||
|
||||
private void debug(String fmt, Object... args) {
|
||||
if (DEBUG) System.err.format(fmt, args);
|
||||
}
|
||||
}
|
||||
|
@ -85,6 +85,30 @@ error.release.value.notnumber=\
|
||||
release {0} not valid
|
||||
error.release.value.toosmall=\
|
||||
release {0} not valid, must be >= 9
|
||||
error.validator.jarfile.exception=\
|
||||
can not validate {0}: {1}
|
||||
error.validator.jarfile.invalid=\
|
||||
invalid multi-release jar file {0} deleted
|
||||
error.validator.bad.entry.name=\
|
||||
entry name malformed, {0}
|
||||
error.validator.version.notnumber=\
|
||||
entry name: {0}, does not have a version number
|
||||
error.validator.entryname.tooshort=\
|
||||
entry name: {0}, too short, not a directory
|
||||
error.validator.isolated.nested.class=\
|
||||
entry: {0}, is an isolated nested class
|
||||
error.validator.new.public.class=\
|
||||
entry: {0}, contains a new public class not found in base entries
|
||||
error.validator.identical.entry=\
|
||||
warning - entry: {0} contains a class that is identical to an entry already in the jar
|
||||
error.validator.incompatible.class.version=\
|
||||
entry: {0}, has a class version incompatible with an earlier version
|
||||
error.validator.different.api=\
|
||||
entry: {0}, contains a class with different api from earlier version
|
||||
error.validator.resources.with.same.name=\
|
||||
warning - entry: {0}, multiple resources with same name
|
||||
error.validator.names.mismatch=\
|
||||
entry: {0}, contains a class with internal name {1}, names do not match
|
||||
out.added.manifest=\
|
||||
added manifest
|
||||
out.added.module-info=\
|
||||
@ -177,7 +201,7 @@ main.help.opt.main.update=\
|
||||
main.help.opt.main.extract=\
|
||||
\ -x, --extract Extract named (or all) files from the archive
|
||||
main.help.opt.main.print-module-descriptor=\
|
||||
\ -p, --print-module-descriptor Print the module descriptor
|
||||
\ -d, --print-module-descriptor Print the module descriptor
|
||||
main.help.opt.any=\
|
||||
\ Operation modifiers valid in any mode:\n\
|
||||
\n\
|
||||
@ -208,8 +232,8 @@ main.help.opt.create.update.hash-modules=\
|
||||
\ matched by the given pattern and that depend upon\n\
|
||||
\ directly or indirectly on a modular jar being\n\
|
||||
\ created or a non-modular jar being updated
|
||||
main.help.opt.create.update.modulepath=\
|
||||
\ --modulepath Location of module dependence for generating
|
||||
main.help.opt.create.update.module-path=\
|
||||
\ -p, --module-path Location of module dependence for generating\n\
|
||||
\ the hash
|
||||
main.help.opt.create.update.index=\
|
||||
\ Operation modifiers valid only in create, update, and generate-index mode:\n
|
||||
@ -226,7 +250,7 @@ main.help.postopt=\
|
||||
\ located in the root of the given directories, or the root of the jar archive\n\
|
||||
\ itself. The following operations are only valid when creating a modular jar,\n\
|
||||
\ or updating an existing non-modular jar: '--module-version',\n\
|
||||
\ '--hash-modules', and '--modulepath'.\n\
|
||||
\ '--hash-modules', and '--module-path'.\n\
|
||||
\n\
|
||||
\ Mandatory or optional arguments to long options are also mandatory or optional\n\
|
||||
\ for any corresponding short options.
|
||||
\ for any corresponding short options.
|
||||
|
@ -61,11 +61,11 @@ class JImageTask {
|
||||
|
||||
new Option<JImageTask>(false, (task, option, arg) -> {
|
||||
task.options.fullVersion = true;
|
||||
}, true, "--fullversion"),
|
||||
}, true, "--full-version"),
|
||||
|
||||
new Option<JImageTask>(false, (task, option, arg) -> {
|
||||
task.options.help = true;
|
||||
}, "--help"),
|
||||
}, "--help", "-h"),
|
||||
|
||||
new Option<JImageTask>(false, (task, option, arg) -> {
|
||||
task.options.verbose = true;
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
main.usage.summary=\
|
||||
Usage: {0} <extract | info | list | verify> <options> jimage...\n\
|
||||
use --help for a list of possible options.
|
||||
use -h or --help for a list of possible options.
|
||||
|
||||
main.usage=\
|
||||
Usage: {0} <extract | info | list | verify> <options> jimage...\n\
|
||||
@ -76,11 +76,11 @@ main.opt.footer=\
|
||||
\ used, one pattern per line\n\
|
||||
|
||||
|
||||
main.opt.fullversion=\
|
||||
\ --fullversion Print full version information
|
||||
main.opt.full-version=\
|
||||
\ --full-version Print full version information
|
||||
|
||||
main.opt.help=\
|
||||
\ --help Print usage message
|
||||
\ -h, --help Print usage message
|
||||
|
||||
main.opt.verbose=\
|
||||
\ --verbose Listing prints entry size and offset attributes
|
||||
|
@ -84,31 +84,32 @@ public class JlinkTask {
|
||||
private static final Option<?>[] recognizedOptions = {
|
||||
new Option<JlinkTask>(false, (task, opt, arg) -> {
|
||||
task.options.help = true;
|
||||
}, "--help"),
|
||||
}, "--help", "-h"),
|
||||
new Option<JlinkTask>(true, (task, opt, arg) -> {
|
||||
String[] dirs = arg.split(File.pathSeparator);
|
||||
int i = 0;
|
||||
Arrays.stream(dirs)
|
||||
.map(Paths::get)
|
||||
.forEach(task.options.modulePath::add);
|
||||
}, "--modulepath", "--mp"),
|
||||
}, "--module-path", "-p"),
|
||||
new Option<JlinkTask>(true, (task, opt, arg) -> {
|
||||
for (String mn : arg.split(",")) {
|
||||
if (mn.isEmpty()) {
|
||||
throw taskHelper.newBadArgs("err.mods.must.be.specified",
|
||||
"--limitmods");
|
||||
"--limit-modules");
|
||||
}
|
||||
task.options.limitMods.add(mn);
|
||||
}
|
||||
}, "--limitmods"),
|
||||
}, "--limit-modules"),
|
||||
new Option<JlinkTask>(true, (task, opt, arg) -> {
|
||||
for (String mn : arg.split(",")) {
|
||||
if (mn.isEmpty()) {
|
||||
throw taskHelper.newBadArgs("err.mods.must.be.specified",
|
||||
"--addmods");
|
||||
"--add-modules");
|
||||
}
|
||||
task.options.addMods.add(mn);
|
||||
}
|
||||
}, "--addmods"),
|
||||
}, "--add-modules"),
|
||||
new Option<JlinkTask>(true, (task, opt, arg) -> {
|
||||
Path path = Paths.get(arg);
|
||||
task.options.output = path;
|
||||
@ -134,10 +135,10 @@ public class JlinkTask {
|
||||
}, true, "--keep-packaged-modules"),
|
||||
new Option<JlinkTask>(true, (task, opt, arg) -> {
|
||||
task.options.saveoptsfile = arg;
|
||||
}, "--saveopts"),
|
||||
}, "--save-opts"),
|
||||
new Option<JlinkTask>(false, (task, opt, arg) -> {
|
||||
task.options.fullVersion = true;
|
||||
}, true, "--fullversion"),};
|
||||
}, true, "--full-version"),};
|
||||
|
||||
private static final String PROGNAME = "jlink";
|
||||
private final OptionsValues options = new OptionsValues();
|
||||
@ -294,7 +295,7 @@ public class JlinkTask {
|
||||
try {
|
||||
options.addMods = checkAddMods(options.addMods);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw taskHelper.newBadArgs("err.mods.must.be.specified", "--addmods")
|
||||
throw taskHelper.newBadArgs("err.mods.must.be.specified", "--add-modules")
|
||||
.showUsage(true);
|
||||
}
|
||||
// First create the image provider
|
||||
|
@ -196,7 +196,7 @@ public final class TaskHelper {
|
||||
// This option is handled prior
|
||||
// to have the options parsed.
|
||||
},
|
||||
"--plugins-modulepath"));
|
||||
"--plugin-module-path"));
|
||||
mainOptions.add(new PlugOption(true, (task, opt, arg) -> {
|
||||
Path path = Paths.get(arg);
|
||||
if (!Files.exists(path) || !Files.isDirectory(path)) {
|
||||
|
@ -25,7 +25,6 @@
|
||||
package jdk.tools.jlink.internal.plugins;
|
||||
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
@ -33,6 +32,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import jdk.internal.misc.JavaLangInvokeAccess;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolEntry;
|
||||
import jdk.tools.jlink.plugin.PluginException;
|
||||
import jdk.tools.jlink.plugin.ResourcePool;
|
||||
@ -54,9 +55,6 @@ public final class GenerateJLIClassesPlugin implements Plugin {
|
||||
|
||||
private static final String DESCRIPTION = PluginsResourceBundle.getDescription(NAME);
|
||||
|
||||
private static final String BMH = "java/lang/invoke/BoundMethodHandle";
|
||||
private static final Method BMH_FACTORY_METHOD;
|
||||
|
||||
private static final String DMH = "java/lang/invoke/DirectMethodHandle$Holder";
|
||||
private static final String DMH_INVOKE_VIRTUAL = "invokeVirtual";
|
||||
private static final String DMH_INVOKE_STATIC = "invokeStatic";
|
||||
@ -64,7 +62,9 @@ public final class GenerateJLIClassesPlugin implements Plugin {
|
||||
private static final String DMH_NEW_INVOKE_SPECIAL = "newInvokeSpecial";
|
||||
private static final String DMH_INVOKE_INTERFACE = "invokeInterface";
|
||||
private static final String DMH_INVOKE_STATIC_INIT = "invokeStaticInit";
|
||||
private static final Method DMH_FACTORY_METHOD;
|
||||
|
||||
private static final JavaLangInvokeAccess JLIA
|
||||
= SharedSecrets.getJavaLangInvokeAccess();
|
||||
|
||||
List<String> speciesTypes;
|
||||
|
||||
@ -232,8 +232,8 @@ public final class GenerateJLIClassesPlugin implements Plugin {
|
||||
private void generateBMHClass(String types, ResourcePoolBuilder out) {
|
||||
try {
|
||||
// Generate class
|
||||
Map.Entry<String, byte[]> result = (Map.Entry<String, byte[]>)
|
||||
BMH_FACTORY_METHOD.invoke(null, types);
|
||||
Map.Entry<String, byte[]> result =
|
||||
JLIA.generateConcreteBMHClassBytes(types);
|
||||
String className = result.getKey();
|
||||
byte[] bytes = result.getValue();
|
||||
|
||||
@ -264,11 +264,8 @@ public final class GenerateJLIClassesPlugin implements Plugin {
|
||||
}
|
||||
}
|
||||
try {
|
||||
byte[] bytes = (byte[])DMH_FACTORY_METHOD
|
||||
.invoke(null,
|
||||
DMH,
|
||||
methodTypes,
|
||||
dmhTypes);
|
||||
byte[] bytes =
|
||||
JLIA.generateDMHClassBytes(DMH, methodTypes, dmhTypes);
|
||||
ResourcePoolEntry ndata = ResourcePoolEntry.create(DMH_ENTRY, bytes);
|
||||
out.add(ndata);
|
||||
} catch (Exception ex) {
|
||||
@ -277,22 +274,6 @@ public final class GenerateJLIClassesPlugin implements Plugin {
|
||||
}
|
||||
private static final String DMH_ENTRY = "/java.base/" + DMH + ".class";
|
||||
|
||||
static {
|
||||
try {
|
||||
Class<?> BMHFactory = Class.forName("java.lang.invoke.BoundMethodHandle$Factory");
|
||||
BMH_FACTORY_METHOD = BMHFactory.getDeclaredMethod("generateConcreteBMHClassBytes",
|
||||
String.class);
|
||||
BMH_FACTORY_METHOD.setAccessible(true);
|
||||
|
||||
Class<?> DMHFactory = Class.forName("java.lang.invoke.DirectMethodHandle");
|
||||
DMH_FACTORY_METHOD = DMHFactory.getDeclaredMethod("generateDMHClassBytes",
|
||||
String.class, MethodType[].class, int[].class);
|
||||
DMH_FACTORY_METHOD.setAccessible(true);
|
||||
} catch (Exception e) {
|
||||
throw new PluginException(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert LL -> LL, L3 -> LLL
|
||||
private static String expandSignature(String signature) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
@ -24,30 +24,31 @@
|
||||
#
|
||||
|
||||
main.usage.summary=\
|
||||
Usage: {0} <options> --modulepath <modulepath> --addmods <mods> --output <path>\n\
|
||||
Usage: {0} <options> --module-path <modulepath> --add-modules <mods> --output <path>\n\
|
||||
use --help for a list of possible options
|
||||
|
||||
main.usage=\
|
||||
Usage: {0} <options> --modulepath <modulepath> --addmods <mods> --output <path>\n\
|
||||
Usage: {0} <options> --module-path <modulepath> --add-modules <mods> --output <path>\n\
|
||||
\Possible options include:
|
||||
|
||||
error.prefix=Error:
|
||||
warn.prefix=Warning:
|
||||
|
||||
main.opt.help=\
|
||||
\ --help Print this help message
|
||||
\ -h, --help Print this help message
|
||||
|
||||
main.opt.version=\
|
||||
\ --version Version information
|
||||
|
||||
main.opt.modulepath=\
|
||||
\ --modulepath <modulepath> Module path
|
||||
main.opt.module-path=\
|
||||
\ -p <modulepath>\n\
|
||||
\ --module-path <modulepath> Module path
|
||||
|
||||
main.opt.addmods=\
|
||||
\ --addmods <mod>[,<mod>...] Root modules to resolve
|
||||
main.opt.add-modules=\
|
||||
\ --add-modules <mod>[,<mod>...] Root modules to resolve
|
||||
|
||||
main.opt.limitmods=\
|
||||
\ --limitmods <mod>[,<mod>...] Limit the universe of observable modules
|
||||
main.opt.limit-modules=\
|
||||
\ --limit-modules <mod>[,<mod>...] Limit the universe of observable modules
|
||||
|
||||
main.opt.output=\
|
||||
\ --output <path> Location of output path
|
||||
@ -58,8 +59,8 @@ main.command.files=\
|
||||
main.opt.endian=\
|
||||
\ --endian <little|big> Byte order of generated jimage (default:native)
|
||||
|
||||
main.opt.saveopts=\
|
||||
\ --saveopts <filename> Save jlink options in the given file
|
||||
main.opt.save-opts=\
|
||||
\ --save-opts <filename> Save jlink options in the given file
|
||||
|
||||
main.msg.bug=\
|
||||
An exception has occurred in jlink. \
|
||||
@ -83,7 +84,7 @@ main.extended.help.footer=\
|
||||
|
||||
err.unknown.byte.order:unknown byte order {0}
|
||||
err.output.must.be.specified:--output must be specified
|
||||
err.modulepath.must.be.specified:--modulepath must be specified
|
||||
err.modulepath.must.be.specified:--module-path must be specified
|
||||
err.mods.must.be.specified:no modules specified to {0}
|
||||
err.path.not.found=path not found: {0}
|
||||
err.path.not.valid=invalid path: {0}
|
||||
|
@ -115,7 +115,7 @@ include-locales.invalidtag=\
|
||||
Invalid language tag: %s
|
||||
|
||||
include-locales.localedatanotfound=\
|
||||
jdk.localedata module was not specified with --addmods option
|
||||
jdk.localedata module was not specified with --add-modules option
|
||||
|
||||
main.status.ok=Functional.
|
||||
|
||||
@ -133,8 +133,8 @@ plugin.opt.post-process-path=\
|
||||
plugin.opt.resources-last-sorter=\
|
||||
\ --resources-last-sorter <name> The last plugin allowed to sort resources
|
||||
|
||||
plugin.opt.plugins-modulepath=\
|
||||
\ --plugin-module-path <modulepath> Custom plugins module path
|
||||
plugin.opt.plugin-module-path=\
|
||||
\ --plugin-module-path <modulepath> Custom plugin module path
|
||||
|
||||
plugin.opt.c=\
|
||||
\ -c, --compress=2 Enable compression of resources (level 2)
|
||||
|
@ -1181,7 +1181,7 @@ public class JmodTask {
|
||||
}
|
||||
}
|
||||
|
||||
private final OptionParser parser = new OptionParser();
|
||||
private final OptionParser parser = new OptionParser("hp");
|
||||
|
||||
private void handleOptions(String[] args) {
|
||||
parser.formatHelpWith(new JmodHelpFormatter());
|
||||
@ -1218,7 +1218,7 @@ public class JmodTask {
|
||||
.withValuesConvertedBy(new PatternConverter());
|
||||
|
||||
OptionSpec<Void> help
|
||||
= parser.accepts("help", getMessage("main.opt.help"))
|
||||
= parser.acceptsAll(Set.of("h", "help"), getMessage("main.opt.help"))
|
||||
.forHelp();
|
||||
|
||||
OptionSpec<Path> libs
|
||||
@ -1232,9 +1232,9 @@ public class JmodTask {
|
||||
.withRequiredArg()
|
||||
.describedAs(getMessage("main.opt.main-class.arg"));
|
||||
|
||||
OptionSpec<Path> modulePath // TODO: short version of --mp ??
|
||||
= parser.acceptsAll(Arrays.asList("mp", "modulepath"),
|
||||
getMessage("main.opt.modulepath"))
|
||||
OptionSpec<Path> modulePath
|
||||
= parser.acceptsAll(Set.of("p", "module-path"),
|
||||
getMessage("main.opt.module-path"))
|
||||
.withRequiredArg()
|
||||
.withValuesSeparatedBy(File.pathSeparatorChar)
|
||||
.withValuesConvertedBy(DirPathConverter.INSTANCE);
|
||||
|
@ -63,7 +63,7 @@ main.opt.os-arch=Operating system architecture
|
||||
main.opt.os-arch.arg=os-arch
|
||||
main.opt.os-version=Operating system version
|
||||
main.opt.os-version.arg=os-version
|
||||
main.opt.modulepath=Module path
|
||||
main.opt.module-path=Module path
|
||||
main.opt.hash-modules=Compute and record hashes to tie a packaged module\
|
||||
\ with modules matching the given <regex-pattern> and depending upon it directly\
|
||||
\ or indirectly. The hashes are recorded in the JMOD file being created, or\
|
||||
|
@ -343,6 +343,9 @@ com/sun/jdi/GetLocalVariables4Test.sh 8067354 windows-
|
||||
|
||||
com/sun/jdi/sde/SourceDebugExtensionTest.java 8158066 windows-all
|
||||
|
||||
com/sun/jdi/ClassesByName2Test.java 8160833 generic-all
|
||||
com/sun/jdi/RedefineCrossEvent.java 8160833 generic-all
|
||||
|
||||
############################################################################
|
||||
|
||||
# jdk_time
|
||||
|
@ -26,12 +26,12 @@ groups=TEST.groups [closed/TEST.groups]
|
||||
# Allow querying of various System properties in @requires clauses
|
||||
requires.properties=sun.arch.data.model java.runtime.name
|
||||
|
||||
# Tests using jtreg 4.2 b02 features
|
||||
requiredVersion=4.2 b02
|
||||
# Tests using jtreg 4.2 b03 features
|
||||
requiredVersion=4.2 b03
|
||||
|
||||
# Path to libraries in the topmost test directory. This is needed so @library
|
||||
# does not need ../../ notation to reach them
|
||||
external.lib.roots = ../../
|
||||
|
||||
# Use new form of -Xpatch
|
||||
useNewXpatch=true
|
||||
# Use new module options
|
||||
useNewOptions=true
|
||||
|
@ -81,9 +81,9 @@ cp ${TESTSRC}${FS}JavaBug.java bug
|
||||
|
||||
chmod -fR 777 bug
|
||||
|
||||
${COMPILEJAVA}${FS}bin${FS}javac -addmods java.corba -d . bug${FS}*.java
|
||||
${COMPILEJAVA}${FS}bin${FS}javac --add-modules java.corba -d . bug${FS}*.java
|
||||
|
||||
${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -addmods java.corba -cp . bug/JavaBug > test.out 2>&1
|
||||
${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} --add-modules java.corba -cp . bug/JavaBug > test.out 2>&1
|
||||
|
||||
grep "NullPointerException" test.out
|
||||
|
||||
|
@ -27,8 +27,8 @@
|
||||
* @summary Four helper classes missing in Sun JDK
|
||||
* @library /lib/testlibrary
|
||||
* @build jdk.testlibrary.*
|
||||
* @compile -addmods java.corba CorbaExceptionsCompileTest.java
|
||||
* @run main/othervm -addmods java.corba CorbaExceptionsCompileTest
|
||||
* @modules java.corba
|
||||
* @run main CorbaExceptionsCompileTest
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
|
@ -25,8 +25,8 @@
|
||||
* @test
|
||||
* @bug 7095856
|
||||
* @summary OutputStreamHook doesn't handle null values
|
||||
* @compile -addmods java.corba HookPutFieldsTest.java
|
||||
* @run main/othervm -addmods java.corba HookPutFieldsTest
|
||||
* @modules java.corba
|
||||
* @run main HookPutFieldsTest
|
||||
*/
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
@ -25,8 +25,8 @@
|
||||
* @test
|
||||
* @bug 8028215
|
||||
* @summary SetDefaultORBTest setting ORB impl via properties test
|
||||
* @compile -addmods java.corba SetDefaultORBTest.java
|
||||
* @run main/othervm -addmods java.corba SetDefaultORBTest
|
||||
* @modules java.corba
|
||||
* @run main SetDefaultORBTest
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -99,11 +99,11 @@ env
|
||||
set -vx
|
||||
#
|
||||
# Compile test class
|
||||
${TESTJAVA}/bin/javac -XaddExports:jdk.jdi/com.sun.tools.example.debug.tty=ALL-UNNAMED \
|
||||
${TESTJAVA}/bin/javac --add-exports jdk.jdi/com.sun.tools.example.debug.tty=ALL-UNNAMED \
|
||||
-d "${TESTCLASSES}" ${CP} -g "${TESTSRC}"/"${TARGETCLASS}".java
|
||||
#
|
||||
# Run the test class, again with the classpath we need:
|
||||
${TESTJAVA}/bin/java -XaddExports:jdk.jdi/com.sun.tools.example.debug.tty=ALL-UNNAMED \
|
||||
${TESTJAVA}/bin/java --add-exports jdk.jdi/com.sun.tools.example.debug.tty=ALL-UNNAMED \
|
||||
${CP} ${TARGETCLASS}
|
||||
status=$?
|
||||
echo "test status was: $status"
|
||||
|
@ -26,6 +26,7 @@
|
||||
* @summary Tests that JNDI/COS naming parser supports the syntax
|
||||
* defined in the new INS standard.
|
||||
* @modules java.corba/com.sun.jndi.cosnaming
|
||||
* @run main/othervm CNNameParser
|
||||
*/
|
||||
|
||||
import javax.naming.*;
|
||||
|
@ -25,6 +25,7 @@
|
||||
* @bug 5042453
|
||||
* @summary Ipv6 address throws Non-numeric port number error
|
||||
* @modules java.corba/com.sun.jndi.cosnaming
|
||||
* @run main/othervm IiopUrlIPv6
|
||||
*/
|
||||
|
||||
import com.sun.jndi.cosnaming.*;
|
||||
|
@ -61,7 +61,7 @@ public class CheckOrigin {
|
||||
|
||||
ProcessBuilder pb = ProcessTools.
|
||||
createJavaProcessBuilder(
|
||||
"-XaddExports:jdk.attach/sun.tools.attach=ALL-UNNAMED",
|
||||
"--add-exports", "jdk.attach/sun.tools.attach=ALL-UNNAMED",
|
||||
"-XX:+UseConcMarkSweepGC", // this will cause UseParNewGC to be FLAG_SET_ERGO
|
||||
"-XX:+UseCodeAging",
|
||||
"-XX:+UseCerealGC", // Should be ignored.
|
||||
|
@ -55,7 +55,7 @@ public class GtkVersionTest {
|
||||
"/bin/java " +
|
||||
(version == null ? "" : "-Djdk.gtk.version=" + version) +
|
||||
" -Djdk.gtk.verbose=true " +
|
||||
"-XaddExports:java.desktop/sun.awt=ALL-UNNAMED " +
|
||||
"--add-exports=java.desktop/sun.awt=ALL-UNNAMED " +
|
||||
"-cp " + System.getProperty("java.class.path", ".") +
|
||||
" GtkVersionTest$LoadGtk");
|
||||
p.waitFor();
|
||||
|
@ -113,8 +113,8 @@ fi
|
||||
case "$OS" in
|
||||
Windows* | CYGWIN* )
|
||||
${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} \
|
||||
-XaddExports:java.desktop/sun.awt=ALL-UNNAMED \
|
||||
-XaddExports:java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
|
||||
--add-exports java.desktop/sun.awt=ALL-UNNAMED \
|
||||
--add-exports java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
|
||||
*.java
|
||||
status=$?
|
||||
if [ ! $status -eq "0" ]; then
|
||||
@ -124,8 +124,8 @@ case "$OS" in
|
||||
|
||||
SunOS | Linux )
|
||||
${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} \
|
||||
-XaddExports:java.desktop/sun.awt=ALL-UNNAMED \
|
||||
-XaddExports:java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
|
||||
--add-exports java.desktop/sun.awt=ALL-UNNAMED \
|
||||
--add-exports java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
|
||||
*.java
|
||||
status=$?
|
||||
if [ ! $status -eq "0" ]; then
|
||||
@ -135,8 +135,8 @@ case "$OS" in
|
||||
|
||||
Darwin)
|
||||
${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} \
|
||||
-XaddExports:java.desktop/sun.awt=ALL-UNNAMED \
|
||||
-XaddExports:java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
|
||||
--add-exports java.desktop/sun.awt=ALL-UNNAMED \
|
||||
--add-exports java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
|
||||
*.java
|
||||
status=$?
|
||||
if [ ! $status -eq "0" ]; then
|
||||
@ -154,16 +154,16 @@ chmod 777 ./*
|
||||
case "$OS" in
|
||||
Windows* | CYGWIN* )
|
||||
${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
|
||||
-XaddExports:java.desktop/sun.awt=ALL-UNNAMED \
|
||||
-XaddExports:java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
|
||||
--add-exports java.desktop/sun.awt=ALL-UNNAMED \
|
||||
--add-exports java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
|
||||
TestWrapped sun.awt.windows.WToolkit
|
||||
status=$?
|
||||
if [ ! $status -eq "0" ]; then
|
||||
fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.windows.WToolkit";
|
||||
fi
|
||||
${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
|
||||
-XaddExports:java.desktop/sun.awt=ALL-UNNAMED \
|
||||
-XaddExports:java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
|
||||
--add-exports java.desktop/sun.awt=ALL-UNNAMED \
|
||||
--add-exports java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
|
||||
-Dawt.toolkit=sun.awt.windows.WToolkit \
|
||||
TestWrapped sun.awt.windows.WToolkit
|
||||
status=$?
|
||||
@ -174,8 +174,8 @@ case "$OS" in
|
||||
|
||||
SunOS | Linux )
|
||||
${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
|
||||
-XaddExports:java.desktop/sun.awt=ALL-UNNAMED \
|
||||
-XaddExports:java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
|
||||
--add-exports java.desktop/sun.awt=ALL-UNNAMED \
|
||||
--add-exports java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
|
||||
-Dawt.toolkit=sun.awt.X11.XToolkit \
|
||||
TestWrapped sun.awt.X11.XToolkit
|
||||
status=$?
|
||||
@ -183,8 +183,8 @@ case "$OS" in
|
||||
fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.xawt.XToolkit";
|
||||
fi
|
||||
AWT_TOOLKIT=XToolkit ${TESTJAVA}/bin/java ${TESTVMOPTS} \
|
||||
-XaddExports:java.desktop/sun.awt=ALL-UNNAMED \
|
||||
-XaddExports:java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
|
||||
--add-exports java.desktop/sun.awt=ALL-UNNAMED \
|
||||
--add-exports java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
|
||||
-Djava.awt.headless=true \
|
||||
TestWrapped sun.awt.X11.XToolkit
|
||||
status=$?
|
||||
@ -195,16 +195,16 @@ case "$OS" in
|
||||
|
||||
Darwin)
|
||||
${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
|
||||
-XaddExports:java.desktop/sun.awt=ALL-UNNAMED \
|
||||
-XaddExports:java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
|
||||
--add-exports java.desktop/sun.awt=ALL-UNNAMED \
|
||||
--add-exports java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
|
||||
TestWrapped sun.lwawt.macosx.LWCToolkit
|
||||
status=$?
|
||||
if [ ! $status -eq "0" ]; then
|
||||
fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.lwawt.macosx.LWCToolkit";
|
||||
fi
|
||||
${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
|
||||
-XaddExports:java.desktop/sun.awt=ALL-UNNAMED \
|
||||
-XaddExports:java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
|
||||
--add-exports java.desktop/sun.awt=ALL-UNNAMED \
|
||||
--add-exports java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
|
||||
-Dawt.toolkit=sun.lwawt.macosx.LWCToolkit \
|
||||
TestWrapped sun.lwawt.macosx.LWCToolkit
|
||||
status=$?
|
||||
|
@ -73,10 +73,11 @@ public class RunTestXEmbed extends TestXEmbedServer {
|
||||
enva[ind++] = "AWT_TOOLKIT=sun.awt.X11.XToolkit";
|
||||
}
|
||||
}
|
||||
Process proc = Runtime.getRuntime().exec(java_home +
|
||||
"/bin/java -XaddExports:java.desktop/sun.awt.X11=ALL-UNNAMED -Dawt.toolkit=sun.awt.X11.XToolkit TesterClient "
|
||||
+ test.getName() + " " + window + buf,
|
||||
enva);
|
||||
Process proc = Runtime.getRuntime().
|
||||
exec(java_home +
|
||||
"/bin/java --add-exports java.desktop/sun.awt.X11=ALL-UNNAMED -Dawt.toolkit=sun.awt.X11.XToolkit TesterClient "
|
||||
+ test.getName() + " " + window + buf,
|
||||
enva);
|
||||
System.err.println("Test for " + test.getName() + " has started.");
|
||||
log.fine("Test for " + test.getName() + " has started.");
|
||||
new InputReader(proc.getInputStream());
|
||||
|
@ -84,11 +84,11 @@ public class TestXEmbedServerJava extends TestXEmbedServer {
|
||||
}
|
||||
if (hasModules) {
|
||||
System.out.println(java_home +
|
||||
"/bin/java -XaddExports:java.desktop/sun.awt.X11=ALL-UNNAMED "+
|
||||
"-XaddExports:java.desktop/sun.awt=ALL-UNNAMED JavaClient " + window);
|
||||
"/bin/java --add-exports java.desktop/sun.awt.X11=ALL-UNNAMED "+
|
||||
"--add-exports java.desktop/sun.awt=ALL-UNNAMED JavaClient " + window);
|
||||
return Runtime.getRuntime().exec(java_home +
|
||||
"/bin/java -XaddExports:java.desktop/sun.awt.X11=ALL-UNNAMED "+
|
||||
"-XaddExports:java.desktop/sun.awt=ALL-UNNAMED JavaClient " + window);
|
||||
"/bin/java --add-exports java.desktop/sun.awt.X11=ALL-UNNAMED "+
|
||||
"--add-exports java.desktop/sun.awt=ALL-UNNAMED JavaClient " + window);
|
||||
}else{
|
||||
System.out.println(java_home + "/bin/java JavaClient " + window);
|
||||
return Runtime.getRuntime().exec(java_home + "/bin/java JavaClient " + window);
|
||||
|
@ -39,7 +39,7 @@ import java.util.List;
|
||||
* java.corba
|
||||
* java.xml.bind
|
||||
* @compile -XDignore.symbol.file TestConstructorFinder.java
|
||||
* @run main/othervm -addmods java.activation -addmods java.transaction -addmods java.corba -addmods java.xml.bind TestConstructorFinder
|
||||
* @run main/othervm --add-modules=java.activation,java.transaction,java.corba,java.xml.bind TestConstructorFinder
|
||||
*/
|
||||
|
||||
public class TestConstructorFinder {
|
||||
|
@ -39,7 +39,7 @@ import java.util.List;
|
||||
* java.corba
|
||||
* java.xml.bind
|
||||
* @compile -XDignore.symbol.file TestMethodFinder.java
|
||||
* @run main/othervm -addmods java.activation -addmods java.transaction -addmods java.corba -addmods java.xml.bind TestMethodFinder
|
||||
* @run main/othervm --add-modules=java.activation,java.transaction,java.corba,java.xml.bind TestMethodFinder
|
||||
*/
|
||||
|
||||
public class TestMethodFinder {
|
||||
|
50
jdk/test/java/io/CharArrayReader/OverflowInRead.java
Normal file
50
jdk/test/java/io/CharArrayReader/OverflowInRead.java
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 8163518
|
||||
* @summary Integer overflow when reading in large buffer
|
||||
* @requires (os.simpleArch == "x64" & os.maxMemory > 8g)
|
||||
* @run main/othervm -Xmx8g OverflowInRead
|
||||
*/
|
||||
|
||||
import java.io.CharArrayReader;
|
||||
|
||||
public class OverflowInRead {
|
||||
public static void main(String[] args) throws Exception {
|
||||
char[] a = "_123456789_123456789_123456789_123456789"
|
||||
.toCharArray(); // a.length > 33
|
||||
try (CharArrayReader car = new CharArrayReader(a)) {
|
||||
int len1 = 33;
|
||||
char[] buf1 = new char[len1];
|
||||
if (car.read(buf1, 0, len1) != len1)
|
||||
throw new Exception("Expected to read " + len1 + " chars");
|
||||
|
||||
int len2 = Integer.MAX_VALUE - 32;
|
||||
char[] buf2 = new char[len2];
|
||||
int expLen2 = a.length - len1;
|
||||
if (car.read(buf2, 0, len2) != expLen2)
|
||||
throw new Exception("Expected to read " + expLen2 + " chars");
|
||||
}
|
||||
}
|
||||
}
|
51
jdk/test/java/io/CharArrayReader/OverflowInSkip.java
Normal file
51
jdk/test/java/io/CharArrayReader/OverflowInSkip.java
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 8163518
|
||||
* @summary Integer overflow when skipping a lot
|
||||
*/
|
||||
|
||||
import java.io.CharArrayReader;
|
||||
|
||||
public class OverflowInSkip {
|
||||
public static void main(String[] args) throws Exception {
|
||||
char[] a = "_123456789_123456789_123456789_123456789"
|
||||
.toCharArray(); // a.length > 33
|
||||
try (CharArrayReader car = new CharArrayReader(a)) {
|
||||
long small = 33;
|
||||
long big = Long.MAX_VALUE;
|
||||
|
||||
long smallSkip = car.skip(small);
|
||||
if (smallSkip != small)
|
||||
throw new Exception("Expected to skip " + small
|
||||
+ " chars, but skipped " + smallSkip);
|
||||
|
||||
long expSkip = a.length - small;
|
||||
long bigSkip = car.skip(big);
|
||||
if (bigSkip != expSkip)
|
||||
throw new Exception("Expected to skip " + expSkip
|
||||
+ " chars, but skipped " + bigSkip);
|
||||
}
|
||||
}
|
||||
}
|
49
jdk/test/java/io/StringBufferInputStream/OverflowInRead.java
Normal file
49
jdk/test/java/io/StringBufferInputStream/OverflowInRead.java
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 8163518
|
||||
* @summary Integer overflow when reading in large buffer
|
||||
* @requires (os.simpleArch == "x64" & os.maxMemory > 4g)
|
||||
* @run main/othervm -Xmx4g OverflowInRead
|
||||
*/
|
||||
|
||||
import java.io.StringBufferInputStream;
|
||||
|
||||
public class OverflowInRead {
|
||||
public static void main(String[] args) throws Exception {
|
||||
String s = "_123456789_123456789_123456789_123456789"; // s.length() > 33
|
||||
try (StringBufferInputStream sbis = new StringBufferInputStream(s)) {
|
||||
int len1 = 33;
|
||||
byte[] buf1 = new byte[len1];
|
||||
if (sbis.read(buf1, 0, len1) != len1)
|
||||
throw new Exception("Expected to read " + len1 + " bytes");
|
||||
|
||||
int len2 = Integer.MAX_VALUE - 32;
|
||||
byte[] buf2 = new byte[len2];
|
||||
int expLen2 = s.length() - len1;
|
||||
if (sbis.read(buf2, 0, len2) != expLen2)
|
||||
throw new Exception("Expected to read " + expLen2 + " bytes");
|
||||
}
|
||||
}
|
||||
}
|
@ -65,7 +65,7 @@ public class TestDriver {
|
||||
public void setup() throws Exception {
|
||||
assertTrue(CompilerUtils.compile(
|
||||
MOD_SRC_DIR, MOD_DEST_DIR,
|
||||
"-modulesourcepath",
|
||||
"--module-source-path",
|
||||
MOD_SRC_DIR.toString()));
|
||||
|
||||
copyDirectories(MOD_DEST_DIR.resolve("m1"), Paths.get("mods1"));
|
||||
@ -76,8 +76,8 @@ public class TestDriver {
|
||||
public void test() throws Exception {
|
||||
String[] options = new String[] {
|
||||
"-cp", TEST_CLASSES,
|
||||
"-mp", MOD_DEST_DIR.toString(),
|
||||
"-addmods", String.join(",", modules),
|
||||
"--module-path", MOD_DEST_DIR.toString(),
|
||||
"--add-modules", String.join(",", modules),
|
||||
"-m", "m2/p2.test.Main"
|
||||
};
|
||||
runTest(options);
|
||||
@ -87,8 +87,8 @@ public class TestDriver {
|
||||
public void testUnnamedModule() throws Exception {
|
||||
String[] options = new String[] {
|
||||
"-cp", TEST_CLASSES,
|
||||
"-mp", MOD_DEST_DIR.toString(),
|
||||
"-addmods", String.join(",", modules),
|
||||
"--module-path", MOD_DEST_DIR.toString(),
|
||||
"--add-modules", String.join(",", modules),
|
||||
"TestMain"
|
||||
};
|
||||
runTest(options);
|
||||
@ -107,8 +107,8 @@ public class TestDriver {
|
||||
@Test
|
||||
public void testDeniedClassLoaderAccess() throws Exception {
|
||||
String[] options = new String[] {
|
||||
"-mp", MOD_DEST_DIR.toString(),
|
||||
"-addmods", String.join(",", modules),
|
||||
"--module-path", MOD_DEST_DIR.toString(),
|
||||
"--add-modules", String.join(",", modules),
|
||||
"-m", "m3/p3.NoGetClassLoaderAccess"
|
||||
};
|
||||
assertTrue(executeTestJava(options)
|
||||
@ -124,8 +124,8 @@ public class TestDriver {
|
||||
String[] options = new String[] {
|
||||
"-Djava.security.manager",
|
||||
"-Djava.security.policy=" + policyFile.toString(),
|
||||
"-mp", MOD_DEST_DIR.toString(),
|
||||
"-addmods", String.join(",", modules),
|
||||
"--module-path", MOD_DEST_DIR.toString(),
|
||||
"--add-modules", String.join(",", modules),
|
||||
"-m", "m3/p3.NoAccess"
|
||||
};
|
||||
assertTrue(executeTestJava(options)
|
||||
|
@ -63,8 +63,8 @@ import jdk.internal.module.Modules;
|
||||
* loads all the classes in the BCL, get their declared fields,
|
||||
* and call setAccessible(false) followed by setAccessible(true);
|
||||
* @modules java.base/jdk.internal.module
|
||||
* @run main/othervm -Djdk.launcher.addmods=ALL-SYSTEM FieldSetAccessibleTest UNSECURE
|
||||
* @run main/othervm -Djdk.launcher.addmods=ALL-SYSTEM FieldSetAccessibleTest SECURE
|
||||
* @run main/othervm --add-modules=ALL-SYSTEM FieldSetAccessibleTest UNSECURE
|
||||
* @run main/othervm --add-modules=ALL-SYSTEM FieldSetAccessibleTest SECURE
|
||||
*
|
||||
* @author danielfuchs
|
||||
*/
|
||||
|
@ -60,15 +60,15 @@ public class ResourcesTest {
|
||||
compiled = CompilerUtils
|
||||
.compile(SRC_DIR,
|
||||
MODS_DIR,
|
||||
"-modulesourcepath", SRC_DIR.toString());
|
||||
"--module-source-path", SRC_DIR.toString());
|
||||
assertTrue(compiled);
|
||||
|
||||
// javac -mp mods -d classes Main.java
|
||||
// javac --module-path mods -d classes Main.java
|
||||
compiled = CompilerUtils
|
||||
.compile(Paths.get(TEST_SRC, "Main.java"),
|
||||
CLASSES_DIR,
|
||||
"-mp", MODS_DIR.toString(),
|
||||
"-addmods", "m1,m2,m3");
|
||||
"--module-path", MODS_DIR.toString(),
|
||||
"--add-modules", "m1,m2,m3");
|
||||
assertTrue(compiled);
|
||||
|
||||
}
|
||||
@ -79,8 +79,8 @@ public class ResourcesTest {
|
||||
public void runTest() throws Exception {
|
||||
|
||||
int exitValue
|
||||
= executeTestJava("-mp", MODS_DIR.toString(),
|
||||
"-addmods", "m1,m2,m3",
|
||||
= executeTestJava("--module-path", MODS_DIR.toString(),
|
||||
"--add-modules", "m1,m2,m3",
|
||||
"-cp", CLASSES_DIR.toString(),
|
||||
"Main")
|
||||
.outputTo(System.out)
|
||||
|
@ -56,19 +56,19 @@ public class ResourcesTest {
|
||||
public void compileAll() throws Exception {
|
||||
boolean compiled;
|
||||
|
||||
// javac -modulesource mods -d mods src/**
|
||||
// javac --module-source-path mods -d mods src/**
|
||||
compiled = CompilerUtils
|
||||
.compile(SRC_DIR,
|
||||
MODS_DIR,
|
||||
"-modulesourcepath", SRC_DIR.toString());
|
||||
"--module-source-path", SRC_DIR.toString());
|
||||
assertTrue(compiled);
|
||||
|
||||
// javac -mp mods -d classes Main.java
|
||||
// javac --module-path mods -d classes Main.java
|
||||
compiled = CompilerUtils
|
||||
.compile(Paths.get(TEST_SRC, "Main.java"),
|
||||
CLASSES_DIR,
|
||||
"-mp", MODS_DIR.toString(),
|
||||
"-addmods", "m1,m2,m3");
|
||||
"--module-path", MODS_DIR.toString(),
|
||||
"--add-modules", "m1,m2,m3");
|
||||
assertTrue(compiled);
|
||||
}
|
||||
|
||||
@ -77,8 +77,8 @@ public class ResourcesTest {
|
||||
*/
|
||||
public void runTest() throws Exception {
|
||||
int exitValue
|
||||
= executeTestJava("-mp", MODS_DIR.toString(),
|
||||
"-addmods", "m1,m2,m3",
|
||||
= executeTestJava("--module-path", MODS_DIR.toString(),
|
||||
"--add-modules", "m1,m2,m3",
|
||||
"-cp", CLASSES_DIR.toString(),
|
||||
"Main")
|
||||
.outputTo(System.out)
|
||||
|
@ -51,15 +51,15 @@ JAVAC="$COMPILEJAVA/bin/javac"
|
||||
JAVA="$TESTJAVA/bin/java ${TESTVMOPTS}"
|
||||
|
||||
mkdir -p mods
|
||||
$JAVAC -d mods -modulesourcepath ${TESTSRC} `find ${TESTSRC}/m -name "*.java"`
|
||||
$JAVAC -d mods --module-source-path ${TESTSRC} `find ${TESTSRC}/m -name "*.java"`
|
||||
|
||||
mkdir -p classes
|
||||
$JAVAC -d classes ${TESTSRC}/Test.java
|
||||
|
||||
$JAVA -cp classes -mp mods -addmods m \
|
||||
$JAVA -cp classes --module-path mods --add-modules m \
|
||||
-Djava.security.manager \
|
||||
-Djava.security.policy=${TESTSRC}/test.policy Test
|
||||
$JAVA -cp classes -mp mods -addmods m \
|
||||
$JAVA -cp classes --module-path mods --add-modules m \
|
||||
-Djava.security.manager=p.CustomSecurityManager \
|
||||
-Djava.security.policy=${TESTSRC}/test.policy Test
|
||||
|
||||
|
@ -38,13 +38,13 @@ import java.security.Permission;
|
||||
* @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT WithSecurityManager
|
||||
* @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT WithSecurityManager
|
||||
*
|
||||
* @run main/othervm -Xverify:all -limitmods java.base WithSecurityManager
|
||||
* @run main/othervm -Xverify:all -limitmods java.base -Djava.lang.invoke.stringConcat=BC_SB WithSecurityManager
|
||||
* @run main/othervm -Xverify:all -limitmods java.base -Djava.lang.invoke.stringConcat=BC_SB_SIZED WithSecurityManager
|
||||
* @run main/othervm -Xverify:all -limitmods java.base -Djava.lang.invoke.stringConcat=MH_SB_SIZED WithSecurityManager
|
||||
* @run main/othervm -Xverify:all -limitmods java.base -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT WithSecurityManager
|
||||
* @run main/othervm -Xverify:all -limitmods java.base -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT WithSecurityManager
|
||||
* @run main/othervm -Xverify:all -limitmods java.base -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT WithSecurityManager
|
||||
* @run main/othervm -Xverify:all --limit-modules=java.base WithSecurityManager
|
||||
* @run main/othervm -Xverify:all --limit-modules=java.base -Djava.lang.invoke.stringConcat=BC_SB WithSecurityManager
|
||||
* @run main/othervm -Xverify:all --limit-modules=java.base -Djava.lang.invoke.stringConcat=BC_SB_SIZED WithSecurityManager
|
||||
* @run main/othervm -Xverify:all --limit-modules=java.base -Djava.lang.invoke.stringConcat=MH_SB_SIZED WithSecurityManager
|
||||
* @run main/othervm -Xverify:all --limit-modules=java.base -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT WithSecurityManager
|
||||
* @run main/othervm -Xverify:all --limit-modules=java.base -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT WithSecurityManager
|
||||
* @run main/othervm -Xverify:all --limit-modules=java.base -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT WithSecurityManager
|
||||
*/
|
||||
public class WithSecurityManager {
|
||||
public static void main(String[] args) throws Throwable {
|
||||
|
@ -87,7 +87,7 @@ ${JAVAC} ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} bootreporter/*.java
|
||||
cd ..
|
||||
|
||||
${JAVAC} ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
|
||||
-XaddExports:java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED ${AGENT}.java asmlib/*.java
|
||||
--add-exports java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED ${AGENT}.java asmlib/*.java
|
||||
${JAVAC} ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -classpath .${PATHSEP}bootpath ${APP}.java
|
||||
|
||||
echo "Manifest-Version: 1.0" > ${AGENT}.mf
|
||||
|
@ -60,7 +60,7 @@ public class ModuleAccessControlTest {
|
||||
for (String mn : modules) {
|
||||
Path msrc = SRC_DIR.resolve(mn);
|
||||
assertTrue(CompilerUtils
|
||||
.compile(msrc, MODS_DIR, "-modulesourcepath", SRC_DIR.toString()));
|
||||
.compile(msrc, MODS_DIR, "--module-source-path", SRC_DIR.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ public class ModuleAccessControlTest {
|
||||
*/
|
||||
@Test
|
||||
public void runTest() throws Exception {
|
||||
int exitValue = executeTestJava("-mp", MODS_DIR.toString(),
|
||||
int exitValue = executeTestJava("--module-path", MODS_DIR.toString(),
|
||||
"-m", "m1/p1.Main")
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
|
@ -63,9 +63,9 @@ public class LayerAndLoadersTest {
|
||||
@BeforeTest
|
||||
public void setup() throws Exception {
|
||||
|
||||
// javac -d mods -modulesourcepath src src/**
|
||||
// javac -d mods --module-source-path src src/**
|
||||
assertTrue(CompilerUtils.compile(SRC_DIR, MODS_DIR,
|
||||
"-modulesourcepath", SRC_DIR.toString()));
|
||||
"--module-source-path", SRC_DIR.toString()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -23,29 +23,44 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @modules java.desktop
|
||||
* @run main/othervm -XaddExports:java.desktop/sun.awt=java.base AddExportsTest
|
||||
* @run main/othervm -XaddExports:java.desktop/sun.awt=ALL-UNNAMED AddExportsTest
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* java.desktop
|
||||
* @run main/othervm --add-exports=java.desktop/sun.awt=java.base AddExportsTest
|
||||
* @run main/othervm --add-exports=java.desktop/sun.awt=ALL-UNNAMED AddExportsTest
|
||||
* @summary Test Module isExported methods with exports changed by -AddExportsTest
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Layer;
|
||||
import java.lang.reflect.Module;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jdk.internal.misc.VM;
|
||||
|
||||
public class AddExportsTest {
|
||||
/*
|
||||
* jtreg sets -Dtest.modules system property to the internal APIs
|
||||
* specified at @modules tag. The test will exclude --add-exports set
|
||||
* for @modules.
|
||||
*/
|
||||
private static final String TEST_MODULES = System.getProperty("test.modules");
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
String addExports = System.getProperty("jdk.launcher.addexports.0");
|
||||
assertTrue(addExports != null, "Expected to be run with -XaddExports");
|
||||
Optional<String> oaddExports = Stream.of(VM.getRuntimeArguments())
|
||||
.filter(arg -> arg.startsWith("--add-exports="))
|
||||
.filter(arg -> !arg.equals("--add-exports=" + TEST_MODULES + "=ALL-UNNAMED"))
|
||||
.map(arg -> arg.substring("--add-exports=".length(), arg.length()))
|
||||
.findFirst();
|
||||
|
||||
assertTrue(oaddExports.isPresent());
|
||||
|
||||
Layer bootLayer = Layer.boot();
|
||||
|
||||
Module unnamedModule = AddExportsTest.class.getModule();
|
||||
assertFalse(unnamedModule.isNamed());
|
||||
|
||||
for (String expr : addExports.split(",")) {
|
||||
for (String expr : oaddExports.get().split(",")) {
|
||||
|
||||
String[] s = expr.split("=");
|
||||
assertTrue(s.length == 2);
|
||||
|
@ -72,8 +72,8 @@ public class AccessTest {
|
||||
*/
|
||||
public void runTest() throws Exception {
|
||||
int exitValue
|
||||
= executeTestJava("-mp", MODS_DIR.toString(),
|
||||
"-addmods", "target",
|
||||
= executeTestJava("--module-path", MODS_DIR.toString(),
|
||||
"--add-modules", "target",
|
||||
"-m", "test/test.Main")
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
|
@ -64,7 +64,7 @@ public class ProxyClassAccessTest {
|
||||
public void compileAll() throws Exception {
|
||||
for (String mn : modules) {
|
||||
Path msrc = SRC_DIR.resolve(mn);
|
||||
assertTrue(CompilerUtils.compile(msrc, MODS_DIR, "-modulesourcepath", SRC_DIR.toString()));
|
||||
assertTrue(CompilerUtils.compile(msrc, MODS_DIR, "--module-source-path", SRC_DIR.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ public class ProxyClassAccessTest {
|
||||
*/
|
||||
@Test
|
||||
public void runTest() throws Exception {
|
||||
int exitValue = executeTestJava("-mp", MODS_DIR.toString(),
|
||||
int exitValue = executeTestJava("--module-path", MODS_DIR.toString(),
|
||||
"-m", "test/jdk.test.ProxyClassAccess")
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
|
@ -65,7 +65,7 @@ public class ProxyLayerTest {
|
||||
public void compileAll() throws Exception {
|
||||
for (String mn : modules) {
|
||||
Path msrc = SRC_DIR.resolve(mn);
|
||||
assertTrue(CompilerUtils.compile(msrc, MODS_DIR, "-modulesourcepath", SRC_DIR.toString()));
|
||||
assertTrue(CompilerUtils.compile(msrc, MODS_DIR, "--module-source-path", SRC_DIR.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ public class ProxyModuleMapping {
|
||||
Module unnamed = ld.getUnnamedModule();
|
||||
new ProxyModuleMapping(unnamed, Runnable.class).test();
|
||||
|
||||
// unnamed module gets access to sun.invoke package (e.g. via -XaddExports)
|
||||
// unnamed module gets access to sun.invoke package (e.g. via --add-exports)
|
||||
new ProxyModuleMapping(sun.invoke.WrapperInstance.class).test();
|
||||
|
||||
Class<?> modulePrivateIntf = Class.forName("sun.net.ProgressListener");
|
||||
|
@ -61,7 +61,7 @@ public class ProxyTest {
|
||||
public void compileAll() throws Exception {
|
||||
for (String mn : modules) {
|
||||
Path msrc = SRC_DIR.resolve(mn);
|
||||
assertTrue(CompilerUtils.compile(msrc, MODS_DIR, "-modulesourcepath", SRC_DIR.toString()));
|
||||
assertTrue(CompilerUtils.compile(msrc, MODS_DIR, "--module-source-path", SRC_DIR.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ public class ProxyTest {
|
||||
@Test
|
||||
public void runTest() throws Exception {
|
||||
int exitValue = executeTestJava("-cp", CPATH_DIR.toString(),
|
||||
"-mp", MODS_DIR.toString(),
|
||||
"--module-path", MODS_DIR.toString(),
|
||||
"-m", "test/jdk.test.Main")
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
|
@ -44,7 +44,7 @@ case "$OS" in
|
||||
;;
|
||||
esac
|
||||
|
||||
EXTRAOPTS="-XaddExports:java.base/sun.net.www=ALL-UNNAMED -XaddExports:java.base/sun.net.www.protocol.http=ALL-UNNAMED"
|
||||
EXTRAOPTS="--add-exports java.base/sun.net.www=ALL-UNNAMED --add-exports java.base/sun.net.www.protocol.http=ALL-UNNAMED"
|
||||
export EXTRAOPTS
|
||||
|
||||
${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . \
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user