Merge
This commit is contained in:
commit
5aac6d6f96
@ -373,3 +373,4 @@ f80c841ae2545eaf9acd2724bccc305d98cefbe2 jdk-9+124
|
||||
b30ae794d974d7dd3eb4e84203f70021823fa6c6 jdk-9+128
|
||||
f5902d3841b82cac6e7716a20c24e8e916fb14a8 jdk-9+129
|
||||
d94d54a3192fea79234c3ac55cd0b4052d45e954 jdk-9+130
|
||||
8728756c2f70a79a90188f4019cfd6b9a275765c jdk-9+131
|
||||
|
@ -305,7 +305,7 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK],
|
||||
BOOT_JDK_SOURCETARGET="-source 8 -target 8"
|
||||
AC_SUBST(BOOT_JDK_SOURCETARGET)
|
||||
|
||||
ADD_JVM_ARG_IF_OK([-Xpatch:foo=bar], dummy, [$JAVA])
|
||||
ADD_JVM_ARG_IF_OK([--patch-module foo=bar], dummy, [$JAVA])
|
||||
AC_MSG_CHECKING([if Boot JDK supports modules])
|
||||
if test "x$JVM_ARG_OK" = "xtrue"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
|
@ -5095,7 +5095,7 @@ VS_SDK_PLATFORM_NAME_2013=
|
||||
#CUSTOM_AUTOCONF_INCLUDE
|
||||
|
||||
# Do not change or remove the following line, it is needed for consistency checks:
|
||||
DATE_WHEN_GENERATED=1470415803
|
||||
DATE_WHEN_GENERATED=1470863189
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
@ -30596,13 +30596,13 @@ $as_echo "$tool_specified" >&6; }
|
||||
|
||||
|
||||
|
||||
$ECHO "Check if jvm arg is ok: -Xpatch:foo=bar" >&5
|
||||
$ECHO "Command: $JAVA -Xpatch:foo=bar -version" >&5
|
||||
OUTPUT=`$JAVA -Xpatch:foo=bar -version 2>&1`
|
||||
$ECHO "Check if jvm arg is ok: --patch-module foo=bar" >&5
|
||||
$ECHO "Command: $JAVA --patch-module foo=bar -version" >&5
|
||||
OUTPUT=`$JAVA --patch-module foo=bar -version 2>&1`
|
||||
FOUND_WARN=`$ECHO "$OUTPUT" | $GREP -i warn`
|
||||
FOUND_VERSION=`$ECHO $OUTPUT | $GREP " version \""`
|
||||
if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then
|
||||
dummy="$dummy -Xpatch:foo=bar"
|
||||
dummy="$dummy --patch-module foo=bar"
|
||||
JVM_ARG_OK=true
|
||||
else
|
||||
$ECHO "Arg failed:" >&5
|
||||
|
@ -585,7 +585,7 @@ INTERIM_OVERRIDE_MODULES := java.compiler jdk.compiler \
|
||||
jdk.jdeps jdk.javadoc jdk.rmic
|
||||
ifeq ($(BOOT_JDK_MODULAR), true)
|
||||
INTERIM_OVERRIDE_MODULES_ARGS = $(foreach m, $(INTERIM_OVERRIDE_MODULES), \
|
||||
-Xpatch:$m=$(BUILDTOOLS_OUTPUTDIR)/override_modules/$m)
|
||||
--patch-module $m=$(BUILDTOOLS_OUTPUTDIR)/override_modules/$m)
|
||||
INTERIM_LANGTOOLS_ARGS = $(INTERIM_OVERRIDE_MODULES_ARGS)
|
||||
JAVAC_MAIN_CLASS = -m jdk.compiler/com.sun.tools.javac.Main
|
||||
JAVADOC_MAIN_CLASS = -m jdk.javadoc/jdk.javadoc.internal.tool.Main
|
||||
|
@ -417,7 +417,7 @@ var getJibProfilesDependencies = function (input, common) {
|
||||
jtreg: {
|
||||
server: "javare",
|
||||
revision: "4.2",
|
||||
build_number: "b02",
|
||||
build_number: "b03",
|
||||
checksum_file: "MD5_VALUES",
|
||||
file: "jtreg_bin-4.2.zip",
|
||||
environment_name: "JT_HOME"
|
||||
|
@ -373,3 +373,4 @@ c7f5ba08fcd4b8416e62c21229f9a07c95498919 jdk-9+126
|
||||
1f093d3f8cd99cd37c3b0af4cf5c3bffaa9c8b98 jdk-9+128
|
||||
c3e83ccab3bb1733ae903d681879a33f85ed465c jdk-9+129
|
||||
77f9692d5976ae155773dd3e07533616bb95bae1 jdk-9+130
|
||||
f7e1d5337c2e550fe553df7a3886bbed80292ecd jdk-9+131
|
||||
|
@ -533,3 +533,4 @@ adc8c84b7cf8c540d920182f78a2bc982366432a jdk-9+126
|
||||
22bf6db9767b1b3a1994cbf32eb3331f31ae2093 jdk-9+128
|
||||
e96b34b76d863ed1fa04e0eeb3f297ac17b490fd jdk-9+129
|
||||
7d54c7056328b6a2bf4877458b8f4d8cd870f93b jdk-9+130
|
||||
943bf73b49c33c2d7cbd796f6a4ae3c7a00ae932 jdk-9+131
|
||||
|
@ -109,6 +109,9 @@ public class HotSpotMethodHandleAccessProvider implements MethodHandleAccessProv
|
||||
if (!s.getReturnType(CLASS).equals(resultType)) {
|
||||
return false;
|
||||
}
|
||||
if (s.getParameterCount(false) != parameterTypes.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < s.getParameterCount(false); ++i) {
|
||||
if (!s.getParameterType(i, CLASS).equals(parameterTypes[i])) {
|
||||
return false;
|
||||
|
@ -57,7 +57,7 @@ public final class Services {
|
||||
if (jvmci != requestorModule) {
|
||||
for (String pkg : jvmci.getPackages()) {
|
||||
// Export all JVMCI packages dynamically instead
|
||||
// of requiring a long list of -XaddExports
|
||||
// of requiring a long list of --add-exports
|
||||
// options on the JVM command line.
|
||||
if (!jvmci.isExported(pkg, requestorModule)) {
|
||||
jvmci.addExports(pkg, requestorModule);
|
||||
|
@ -140,7 +140,7 @@ PerfCounter* ClassLoader::_unsafe_defineClassCallCounter = NULL;
|
||||
PerfCounter* ClassLoader::_isUnsyncloadClass = NULL;
|
||||
PerfCounter* ClassLoader::_load_instance_class_failCounter = NULL;
|
||||
|
||||
GrowableArray<ModuleClassPathList*>* ClassLoader::_xpatch_entries = NULL;
|
||||
GrowableArray<ModuleClassPathList*>* ClassLoader::_patch_mod_entries = NULL;
|
||||
GrowableArray<ModuleClassPathList*>* ClassLoader::_exploded_entries = NULL;
|
||||
ClassPathEntry* ClassLoader::_jrt_entry = NULL;
|
||||
ClassPathEntry* ClassLoader::_first_append_entry = NULL;
|
||||
@ -685,27 +685,27 @@ bool ClassLoader::check_shared_paths_misc_info(void *buf, int size) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Construct the array of module/path pairs as specified to -Xpatch
|
||||
// Construct the array of module/path pairs as specified to --patch-module
|
||||
// for the boot loader to search ahead of the jimage, if the class being
|
||||
// loaded is defined to a module that has been specified to -Xpatch.
|
||||
void ClassLoader::setup_xpatch_entries() {
|
||||
// loaded is defined to a module that has been specified to --patch-module.
|
||||
void ClassLoader::setup_patch_mod_entries() {
|
||||
Thread* THREAD = Thread::current();
|
||||
GrowableArray<ModuleXPatchPath*>* xpatch_args = Arguments::get_xpatchprefix();
|
||||
int num_of_entries = xpatch_args->length();
|
||||
GrowableArray<ModulePatchPath*>* patch_mod_args = Arguments::get_patch_mod_prefix();
|
||||
int num_of_entries = patch_mod_args->length();
|
||||
|
||||
assert(!DumpSharedSpaces, "DumpSharedSpaces not supported with -Xpatch");
|
||||
assert(!UseSharedSpaces, "UseSharedSpaces not supported with -Xpatch");
|
||||
assert(!DumpSharedSpaces, "DumpSharedSpaces not supported with --patch-module");
|
||||
assert(!UseSharedSpaces, "UseSharedSpaces not supported with --patch-module");
|
||||
|
||||
// Set up the boot loader's _xpatch_entries list
|
||||
_xpatch_entries = new (ResourceObj::C_HEAP, mtModule) GrowableArray<ModuleClassPathList*>(num_of_entries, true);
|
||||
// Set up the boot loader's _patch_mod_entries list
|
||||
_patch_mod_entries = new (ResourceObj::C_HEAP, mtModule) GrowableArray<ModuleClassPathList*>(num_of_entries, true);
|
||||
|
||||
for (int i = 0; i < num_of_entries; i++) {
|
||||
const char* module_name = (xpatch_args->at(i))->module_name();
|
||||
const char* module_name = (patch_mod_args->at(i))->module_name();
|
||||
Symbol* const module_sym = SymbolTable::lookup(module_name, (int)strlen(module_name), CHECK);
|
||||
assert(module_sym != NULL, "Failed to obtain Symbol for module name");
|
||||
ModuleClassPathList* module_cpl = new ModuleClassPathList(module_sym);
|
||||
|
||||
char* class_path = (xpatch_args->at(i))->path_string();
|
||||
char* class_path = (patch_mod_args->at(i))->path_string();
|
||||
int len = (int)strlen(class_path);
|
||||
int end = 0;
|
||||
// Iterate over the module's class path entries
|
||||
@ -735,10 +735,10 @@ void ClassLoader::setup_xpatch_entries() {
|
||||
}
|
||||
}
|
||||
|
||||
// Record the module into the list of -Xpatch entries only if
|
||||
// Record the module into the list of --patch-module entries only if
|
||||
// valid ClassPathEntrys have been created
|
||||
if (module_cpl->module_first_entry() != NULL) {
|
||||
_xpatch_entries->push(module_cpl);
|
||||
_patch_mod_entries->push(module_cpl);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1020,9 +1020,9 @@ void ClassLoader::print_bootclasspath() {
|
||||
ClassPathEntry* e;
|
||||
tty->print("[bootclasspath= ");
|
||||
|
||||
// Print -Xpatch module/path specifications first
|
||||
if (_xpatch_entries != NULL) {
|
||||
print_module_entry_table(_xpatch_entries);
|
||||
// Print --patch-module module/path specifications first
|
||||
if (_patch_mod_entries != NULL) {
|
||||
print_module_entry_table(_patch_mod_entries);
|
||||
}
|
||||
|
||||
// [jimage | exploded modules build]
|
||||
@ -1341,7 +1341,7 @@ const char* ClassLoader::file_name_for_class_name(const char* class_name,
|
||||
return file_name;
|
||||
}
|
||||
|
||||
// Search either the xpatch or exploded build entries for class
|
||||
// Search either the patch-module or exploded build entries for class
|
||||
ClassFileStream* ClassLoader::search_module_entries(const GrowableArray<ModuleClassPathList*>* const module_list,
|
||||
const char* const class_name, const char* const file_name, TRAPS) {
|
||||
ClassFileStream* stream = NULL;
|
||||
@ -1366,7 +1366,7 @@ ClassFileStream* ClassLoader::search_module_entries(const GrowableArray<ModuleCl
|
||||
int num_of_entries = module_list->length();
|
||||
const Symbol* class_module_name = mod_entry->name();
|
||||
|
||||
// Loop through all the modules in either the xpatch or exploded entries looking for module
|
||||
// Loop through all the modules in either the patch-module or exploded entries looking for module
|
||||
for (int i = 0; i < num_of_entries; i++) {
|
||||
ModuleClassPathList* module_cpl = module_list->at(i);
|
||||
Symbol* module_cpl_name = module_cpl->module_name();
|
||||
@ -1378,7 +1378,7 @@ ClassFileStream* ClassLoader::search_module_entries(const GrowableArray<ModuleCl
|
||||
while (e != NULL) {
|
||||
stream = e->open_stream(file_name, CHECK_NULL);
|
||||
// No context.check is required since CDS is not supported
|
||||
// for an exploded modules build or if -Xpatch is specified.
|
||||
// for an exploded modules build or if --patch-module is specified.
|
||||
if (NULL != stream) {
|
||||
return stream;
|
||||
}
|
||||
@ -1420,32 +1420,32 @@ instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_onl
|
||||
|
||||
// If DumpSharedSpaces is true boot loader visibility boundaries are set to:
|
||||
// - [jimage] + [_first_append_entry to _last_append_entry] (all path entries).
|
||||
// No -Xpatch entries or exploded module builds are included since CDS
|
||||
// is not supported if -Xpatch or exploded module builds are used.
|
||||
// No --patch-module entries or exploded module builds are included since CDS
|
||||
// is not supported if --patch-module or exploded module builds are used.
|
||||
//
|
||||
// If search_append_only is true, boot loader visibility boundaries are
|
||||
// set to be _first_append_entry to the end. This includes:
|
||||
// [-Xbootclasspath/a]; [jvmti appended entries]
|
||||
//
|
||||
// If both DumpSharedSpaces and search_append_only are false, boot loader
|
||||
// visibility boundaries are set to be the -Xpatch entries plus the base piece.
|
||||
// visibility boundaries are set to be the --patch-module entries plus the base piece.
|
||||
// This would include:
|
||||
// [-Xpatch:<module>=<file>(<pathsep><file>)*]; [jimage | exploded module build]
|
||||
// [--patch-module=<module>=<file>(<pathsep><file>)*]; [jimage | exploded module build]
|
||||
//
|
||||
// DumpSharedSpaces and search_append_only are mutually exclusive and cannot
|
||||
// be true at the same time.
|
||||
assert(!(DumpSharedSpaces && search_append_only), "DumpSharedSpaces and search_append_only are both true");
|
||||
|
||||
// Load Attempt #1: -Xpatch
|
||||
// Determine the class' defining module. If it appears in the _xpatch_entries,
|
||||
// Load Attempt #1: --patch-module
|
||||
// Determine the class' defining module. If it appears in the _patch_mod_entries,
|
||||
// attempt to load the class from those locations specific to the module.
|
||||
// Specifications to -Xpatch can contain a partial number of classes
|
||||
// Specifications to --patch-module can contain a partial number of classes
|
||||
// that are part of the overall module definition. So if a particular class is not
|
||||
// found within its module specification, the search should continue to Load Attempt #2.
|
||||
// Note: The -Xpatch entries are never searched if the boot loader's
|
||||
// Note: The --patch-module entries are never searched if the boot loader's
|
||||
// visibility boundary is limited to only searching the append entries.
|
||||
if (_xpatch_entries != NULL && !search_append_only && !DumpSharedSpaces) {
|
||||
stream = search_module_entries(_xpatch_entries, class_name, file_name, CHECK_NULL);
|
||||
if (_patch_mod_entries != NULL && !search_append_only && !DumpSharedSpaces) {
|
||||
stream = search_module_entries(_patch_mod_entries, class_name, file_name, CHECK_NULL);
|
||||
}
|
||||
|
||||
// Load Attempt #2: [jimage | exploded build]
|
||||
@ -1650,11 +1650,11 @@ void ClassLoader::classLoader_init2(TRAPS) {
|
||||
// Create the moduleEntry for java.base
|
||||
create_javabase();
|
||||
|
||||
// Setup the list of module/path pairs for -Xpatch processing
|
||||
// Setup the list of module/path pairs for --patch-module processing
|
||||
// This must be done after the SymbolTable is created in order
|
||||
// to use fast_compare on module names instead of a string compare.
|
||||
if (Arguments::get_xpatchprefix() != NULL) {
|
||||
setup_xpatch_entries();
|
||||
if (Arguments::get_patch_mod_prefix() != NULL) {
|
||||
setup_patch_mod_entries();
|
||||
}
|
||||
|
||||
// Setup the initial java.base/path pair for the exploded build entries.
|
||||
|
@ -150,7 +150,7 @@ public:
|
||||
|
||||
// ModuleClassPathList contains a linked list of ClassPathEntry's
|
||||
// that have been specified for a specific module. Currently,
|
||||
// the only way to specify a module/path pair is via the -Xpatch
|
||||
// the only way to specify a module/path pair is via the --patch-module
|
||||
// command line option.
|
||||
class ModuleClassPathList : public CHeapObj<mtClass> {
|
||||
private:
|
||||
@ -213,8 +213,8 @@ class ClassLoader: AllStatic {
|
||||
static PerfCounter* _load_instance_class_failCounter;
|
||||
|
||||
// The boot class path consists of 3 ordered pieces:
|
||||
// 1. the module/path pairs specified to -Xpatch
|
||||
// -Xpatch:<module>=<file>(<pathsep><file>)*
|
||||
// 1. the module/path pairs specified to --patch-module
|
||||
// --patch-module=<module>=<file>(<pathsep><file>)*
|
||||
// 2. the base piece
|
||||
// [jimage | build with exploded modules]
|
||||
// 3. boot loader append path
|
||||
@ -223,8 +223,8 @@ class ClassLoader: AllStatic {
|
||||
// The boot loader must obey this order when attempting
|
||||
// to load a class.
|
||||
|
||||
// 1. Contains the module/path pairs specified to -Xpatch
|
||||
static GrowableArray<ModuleClassPathList*>* _xpatch_entries;
|
||||
// 1. Contains the module/path pairs specified to --patch-module
|
||||
static GrowableArray<ModuleClassPathList*>* _patch_mod_entries;
|
||||
|
||||
// 2. the base piece
|
||||
// Contains the ClassPathEntry of the modular java runtime image.
|
||||
@ -256,11 +256,11 @@ class ClassLoader: AllStatic {
|
||||
|
||||
// Initialization:
|
||||
// - setup the boot loader's system class path
|
||||
// - setup the boot loader's xpatch entries, if present
|
||||
// - setup the boot loader's patch mod entries, if present
|
||||
// - create the ModuleEntry for java.base
|
||||
static void setup_bootstrap_search_path();
|
||||
static void setup_search_path(const char *class_path, bool setting_bootstrap);
|
||||
static void setup_xpatch_entries();
|
||||
static void setup_patch_mod_entries();
|
||||
static void create_javabase();
|
||||
|
||||
static void load_zip_library();
|
||||
@ -363,7 +363,7 @@ class ClassLoader: AllStatic {
|
||||
// Add a module's exploded directory to the boot loader's exploded module build list
|
||||
static void add_to_exploded_build_list(Symbol* module_name, TRAPS);
|
||||
|
||||
// Attempt load of individual class from either the xpatch or exploded modules build lists
|
||||
// Attempt load of individual class from either the patched or exploded modules build lists
|
||||
static ClassFileStream* search_module_entries(const GrowableArray<ModuleClassPathList*>* const module_list,
|
||||
const char* const class_name,
|
||||
const char* const file_name, TRAPS);
|
||||
|
@ -911,8 +911,8 @@ bool FileMapInfo::FileMapHeader::validate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Arguments::get_xpatchprefix() != NULL) {
|
||||
FileMapInfo::fail_continue("The shared archive file cannot be used with -Xpatch.");
|
||||
if (Arguments::get_patch_mod_prefix() != NULL) {
|
||||
FileMapInfo::fail_continue("The shared archive file cannot be used with --patch-module.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/classLoaderExt.hpp"
|
||||
#include "classfile/javaClasses.inline.hpp"
|
||||
#include "classfile/stringTable.hpp"
|
||||
#include "classfile/modules.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "classfile/vmSymbols.hpp"
|
||||
@ -224,6 +226,7 @@ JvmtiEnv::GetNamedModule(jobject class_loader, const char* package_name, jobject
|
||||
return JVMTI_ERROR_NONE;
|
||||
} /* end GetNamedModule */
|
||||
|
||||
|
||||
//
|
||||
// Class functions
|
||||
//
|
||||
@ -3465,28 +3468,35 @@ jvmtiError
|
||||
JvmtiEnv::GetSystemProperties(jint* count_ptr, char*** property_ptr) {
|
||||
jvmtiError err = JVMTI_ERROR_NONE;
|
||||
|
||||
*count_ptr = Arguments::PropertyList_count(Arguments::system_properties());
|
||||
// Get the number of readable properties.
|
||||
*count_ptr = Arguments::PropertyList_readable_count(Arguments::system_properties());
|
||||
|
||||
// Allocate memory to hold the exact number of readable properties.
|
||||
err = allocate(*count_ptr * sizeof(char *), (unsigned char **)property_ptr);
|
||||
if (err != JVMTI_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
int i = 0 ;
|
||||
for (SystemProperty* p = Arguments::system_properties(); p != NULL && i < *count_ptr; p = p->next(), i++) {
|
||||
const char *key = p->key();
|
||||
char **tmp_value = *property_ptr+i;
|
||||
err = allocate((strlen(key)+1) * sizeof(char), (unsigned char**)tmp_value);
|
||||
if (err == JVMTI_ERROR_NONE) {
|
||||
strcpy(*tmp_value, key);
|
||||
} else {
|
||||
// clean up previously allocated memory.
|
||||
for (int j=0; j<i; j++) {
|
||||
Deallocate((unsigned char*)*property_ptr+j);
|
||||
int readable_count = 0;
|
||||
// Loop through the system properties until all the readable properties are found.
|
||||
for (SystemProperty* p = Arguments::system_properties(); p != NULL && readable_count < *count_ptr; p = p->next()) {
|
||||
if (p->is_readable()) {
|
||||
const char *key = p->key();
|
||||
char **tmp_value = *property_ptr+readable_count;
|
||||
readable_count++;
|
||||
err = allocate((strlen(key)+1) * sizeof(char), (unsigned char**)tmp_value);
|
||||
if (err == JVMTI_ERROR_NONE) {
|
||||
strcpy(*tmp_value, key);
|
||||
} else {
|
||||
// clean up previously allocated memory.
|
||||
for (int j=0; j<readable_count; j++) {
|
||||
Deallocate((unsigned char*)*property_ptr+j);
|
||||
}
|
||||
Deallocate((unsigned char*)property_ptr);
|
||||
break;
|
||||
}
|
||||
Deallocate((unsigned char*)property_ptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(err != JVMTI_ERROR_NONE || readable_count == *count_ptr, "Bad readable property count");
|
||||
return err;
|
||||
} /* end GetSystemProperties */
|
||||
|
||||
@ -3498,7 +3508,8 @@ JvmtiEnv::GetSystemProperty(const char* property, char** value_ptr) {
|
||||
jvmtiError err = JVMTI_ERROR_NONE;
|
||||
const char *value;
|
||||
|
||||
value = Arguments::PropertyList_get_value(Arguments::system_properties(), property);
|
||||
// Return JVMTI_ERROR_NOT_AVAILABLE if property is not readable or doesn't exist.
|
||||
value = Arguments::PropertyList_get_readable_value(Arguments::system_properties(), property);
|
||||
if (value == NULL) {
|
||||
err = JVMTI_ERROR_NOT_AVAILABLE;
|
||||
} else {
|
||||
|
@ -110,7 +110,7 @@ SystemProperty *Arguments::_java_home = NULL;
|
||||
SystemProperty *Arguments::_java_class_path = NULL;
|
||||
SystemProperty *Arguments::_jdk_boot_class_path_append = NULL;
|
||||
|
||||
GrowableArray<ModuleXPatchPath*> *Arguments::_xpatchprefix = NULL;
|
||||
GrowableArray<ModulePatchPath*> *Arguments::_patch_mod_prefix = NULL;
|
||||
PathString *Arguments::_system_boot_class_path = NULL;
|
||||
bool Arguments::_has_jimage = false;
|
||||
|
||||
@ -161,6 +161,30 @@ static void logOption(const char* opt) {
|
||||
}
|
||||
}
|
||||
|
||||
bool needs_module_property_warning = false;
|
||||
|
||||
#define MODULE_PROPERTY_PREFIX "jdk.module"
|
||||
#define MODULE_PROPERTY_PREFIX_LEN 10
|
||||
#define MODULE_MAIN_PROPERTY "jdk.module.main"
|
||||
#define MODULE_MAIN_PROPERTY_LEN 15
|
||||
|
||||
// Return TRUE if option matches property, or property=, or property..
|
||||
static bool matches_property_prefix(const char* option, const char* property, size_t len) {
|
||||
return (strncmp(option, property, len) == 0) &&
|
||||
(option[len] == '=' || option[len] == '.' || option[len] == '\0');
|
||||
}
|
||||
|
||||
// Return true if the property is either "jdk.module" or starts with "jdk.module.",
|
||||
// but does not start with "jdk.module.main".
|
||||
// Return false if jdk.module.main because jdk.module.main and jdk.module.main.class
|
||||
// are valid non-internal system properties.
|
||||
// "property" should be passed without the leading "-D".
|
||||
bool Arguments::is_internal_module_property(const char* property) {
|
||||
assert((strncmp(property, "-D", 2) != 0), "Unexpected leading -D");
|
||||
return (matches_property_prefix(property, MODULE_PROPERTY_PREFIX, MODULE_PROPERTY_PREFIX_LEN) &&
|
||||
!matches_property_prefix(property, MODULE_MAIN_PROPERTY, MODULE_MAIN_PROPERTY_LEN));
|
||||
}
|
||||
|
||||
// Process java launcher properties.
|
||||
void Arguments::process_sun_java_launcher_properties(JavaVMInitArgs* args) {
|
||||
// See if sun.java.launcher, sun.java.launcher.is_altjvm or
|
||||
@ -197,7 +221,7 @@ void Arguments::init_system_properties() {
|
||||
_system_boot_class_path = new PathString(NULL);
|
||||
|
||||
PropertyList_add(&_system_properties, new SystemProperty("java.vm.specification.name",
|
||||
"Java Virtual Machine Specification", false));
|
||||
"Java Virtual Machine Specification", false));
|
||||
PropertyList_add(&_system_properties, new SystemProperty("java.vm.version", VM_Version::vm_release(), false));
|
||||
PropertyList_add(&_system_properties, new SystemProperty("java.vm.name", VM_Version::vm_name(), false));
|
||||
PropertyList_add(&_system_properties, new SystemProperty("java.vm.info", VM_Version::vm_info_string(), true));
|
||||
@ -1198,7 +1222,7 @@ const char* Arguments::get_property(const char* key) {
|
||||
return PropertyList_get_value(system_properties(), key);
|
||||
}
|
||||
|
||||
bool Arguments::add_property(const char* prop) {
|
||||
bool Arguments::add_property(const char* prop, PropertyWriteable writeable, PropertyInternal internal) {
|
||||
const char* eq = strchr(prop, '=');
|
||||
const char* key;
|
||||
const char* value = "";
|
||||
@ -1228,7 +1252,9 @@ bool Arguments::add_property(const char* prop) {
|
||||
// private and are processed in process_sun_java_launcher_properties();
|
||||
// the sun.java.launcher property is passed on to the java application
|
||||
} else if (strcmp(key, "sun.boot.library.path") == 0) {
|
||||
PropertyList_unique_add(&_system_properties, key, value, true);
|
||||
// append is true, writable is true, internal is false
|
||||
PropertyList_unique_add(&_system_properties, key, value, AppendProperty,
|
||||
WriteableProperty, ExternalProperty);
|
||||
} else {
|
||||
if (strcmp(key, "sun.java.command") == 0) {
|
||||
char *old_java_command = _java_command;
|
||||
@ -1248,7 +1274,7 @@ bool Arguments::add_property(const char* prop) {
|
||||
}
|
||||
|
||||
// Create new property and add at the end of the list
|
||||
PropertyList_unique_add(&_system_properties, key, value);
|
||||
PropertyList_unique_add(&_system_properties, key, value, AddProperty, writeable, internal);
|
||||
}
|
||||
|
||||
if (key != prop) {
|
||||
@ -1260,9 +1286,9 @@ bool Arguments::add_property(const char* prop) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// sets or adds a module name to the jdk.launcher.addmods property
|
||||
// sets or adds a module name to the jdk.module.addmods property
|
||||
bool Arguments::append_to_addmods_property(const char* module_name) {
|
||||
const char* key = "jdk.launcher.addmods";
|
||||
const char* key = "jdk.module.addmods";
|
||||
const char* old_value = Arguments::get_property(key);
|
||||
size_t buf_len = strlen(key) + strlen(module_name) + 2;
|
||||
if (old_value != NULL) {
|
||||
@ -1277,7 +1303,7 @@ bool Arguments::append_to_addmods_property(const char* module_name) {
|
||||
} else {
|
||||
jio_snprintf(new_value, buf_len, "%s=%s,%s", key, old_value, module_name);
|
||||
}
|
||||
bool added = add_property(new_value);
|
||||
bool added = add_property(new_value, UnwriteableProperty, InternalProperty);
|
||||
FreeHeap(new_value);
|
||||
return added;
|
||||
}
|
||||
@ -1287,14 +1313,14 @@ void Arguments::check_unsupported_dumping_properties() {
|
||||
assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
|
||||
const char* unsupported_properties[5] = { "jdk.module.main",
|
||||
"jdk.module.path",
|
||||
"jdk.upgrade.module.path",
|
||||
"jdk.launcher.addmods",
|
||||
"jdk.launcher.limitmods" };
|
||||
"jdk.module.upgrade.path",
|
||||
"jdk.module.addmods",
|
||||
"jdk.module.limitmods" };
|
||||
const char* unsupported_options[5] = { "-m",
|
||||
"-modulepath",
|
||||
"-upgrademodulepath",
|
||||
"-addmods",
|
||||
"-limitmods" };
|
||||
"--module-path",
|
||||
"--upgrade-module-path",
|
||||
"--add-modules",
|
||||
"--limit-modules" };
|
||||
SystemProperty* sp = system_properties();
|
||||
while (sp != NULL) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
@ -1326,7 +1352,7 @@ void Arguments::set_mode_flags(Mode mode) {
|
||||
// Ensure Agent_OnLoad has the correct initial values.
|
||||
// This may not be the final mode; mode may change later in onload phase.
|
||||
PropertyList_unique_add(&_system_properties, "java.vm.info",
|
||||
VM_Version::vm_info_string(), false);
|
||||
VM_Version::vm_info_string(), AddProperty, UnwriteableProperty, ExternalProperty);
|
||||
|
||||
UseInterpreter = true;
|
||||
UseCompiler = true;
|
||||
@ -2516,6 +2542,41 @@ bool Arguments::parse_uintx(const char* value,
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int addreads_count = 0;
|
||||
unsigned int addexports_count = 0;
|
||||
unsigned int patch_mod_count = 0;
|
||||
const char* add_modules_value = NULL;
|
||||
|
||||
bool Arguments::create_property(const char* prop_name, const char* prop_value, PropertyInternal internal) {
|
||||
size_t prop_len = strlen(prop_name) + strlen(prop_value) + 2;
|
||||
char* property = AllocateHeap(prop_len, mtArguments);
|
||||
int ret = jio_snprintf(property, prop_len, "%s=%s", prop_name, prop_value);
|
||||
if (ret < 0 || ret >= (int)prop_len) {
|
||||
FreeHeap(property);
|
||||
return false;
|
||||
}
|
||||
bool added = add_property(property, UnwriteableProperty, internal);
|
||||
FreeHeap(property);
|
||||
return added;
|
||||
}
|
||||
|
||||
bool Arguments::create_numbered_property(const char* prop_base_name, const char* prop_value, unsigned int count) {
|
||||
// Make sure count is < 1,000. Otherwise, memory allocation will be too small.
|
||||
if (count < 1000) {
|
||||
size_t prop_len = strlen(prop_base_name) + strlen(prop_value) + 5;
|
||||
char* property = AllocateHeap(prop_len, mtArguments);
|
||||
int ret = jio_snprintf(property, prop_len, "%s.%d=%s", prop_base_name, count, prop_value);
|
||||
if (ret < 0 || ret >= (int)prop_len) {
|
||||
FreeHeap(property);
|
||||
return false;
|
||||
}
|
||||
bool added = add_property(property, UnwriteableProperty, InternalProperty);
|
||||
FreeHeap(property);
|
||||
return added;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Arguments::ArgsRange Arguments::parse_memory_size(const char* s,
|
||||
julong* long_arg,
|
||||
julong min_size) {
|
||||
@ -2528,7 +2589,7 @@ Arguments::ArgsRange Arguments::parse_memory_size(const char* s,
|
||||
jint Arguments::parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args,
|
||||
const JavaVMInitArgs *java_options_args,
|
||||
const JavaVMInitArgs *cmd_line_args) {
|
||||
bool xpatch_javabase = false;
|
||||
bool patch_mod_javabase = false;
|
||||
|
||||
// Save default settings for some mode flags
|
||||
Arguments::_AlwaysCompileLoopMethods = AlwaysCompileLoopMethods;
|
||||
@ -2545,20 +2606,20 @@ jint Arguments::parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args,
|
||||
|
||||
// Parse args structure generated from JAVA_TOOL_OPTIONS environment
|
||||
// variable (if present).
|
||||
jint result = parse_each_vm_init_arg(java_tool_options_args, &xpatch_javabase, Flag::ENVIRON_VAR);
|
||||
jint result = parse_each_vm_init_arg(java_tool_options_args, &patch_mod_javabase, Flag::ENVIRON_VAR);
|
||||
if (result != JNI_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Parse args structure generated from the command line flags.
|
||||
result = parse_each_vm_init_arg(cmd_line_args, &xpatch_javabase, Flag::COMMAND_LINE);
|
||||
result = parse_each_vm_init_arg(cmd_line_args, &patch_mod_javabase, Flag::COMMAND_LINE);
|
||||
if (result != JNI_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Parse args structure generated from the _JAVA_OPTIONS environment
|
||||
// variable (if present) (mimics classic VM)
|
||||
result = parse_each_vm_init_arg(java_options_args, &xpatch_javabase, Flag::ENVIRON_VAR);
|
||||
result = parse_each_vm_init_arg(java_options_args, &patch_mod_javabase, Flag::ENVIRON_VAR);
|
||||
if (result != JNI_OK) {
|
||||
return result;
|
||||
}
|
||||
@ -2617,7 +2678,35 @@ bool valid_jdwp_agent(char *name, bool is_path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* xpatch_javabase, Flag::Flags origin) {
|
||||
int Arguments::process_patch_mod_option(const char* patch_mod_tail, bool* patch_mod_javabase) {
|
||||
// --patch-module=<module>=<file>(<pathsep><file>)*
|
||||
assert(patch_mod_tail != NULL, "Unexpected NULL patch-module value");
|
||||
// Find the equal sign between the module name and the path specification
|
||||
const char* module_equal = strchr(patch_mod_tail, '=');
|
||||
if (module_equal == NULL) {
|
||||
jio_fprintf(defaultStream::output_stream(), "Missing '=' in --patch-module specification\n");
|
||||
return JNI_ERR;
|
||||
} else {
|
||||
// Pick out the module name
|
||||
size_t module_len = module_equal - patch_mod_tail;
|
||||
char* module_name = NEW_C_HEAP_ARRAY_RETURN_NULL(char, module_len+1, mtArguments);
|
||||
if (module_name != NULL) {
|
||||
memcpy(module_name, patch_mod_tail, module_len);
|
||||
*(module_name + module_len) = '\0';
|
||||
// The path piece begins one past the module_equal sign
|
||||
add_patch_mod_prefix(module_name, module_equal + 1, patch_mod_javabase);
|
||||
FREE_C_HEAP_ARRAY(char, module_name);
|
||||
if (!create_numbered_property("jdk.module.patch", patch_mod_tail, patch_mod_count++)) {
|
||||
return JNI_ENOMEM;
|
||||
}
|
||||
} else {
|
||||
return JNI_ENOMEM;
|
||||
}
|
||||
}
|
||||
return JNI_OK;
|
||||
}
|
||||
|
||||
jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* patch_mod_javabase, Flag::Flags origin) {
|
||||
// For match_option to return remaining or value part of option string
|
||||
const char* tail;
|
||||
|
||||
@ -2701,6 +2790,34 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* xpatch_
|
||||
#endif // !INCLUDE_JVMTI
|
||||
add_init_library(name, options);
|
||||
}
|
||||
} else if (match_option(option, "--add-reads=", &tail)) {
|
||||
if (!create_numbered_property("jdk.module.addreads", tail, addreads_count++)) {
|
||||
return JNI_ENOMEM;
|
||||
}
|
||||
} else if (match_option(option, "--add-exports=", &tail)) {
|
||||
if (!create_numbered_property("jdk.module.addexports", tail, addexports_count++)) {
|
||||
return JNI_ENOMEM;
|
||||
}
|
||||
} else if (match_option(option, "--add-modules=", &tail)) {
|
||||
add_modules_value = tail;
|
||||
} else if (match_option(option, "--limit-modules=", &tail)) {
|
||||
if (!create_property("jdk.module.limitmods", tail, InternalProperty)) {
|
||||
return JNI_ENOMEM;
|
||||
}
|
||||
} else if (match_option(option, "--module-path=", &tail)) {
|
||||
if (!create_property("jdk.module.path", tail, ExternalProperty)) {
|
||||
return JNI_ENOMEM;
|
||||
}
|
||||
} else if (match_option(option, "--upgrade-module-path=", &tail)) {
|
||||
if (!create_property("jdk.module.upgrade.path", tail, ExternalProperty)) {
|
||||
return JNI_ENOMEM;
|
||||
}
|
||||
} else if (match_option(option, "--patch-module=", &tail)) {
|
||||
// --patch-module=<module>=<file>(<pathsep><file>)*
|
||||
int res = process_patch_mod_option(tail, patch_mod_javabase);
|
||||
if (res != JNI_OK) {
|
||||
return res;
|
||||
}
|
||||
// -agentlib and -agentpath
|
||||
} else if (match_option(option, "-agentlib:", &tail) ||
|
||||
(is_absolute_path = match_option(option, "-agentpath:", &tail))) {
|
||||
@ -2992,6 +3109,13 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* xpatch_
|
||||
"-Djava.ext.dirs=%s is not supported. Use -classpath instead.\n", value);
|
||||
return JNI_EINVAL;
|
||||
}
|
||||
// Check for module related properties. They must be set using the modules
|
||||
// options. For example: use "--add-modules=java.sql", not
|
||||
// "-Djdk.module.addmods=java.sql"
|
||||
if (is_internal_module_property(option->optionString + 2)) {
|
||||
needs_module_property_warning = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!add_property(tail)) {
|
||||
return JNI_ENOMEM;
|
||||
@ -3012,33 +3136,6 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* xpatch_
|
||||
return JNI_ERR;
|
||||
#endif
|
||||
}
|
||||
if (match_option(option, "-Djdk.launcher.patch.", &tail)) {
|
||||
// -Djdk.launcher.patch.#=<module>=<file>(<pathsep><file>)*
|
||||
// The number, #, specified will be increasing with each -Xpatch
|
||||
// specified on the command line.
|
||||
// Pick up module name, following the -D property's equal sign.
|
||||
const char* property_equal = strchr(tail, '=');
|
||||
if (property_equal == NULL) {
|
||||
jio_fprintf(defaultStream::output_stream(), "Missing '=' in -Xpatch specification\n");
|
||||
return JNI_ERR;
|
||||
} else {
|
||||
// Find the equal sign between the module name and the path specification
|
||||
const char* module_equal = strchr(property_equal + 1, '=');
|
||||
if (module_equal == NULL) {
|
||||
jio_fprintf(defaultStream::output_stream(), "Bad value for -Xpatch, no module name specified\n");
|
||||
return JNI_ERR;
|
||||
} else {
|
||||
// Pick out the module name, in between the two equal signs
|
||||
size_t module_len = module_equal - property_equal - 1;
|
||||
char* module_name = NEW_C_HEAP_ARRAY(char, module_len+1, mtArguments);
|
||||
memcpy(module_name, property_equal + 1, module_len);
|
||||
*(module_name + module_len) = '\0';
|
||||
// The path piece begins one past the module_equal sign
|
||||
Arguments::add_xpatchprefix(module_name, module_equal + 1, xpatch_javabase);
|
||||
FREE_C_HEAP_ARRAY(char, module_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
// -Xint
|
||||
} else if (match_option(option, "-Xint")) {
|
||||
set_mode_flags(_int);
|
||||
@ -3298,25 +3395,25 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* xpatch_
|
||||
return JNI_OK;
|
||||
}
|
||||
|
||||
void Arguments::add_xpatchprefix(const char* module_name, const char* path, bool* xpatch_javabase) {
|
||||
// For java.base check for duplicate -Xpatch options being specified on the command line.
|
||||
void Arguments::add_patch_mod_prefix(const char* module_name, const char* path, bool* patch_mod_javabase) {
|
||||
// For java.base check for duplicate --patch-module options being specified on the command line.
|
||||
// This check is only required for java.base, all other duplicate module specifications
|
||||
// will be checked during module system initialization. The module system initialization
|
||||
// will throw an ExceptionInInitializerError if this situation occurs.
|
||||
if (strcmp(module_name, "java.base") == 0) {
|
||||
if (*xpatch_javabase) {
|
||||
vm_exit_during_initialization("Cannot specify java.base more than once to -Xpatch");
|
||||
if (*patch_mod_javabase) {
|
||||
vm_exit_during_initialization("Cannot specify java.base more than once to --patch-module");
|
||||
} else {
|
||||
*xpatch_javabase = true;
|
||||
*patch_mod_javabase = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Create GrowableArray lazily, only if -Xpatch has been specified
|
||||
if (_xpatchprefix == NULL) {
|
||||
_xpatchprefix = new (ResourceObj::C_HEAP, mtArguments) GrowableArray<ModuleXPatchPath*>(10, true);
|
||||
// Create GrowableArray lazily, only if --patch-module has been specified
|
||||
if (_patch_mod_prefix == NULL) {
|
||||
_patch_mod_prefix = new (ResourceObj::C_HEAP, mtArguments) GrowableArray<ModulePatchPath*>(10, true);
|
||||
}
|
||||
|
||||
_xpatchprefix->push(new ModuleXPatchPath(module_name, path));
|
||||
_patch_mod_prefix->push(new ModulePatchPath(module_name, path));
|
||||
}
|
||||
|
||||
// Remove all empty paths from the app classpath (if IgnoreEmptyClassPaths is enabled)
|
||||
@ -3441,6 +3538,15 @@ jint Arguments::finalize_vm_init_args() {
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
// Append the value of the last --add-modules option specified on the command line.
|
||||
// This needs to be done here, to prevent overwriting possible values written
|
||||
// to the jdk.module.addmods property by -javaagent and other options.
|
||||
if (add_modules_value != NULL) {
|
||||
if (!append_to_addmods_property(add_modules_value)) {
|
||||
return JNI_ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
// This must be done after all arguments have been processed.
|
||||
// java_compiler() true means set to "NONE" or empty.
|
||||
if (java_compiler() && !xdebug_mode()) {
|
||||
@ -3795,9 +3901,9 @@ jint Arguments::parse_options_buffer(const char* name, char* buffer, const size_
|
||||
|
||||
void Arguments::set_shared_spaces_flags() {
|
||||
if (DumpSharedSpaces) {
|
||||
if (Arguments::get_xpatchprefix() != NULL) {
|
||||
if (Arguments::get_patch_mod_prefix() != NULL) {
|
||||
vm_exit_during_initialization(
|
||||
"Cannot use the following option when dumping the shared archive", "-Xpatch");
|
||||
"Cannot use the following option when dumping the shared archive: --patch-module");
|
||||
}
|
||||
|
||||
if (RequireSharedSpaces) {
|
||||
@ -4180,6 +4286,11 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) {
|
||||
hotspotrc, hotspotrc);
|
||||
}
|
||||
|
||||
if (needs_module_property_warning) {
|
||||
warning("Ignoring system property options whose names start with '-Djdk.module'."
|
||||
" They are reserved for internal use.");
|
||||
}
|
||||
|
||||
#if defined(_ALLBSD_SOURCE) || defined(AIX) // UseLargePages is not yet supported on BSD and AIX.
|
||||
UNSUPPORTED_OPTION(UseLargePages);
|
||||
#endif
|
||||
@ -4404,6 +4515,18 @@ int Arguments::PropertyList_count(SystemProperty* pl) {
|
||||
return count;
|
||||
}
|
||||
|
||||
// Return the number of readable properties.
|
||||
int Arguments::PropertyList_readable_count(SystemProperty* pl) {
|
||||
int count = 0;
|
||||
while(pl != NULL) {
|
||||
if (pl->is_readable()) {
|
||||
count++;
|
||||
}
|
||||
pl = pl->next();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
const char* Arguments::PropertyList_get_value(SystemProperty *pl, const char* key) {
|
||||
assert(key != NULL, "just checking");
|
||||
SystemProperty* prop;
|
||||
@ -4413,6 +4536,27 @@ const char* Arguments::PropertyList_get_value(SystemProperty *pl, const char* ke
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Return the value of the requested property provided that it is a readable property.
|
||||
const char* Arguments::PropertyList_get_readable_value(SystemProperty *pl, const char* key) {
|
||||
assert(key != NULL, "just checking");
|
||||
SystemProperty* prop;
|
||||
// Return the property value if the keys match and the property is not internal or
|
||||
// it's the special internal property "jdk.boot.class.path.append".
|
||||
for (prop = pl; prop != NULL; prop = prop->next()) {
|
||||
if (strcmp(key, prop->key()) == 0) {
|
||||
if (!prop->internal()) {
|
||||
return prop->value();
|
||||
} else if (strcmp(key, "jdk.boot.class.path.append") == 0) {
|
||||
return prop->value();
|
||||
} else {
|
||||
// Property is internal and not jdk.boot.class.path.append so return NULL.
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* Arguments::PropertyList_get_key_at(SystemProperty *pl, int index) {
|
||||
int count = 0;
|
||||
const char* ret_val = NULL;
|
||||
@ -4457,11 +4601,12 @@ void Arguments::PropertyList_add(SystemProperty** plist, SystemProperty *new_p)
|
||||
}
|
||||
}
|
||||
|
||||
void Arguments::PropertyList_add(SystemProperty** plist, const char* k, const char* v) {
|
||||
void Arguments::PropertyList_add(SystemProperty** plist, const char* k, const char* v,
|
||||
bool writeable, bool internal) {
|
||||
if (plist == NULL)
|
||||
return;
|
||||
|
||||
SystemProperty* new_p = new SystemProperty(k, v, true);
|
||||
SystemProperty* new_p = new SystemProperty(k, v, writeable, internal);
|
||||
PropertyList_add(plist, new_p);
|
||||
}
|
||||
|
||||
@ -4470,7 +4615,9 @@ void Arguments::PropertyList_add(SystemProperty *element) {
|
||||
}
|
||||
|
||||
// This add maintains unique property key in the list.
|
||||
void Arguments::PropertyList_unique_add(SystemProperty** plist, const char* k, const char* v, jboolean append) {
|
||||
void Arguments::PropertyList_unique_add(SystemProperty** plist, const char* k, const char* v,
|
||||
PropertyAppendable append, PropertyWriteable writeable,
|
||||
PropertyInternal internal) {
|
||||
if (plist == NULL)
|
||||
return;
|
||||
|
||||
@ -4478,16 +4625,16 @@ void Arguments::PropertyList_unique_add(SystemProperty** plist, const char* k, c
|
||||
SystemProperty* prop;
|
||||
for (prop = *plist; prop != NULL; prop = prop->next()) {
|
||||
if (strcmp(k, prop->key()) == 0) {
|
||||
if (append) {
|
||||
if (append == AppendProperty) {
|
||||
prop->append_value(v);
|
||||
} else {
|
||||
prop->set_writeable_value(v);
|
||||
prop->set_value(v);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PropertyList_add(plist, k, v);
|
||||
PropertyList_add(plist, k, v, writeable == WriteableProperty, internal == InternalProperty);
|
||||
}
|
||||
|
||||
// Copies src into buf, replacing "%%" with "%" and "%p" with pid
|
||||
|
@ -43,7 +43,7 @@ extern "C" {
|
||||
|
||||
// PathString is used as:
|
||||
// - the underlying value for a SystemProperty
|
||||
// - the path portion of an -Xpatch module/path pair
|
||||
// - the path portion of an --patch-module module/path pair
|
||||
// - the string that represents the system boot class path, Arguments::_system_boot_class_path.
|
||||
class PathString : public CHeapObj<mtArguments> {
|
||||
protected:
|
||||
@ -107,13 +107,13 @@ class PathString : public CHeapObj<mtArguments> {
|
||||
}
|
||||
};
|
||||
|
||||
// ModuleXPatchPath records the module/path pair as specified to -Xpatch.
|
||||
class ModuleXPatchPath : public CHeapObj<mtInternal> {
|
||||
// ModulePatchPath records the module/path pair as specified to --patch-module.
|
||||
class ModulePatchPath : public CHeapObj<mtInternal> {
|
||||
private:
|
||||
char* _module_name;
|
||||
PathString* _path;
|
||||
public:
|
||||
ModuleXPatchPath(const char* module_name, const char* path) {
|
||||
ModulePatchPath(const char* module_name, const char* path) {
|
||||
assert(module_name != NULL && path != NULL, "Invalid module name or path value");
|
||||
size_t len = strlen(module_name) + 1;
|
||||
_module_name = AllocateHeap(len, mtInternal);
|
||||
@ -121,7 +121,7 @@ public:
|
||||
_path = new PathString(path);
|
||||
}
|
||||
|
||||
~ModuleXPatchPath() {
|
||||
~ModulePatchPath() {
|
||||
if (_module_name != NULL) {
|
||||
FreeHeap(_module_name);
|
||||
_module_name = NULL;
|
||||
@ -158,6 +158,10 @@ class SystemProperty : public PathString {
|
||||
SystemProperty* next() const { return _next; }
|
||||
void set_next(SystemProperty* next) { _next = next; }
|
||||
|
||||
bool is_readable() const {
|
||||
return !_internal || strcmp(_key, "jdk.boot.class.path.append") == 0;
|
||||
}
|
||||
|
||||
// A system property should only have its value set
|
||||
// via an external interface if it is a writeable property.
|
||||
// The internal, non-writeable property jdk.boot.class.path.append
|
||||
@ -325,6 +329,21 @@ class Arguments : AllStatic {
|
||||
arg_in_range = 0
|
||||
};
|
||||
|
||||
enum PropertyAppendable {
|
||||
AppendProperty,
|
||||
AddProperty
|
||||
};
|
||||
|
||||
enum PropertyWriteable {
|
||||
WriteableProperty,
|
||||
UnwriteableProperty
|
||||
};
|
||||
|
||||
enum PropertyInternal {
|
||||
InternalProperty,
|
||||
ExternalProperty
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
// a pointer to the flags file name if it is specified
|
||||
@ -348,18 +367,18 @@ class Arguments : AllStatic {
|
||||
static SystemProperty *_java_class_path;
|
||||
static SystemProperty *_jdk_boot_class_path_append;
|
||||
|
||||
// -Xpatch:module=<file>(<pathsep><file>)*
|
||||
// --patch-module=module=<file>(<pathsep><file>)*
|
||||
// Each element contains the associated module name, path
|
||||
// string pair as specified to -Xpatch.
|
||||
static GrowableArray<ModuleXPatchPath*>* _xpatchprefix;
|
||||
// string pair as specified to --patch-module.
|
||||
static GrowableArray<ModulePatchPath*>* _patch_mod_prefix;
|
||||
|
||||
// The constructed value of the system class path after
|
||||
// argument processing and JVMTI OnLoad additions via
|
||||
// calls to AddToBootstrapClassLoaderSearch. This is the
|
||||
// final form before ClassLoader::setup_bootstrap_search().
|
||||
// Note: since -Xpatch is a module name/path pair, the system
|
||||
// boot class path string no longer contains the "prefix" to
|
||||
// the boot class path base piece as it did when
|
||||
// Note: since --patch-module is a module name/path pair, the
|
||||
// system boot class path string no longer contains the "prefix"
|
||||
// to the boot class path base piece as it did when
|
||||
// -Xbootclasspath/p was supported.
|
||||
static PathString *_system_boot_class_path;
|
||||
|
||||
@ -462,7 +481,13 @@ class Arguments : AllStatic {
|
||||
static vfprintf_hook_t _vfprintf_hook;
|
||||
|
||||
// System properties
|
||||
static bool add_property(const char* prop);
|
||||
static bool add_property(const char* prop, PropertyWriteable writeable=WriteableProperty,
|
||||
PropertyInternal internal=ExternalProperty);
|
||||
|
||||
static bool create_property(const char* prop_name, const char* prop_value, PropertyInternal internal);
|
||||
static bool create_numbered_property(const char* prop_base_name, const char* prop_value, unsigned int count);
|
||||
|
||||
static int process_patch_mod_option(const char* patch_mod_tail, bool* patch_mod_javabase);
|
||||
|
||||
// Miscellaneous system property setter
|
||||
static bool append_to_addmods_property(const char* module_name);
|
||||
@ -500,7 +525,7 @@ class Arguments : AllStatic {
|
||||
static jint parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args,
|
||||
const JavaVMInitArgs *java_options_args,
|
||||
const JavaVMInitArgs *cmd_line_args);
|
||||
static jint parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* xpatch_javabase, Flag::Flags origin);
|
||||
static jint parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* patch_mod_javabase, Flag::Flags origin);
|
||||
static jint finalize_vm_init_args();
|
||||
static bool is_bad_option(const JavaVMOption* option, jboolean ignore, const char* option_type);
|
||||
|
||||
@ -708,16 +733,20 @@ class Arguments : AllStatic {
|
||||
// Property List manipulation
|
||||
static void PropertyList_add(SystemProperty *element);
|
||||
static void PropertyList_add(SystemProperty** plist, SystemProperty *element);
|
||||
static void PropertyList_add(SystemProperty** plist, const char* k, const char* v);
|
||||
static void PropertyList_unique_add(SystemProperty** plist, const char* k, const char* v) {
|
||||
PropertyList_unique_add(plist, k, v, false);
|
||||
}
|
||||
static void PropertyList_unique_add(SystemProperty** plist, const char* k, const char* v, jboolean append);
|
||||
static void PropertyList_add(SystemProperty** plist, const char* k, const char* v, bool writeable, bool internal);
|
||||
|
||||
static void PropertyList_unique_add(SystemProperty** plist, const char* k, const char* v,
|
||||
PropertyAppendable append, PropertyWriteable writeable,
|
||||
PropertyInternal internal);
|
||||
static const char* PropertyList_get_value(SystemProperty* plist, const char* key);
|
||||
static const char* PropertyList_get_readable_value(SystemProperty* plist, const char* key);
|
||||
static int PropertyList_count(SystemProperty* pl);
|
||||
static int PropertyList_readable_count(SystemProperty* pl);
|
||||
static const char* PropertyList_get_key_at(SystemProperty* pl,int index);
|
||||
static char* PropertyList_get_value_at(SystemProperty* pl,int index);
|
||||
|
||||
static bool is_internal_module_property(const char* option);
|
||||
|
||||
// Miscellaneous System property value getter and setters.
|
||||
static void set_dll_dir(const char *value) { _sun_boot_library_path->set_value(value); }
|
||||
static void set_java_home(const char *value) { _java_home->set_value(value); }
|
||||
@ -725,7 +754,7 @@ class Arguments : AllStatic {
|
||||
static void set_ext_dirs(char *value) { _ext_dirs = os::strdup_check_oom(value); }
|
||||
|
||||
// Set up the underlying pieces of the system boot class path
|
||||
static void add_xpatchprefix(const char *module_name, const char *path, bool* xpatch_javabase);
|
||||
static void add_patch_mod_prefix(const char *module_name, const char *path, bool* patch_mod_javabase);
|
||||
static void set_sysclasspath(const char *value, bool has_jimage) {
|
||||
// During start up, set by os::set_boot_path()
|
||||
assert(get_sysclasspath() == NULL, "System boot class path previously set");
|
||||
@ -737,7 +766,7 @@ class Arguments : AllStatic {
|
||||
_jdk_boot_class_path_append->append_value(value);
|
||||
}
|
||||
|
||||
static GrowableArray<ModuleXPatchPath*>* get_xpatchprefix() { return _xpatchprefix; }
|
||||
static GrowableArray<ModulePatchPath*>* get_patch_mod_prefix() { return _patch_mod_prefix; }
|
||||
static char* get_sysclasspath() { return _system_boot_class_path->value(); }
|
||||
static char* get_jdk_boot_class_path_append() { return _jdk_boot_class_path_append->value(); }
|
||||
static bool has_jimage() { return _has_jimage; }
|
||||
|
@ -703,13 +703,15 @@ void defaultStream::start_log() {
|
||||
// System properties don't generally contain newlines, so don't bother with unparsing.
|
||||
outputStream *text = xs->text();
|
||||
for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) {
|
||||
// Print in two stages to avoid problems with long
|
||||
// keys/values.
|
||||
assert(p->key() != NULL, "p->key() is NULL");
|
||||
text->print_raw(p->key());
|
||||
text->put('=');
|
||||
assert(p->value() != NULL, "p->value() is NULL");
|
||||
text->print_raw_cr(p->value());
|
||||
if (p->is_readable()) {
|
||||
// Print in two stages to avoid problems with long
|
||||
// keys/values.
|
||||
text->print_raw(p->key());
|
||||
text->put('=');
|
||||
assert(p->value() != NULL, "p->value() is NULL");
|
||||
text->print_raw_cr(p->value());
|
||||
}
|
||||
}
|
||||
xs->tail("properties");
|
||||
}
|
||||
|
@ -46,12 +46,12 @@ requires.properties= \
|
||||
vm.gc.Parallel \
|
||||
vm.gc.ConcMarkSweep
|
||||
|
||||
# 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
|
||||
|
@ -40,7 +40,7 @@
|
||||
* -XX:CompileCommand=dontinline,compiler.unsafe.UnsafeGetConstantField::checkGetAddress
|
||||
* -XX:CompileCommand=dontinline,*::test*
|
||||
* -XX:+UseUnalignedAccesses
|
||||
* -XaddReads:java.base=ALL-UNNAMED
|
||||
* --add-reads=java.base=ALL-UNNAMED
|
||||
* compiler.unsafe.UnsafeGetConstantField
|
||||
*
|
||||
* @run main/bootclasspath/othervm -XX:+UnlockDiagnosticVMOptions
|
||||
@ -50,7 +50,7 @@
|
||||
* -XX:CompileCommand=dontinline,*::test*
|
||||
* -XX:CompileCommand=inline,*Unsafe::get*
|
||||
* -XX:-UseUnalignedAccesses
|
||||
* -XaddReads:java.base=ALL-UNNAMED
|
||||
* --add-reads=java.base=ALL-UNNAMED
|
||||
* compiler.unsafe.UnsafeGetConstantField
|
||||
*/
|
||||
|
||||
|
@ -88,7 +88,7 @@ public class TestMaxMinHeapFreeRatioFlags {
|
||||
(useXmaxf ? "-Xmaxf" + maxRatio / 100.0 : "-XX:MaxHeapFreeRatio=" + maxRatio),
|
||||
"-Xmx" + MAX_HEAP_SIZE,
|
||||
"-Xms" + HEAP_SIZE,
|
||||
"-XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED",
|
||||
"--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",
|
||||
"-XX:NewSize=" + NEW_SIZE,
|
||||
"-XX:MaxNewSize=" + MAX_NEW_SIZE,
|
||||
"-XX:" + (shrinkHeapInSteps ? '+' : '-') + "ShrinkHeapInSteps",
|
||||
@ -120,7 +120,7 @@ public class TestMaxMinHeapFreeRatioFlags {
|
||||
Collections.addAll(vmOptions,
|
||||
(useXminf ? "-Xminf" + minRatio / 100.0 : "-XX:MinHeapFreeRatio=" + minRatio),
|
||||
(useXmaxf ? "-Xmaxf" + maxRatio / 100.0 : "-XX:MaxHeapFreeRatio=" + maxRatio),
|
||||
"-XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED",
|
||||
"--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",
|
||||
"-version"
|
||||
);
|
||||
ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(vmOptions.toArray(new String[vmOptions.size()]));
|
||||
|
@ -74,7 +74,7 @@ public class TestSurvivorRatioFlag {
|
||||
|
||||
Collections.addAll(vmOptions,
|
||||
"-Xbootclasspath/a:.",
|
||||
"-XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED",
|
||||
"--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:+WhiteBoxAPI",
|
||||
"-XX:GCLockerEdenExpansionPercent=0",
|
||||
|
@ -132,7 +132,7 @@ public class TestTargetSurvivorRatioFlag {
|
||||
LinkedList<String> vmOptions = new LinkedList<>(options);
|
||||
Collections.addAll(vmOptions,
|
||||
"-Xbootclasspath/a:.",
|
||||
"-XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED",
|
||||
"--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:+WhiteBoxAPI",
|
||||
"-XX:+UseAdaptiveSizePolicy",
|
||||
|
@ -53,7 +53,7 @@ public class TestShrinkAuxiliaryData {
|
||||
"-Xlog:gc=debug",
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:+WhiteBoxAPI",
|
||||
"-XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED",
|
||||
"--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",
|
||||
"-Xbootclasspath/a:.",
|
||||
};
|
||||
|
||||
|
@ -48,7 +48,7 @@ public class BootstrapRedefine {
|
||||
"-Xmodule:java.base"),
|
||||
"mods/java.base");
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.base=mods/java.base", "-version");
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("--patch-module=java.base=mods/java.base", "-version");
|
||||
new OutputAnalyzer(pb.start())
|
||||
.shouldContain("Incompatible definition of java.lang.Object")
|
||||
.shouldHaveExitValue(1);
|
||||
|
@ -27,7 +27,7 @@ import java.io.File;
|
||||
* @test
|
||||
* @build BootClassPathAppendProp
|
||||
* @run main/othervm -Xbootclasspath/a:/usr/lib -showversion -Xbootclasspath/a:/i/dont/exist BootClassPathAppendProp
|
||||
* @run main/othervm -Xpatch:/not/here -Xbootclasspath/a:/i/may/exist BootClassPathAppendProp
|
||||
* @run main/othervm --patch-module=no_module=/not/here -Xbootclasspath/a:/i/may/exist BootClassPathAppendProp
|
||||
* @run main/othervm -Djdk.boot.class.path.append=newdir BootClassPathAppendProp
|
||||
* @run main/othervm BootClassPathAppendProp
|
||||
*/
|
||||
|
@ -56,7 +56,7 @@ public class CreateCoredumpOnCrash {
|
||||
public static OutputAnalyzer runTest(String option) throws Exception {
|
||||
return new OutputAnalyzer(
|
||||
ProcessTools.createJavaProcessBuilder(
|
||||
"-Xmx64m", "-XX:-TransmitErrorReport", "-XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED", option, Crasher.class.getName())
|
||||
"-Xmx64m", "-XX:-TransmitErrorReport", "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", option, Crasher.class.getName())
|
||||
.start());
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public class ProblematicFrameTest {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-Xmx64m", "-XX:-TransmitErrorReport", "-XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED", "-XX:-CreateCoredumpOnCrash", Crasher.class.getName());
|
||||
"-Xmx64m", "-XX:-TransmitErrorReport", "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", "-XX:-CreateCoredumpOnCrash", Crasher.class.getName());
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldNotContain("Exception in thread");
|
||||
output.shouldNotMatch("error occurred during error reporting \\(printing problematic frame\\)");
|
||||
|
@ -160,10 +160,10 @@ public class BootAppendTests {
|
||||
|
||||
// Test #3: If a class on -Xbootclasspath/a is from a package defined in boot modules,
|
||||
// the class can be loaded from -Xbootclasspath/a when the module is excluded
|
||||
// using -limitmods. Verify the behavior is the same at runtime when CDS is
|
||||
// enabled.
|
||||
// using --limit-modules. Verify the behavior is the same at runtime when CDS
|
||||
// is enabled.
|
||||
//
|
||||
// The java.desktop module is excluded using -limitmods at runtime,
|
||||
// The java.desktop module is excluded using --limit-modules at runtime,
|
||||
// javax.sound.sampled.MyClass is archived from -Xbootclasspath/a. It can be
|
||||
// loaded from the archive at runtime.
|
||||
public static void testBootAppendExcludedModuleClass() throws Exception {
|
||||
@ -174,7 +174,7 @@ public class BootAppendTests {
|
||||
"-XX:+TraceClassLoading",
|
||||
"-cp", appJar,
|
||||
"-Xbootclasspath/a:" + bootAppendJar,
|
||||
"-limitmods", "java.base",
|
||||
"--limit-modules=java.base",
|
||||
"-Xshare:" + mode,
|
||||
APP_CLASS,
|
||||
BOOT_APPEND_MODULE_CLASS_NAME);
|
||||
@ -191,8 +191,8 @@ public class BootAppendTests {
|
||||
// Test #4: If a class on -Xbootclasspath/a has the same fully qualified
|
||||
// name as a class defined in boot modules, the class is loaded
|
||||
// from -Xbootclasspath/a when the boot module is excluded using
|
||||
// -limitmods. Verify the behavior is the same at runtime when CDS is
|
||||
// enabled.
|
||||
// --limit-modules. Verify the behavior is the same at runtime
|
||||
// when CDS is enabled.
|
||||
//
|
||||
// The org.omg.CORBA.Context is a boot module class. The class
|
||||
// on -Xbootclasspath/a that has the same fully-qualified name
|
||||
@ -206,7 +206,7 @@ public class BootAppendTests {
|
||||
"-XX:+TraceClassLoading",
|
||||
"-cp", appJar,
|
||||
"-Xbootclasspath/a:" + bootAppendJar,
|
||||
"-limitmods", "java.base",
|
||||
"--limit-modules=java.base",
|
||||
"-Xshare:" + mode,
|
||||
APP_CLASS,
|
||||
BOOT_APPEND_DUPLICATE_MODULE_CLASS_NAME);
|
||||
|
@ -89,10 +89,11 @@ public class SASymbolTableTest {
|
||||
long pid = p.getPid();
|
||||
System.out.println("Attaching agent " + pid);
|
||||
ProcessBuilder tool = ProcessTools.createJavaProcessBuilder(
|
||||
"-XaddExports:jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED",
|
||||
"-XaddExports:jdk.hotspot.agent/sun.jvm.hotspot.memory=ALL-UNNAMED",
|
||||
"-XaddExports:jdk.hotspot.agent/sun.jvm.hotspot.runtime=ALL-UNNAMED",
|
||||
"-XaddExports:jdk.hotspot.agent/sun.jvm.hotspot.tools=ALL-UNNAMED",
|
||||
"--add-modules=jdk.hotspot.agent",
|
||||
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED",
|
||||
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.memory=ALL-UNNAMED",
|
||||
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.runtime=ALL-UNNAMED",
|
||||
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.tools=ALL-UNNAMED",
|
||||
"SASymbolTableTestAgent",
|
||||
Long.toString(pid));
|
||||
OutputAnalyzer output = ProcessTools.executeProcess(tool);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -44,7 +44,7 @@ public class RangeCheck {
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
true,
|
||||
"-Xmx32m",
|
||||
"-XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED",
|
||||
"--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",
|
||||
"-XX:-TransmitErrorReport",
|
||||
"-XX:-CreateCoredumpOnCrash",
|
||||
"-XX:-InlineUnsafeOps", // The compiler intrinsics doesn't have the assert
|
||||
|
@ -98,7 +98,7 @@ public class GetSysPkgTest {
|
||||
ClassFileInstaller.writeClassToDisk("GetSysPkg_package/GetSysClass", klassbuf);
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xbootclasspath/a:bl_dir",
|
||||
"-XaddExports:java.base/jdk.internal.loader=ALL-UNNAMED", "-cp", "." + File.pathSeparator +
|
||||
"--add-exports=java.base/jdk.internal.loader=ALL-UNNAMED", "-cp", "." + File.pathSeparator +
|
||||
System.getProperty("test.classes"), "GetSysPkgTest", "do_tests");
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldHaveExitValue(0);
|
||||
|
75
hotspot/test/runtime/modules/IgnoreModulePropertiesTest.java
Normal file
75
hotspot/test/runtime/modules/IgnoreModulePropertiesTest.java
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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 8136930
|
||||
* @summary Test that the VM ignores explicitly specified module internal properties.
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @library /testlibrary
|
||||
*/
|
||||
|
||||
import jdk.test.lib.*;
|
||||
|
||||
// Test that the VM ignores module related properties such as "jdk.module.addmods"
|
||||
// and jdk.module.addreads.0" that can only be set using module options.
|
||||
public class IgnoreModulePropertiesTest {
|
||||
|
||||
// Test that the specified property and its value are ignored. If the VM accepted
|
||||
// the property and value then an exception would be thrown because the value is
|
||||
// bogus for that property. But, since the property is ignored no exception is
|
||||
// thrown.
|
||||
public static void testProperty(String prop, String value) throws Exception {
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-D" + prop + "=" + value, "-version");
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldContain("java version ");
|
||||
output.shouldHaveExitValue(0);
|
||||
|
||||
// Ensure that the property and its value aren't available.
|
||||
if (System.getProperty(prop) != null) {
|
||||
throw new RuntimeException(
|
||||
"Unexpected non-null value for property " + prop);
|
||||
}
|
||||
}
|
||||
|
||||
// For options of the form "option=value", check that an exception gets thrown for
|
||||
// the illegal value and then check that its corresponding property is handled
|
||||
// correctly.
|
||||
public static void testOption(String option, String value,
|
||||
String prop, String result) throws Exception {
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
option + "=" + value, "-version");
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldContain(result);
|
||||
testProperty(prop, value);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
testOption("--add-modules", "java.sqlx", "jdk.module.addmods", "java.lang.module.ResolutionException");
|
||||
testOption("--limit-modules", "java.sqlx", "jdk.module.limitmods", "java.lang.module.ResolutionException");
|
||||
testOption("--add-reads", "xyzz=yyzd", "jdk.module.addreads.0", "java.lang.RuntimeException");
|
||||
testOption("--add-exports", "java.base/xyzz=yyzd", "jdk.module.addexports.0", "java.lang.RuntimeException");
|
||||
testOption("--patch-module", "=d", "jdk.module.patch.0", "IllegalArgumentException");
|
||||
}
|
||||
}
|
54
hotspot/test/runtime/modules/ModuleOptionsTest.java
Normal file
54
hotspot/test/runtime/modules/ModuleOptionsTest.java
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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 8136930
|
||||
* @summary Test that the VM only recognizes the last specified --add-modules
|
||||
* and --list-modules options
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @library /testlibrary
|
||||
*/
|
||||
|
||||
import jdk.test.lib.*;
|
||||
|
||||
// Test that the VM behaves correctly when processing module related options.
|
||||
public class ModuleOptionsTest {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
// Test that last --add-modules is the only one recognized. No exception
|
||||
// should be thrown.
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
"--add-modules=i_dont_exist", "--add-modules=java.base", "-version");
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldHaveExitValue(0);
|
||||
|
||||
// Test that last --limit-modules is the only one recognized. No exception
|
||||
// should be thrown.
|
||||
pb = ProcessTools.createJavaProcessBuilder(
|
||||
"--limit-modules=i_dont_exist", "--limit-modules=java.base", "-version");
|
||||
output = new OutputAnalyzer(pb.start());
|
||||
output.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
60
hotspot/test/runtime/modules/ModuleOptionsWarn.java
Normal file
60
hotspot/test/runtime/modules/ModuleOptionsWarn.java
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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 8162415
|
||||
* @summary Test warnings for ignored properties.
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @library /testlibrary
|
||||
*/
|
||||
|
||||
import jdk.test.lib.*;
|
||||
|
||||
// Test that the VM behaves correctly when processing command line module system properties.
|
||||
public class ModuleOptionsWarn {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
// Test that a warning is issued for module related properties that get ignored.
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-XX:+PrintWarnings", "-Djdk.module.ignored", "-version");
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldContain("Ignoring system property option");
|
||||
output.shouldHaveExitValue(0);
|
||||
|
||||
// Test that a warning can be suppressed for module related properties that get ignored.
|
||||
pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-Djdk.module.ignored", "-XX:-PrintWarnings", "-version");
|
||||
output = new OutputAnalyzer(pb.start());
|
||||
output.shouldNotContain("Ignoring system property option");
|
||||
output.shouldHaveExitValue(0);
|
||||
|
||||
// Test that a warning is not issued for properties of the form "jdk.module.main"
|
||||
pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-XX:+PrintWarnings", "-Djdk.module.main.ignored", "-version");
|
||||
output = new OutputAnalyzer(pb.start());
|
||||
output.shouldNotContain("Ignoring system property option");
|
||||
output.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
@ -62,8 +62,8 @@ public class ExportModuleStressTest {
|
||||
compiled = CompilerUtils.compile(
|
||||
SRC_DIR.resolve("jdk.translet"),
|
||||
MODS_DIR.resolve("jdk.translet"),
|
||||
"-XaddExports:jdk.test/test=jdk.translet",
|
||||
"-mp", MODS_DIR.toString());
|
||||
"--add-exports=jdk.test/test=jdk.translet",
|
||||
"-p", MODS_DIR.toString());
|
||||
if (!compiled) {
|
||||
throw new RuntimeException("Test failed to compile module jdk.translet");
|
||||
}
|
||||
@ -71,7 +71,7 @@ public class ExportModuleStressTest {
|
||||
// Sanity check that the test, jdk.test/test/Main.java
|
||||
// runs without error.
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-mp", MODS_DIR.toString(),
|
||||
"-p", MODS_DIR.toString(),
|
||||
"-m", "jdk.test/test.Main");
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldContain("failed: 0")
|
||||
|
@ -62,8 +62,8 @@ public class ModuleStressGC {
|
||||
compiled = CompilerUtils.compile(
|
||||
SRC_DIR.resolve("jdk.translet"),
|
||||
MODS_DIR.resolve("jdk.translet"),
|
||||
"-XaddExports:jdk.test/test=jdk.translet",
|
||||
"-mp", MODS_DIR.toString());
|
||||
"--add-exports=jdk.test/test=jdk.translet",
|
||||
"-p", MODS_DIR.toString());
|
||||
if (!compiled) {
|
||||
throw new RuntimeException("Test failed to compile module jdk.translet");
|
||||
}
|
||||
@ -74,7 +74,7 @@ public class ModuleStressGC {
|
||||
// GC safepoints.
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-Xlog:modules=trace",
|
||||
"-mp", MODS_DIR.toString(),
|
||||
"-p", MODS_DIR.toString(),
|
||||
"-m", "jdk.test/test.MainGC");
|
||||
OutputAnalyzer oa = new OutputAnalyzer(pb.start());
|
||||
oa.shouldContain("package test defined in module jdk.test, exports list being walked")
|
||||
|
@ -23,17 +23,17 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Make sure -Xpatch works with multiple directories.
|
||||
* @summary Make sure --patch-module works with multiple directories.
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @library /testlibrary
|
||||
* @compile Xpatch2DirsMain.java
|
||||
* @run main Xpatch2Dirs
|
||||
* @compile PatchModule2DirsMain.java
|
||||
* @run main PatchModule2Dirs
|
||||
*/
|
||||
|
||||
import jdk.test.lib.*;
|
||||
import java.io.File;
|
||||
|
||||
public class Xpatch2Dirs {
|
||||
public class PatchModule2Dirs {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String source1 = "package javax.naming.spi; " +
|
||||
@ -58,9 +58,9 @@ public class Xpatch2Dirs {
|
||||
"mods2/java.desktop");
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-Xpatch:java.naming=mods/java.naming",
|
||||
"-Xpatch:java.desktop=mods2/java.desktop",
|
||||
"Xpatch2DirsMain", "javax.naming.spi.NamingManager", "java.beans.Encoder");
|
||||
"--patch-module=java.naming=mods/java.naming",
|
||||
"--patch-module=java.desktop=mods2/java.desktop",
|
||||
"PatchModule2DirsMain", "javax.naming.spi.NamingManager", "java.beans.Encoder");
|
||||
|
||||
OutputAnalyzer oa = new OutputAnalyzer(pb.start());
|
||||
oa.shouldContain("I pass one!");
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -21,9 +21,9 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// This loads the class affected by the -Xpatch option. For the test to pass
|
||||
// it must load both classes from the -Xpatch directory, not the jimage file.
|
||||
public class Xpatch2DirsMain {
|
||||
// This loads the class affected by the --patch-module option. For the test to pass
|
||||
// it must load both classes from the --patch-module directory, not the jimage file.
|
||||
public class PatchModule2DirsMain {
|
||||
public static void main(String[] args) throws Exception {
|
||||
Class.forName(args[0]);
|
||||
Class.forName(args[1]);
|
@ -25,22 +25,22 @@
|
||||
* @test
|
||||
* @library /testlibrary
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @run main XpatchCDS
|
||||
* @run main PatchModuleCDS
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import jdk.test.lib.*;
|
||||
|
||||
public class XpatchCDS {
|
||||
public class PatchModuleCDS {
|
||||
|
||||
public static void main(String args[]) throws Throwable {
|
||||
System.out.println("Test that -Xpatch and -Xshare:dump are incompatibable");
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.naming=mods/java.naming", "-Xshare:dump");
|
||||
System.out.println("Test that --patch-module and -Xshare:dump are incompatibable");
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("--patch-module=java.naming=mods/java.naming", "-Xshare:dump");
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldContain("Cannot use the following option when dumping the shared archive: -Xpatch");
|
||||
output.shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
|
||||
|
||||
System.out.println("Test that -Xpatch and -Xshare:on are incompatibable");
|
||||
String filename = "Xpatch.jsa";
|
||||
System.out.println("Test that --patch-module and -Xshare:on are incompatibable");
|
||||
String filename = "patch_module.jsa";
|
||||
pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:SharedArchiveFile=" + filename,
|
||||
@ -52,10 +52,10 @@ public class XpatchCDS {
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:SharedArchiveFile=" + filename,
|
||||
"-Xshare:on",
|
||||
"-Xpatch:java.naming=mods/java.naming",
|
||||
"--patch-module=java.naming=mods/java.naming",
|
||||
"-version");
|
||||
output = new OutputAnalyzer(pb.start());
|
||||
output.shouldContain("The shared archive file cannot be used with -Xpatch");
|
||||
output.shouldContain("The shared archive file cannot be used with --patch-module");
|
||||
|
||||
output.shouldHaveExitValue(1);
|
||||
}
|
@ -23,23 +23,23 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary VM exit initialization results if java.base is specificed more than once to Xpatch.
|
||||
* @summary VM exit initialization results if java.base is specificed more than once to --patch-module.
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @library /testlibrary
|
||||
*/
|
||||
|
||||
import jdk.test.lib.*;
|
||||
|
||||
public class XpatchDupJavaBase {
|
||||
public class PatchModuleDupJavaBase {
|
||||
// The VM should exit initialization if java.base is specified
|
||||
// more than once to -Xpatch.
|
||||
// more than once to --patch-module.
|
||||
public static void main(String args[]) throws Exception {
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-Xpatch:java.base=javabase_dir",
|
||||
"-Xpatch:java.base=javabase_dir",
|
||||
"--patch-module=java.base=javabase_dir",
|
||||
"--patch-module=java.base=javabase_dir",
|
||||
"-version");
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldContain("Cannot specify java.base more than once to -Xpatch");
|
||||
output.shouldContain("Cannot specify java.base more than once to --patch-module");
|
||||
output.shouldHaveExitValue(1);
|
||||
}
|
||||
}
|
@ -23,26 +23,25 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Module system initialization exception results if a module is specificed twice to Xpatch.
|
||||
* @summary Module system initialization exception results if a module is specificed twice to --patch-module.
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @library /testlibrary
|
||||
*/
|
||||
|
||||
import jdk.test.lib.*;
|
||||
|
||||
public class XpatchDupModule {
|
||||
public class PatchModuleDupModule {
|
||||
|
||||
// The module system initialization should generate an ExceptionInInitializerError
|
||||
// if -Xpatch is specified with the same module more than once.
|
||||
// if --patch-module is specified with the same module more than once.
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-Xpatch:module1=module1_dir",
|
||||
"-Xpatch:module1=module1_dir",
|
||||
"--patch-module=module1=module1_dir",
|
||||
"--patch-module=module1=module1_dir",
|
||||
"-version");
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldContain("java.lang.ExceptionInInitializerError");
|
||||
output.shouldHaveExitValue(1);
|
||||
}
|
||||
}
|
||||
|
@ -24,16 +24,16 @@
|
||||
/*
|
||||
* @test
|
||||
* @bug 8130399
|
||||
* @summary Make sure -Xpatch works for java.base.
|
||||
* @summary Make sure --patch-module works for java.base.
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @library /testlibrary
|
||||
* @compile XpatchMain.java
|
||||
* @run main XpatchJavaBase
|
||||
* @compile PatchModuleMain.java
|
||||
* @run main PatchModuleJavaBase
|
||||
*/
|
||||
|
||||
import jdk.test.lib.*;
|
||||
|
||||
public class XpatchJavaBase {
|
||||
public class PatchModuleJavaBase {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String source = "package java.lang; " +
|
||||
@ -47,8 +47,8 @@ public class XpatchJavaBase {
|
||||
InMemoryJavaCompiler.compile("java.lang.NewClass", source, "-Xmodule:java.base"),
|
||||
"mods/java.base");
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.base=mods/java.base",
|
||||
"XpatchMain", "java.lang.NewClass");
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("--patch-module=java.base=mods/java.base",
|
||||
"PatchModuleMain", "java.lang.NewClass");
|
||||
|
||||
new OutputAnalyzer(pb.start())
|
||||
.shouldContain("I pass!")
|
@ -21,9 +21,9 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// This loads the class affected by the -Xpatch option. For the test to pass
|
||||
// it must load the class from the -Xpatch directory, not the jimage file.
|
||||
public class XpatchMain {
|
||||
// This loads the class affected by the --patch-module option. For the test to pass
|
||||
// it must load the class from the --patch-module directory, not the jimage file.
|
||||
public class PatchModuleMain {
|
||||
public static void main(String[] args) throws Exception {
|
||||
Class.forName(args[0]);
|
||||
}
|
@ -24,16 +24,16 @@
|
||||
/*
|
||||
* @test
|
||||
* @bug 8130399
|
||||
* @summary Make sure -Xpatch works for modules besides java.base.
|
||||
* @summary Make sure --patch-module works for modules besides java.base.
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @library /testlibrary
|
||||
* @compile XpatchMain.java
|
||||
* @run main XpatchTest
|
||||
* @compile PatchModuleMain.java
|
||||
* @run main PatchModuleTest
|
||||
*/
|
||||
|
||||
import jdk.test.lib.*;
|
||||
|
||||
public class XpatchTest {
|
||||
public class PatchModuleTest {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String source = "package javax.naming.spi; " +
|
||||
@ -47,8 +47,8 @@ public class XpatchTest {
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
|
||||
"mods/java.naming");
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.naming=mods/java.naming",
|
||||
"XpatchMain", "javax.naming.spi.NamingManager");
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("--patch-module=java.naming=mods/java.naming",
|
||||
"PatchModuleMain", "javax.naming.spi.NamingManager");
|
||||
|
||||
new OutputAnalyzer(pb.start())
|
||||
.shouldContain("I pass!")
|
@ -23,18 +23,18 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Make sure -Xpatch works when a jar file is specified for a module
|
||||
* @summary Make sure --patch-module works when a jar file is specified for a module
|
||||
* @library /testlibrary
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* jdk.jartool/sun.tools.jar
|
||||
* @build BasicJarBuilder
|
||||
* @compile XpatchMain.java
|
||||
* @run main XpatchTestJar
|
||||
* @compile PatchModuleMain.java
|
||||
* @run main PatchModuleTestJar
|
||||
*/
|
||||
|
||||
import jdk.test.lib.*;
|
||||
|
||||
public class XpatchTestJar {
|
||||
public class PatchModuleTestJar {
|
||||
private static String moduleJar;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
@ -72,9 +72,9 @@ public class XpatchTestJar {
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
|
||||
System.getProperty("test.classes"));
|
||||
|
||||
// Supply -Xpatch with the name of the jar file for the module java.naming.
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.naming=" + moduleJar,
|
||||
"XpatchMain", "javax.naming.spi.NamingManager");
|
||||
// Supply --patch-module with the name of the jar file for the module java.naming.
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("--patch-module=java.naming=" + moduleJar,
|
||||
"PatchModuleMain", "javax.naming.spi.NamingManager");
|
||||
|
||||
new OutputAnalyzer(pb.start())
|
||||
.shouldContain("I pass!")
|
@ -23,20 +23,20 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Make sure -Xpatch works when a jar file and a directory is specified for a module
|
||||
* @summary Make sure --patch-module works when a jar file and a directory is specified for a module
|
||||
* @library /testlibrary
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* jdk.jartool/sun.tools.jar
|
||||
* @build BasicJarBuilder
|
||||
* @compile Xpatch2DirsMain.java
|
||||
* @run main XpatchTestJarDir
|
||||
* @compile PatchModule2DirsMain.java
|
||||
* @run main PatchModuleTestJarDir
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import jdk.test.lib.*;
|
||||
|
||||
public class XpatchTestJarDir {
|
||||
public class PatchModuleTestJarDir {
|
||||
private static String moduleJar;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
@ -88,12 +88,12 @@ public class XpatchTestJarDir {
|
||||
(System.getProperty("test.classes") + "/mods/java.naming"));
|
||||
|
||||
|
||||
// Supply -Xpatch with the name of the jar file for the module java.naming.
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.naming=" +
|
||||
// Supply --patch-module with the name of the jar file for the module java.naming.
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("--patch-module=java.naming=" +
|
||||
moduleJar +
|
||||
File.pathSeparator +
|
||||
System.getProperty("test.classes") + "/mods/java.naming",
|
||||
"Xpatch2DirsMain",
|
||||
"PatchModule2DirsMain",
|
||||
"javax.naming.spi.NamingManager1",
|
||||
"javax.naming.spi.NamingManager2");
|
||||
|
@ -25,17 +25,17 @@
|
||||
* @test
|
||||
* @bug 8069469
|
||||
* @summary Make sure -Xlog:classload=info works properly with "modules" jimage,
|
||||
-Xpatch, and with -Xbootclasspath/a
|
||||
--patch-module, and with -Xbootclasspath/a
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @library /testlibrary
|
||||
* @compile XpatchMain.java
|
||||
* @run main XpatchTraceCL
|
||||
* @compile PatchModuleMain.java
|
||||
* @run main PatchModuleTraceCL
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import jdk.test.lib.*;
|
||||
|
||||
public class XpatchTraceCL {
|
||||
public class PatchModuleTraceCL {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String source = "package javax.naming.spi; " +
|
||||
@ -45,39 +45,39 @@ public class XpatchTraceCL {
|
||||
" } " +
|
||||
"}";
|
||||
|
||||
// Test -Xlog:classload=info output for -Xpatch
|
||||
// Test -Xlog:classload=info output for --patch-module
|
||||
ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
|
||||
InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
|
||||
"mods/java.naming");
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:java.naming=mods/java.naming",
|
||||
"-Xlog:class+load=info", "XpatchMain", "javax.naming.spi.NamingManager");
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("--patch-module=java.naming=mods/java.naming",
|
||||
"-Xlog:class+load=info", "PatchModuleMain", "javax.naming.spi.NamingManager");
|
||||
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
// "modules" jimage case.
|
||||
output.shouldContain("[class,load] java.lang.Thread source: jrt:/java.base");
|
||||
// -Xpatch case.
|
||||
// --patch-module case.
|
||||
output.shouldContain("[class,load] javax.naming.spi.NamingManager source: mods/java.naming");
|
||||
// -cp case.
|
||||
output.shouldContain("[class,load] XpatchMain source: file");
|
||||
output.shouldContain("[class,load] PatchModuleMain source: file");
|
||||
|
||||
// Test -Xlog:classload=info output for -Xbootclasspath/a
|
||||
source = "package XpatchTraceCL_pkg; " +
|
||||
source = "package PatchModuleTraceCL_pkg; " +
|
||||
"public class ItIsI { " +
|
||||
" static { " +
|
||||
" System.out.println(\"I also pass!\"); " +
|
||||
" } " +
|
||||
"}";
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("XpatchTraceCL_pkg/ItIsI",
|
||||
InMemoryJavaCompiler.compile("XpatchTraceCL_pkg.ItIsI", source),
|
||||
ClassFileInstaller.writeClassToDisk("PatchModuleTraceCL_pkg/ItIsI",
|
||||
InMemoryJavaCompiler.compile("PatchModuleTraceCL_pkg.ItIsI", source),
|
||||
"xbcp");
|
||||
|
||||
pb = ProcessTools.createJavaProcessBuilder("-Xbootclasspath/a:xbcp",
|
||||
"-Xlog:class+load=info", "XpatchMain", "XpatchTraceCL_pkg.ItIsI");
|
||||
"-Xlog:class+load=info", "PatchModuleMain", "PatchModuleTraceCL_pkg.ItIsI");
|
||||
output = new OutputAnalyzer(pb.start());
|
||||
// -Xbootclasspath/a case.
|
||||
output.shouldContain("[class,load] XpatchTraceCL_pkg.ItIsI source: xbcp");
|
||||
output.shouldContain("[class,load] PatchModuleTraceCL_pkg.ItIsI source: xbcp");
|
||||
output.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
@ -23,13 +23,13 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Ensure that a newly introduced java.base package placed within the -Xpatch directory
|
||||
* is considered part of the boot loader's visibility boundary
|
||||
* @summary Ensure that a newly introduced java.base package placed within the --patch-module
|
||||
* directory is considered part of the boot loader's visibility boundary
|
||||
* @requires !(os.family == "windows")
|
||||
* @library /testlibrary
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* java.management
|
||||
* @run main/othervm XpatchVisibility
|
||||
* @run main/othervm PatchModuleVisibility
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
@ -38,7 +38,7 @@ import java.nio.file.Paths;
|
||||
|
||||
import jdk.test.lib.*;
|
||||
|
||||
public class XpatchVisibility {
|
||||
public class PatchModuleVisibility {
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
|
||||
@ -55,19 +55,19 @@ public class XpatchVisibility {
|
||||
"public class Vis2_A {" +
|
||||
" public static void main(String args[]) throws Exception {" +
|
||||
// Try loading a class within a newly introduced java.base
|
||||
// package. Make sure the class can be found via -Xpatch.
|
||||
// package. Make sure the class can be found via --patch-module.
|
||||
" try {" +
|
||||
" p2.Vis2_B b = new p2.Vis2_B();" +
|
||||
" if (b.getClass().getClassLoader() != null) {" +
|
||||
" throw new RuntimeException(\"XpatchVisibility FAILED - class B " +
|
||||
" throw new RuntimeException(\"PatchModuleVisibility FAILED - class B " +
|
||||
"should be loaded by boot class loader\\n\");" +
|
||||
" }" +
|
||||
" b.m();" +
|
||||
" } catch (Throwable e) {" +
|
||||
" throw new RuntimeException(\"XpatchVisibility FAILED - test " +
|
||||
" throw new RuntimeException(\"PatchModuleVisibility FAILED - test " +
|
||||
"should not throw an error or exception\\n\");" +
|
||||
" }" +
|
||||
" System.out.println(\"XpatchVisibility PASSED\\n\");" +
|
||||
" System.out.println(\"PatchModuleVisibility PASSED\\n\");" +
|
||||
" }" +
|
||||
"}";
|
||||
|
||||
@ -83,8 +83,8 @@ public class XpatchVisibility {
|
||||
"p2" + File.separator + "Vis2_B.class"));
|
||||
|
||||
new OutputAnalyzer(ProcessTools.createJavaProcessBuilder(
|
||||
"-Xpatch:java.base=mods2/java.base",
|
||||
"-XaddExports:java.base/p2=ALL-UNNAMED",
|
||||
"--patch-module=java.base=mods2/java.base",
|
||||
"--add-exports=java.base/p2=ALL-UNNAMED",
|
||||
"Vis2_A")
|
||||
.start()).shouldHaveExitValue(0);
|
||||
}
|
@ -50,7 +50,7 @@ public class XbootcpNoVisibility {
|
||||
// Try loading a class within a named package in a module which has been defined
|
||||
// to the boot loader. In this situation, the class should only be attempted
|
||||
// to be loaded from the boot loader's module path which consists of:
|
||||
// [-Xpatch]; exploded build | "modules" jimage
|
||||
// [--patch-module]; exploded build | "modules" jimage
|
||||
//
|
||||
// Since the class is located on the boot loader's append path via
|
||||
// -Xbootclasspath/a specification, it should not be found.
|
||||
|
@ -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
|
||||
@ -27,7 +27,7 @@ import java.lang.module.ModuleDescriptor;
|
||||
|
||||
/**
|
||||
* A helper class intended to be injected into java.lang.reflect using the
|
||||
* java -Xpatch option. The helper class provides access to package private
|
||||
* java --patch-module option. The helper class provides access to package private
|
||||
* methods in java.lang.reflect.Module.
|
||||
*/
|
||||
|
||||
|
@ -113,9 +113,10 @@ public class TestInstanceKlassSize {
|
||||
};
|
||||
String[] toolArgs = {
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XaddExports:jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED",
|
||||
"-XaddExports:jdk.hotspot.agent/sun.jvm.hotspot.utilities=ALL-UNNAMED",
|
||||
"-XaddExports:jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED",
|
||||
"--add-modules=jdk.hotspot.agent",
|
||||
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED",
|
||||
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.utilities=ALL-UNNAMED",
|
||||
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED",
|
||||
"TestInstanceKlassSize",
|
||||
Long.toString(app.getPid())
|
||||
};
|
||||
|
@ -107,9 +107,10 @@ public class TestInstanceKlassSizeForInterface {
|
||||
// Grab the pid from the current java process and pass it
|
||||
String[] toolArgs = {
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XaddExports:jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED",
|
||||
"-XaddExports:jdk.hotspot.agent/sun.jvm.hotspot.utilities=ALL-UNNAMED",
|
||||
"-XaddExports:jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED",
|
||||
"--add-modules=jdk.hotspot.agent",
|
||||
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED",
|
||||
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.utilities=ALL-UNNAMED",
|
||||
"--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED",
|
||||
"TestInstanceKlassSizeForInterface",
|
||||
Long.toString(ProcessTools.getProcessId())
|
||||
};
|
||||
|
@ -87,7 +87,7 @@ public class JMapHProfLargeHeapTest {
|
||||
String expectedFormat) throws Exception, IOException,
|
||||
InterruptedException, FileNotFoundException {
|
||||
ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(
|
||||
"-XaddExports:java.management/sun.management=ALL-UNNAMED", vmArgs, "JMapHProfLargeHeapProc", String.valueOf(heapSize));
|
||||
"--add-exports=java.management/sun.management=ALL-UNNAMED", vmArgs, "JMapHProfLargeHeapProc", String.valueOf(heapSize));
|
||||
procBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
|
||||
Process largeHeapProc = procBuilder.start();
|
||||
|
||||
|
@ -58,10 +58,10 @@ cleantmp:
|
||||
|
||||
ctw.jar: filelist wb.jar
|
||||
@mkdir -p $(OUTPUT_DIR)
|
||||
$(JAVAC) -XaddExports:java.base/jdk.internal.jimage=ALL-UNNAMED \
|
||||
-XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED \
|
||||
-XaddExports:java.base/jdk.internal.reflect=ALL-UNNAMED \
|
||||
-sourcepath $(SRC_DIR) -d $(OUTPUT_DIR) -cp wb.jar @filelist
|
||||
$(JAVAC) --add-exports java.base/jdk.internal.jimage=ALL-UNNAMED \
|
||||
--add-exports java.base/jdk.internal.misc=ALL-UNNAMED \
|
||||
--add-exports java.base/jdk.internal.reflect=ALL-UNNAMED \
|
||||
-sourcepath $(SRC_DIR) -d $(OUTPUT_DIR) -cp wb.jar @filelist
|
||||
$(JAR) --create --file=$@ --main-class $(MAIN_CLASS) -C $(OUTPUT_DIR) .
|
||||
|
||||
wb.jar: wb_filelist
|
||||
|
@ -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
|
||||
@ -95,10 +95,10 @@ manifest:
|
||||
@echo 'Main-Class: jdk.test.lib.jittester.Automatic' >> $(MANIFEST)
|
||||
|
||||
compile_testlib: INIT
|
||||
$(JAVAC) -XDignore.symbol.file -XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED -XaddExports:java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED -Xlint $(TESTLIBRARY_SRC_FILES) -d $(CLASSES_DIR)
|
||||
$(JAVAC) -XDignore.symbol.file --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED --add-exports=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED -Xlint $(TESTLIBRARY_SRC_FILES) -d $(CLASSES_DIR)
|
||||
|
||||
COMPILE: INIT filelist compile_testlib
|
||||
$(JAVAC) -cp $(CLASSES_DIR) -XDignore.symbol.file -XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED -XaddExports:java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED -Xlint -sourcepath $(SRC_DIR) -d $(CLASSES_DIR) @filelist
|
||||
$(JAVAC) -cp $(CLASSES_DIR) -XDignore.symbol.file --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED --add-exports=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED -Xlint -sourcepath $(SRC_DIR) -d $(CLASSES_DIR) @filelist
|
||||
|
||||
filelist: $(SRC_FILES)
|
||||
@rm -f $@
|
||||
@ -109,7 +109,7 @@ INIT: $(DIST_DIR)
|
||||
$(shell if [ ! -d $(CLASSES_DIR) ]; then mkdir -p $(CLASSES_DIR); fi)
|
||||
|
||||
install: clean_testbase testgroup testroot copytestlibrary JAR cleantmp
|
||||
$(JAVA) -XaddExports:java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED -ea -jar $(DIST_JAR) $(APPLICATION_ARGS)
|
||||
$(JAVA) --add-exports=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED -ea -jar $(DIST_JAR) $(APPLICATION_ARGS)
|
||||
|
||||
clean_testbase:
|
||||
@rm -rf $(TESTBASE_DIR)
|
||||
|
@ -373,3 +373,4 @@ bdc3c0b737efbf899709eb3121ce760dcfb51151 jdk-9+127
|
||||
8a7681a9d70640ac7fbf05c28f53c1d51d8d00a1 jdk-9+128
|
||||
74241304e87b0d463391a8ecab40979b5af86dc2 jdk-9+129
|
||||
e66cdc2de6b02443911d386fc9217b0d824d0686 jdk-9+130
|
||||
874082a9b565a7092a40bfa934a6e3e3c3455a60 jdk-9+131
|
||||
|
@ -37,5 +37,3 @@ parser.quantifier.2=Invalid quantifier. Invalid quantity or a '}' is missing.
|
||||
parser.quantifier.3=Invalid quantifier. A digit or '}' is expected.
|
||||
parser.quantifier.4=Invalid quantifier. A min quantity must be <= a max quantity.
|
||||
parser.quantifier.5=Invalid quantifier. A quantity value overflow.
|
||||
null
|
||||
null
|
||||
|
@ -23,4 +23,7 @@ modules=java.xml
|
||||
groups=TEST.groups
|
||||
|
||||
# Minimum jtreg version
|
||||
requiredVersion=4.2 b02
|
||||
requiredVersion=4.2 b03
|
||||
|
||||
# Use new module options
|
||||
useNewOptions=true
|
||||
|
@ -37,7 +37,7 @@ public class BasePolicy implements ITestListener {
|
||||
try {
|
||||
JAXPPolicyManager.teardownPolicyManager();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to teardonw the policy manager", e);
|
||||
throw new RuntimeException("Failed to teardown the policy manager", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,10 +28,8 @@ import static jaxp.library.JAXPTestUtilities.getSystemProperty;
|
||||
import static jaxp.library.JAXPTestUtilities.setSystemProperty;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.net.SocketTimeoutException;
|
||||
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.URIResolver;
|
||||
@ -52,7 +50,7 @@ import org.xml.sax.SAXParseException;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8158084 8162438 8162442
|
||||
* @bug 8158084 8162438 8162442 8163535
|
||||
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
|
||||
* @run testng/othervm -DrunSecMngr=true catalog.CatalogSupport2
|
||||
* @run testng/othervm catalog.CatalogSupport2
|
||||
@ -97,7 +95,7 @@ public class CatalogSupport2 extends CatalogSupportBase {
|
||||
/*
|
||||
Verifies the Catalog support on SAXParser.
|
||||
*/
|
||||
@Test(dataProvider = "data_SAXC", expectedExceptions = FileNotFoundException.class)
|
||||
@Test(dataProvider = "data_SAXC", expectedExceptions = IOException.class)
|
||||
public void testSAXC(boolean setUseCatalog, boolean useCatalog, String catalog, String
|
||||
xml, MyHandler handler, String expected) throws Exception {
|
||||
testSAX(setUseCatalog, useCatalog, catalog, xml, handler, expected);
|
||||
@ -106,7 +104,7 @@ public class CatalogSupport2 extends CatalogSupportBase {
|
||||
/*
|
||||
Verifies the Catalog support on XMLReader.
|
||||
*/
|
||||
@Test(dataProvider = "data_SAXC", expectedExceptions = FileNotFoundException.class)
|
||||
@Test(dataProvider = "data_SAXC", expectedExceptions = IOException.class)
|
||||
public void testXMLReaderC(boolean setUseCatalog, boolean useCatalog, String catalog,
|
||||
String xml, MyHandler handler, String expected) throws Exception {
|
||||
testXMLReader(setUseCatalog, useCatalog, catalog, xml, handler, expected);
|
||||
@ -124,7 +122,7 @@ public class CatalogSupport2 extends CatalogSupportBase {
|
||||
/*
|
||||
Verifies the Catalog support on DOM parser.
|
||||
*/
|
||||
@Test(dataProvider = "data_DOMC", expectedExceptions = {FileNotFoundException.class, SocketTimeoutException.class})
|
||||
@Test(dataProvider = "data_DOMC", expectedExceptions = IOException.class)
|
||||
public void testDOMC(boolean setUseCatalog, boolean useCatalog, String catalog,
|
||||
String xml, MyHandler handler, String expected) throws Exception {
|
||||
testDOM(setUseCatalog, useCatalog, catalog, xml, handler, expected);
|
||||
@ -141,7 +139,7 @@ public class CatalogSupport2 extends CatalogSupportBase {
|
||||
testValidation(setUseCatalog, useCatalog, catalog, xsd, resolver) ;
|
||||
}
|
||||
|
||||
@Test(dataProvider = "data_ValidatorC", expectedExceptions = {SAXException.class, FileNotFoundException.class})
|
||||
@Test(dataProvider = "data_ValidatorC", expectedExceptions = {SAXException.class, IOException.class})
|
||||
public void testValidatorC(boolean setUseCatalog1, boolean setUseCatalog2, boolean useCatalog,
|
||||
Source source, LSResourceResolver resolver1, LSResourceResolver resolver2,
|
||||
String catalog1, String catalog2)
|
||||
|
@ -27,10 +27,8 @@ import static jaxp.library.JAXPTestUtilities.getSystemProperty;
|
||||
import static jaxp.library.JAXPTestUtilities.setSystemProperty;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.net.SocketTimeoutException;
|
||||
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.URIResolver;
|
||||
@ -51,7 +49,7 @@ import org.xml.sax.SAXParseException;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8158084 8162438 8162442
|
||||
* @bug 8158084 8162438 8162442 8163535
|
||||
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
|
||||
* @run testng/othervm -DrunSecMngr=true catalog.CatalogSupport3
|
||||
* @run testng/othervm catalog.CatalogSupport3
|
||||
@ -93,7 +91,7 @@ public class CatalogSupport3 extends CatalogSupportBase {
|
||||
/*
|
||||
Verifies the Catalog support on SAXParser.
|
||||
*/
|
||||
@Test(dataProvider = "data_SAXC", expectedExceptions = FileNotFoundException.class)
|
||||
@Test(dataProvider = "data_SAXC", expectedExceptions = IOException.class)
|
||||
public void testSAXC(boolean setUseCatalog, boolean useCatalog, String catalog,
|
||||
String xml, MyHandler handler, String expected) throws Exception {
|
||||
testSAX(setUseCatalog, useCatalog, catalog, xml, handler, expected);
|
||||
@ -102,7 +100,7 @@ public class CatalogSupport3 extends CatalogSupportBase {
|
||||
/*
|
||||
Verifies the Catalog support on XMLReader.
|
||||
*/
|
||||
@Test(dataProvider = "data_SAXC", expectedExceptions = FileNotFoundException.class)
|
||||
@Test(dataProvider = "data_SAXC", expectedExceptions = IOException.class)
|
||||
public void testXMLReaderC(boolean setUseCatalog, boolean useCatalog, String catalog,
|
||||
String xml, MyHandler handler, String expected) throws Exception {
|
||||
testXMLReader(setUseCatalog, useCatalog, catalog, xml, handler, expected);
|
||||
@ -120,7 +118,7 @@ public class CatalogSupport3 extends CatalogSupportBase {
|
||||
/*
|
||||
Verifies the Catalog support on DOM parser.
|
||||
*/
|
||||
@Test(dataProvider = "data_DOMC", expectedExceptions = {FileNotFoundException.class, SocketTimeoutException.class})
|
||||
@Test(dataProvider = "data_DOMC", expectedExceptions = IOException.class)
|
||||
public void testDOMC(boolean setUseCatalog, boolean useCatalog, String catalog,
|
||||
String xml, MyHandler handler, String expected) throws Exception {
|
||||
testDOM(setUseCatalog, useCatalog, catalog, xml, handler, expected);
|
||||
@ -141,7 +139,7 @@ public class CatalogSupport3 extends CatalogSupportBase {
|
||||
@bug 8158084 8162438 these tests also verifies the fix for 8162438
|
||||
Verifies the Catalog support on the Schema Validator.
|
||||
*/
|
||||
@Test(dataProvider = "data_ValidatorC", expectedExceptions = {SAXException.class, FileNotFoundException.class})
|
||||
@Test(dataProvider = "data_ValidatorC", expectedExceptions = {SAXException.class, IOException.class})
|
||||
public void testValidatorC(boolean setUseCatalog1, boolean setUseCatalog2, boolean useCatalog,
|
||||
Source source, LSResourceResolver resolver1, LSResourceResolver resolver2,
|
||||
String catalog1, String catalog2)
|
||||
|
@ -32,11 +32,10 @@ import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
@ -69,6 +68,7 @@ public class Bug6773084Test {
|
||||
private static final ExecutorService EXEC = Executors.newCachedThreadPool();
|
||||
|
||||
private static final CyclicBarrier BARRIER = new CyclicBarrier(NTHREADS);
|
||||
private static final int TIMEOUT = 110;
|
||||
|
||||
public static final String IN_FOLDER = Bug6773084Test.class.getResource("Bug6773084In").getPath();
|
||||
public static final String XSD_PATH = Bug6773084Test.class.getResource("Bug6773084.xsd").getPath();
|
||||
@ -93,20 +93,23 @@ public class Bug6773084Test {
|
||||
}
|
||||
});
|
||||
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setNamespaceAware(true);
|
||||
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
EXEC.execute(new XMLValiddator(files[i], i));
|
||||
EXEC.execute(new XMLValiddator(dbf.newDocumentBuilder().parse(files[i]), i));
|
||||
}
|
||||
runWithAllPerm(() -> EXEC.shutdown());
|
||||
|
||||
EXEC.awaitTermination(TIMEOUT, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private static class XMLValiddator implements Runnable {
|
||||
|
||||
private File file;
|
||||
private Document document;
|
||||
private int index;
|
||||
|
||||
public XMLValiddator(File file, int index) {
|
||||
this.file = file;
|
||||
public XMLValiddator(Document document, int index) {
|
||||
this.document = document;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@ -117,23 +120,14 @@ public class Bug6773084Test {
|
||||
BARRIER.await();
|
||||
System.out.println("Validating....");
|
||||
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
Document document = builder.parse(file);
|
||||
|
||||
Validator validator = schema.newValidator();
|
||||
validator.setErrorHandler(new ErrorHandlerImpl());
|
||||
validator.validate(new DOMSource(document));
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SAXException e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail("Test failed.");
|
||||
} catch (ParserConfigurationException e) {
|
||||
e.printStackTrace();
|
||||
} catch (BrokenBarrierException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InterruptedException e) {
|
||||
|
@ -373,3 +373,4 @@ c40c8739bcdc88892ff58ebee3fd8a3f287be94d jdk-9+123
|
||||
9446c534f0222b4eecfd9d9e25ab37c4fd4400a5 jdk-9+128
|
||||
47699aa2e69ec2702542dc73eb01de3bfb61aea0 jdk-9+129
|
||||
6c827500e34587061af97ad6fef0e859280255c5 jdk-9+130
|
||||
8c57f4c293bbc5609928308a6d91ba765760b5f9 jdk-9+131
|
||||
|
@ -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);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -53,10 +53,37 @@ abstract class HmacCore extends MacSpi implements Cloneable {
|
||||
private final int blockLen;
|
||||
|
||||
/**
|
||||
* Standard constructor, creates a new HmacCore instance using the
|
||||
* specified MessageDigest object.
|
||||
* Standard constructor, creates a new HmacCore instance instantiating
|
||||
* a MessageDigest of the specified name.
|
||||
*/
|
||||
HmacCore(MessageDigest md, int bl) {
|
||||
HmacCore(String digestAlgo, int bl) throws NoSuchAlgorithmException {
|
||||
MessageDigest md = MessageDigest.getInstance(digestAlgo);
|
||||
if (!(md instanceof Cloneable)) {
|
||||
// use SUN provider if the most preferred one does not support
|
||||
// cloning
|
||||
Provider sun = Security.getProvider("SUN");
|
||||
if (sun != null) {
|
||||
md = MessageDigest.getInstance(digestAlgo, sun);
|
||||
} else {
|
||||
String noCloneProv = md.getProvider().getName();
|
||||
// if no Sun provider, use provider list
|
||||
Provider[] provs = Security.getProviders();
|
||||
for (Provider p : provs) {
|
||||
try {
|
||||
if (!p.getName().equals(noCloneProv)) {
|
||||
MessageDigest md2 =
|
||||
MessageDigest.getInstance(digestAlgo, p);
|
||||
if (md2 instanceof Cloneable) {
|
||||
md = md2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.md = md;
|
||||
this.blockLen = bl;
|
||||
this.k_ipad = new byte[blockLen];
|
||||
@ -64,14 +91,6 @@ abstract class HmacCore extends MacSpi implements Cloneable {
|
||||
first = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard constructor, creates a new HmacCore instance instantiating
|
||||
* a MessageDigest of the specified name.
|
||||
*/
|
||||
HmacCore(String digestAlgorithm, int bl) throws NoSuchAlgorithmException {
|
||||
this(MessageDigest.getInstance(digestAlgorithm), bl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of the HMAC in bytes.
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
@ -865,7 +846,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Lookup LOOKUP = Lookup.IMPL_LOOKUP;
|
||||
static final Lookup LOOKUP = Lookup.IMPL_LOOKUP;
|
||||
|
||||
/**
|
||||
* All subclasses must provide such a value describing their type signature.
|
||||
|
@ -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 ||
|
||||
@ -273,7 +259,7 @@ class DirectMethodHandle extends MethodHandle {
|
||||
}
|
||||
|
||||
private static void maybeCompile(LambdaForm lform, MemberName m) {
|
||||
if (VerifyAccess.isSamePackage(m.getDeclaringClass(), MethodHandle.class))
|
||||
if (lform.vmentry == null && VerifyAccess.isSamePackage(m.getDeclaringClass(), MethodHandle.class))
|
||||
// Help along bootstrapping...
|
||||
lform.compileToBytecode();
|
||||
}
|
||||
@ -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;
|
||||
@ -576,25 +562,36 @@ class DirectMethodHandle extends MethodHandle {
|
||||
return lform;
|
||||
}
|
||||
|
||||
private static final Wrapper[] ALL_WRAPPERS = Wrapper.values();
|
||||
|
||||
private static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
|
||||
boolean isGetter = (formOp & 1) == (AF_GETFIELD & 1);
|
||||
boolean isStatic = (formOp >= AF_GETSTATIC);
|
||||
boolean needsInit = (formOp >= AF_GETSTATIC_INIT);
|
||||
boolean needsCast = (ftypeKind == FT_CHECKED_REF);
|
||||
Wrapper fw = (needsCast ? Wrapper.OBJECT : Wrapper.values()[ftypeKind]);
|
||||
Wrapper fw = (needsCast ? Wrapper.OBJECT : ALL_WRAPPERS[ftypeKind]);
|
||||
Class<?> ft = fw.primitiveType();
|
||||
assert(ftypeKind(needsCast ? String.class : ft) == ftypeKind);
|
||||
String tname = fw.primitiveSimpleName();
|
||||
String ctname = Character.toUpperCase(tname.charAt(0)) + tname.substring(1);
|
||||
if (isVolatile) ctname += "Volatile";
|
||||
String getOrPut = (isGetter ? "get" : "put");
|
||||
String linkerName = (getOrPut + ctname); // getObject, putIntVolatile, etc.
|
||||
|
||||
// getObject, putIntVolatile, etc.
|
||||
StringBuilder nameBuilder = new StringBuilder();
|
||||
if (isGetter) {
|
||||
nameBuilder.append("get");
|
||||
} else {
|
||||
nameBuilder.append("put");
|
||||
}
|
||||
nameBuilder.append(fw.primitiveSimpleName());
|
||||
nameBuilder.setCharAt(3, Character.toUpperCase(nameBuilder.charAt(3)));
|
||||
if (isVolatile) {
|
||||
nameBuilder.append("Volatile");
|
||||
}
|
||||
|
||||
MethodType linkerType;
|
||||
if (isGetter)
|
||||
linkerType = MethodType.methodType(ft, Object.class, long.class);
|
||||
else
|
||||
linkerType = MethodType.methodType(void.class, Object.class, long.class, ft);
|
||||
MemberName linker = new MemberName(Unsafe.class, linkerName, linkerType, REF_invokeVirtual);
|
||||
MemberName linker = new MemberName(Unsafe.class, nameBuilder.toString(), linkerType, REF_invokeVirtual);
|
||||
try {
|
||||
linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, NoSuchMethodException.class);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
@ -649,11 +646,16 @@ class DirectMethodHandle extends MethodHandle {
|
||||
if (needsCast && isGetter)
|
||||
names[POST_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[LINKER_CALL]);
|
||||
for (Name n : names) assert(n != null);
|
||||
String fieldOrStatic = (isStatic ? "Static" : "Field");
|
||||
String lambdaName = (linkerName + fieldOrStatic); // significant only for debugging
|
||||
if (needsCast) lambdaName += "Cast";
|
||||
if (needsInit) lambdaName += "Init";
|
||||
return new LambdaForm(lambdaName, ARG_LIMIT, names, RESULT);
|
||||
// add some detail to the lambdaForm debugname,
|
||||
// significant only for debugging
|
||||
if (isStatic) {
|
||||
nameBuilder.append("Static");
|
||||
} else {
|
||||
nameBuilder.append("Field");
|
||||
}
|
||||
if (needsCast) nameBuilder.append("Cast");
|
||||
if (needsInit) nameBuilder.append("Init");
|
||||
return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
@ -40,8 +40,8 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.lang.invoke.LambdaForm.*;
|
||||
@ -68,9 +68,10 @@ class InvokerBytecodeGenerator {
|
||||
private static final String LFN_SIG = "L" + LFN + ";";
|
||||
private static final String LL_SIG = "(L" + OBJ + ";)L" + OBJ + ";";
|
||||
private static final String LLV_SIG = "(L" + OBJ + ";L" + OBJ + ";)V";
|
||||
private static final String CLASS_PREFIX = LF + "$";
|
||||
|
||||
/** 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;
|
||||
@ -96,15 +97,15 @@ class InvokerBytecodeGenerator {
|
||||
/** Main constructor; other constructors delegate to this one. */
|
||||
private InvokerBytecodeGenerator(LambdaForm lambdaForm, int localsMapSize,
|
||||
String className, String invokerName, MethodType invokerType) {
|
||||
if (invokerName.contains(".")) {
|
||||
int p = invokerName.indexOf('.');
|
||||
int p = invokerName.indexOf('.');
|
||||
if (p > -1) {
|
||||
className = invokerName.substring(0, p);
|
||||
invokerName = invokerName.substring(p+1);
|
||||
invokerName = invokerName.substring(p + 1);
|
||||
}
|
||||
if (DUMP_CLASS_FILES) {
|
||||
className = makeDumpableClassName(className);
|
||||
}
|
||||
this.className = LF + "$" + className;
|
||||
this.className = CLASS_PREFIX + className;
|
||||
this.sourceFile = "LambdaForm$" + className;
|
||||
this.lambdaForm = lambdaForm;
|
||||
this.invokerName = invokerName;
|
||||
@ -124,7 +125,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.
|
||||
@ -201,38 +202,34 @@ class InvokerBytecodeGenerator {
|
||||
|
||||
class CpPatch {
|
||||
final int index;
|
||||
final String placeholder;
|
||||
final Object value;
|
||||
CpPatch(int index, String placeholder, Object value) {
|
||||
CpPatch(int index, Object value) {
|
||||
this.index = index;
|
||||
this.placeholder = placeholder;
|
||||
this.value = value;
|
||||
}
|
||||
public String toString() {
|
||||
return "CpPatch/index="+index+",placeholder="+placeholder+",value="+value;
|
||||
return "CpPatch/index="+index+",value="+value;
|
||||
}
|
||||
}
|
||||
|
||||
Map<Object, CpPatch> cpPatches = new HashMap<>();
|
||||
private final ArrayList<CpPatch> cpPatches = new ArrayList<>();
|
||||
|
||||
int cph = 0; // for counting constant placeholders
|
||||
private int cph = 0; // for counting constant placeholders
|
||||
|
||||
String constantPlaceholder(Object arg) {
|
||||
String cpPlaceholder = "CONSTANT_PLACEHOLDER_" + cph++;
|
||||
if (DUMP_CLASS_FILES) cpPlaceholder += " <<" + debugString(arg) + ">>"; // debugging aid
|
||||
if (cpPatches.containsKey(cpPlaceholder)) {
|
||||
throw new InternalError("observed CP placeholder twice: " + cpPlaceholder);
|
||||
}
|
||||
if (DUMP_CLASS_FILES) cpPlaceholder += " <<" + debugString(arg) + ">>";
|
||||
// TODO check if arg is already in the constant pool
|
||||
// insert placeholder in CP and remember the patch
|
||||
int index = cw.newConst((Object) cpPlaceholder); // TODO check if already in the constant pool
|
||||
cpPatches.put(cpPlaceholder, new CpPatch(index, cpPlaceholder, arg));
|
||||
int index = cw.newConst((Object) cpPlaceholder);
|
||||
cpPatches.add(new CpPatch(index, arg));
|
||||
return cpPlaceholder;
|
||||
}
|
||||
|
||||
Object[] cpPatches(byte[] classFile) {
|
||||
int size = getConstantPoolSize(classFile);
|
||||
Object[] res = new Object[size];
|
||||
for (CpPatch p : cpPatches.values()) {
|
||||
for (CpPatch p : cpPatches) {
|
||||
if (p.index >= size)
|
||||
throw new InternalError("in cpool["+size+"]: "+p+"\n"+Arrays.toString(Arrays.copyOf(classFile, 20)));
|
||||
res[p.index] = p.value;
|
||||
@ -655,35 +652,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.
|
||||
@ -765,7 +738,7 @@ class InvokerBytecodeGenerator {
|
||||
continue;
|
||||
case IDENTITY:
|
||||
assert(name.arguments.length == 1);
|
||||
emitPushArguments(name);
|
||||
emitPushArguments(name, 0);
|
||||
continue;
|
||||
case ZERO:
|
||||
assert(name.arguments.length == 0);
|
||||
@ -819,7 +792,7 @@ class InvokerBytecodeGenerator {
|
||||
assert arrayOpcode == Opcodes.AALOAD || arrayOpcode == Opcodes.AASTORE || arrayOpcode == Opcodes.ARRAYLENGTH;
|
||||
Class<?> elementType = name.function.methodType().parameterType(0).getComponentType();
|
||||
assert elementType != null;
|
||||
emitPushArguments(name);
|
||||
emitPushArguments(name, 0);
|
||||
if (arrayOpcode != Opcodes.ARRAYLENGTH && elementType.isPrimitive()) {
|
||||
Wrapper w = Wrapper.forPrimitiveType(elementType);
|
||||
arrayOpcode = arrayInsnOpcode(arrayTypeCode(w), arrayOpcode);
|
||||
@ -848,7 +821,7 @@ class InvokerBytecodeGenerator {
|
||||
}
|
||||
|
||||
// push arguments
|
||||
emitPushArguments(name);
|
||||
emitPushArguments(name, 0);
|
||||
|
||||
// invocation
|
||||
MethodType type = name.function.methodType();
|
||||
@ -947,7 +920,7 @@ class InvokerBytecodeGenerator {
|
||||
assert(!(member.getDeclaringClass().isInterface() && refKind == REF_invokeVirtual));
|
||||
|
||||
// push arguments
|
||||
emitPushArguments(name);
|
||||
emitPushArguments(name, 0);
|
||||
|
||||
// invocation
|
||||
if (member.isMethod()) {
|
||||
@ -1468,13 +1441,10 @@ class InvokerBytecodeGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
private void emitPushArguments(Name args) {
|
||||
emitPushArguments(args, 0);
|
||||
}
|
||||
|
||||
private void emitPushArguments(Name args, int start) {
|
||||
MethodType type = args.function.methodType();
|
||||
for (int i = start; i < args.arguments.length; i++) {
|
||||
emitPushArgument(args, i);
|
||||
emitPushArgument(type.parameterType(i), args.arguments[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,9 +149,9 @@ class LambdaForm {
|
||||
static final int ARG_TYPE_LIMIT = ARG_TYPES.length;
|
||||
static final int TYPE_LIMIT = ALL_TYPES.length;
|
||||
|
||||
private final char btChar;
|
||||
private final Class<?> btClass;
|
||||
private final Wrapper btWrapper;
|
||||
final char btChar;
|
||||
final Class<?> btClass;
|
||||
final Wrapper btWrapper;
|
||||
|
||||
private BasicType(char btChar, Class<?> btClass, Wrapper wrapper) {
|
||||
this.btChar = btChar;
|
||||
@ -1366,10 +1366,11 @@ class LambdaForm {
|
||||
}
|
||||
|
||||
public static String basicTypeSignature(MethodType type) {
|
||||
char[] sig = new char[type.parameterCount() + 2];
|
||||
int params = type.parameterCount();
|
||||
char[] sig = new char[params + 2];
|
||||
int sigp = 0;
|
||||
for (Class<?> pt : type.parameterList()) {
|
||||
sig[sigp++] = basicTypeChar(pt);
|
||||
while (sigp < params) {
|
||||
sig[sigp] = basicTypeChar(type.parameterType(sigp++));
|
||||
}
|
||||
sig[sigp++] = '_';
|
||||
sig[sigp++] = basicTypeChar(type.returnType());
|
||||
@ -1407,7 +1408,7 @@ class LambdaForm {
|
||||
|
||||
static final class Name {
|
||||
final BasicType type;
|
||||
private short index;
|
||||
@Stable short index;
|
||||
final NamedFunction function;
|
||||
final Object constraint; // additional type information, if not null
|
||||
@Stable final Object[] arguments;
|
||||
|
@ -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;
|
||||
@ -81,7 +78,7 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError;
|
||||
private int flags; // modifier bits; see reflect.Modifier
|
||||
//@Injected JVM_Method* vmtarget;
|
||||
//@Injected int vmindex;
|
||||
private Object resolution; // if null, this guy is resolved
|
||||
Object resolution; // if null, this guy is resolved
|
||||
|
||||
/** Return the declaring class of this member.
|
||||
* In the case of a bare name and type, the declaring class will be null.
|
||||
@ -829,7 +826,7 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError;
|
||||
return resolution == null;
|
||||
}
|
||||
|
||||
private void initResolved(boolean isResolved) {
|
||||
void initResolved(boolean isResolved) {
|
||||
assert(this.resolution == null); // not initialized yet!
|
||||
if (!isResolved)
|
||||
this.resolution = this;
|
||||
@ -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;
|
||||
@ -38,12 +40,11 @@ import sun.invoke.util.VerifyType;
|
||||
import sun.invoke.util.Wrapper;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
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;
|
||||
|
||||
@ -57,19 +58,6 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||
* @author jrose
|
||||
*/
|
||||
/*non-public*/ abstract class MethodHandleImpl {
|
||||
// Do not adjust this except for special platforms:
|
||||
private static final int MAX_ARITY;
|
||||
static {
|
||||
final Object[] values = { 255 };
|
||||
AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||
@Override
|
||||
public Void run() {
|
||||
values[0] = Integer.getInteger(MethodHandleImpl.class.getName()+".MAX_ARITY", 255);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
MAX_ARITY = (Integer) values[0];
|
||||
}
|
||||
|
||||
/// Factory methods to create method handles:
|
||||
|
||||
@ -649,7 +637,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||
MethodType srcType = targetType // (a..., [b...])=>r
|
||||
.dropParameterTypes(collectArgPos, collectArgPos+collectValCount);
|
||||
if (!retainOriginalArgs) { // (a..., b...)=>r
|
||||
srcType = srcType.insertParameterTypes(collectArgPos, collectorType.parameterList());
|
||||
srcType = srcType.insertParameterTypes(collectArgPos, collectorType.parameterArray());
|
||||
}
|
||||
// in arglist: [0: ...keep1 | cpos: collect... | cpos+cacount: keep2... ]
|
||||
// out arglist: [0: ...keep1 | cpos: collectVal? | cpos+cvcount: keep2... ]
|
||||
@ -1094,7 +1082,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||
int arity = type.parameterCount();
|
||||
if (arity > 1) {
|
||||
MethodHandle mh = throwException(type.dropParameterTypes(1, arity));
|
||||
mh = MethodHandles.dropArguments(mh, 1, type.parameterList().subList(1, arity));
|
||||
mh = MethodHandles.dropArguments(mh, 1, Arrays.copyOfRange(type.parameterArray(), 1, arity));
|
||||
return mh;
|
||||
}
|
||||
return makePairwiseConvert(NF_throwException.resolvedHandle(), type, false, true);
|
||||
@ -1710,6 +1698,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(). */
|
||||
|
@ -53,6 +53,7 @@ import java.util.Properties;
|
||||
static final boolean PROFILE_GWT;
|
||||
static final int CUSTOMIZE_THRESHOLD;
|
||||
static final boolean VAR_HANDLE_GUARDS;
|
||||
static final int MAX_ARITY;
|
||||
|
||||
static {
|
||||
Properties props = GetPropertyAction.privilegedGetProperties();
|
||||
@ -79,6 +80,10 @@ import java.util.Properties;
|
||||
VAR_HANDLE_GUARDS = Boolean.parseBoolean(
|
||||
props.getProperty("java.lang.invoke.VarHandle.VAR_HANDLE_GUARDS", "true"));
|
||||
|
||||
// Do not adjust this except for special platforms:
|
||||
MAX_ARITY = Integer.parseInt(
|
||||
props.getProperty("java.lang.invoke.MethodHandleImpl.MAX_ARITY", "255"));
|
||||
|
||||
if (CUSTOMIZE_THRESHOLD < -1 || CUSTOMIZE_THRESHOLD > 127) {
|
||||
throw newInternalError("CUSTOMIZE_THRESHOLD should be in [-1...127] range");
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ public class MethodHandles {
|
||||
|
||||
private MethodHandles() { } // do not instantiate
|
||||
|
||||
private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
|
||||
static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
|
||||
|
||||
// See IMPL_LOOKUP below.
|
||||
|
||||
@ -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));
|
||||
@ -3268,12 +3268,11 @@ assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
|
||||
*/
|
||||
public static
|
||||
MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
|
||||
return dropArguments0(target, pos, copyTypes(valueTypes));
|
||||
return dropArguments0(target, pos, copyTypes(valueTypes.toArray()));
|
||||
}
|
||||
|
||||
private static List<Class<?>> copyTypes(List<Class<?>> types) {
|
||||
Object[] a = types.toArray();
|
||||
return Arrays.asList(Arrays.copyOf(a, a.length, Class[].class));
|
||||
private static List<Class<?>> copyTypes(Object[] array) {
|
||||
return Arrays.asList(Arrays.copyOf(array, array.length, Class[].class));
|
||||
}
|
||||
|
||||
private static
|
||||
@ -3352,13 +3351,13 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
|
||||
*/
|
||||
public static
|
||||
MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
|
||||
return dropArguments(target, pos, Arrays.asList(valueTypes));
|
||||
return dropArguments0(target, pos, copyTypes(valueTypes));
|
||||
}
|
||||
|
||||
// private version which allows caller some freedom with error handling
|
||||
private static MethodHandle dropArgumentsToMatch(MethodHandle target, int skip, List<Class<?>> newTypes, int pos,
|
||||
boolean nullOnFailure) {
|
||||
newTypes = copyTypes(newTypes);
|
||||
newTypes = copyTypes(newTypes.toArray());
|
||||
List<Class<?>> oldTypes = target.type().parameterList();
|
||||
int match = oldTypes.size();
|
||||
if (skip != 0) {
|
||||
@ -3900,10 +3899,14 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
|
||||
int foldVals = rtype == void.class ? 0 : 1;
|
||||
int afterInsertPos = foldPos + foldVals;
|
||||
boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs);
|
||||
if (ok && !(combinerType.parameterList()
|
||||
.equals(targetType.parameterList().subList(afterInsertPos,
|
||||
afterInsertPos + foldArgs))))
|
||||
ok = false;
|
||||
if (ok) {
|
||||
for (int i = 0; i < foldArgs; i++) {
|
||||
if (combinerType.parameterType(i) != targetType.parameterType(i + afterInsertPos)) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ok && foldVals != 0 && combinerType.returnType() != targetType.parameterType(foldPos))
|
||||
ok = false;
|
||||
if (!ok)
|
||||
|
@ -539,10 +539,10 @@ class MethodType implements java.io.Serializable {
|
||||
return res;
|
||||
} else {
|
||||
// insert after (if need be), then before
|
||||
if (pos < parameterList().size() - 1) {
|
||||
res = res.insertParameterTypes(arrayLength, parameterList().subList(pos + 1, parameterList().size()));
|
||||
if (pos < ptypes.length - 1) {
|
||||
res = res.insertParameterTypes(arrayLength, Arrays.copyOfRange(ptypes, pos + 1, ptypes.length));
|
||||
}
|
||||
return res.insertParameterTypes(0, parameterList().subList(0, pos));
|
||||
return res.insertParameterTypes(0, Arrays.copyOf(ptypes, pos));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,12 +281,11 @@ 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 {
|
||||
// Not a special characters, this is a constant embedded into
|
||||
// Not a special character, this is a constant embedded into
|
||||
// the recipe itself.
|
||||
acc.append(c);
|
||||
}
|
||||
@ -322,31 +321,31 @@ public final class StringConcatFactory {
|
||||
private static final class RecipeElement {
|
||||
private final Object value;
|
||||
private final int argPos;
|
||||
private final Tag tag;
|
||||
private final char tag;
|
||||
|
||||
public RecipeElement(Object cnst) {
|
||||
this.value = Objects.requireNonNull(cnst);
|
||||
this.argPos = -1;
|
||||
this.tag = Tag.CONST;
|
||||
this.tag = TAG_CONST;
|
||||
}
|
||||
|
||||
public RecipeElement(int arg) {
|
||||
this.value = null;
|
||||
this.argPos = arg;
|
||||
this.tag = Tag.ARG;
|
||||
this.tag = TAG_ARG;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
assert (tag == Tag.CONST);
|
||||
assert (tag == TAG_CONST);
|
||||
return value;
|
||||
}
|
||||
|
||||
public int getArgPos() {
|
||||
assert (tag == Tag.ARG);
|
||||
assert (tag == TAG_ARG);
|
||||
return argPos;
|
||||
}
|
||||
|
||||
public Tag getTag() {
|
||||
public char getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
@ -357,22 +356,18 @@ 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;
|
||||
if (this.tag != that.tag) return false;
|
||||
if (this.tag == TAG_CONST && (!value.equals(that.value))) return false;
|
||||
if (this.tag == TAG_ARG && (argPos != that.argPos)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return tag.hashCode();
|
||||
return (int)tag;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@ -649,19 +644,20 @@ public final class StringConcatFactory {
|
||||
* @return argument types the strategy is going to use
|
||||
*/
|
||||
private static MethodType adaptType(MethodType args) {
|
||||
Class<?>[] ptypes = args.parameterArray();
|
||||
boolean changed = false;
|
||||
for (int i = 0; i < ptypes.length; i++) {
|
||||
Class<?> ptype = ptypes[i];
|
||||
Class<?>[] ptypes = null;
|
||||
for (int i = 0; i < args.parameterCount(); i++) {
|
||||
Class<?> ptype = args.parameterType(i);
|
||||
if (!ptype.isPrimitive() &&
|
||||
ptype != String.class &&
|
||||
ptype != Object.class) { // truncate to Object
|
||||
if (ptypes == null) {
|
||||
ptypes = args.parameterArray();
|
||||
}
|
||||
ptypes[i] = Object.class;
|
||||
changed = true;
|
||||
}
|
||||
// else other primitives or String or Object (unchanged)
|
||||
}
|
||||
return changed
|
||||
return (ptypes != null)
|
||||
? MethodType.methodType(args.returnType(), ptypes)
|
||||
: args;
|
||||
}
|
||||
@ -881,11 +877,10 @@ public final class StringConcatFactory {
|
||||
int off = 0;
|
||||
for (RecipeElement el : recipe.getElements()) {
|
||||
switch (el.getTag()) {
|
||||
case CONST: {
|
||||
case TAG_CONST:
|
||||
// Guaranteed non-null, no null check required.
|
||||
break;
|
||||
}
|
||||
case ARG: {
|
||||
case TAG_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
|
||||
@ -902,7 +897,6 @@ public final class StringConcatFactory {
|
||||
}
|
||||
off += getParameterSize(cl);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new StringConcatException("Unhandled tag: " + el.getTag());
|
||||
}
|
||||
@ -926,12 +920,11 @@ public final class StringConcatFactory {
|
||||
|
||||
for (RecipeElement el : recipe.getElements()) {
|
||||
switch (el.getTag()) {
|
||||
case CONST: {
|
||||
case TAG_CONST:
|
||||
Object cnst = el.getValue();
|
||||
len += cnst.toString().length();
|
||||
break;
|
||||
}
|
||||
case ARG: {
|
||||
case TAG_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
|
||||
@ -953,7 +946,6 @@ public final class StringConcatFactory {
|
||||
}
|
||||
off += getParameterSize(cl);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new StringConcatException("Unhandled tag: " + el.getTag());
|
||||
}
|
||||
@ -988,22 +980,21 @@ public final class StringConcatFactory {
|
||||
for (RecipeElement el : recipe.getElements()) {
|
||||
String desc;
|
||||
switch (el.getTag()) {
|
||||
case CONST: {
|
||||
case TAG_CONST:
|
||||
Object cnst = el.getValue();
|
||||
mv.visitLdcInsn(cnst);
|
||||
desc = getSBAppendDesc(cnst.getClass());
|
||||
break;
|
||||
}
|
||||
case ARG: {
|
||||
case TAG_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());
|
||||
}
|
||||
|
||||
mv.visitMethodInsn(
|
||||
INVOKEVIRTUAL,
|
||||
"java/lang/StringBuilder",
|
||||
@ -1271,7 +1262,6 @@ public final class StringConcatFactory {
|
||||
}
|
||||
}
|
||||
|
||||
List<Class<?>> ptypesList = Arrays.asList(ptypes);
|
||||
MethodHandle[] lengthers = new MethodHandle[pc];
|
||||
|
||||
// Figure out lengths: constants' lengths can be deduced on the spot.
|
||||
@ -1280,14 +1270,13 @@ public final class StringConcatFactory {
|
||||
int initial = 0;
|
||||
for (RecipeElement el : recipe.getElements()) {
|
||||
switch (el.getTag()) {
|
||||
case CONST: {
|
||||
case TAG_CONST:
|
||||
Object cnst = el.getValue();
|
||||
initial += cnst.toString().length();
|
||||
break;
|
||||
}
|
||||
case ARG: {
|
||||
case TAG_ARG:
|
||||
final int i = el.getArgPos();
|
||||
Class<?> type = ptypesList.get(i);
|
||||
Class<?> type = ptypes[i];
|
||||
if (type.isPrimitive()) {
|
||||
MethodHandle est = MethodHandles.constant(int.class, estimateSize(type));
|
||||
est = MethodHandles.dropArguments(est, 0, type);
|
||||
@ -1296,14 +1285,13 @@ public final class StringConcatFactory {
|
||||
lengthers[i] = STRING_LENGTH;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new StringConcatException("Unhandled tag: " + el.getTag());
|
||||
}
|
||||
}
|
||||
|
||||
// Create (StringBuilder, <args>) shape for appending:
|
||||
MethodHandle builder = MethodHandles.dropArguments(MethodHandles.identity(StringBuilder.class), 1, ptypesList);
|
||||
MethodHandle builder = MethodHandles.dropArguments(MethodHandles.identity(StringBuilder.class), 1, ptypes);
|
||||
|
||||
// Compose append calls. This is done in reverse because the application order is
|
||||
// reverse as well.
|
||||
@ -1312,23 +1300,21 @@ public final class StringConcatFactory {
|
||||
RecipeElement el = elements.get(i);
|
||||
MethodHandle appender;
|
||||
switch (el.getTag()) {
|
||||
case CONST: {
|
||||
case TAG_CONST:
|
||||
Object constant = el.getValue();
|
||||
MethodHandle mh = appender(adaptToStringBuilder(constant.getClass()));
|
||||
appender = MethodHandles.insertArguments(mh, 1, constant);
|
||||
break;
|
||||
}
|
||||
case ARG: {
|
||||
case TAG_ARG:
|
||||
int ac = el.getArgPos();
|
||||
appender = appender(ptypesList.get(ac));
|
||||
appender = appender(ptypes[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));
|
||||
appender = MethodHandles.dropArguments(appender, 1, Arrays.copyOf(ptypes, ac));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new StringConcatException("Unhandled tag: " + el.getTag());
|
||||
}
|
||||
@ -1500,7 +1486,6 @@ public final class StringConcatFactory {
|
||||
ptypes[i] = filter.type().returnType();
|
||||
}
|
||||
}
|
||||
List<Class<?>> ptypesList = Arrays.asList(ptypes);
|
||||
|
||||
// Start building the combinator tree. The tree "starts" with (<parameters>)String, and "finishes"
|
||||
// with the (int, byte[], byte)String in String helper. The combinators are assembled bottom-up,
|
||||
@ -1522,16 +1507,14 @@ public final class StringConcatFactory {
|
||||
for (RecipeElement el : recipe.getElements()) {
|
||||
MethodHandle prepender;
|
||||
switch (el.getTag()) {
|
||||
case CONST: {
|
||||
case TAG_CONST:
|
||||
Object cnst = el.getValue();
|
||||
prepender = MethodHandles.insertArguments(prepender(cnst.getClass()), 3, cnst);
|
||||
break;
|
||||
}
|
||||
case ARG: {
|
||||
case TAG_ARG:
|
||||
int pos = el.getArgPos();
|
||||
prepender = selectArgument(prepender(ptypesList.get(pos)), 3, ptypesList, pos);
|
||||
prepender = selectArgument(prepender(ptypes[pos]), 3, ptypes, pos);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new StringConcatException("Unhandled tag: " + el.getTag());
|
||||
}
|
||||
@ -1554,7 +1537,7 @@ public final class StringConcatFactory {
|
||||
}
|
||||
|
||||
// Fold in byte[] instantiation at argument 0.
|
||||
MethodHandle combiner = MethodHandles.dropArguments(NEW_ARRAY, 2, ptypesList);
|
||||
MethodHandle combiner = MethodHandles.dropArguments(NEW_ARRAY, 2, ptypes);
|
||||
mh = MethodHandles.foldArguments(mh, combiner);
|
||||
|
||||
// Start combining length and coder mixers.
|
||||
@ -1574,22 +1557,21 @@ public final class StringConcatFactory {
|
||||
int initialLen = 0; // initial length, in characters
|
||||
for (RecipeElement el : recipe.getElements()) {
|
||||
switch (el.getTag()) {
|
||||
case CONST: {
|
||||
case TAG_CONST:
|
||||
Object constant = el.getValue();
|
||||
String s = constant.toString();
|
||||
initialCoder = (byte) coderMixer(String.class).invoke(initialCoder, s);
|
||||
initialLen += s.length();
|
||||
break;
|
||||
}
|
||||
case ARG: {
|
||||
case TAG_ARG:
|
||||
int ac = el.getArgPos();
|
||||
|
||||
Class<?> argClass = ptypesList.get(ac);
|
||||
MethodHandle lm = selectArgument(lengthMixer(argClass), 1, ptypesList, ac);
|
||||
Class<?> argClass = ptypes[ac];
|
||||
MethodHandle lm = selectArgument(lengthMixer(argClass), 1, ptypes, ac);
|
||||
lm = MethodHandles.dropArguments(lm, 0, byte.class); // (*)
|
||||
lm = MethodHandles.dropArguments(lm, 2, byte.class);
|
||||
|
||||
MethodHandle cm = selectArgument(coderMixer(argClass), 1, ptypesList, ac);
|
||||
MethodHandle cm = selectArgument(coderMixer(argClass), 1, ptypes, ac);
|
||||
cm = MethodHandles.dropArguments(cm, 0, int.class); // (**)
|
||||
|
||||
// Read this bottom up:
|
||||
@ -1607,7 +1589,6 @@ public final class StringConcatFactory {
|
||||
|
||||
// 1. The mh shape here is ("old-index", "old-coder", <args>)
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new StringConcatException("Unhandled tag: " + el.getTag());
|
||||
}
|
||||
@ -1636,14 +1617,14 @@ public final class StringConcatFactory {
|
||||
}
|
||||
|
||||
// Adapts: (...prefix..., parameter[pos])R -> (...prefix..., ...parameters...)R
|
||||
private static MethodHandle selectArgument(MethodHandle mh, int prefix, List<Class<?>> ptypes, int pos) {
|
||||
private static MethodHandle selectArgument(MethodHandle mh, int prefix, Class<?>[] ptypes, int pos) {
|
||||
if (pos == 0) {
|
||||
return MethodHandles.dropArguments(mh, prefix + 1, ptypes.subList(1, ptypes.size()));
|
||||
} else if (pos == ptypes.size() - 1) {
|
||||
return MethodHandles.dropArguments(mh, prefix, ptypes.subList(0, ptypes.size() - 1));
|
||||
return MethodHandles.dropArguments(mh, prefix + 1, Arrays.copyOfRange(ptypes, 1, ptypes.length));
|
||||
} else if (pos == ptypes.length - 1) {
|
||||
return MethodHandles.dropArguments(mh, prefix, Arrays.copyOf(ptypes, ptypes.length - 1));
|
||||
} else { // 0 < pos < ptypes.size() - 1
|
||||
MethodHandle t = MethodHandles.dropArguments(mh, prefix, ptypes.subList(0, pos));
|
||||
return MethodHandles.dropArguments(t, prefix + 1 + pos, ptypes.subList(pos + 1, ptypes.size()));
|
||||
MethodHandle t = MethodHandles.dropArguments(mh, prefix, Arrays.copyOf(ptypes, pos));
|
||||
return MethodHandles.dropArguments(t, prefix + 1 + pos, Arrays.copyOfRange(ptypes, pos + 1, ptypes.length));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1702,8 +1683,8 @@ public final class StringConcatFactory {
|
||||
private static final ConcurrentMap<Class<?>, MethodHandle> PREPENDERS;
|
||||
private static final ConcurrentMap<Class<?>, MethodHandle> LENGTH_MIXERS;
|
||||
private static final ConcurrentMap<Class<?>, MethodHandle> CODER_MIXERS;
|
||||
private static final Class<?> STRING_HELPER;
|
||||
private static final byte INITIAL_CODER;
|
||||
static final Class<?> STRING_HELPER;
|
||||
|
||||
static {
|
||||
try {
|
||||
@ -1805,7 +1786,7 @@ public final class StringConcatFactory {
|
||||
|
||||
/* ------------------------------- Common utilities ------------------------------------ */
|
||||
|
||||
private static MethodHandle lookupStatic(Lookup lookup, Class<?> refc, String name, Class<?> rtype, Class<?>... ptypes) {
|
||||
static MethodHandle lookupStatic(Lookup lookup, Class<?> refc, String name, Class<?> rtype, Class<?>... ptypes) {
|
||||
try {
|
||||
return lookup.findStatic(refc, name, MethodType.methodType(rtype, ptypes));
|
||||
} catch (NoSuchMethodException | IllegalAccessException e) {
|
||||
@ -1813,7 +1794,7 @@ public final class StringConcatFactory {
|
||||
}
|
||||
}
|
||||
|
||||
private static MethodHandle lookupVirtual(Lookup lookup, Class<?> refc, String name, Class<?> rtype, Class<?>... ptypes) {
|
||||
static MethodHandle lookupVirtual(Lookup lookup, Class<?> refc, String name, Class<?> rtype, Class<?>... ptypes) {
|
||||
try {
|
||||
return lookup.findVirtual(refc, name, MethodType.methodType(rtype, ptypes));
|
||||
} catch (NoSuchMethodException | IllegalAccessException e) {
|
||||
@ -1821,7 +1802,7 @@ public final class StringConcatFactory {
|
||||
}
|
||||
}
|
||||
|
||||
private static MethodHandle lookupConstructor(Lookup lookup, Class<?> refc, Class<?> ptypes) {
|
||||
static MethodHandle lookupConstructor(Lookup lookup, Class<?> refc, Class<?> ptypes) {
|
||||
try {
|
||||
return lookup.findConstructor(refc, MethodType.methodType(void.class, ptypes));
|
||||
} catch (NoSuchMethodException | IllegalAccessException e) {
|
||||
@ -1829,7 +1810,7 @@ public final class StringConcatFactory {
|
||||
}
|
||||
}
|
||||
|
||||
private static int estimateSize(Class<?> cl) {
|
||||
static int estimateSize(Class<?> cl) {
|
||||
if (cl == Integer.TYPE) {
|
||||
return 11; // "-2147483648"
|
||||
} else if (cl == Boolean.TYPE) {
|
||||
@ -1851,7 +1832,7 @@ public final class StringConcatFactory {
|
||||
}
|
||||
}
|
||||
|
||||
private static Class<?> adaptToStringBuilder(Class<?> c) {
|
||||
static Class<?> adaptToStringBuilder(Class<?> c) {
|
||||
if (c.isPrimitive()) {
|
||||
if (c == Byte.TYPE || c == Short.TYPE) {
|
||||
return int.class;
|
||||
|
@ -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/";
|
||||
|
@ -31,7 +31,6 @@ import java.lang.invoke.VarHandle.AccessMode;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -54,7 +53,8 @@ final class VarForm {
|
||||
List<Class<?>> l = new ArrayList<>();
|
||||
if (receiver != null)
|
||||
l.add(receiver);
|
||||
l.addAll(Arrays.asList(intermediate));
|
||||
for (Class<?> c : intermediate)
|
||||
l.add(c);
|
||||
|
||||
// (Receiver, <Intermediates>)Value
|
||||
methodType_table[VarHandle.AccessType.GET.ordinal()] =
|
||||
|
@ -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;
|
||||
|
@ -147,11 +147,7 @@ public class AtomicBoolean implements java.io.Serializable {
|
||||
* @return the previous value
|
||||
*/
|
||||
public final boolean getAndSet(boolean newValue) {
|
||||
boolean prev;
|
||||
do {
|
||||
prev = get();
|
||||
} while (!compareAndSet(prev, newValue));
|
||||
return prev;
|
||||
return (int)VALUE.getAndSet(this, (newValue ? 1 : 0)) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -263,6 +263,47 @@ public class StampedLock implements java.io.Serializable {
|
||||
* is theoretically possible, so we additionally add a
|
||||
* storeStoreFence after lock acquisition CAS.
|
||||
*
|
||||
* ----------------------------------------------------------------
|
||||
* Here's an informal proof that plain reads by _successful_
|
||||
* readers see plain writes from preceding but not following
|
||||
* writers (following Boehm and the C++ standard [atomics.fences]):
|
||||
*
|
||||
* Because of the total synchronization order of accesses to
|
||||
* volatile long state containing the sequence number, writers and
|
||||
* _successful_ readers can be globally sequenced.
|
||||
*
|
||||
* int x, y;
|
||||
*
|
||||
* Writer 1:
|
||||
* inc sequence (odd - "locked")
|
||||
* storeStoreFence();
|
||||
* x = 1; y = 2;
|
||||
* inc sequence (even - "unlocked")
|
||||
*
|
||||
* Successful Reader:
|
||||
* read sequence (even)
|
||||
* // must see writes from Writer 1 but not Writer 2
|
||||
* r1 = x; r2 = y;
|
||||
* acquireFence();
|
||||
* read sequence (even - validated unchanged)
|
||||
* // use r1 and r2
|
||||
*
|
||||
* Writer 2:
|
||||
* inc sequence (odd - "locked")
|
||||
* storeStoreFence();
|
||||
* x = 3; y = 4;
|
||||
* inc sequence (even - "unlocked")
|
||||
*
|
||||
* Visibility of writer 1's stores is normal - reader's initial
|
||||
* read of state synchronizes with writer 1's final write to state.
|
||||
* Lack of visibility of writer 2's plain writes is less obvious.
|
||||
* If reader's read of x or y saw writer 2's write, then (assuming
|
||||
* semantics of C++ fences) the storeStoreFence would "synchronize"
|
||||
* with reader's acquireFence and reader's validation read must see
|
||||
* writer 2's initial write to state and so validation must fail.
|
||||
* But making this "proof" formal and rigorous is an open problem!
|
||||
* ----------------------------------------------------------------
|
||||
*
|
||||
* The memory layout keeps lock state and queue pointers together
|
||||
* (normally on the same cache line). This usually works well for
|
||||
* read-mostly loads. In most other cases, the natural tendency of
|
||||
@ -276,14 +317,14 @@ public class StampedLock implements java.io.Serializable {
|
||||
/** Number of processors, for spin control */
|
||||
private static final int NCPU = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
/** Maximum number of retries before enqueuing on acquisition */
|
||||
private static final int SPINS = (NCPU > 1) ? 1 << 6 : 0;
|
||||
/** Maximum number of retries before enqueuing on acquisition; at least 1 */
|
||||
private static final int SPINS = (NCPU > 1) ? 1 << 6 : 1;
|
||||
|
||||
/** Maximum number of retries before blocking at head on acquisition */
|
||||
private static final int HEAD_SPINS = (NCPU > 1) ? 1 << 10 : 0;
|
||||
/** Maximum number of tries before blocking at head on acquisition */
|
||||
private static final int HEAD_SPINS = (NCPU > 1) ? 1 << 10 : 1;
|
||||
|
||||
/** Maximum number of retries before re-blocking */
|
||||
private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 16 : 0;
|
||||
private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 16 : 1;
|
||||
|
||||
/** The period for yielding when waiting for overflow spinlock */
|
||||
private static final int OVERFLOW_YIELD_RATE = 7; // must be power 2 - 1
|
||||
@ -1228,6 +1269,11 @@ public class StampedLock implements java.io.Serializable {
|
||||
WCOWAIT.compareAndSet(h, c, c.cowait) &&
|
||||
(w = c.thread) != null) // help release
|
||||
LockSupport.unpark(w);
|
||||
if (Thread.interrupted()) {
|
||||
if (interruptible)
|
||||
return cancelWaiter(node, p, true);
|
||||
wasInterrupted = true;
|
||||
}
|
||||
if (h == (pp = p.prev) || h == p || pp == null) {
|
||||
long m, s, ns;
|
||||
do {
|
||||
@ -1264,11 +1310,6 @@ public class StampedLock implements java.io.Serializable {
|
||||
LockSupport.parkNanos(this, time);
|
||||
}
|
||||
node.thread = null;
|
||||
if (Thread.interrupted()) {
|
||||
if (interruptible)
|
||||
return cancelWaiter(node, p, true);
|
||||
wasInterrupted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user