diff --git a/.hgtags b/.hgtags index da69c7e51c4..39ca1fe7089 100644 --- a/.hgtags +++ b/.hgtags @@ -373,3 +373,4 @@ d53037a90c441cb528dc41c30827985de0e67c62 jdk-9+123 5bf88dce615f6804f9e101a96ffa7c9dfb4fbbbe jdk-9+128 e8373543a3f0f60589b7d72b1f9b172721124caf jdk-9+129 e613affb88d178dc7c589f1679db113d589bddb4 jdk-9+130 +4d2a15091124488080d65848b704e25599b2aaeb jdk-9+131 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index b44b5caeac9..9c7560ce460 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -373,3 +373,4 @@ f80c841ae2545eaf9acd2724bccc305d98cefbe2 jdk-9+124 b30ae794d974d7dd3eb4e84203f70021823fa6c6 jdk-9+128 f5902d3841b82cac6e7716a20c24e8e916fb14a8 jdk-9+129 d94d54a3192fea79234c3ac55cd0b4052d45e954 jdk-9+130 +8728756c2f70a79a90188f4019cfd6b9a275765c jdk-9+131 diff --git a/common/autoconf/boot-jdk.m4 b/common/autoconf/boot-jdk.m4 index d3fd298d704..83ec28e39bb 100644 --- a/common/autoconf/boot-jdk.m4 +++ b/common/autoconf/boot-jdk.m4 @@ -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]) diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 02375c62e7f..92e055d9a12 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -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 diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index 510764002a2..e4d41e81b43 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -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 diff --git a/common/conf/jib-profiles.js b/common/conf/jib-profiles.js index 2fa29a7c634..e57bbf7e4bd 100644 --- a/common/conf/jib-profiles.js +++ b/common/conf/jib-profiles.js @@ -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" diff --git a/corba/.hgtags b/corba/.hgtags index c046996c773..1e46a9e1c46 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -373,3 +373,4 @@ c7f5ba08fcd4b8416e62c21229f9a07c95498919 jdk-9+126 1f093d3f8cd99cd37c3b0af4cf5c3bffaa9c8b98 jdk-9+128 c3e83ccab3bb1733ae903d681879a33f85ed465c jdk-9+129 77f9692d5976ae155773dd3e07533616bb95bae1 jdk-9+130 +f7e1d5337c2e550fe553df7a3886bbed80292ecd jdk-9+131 diff --git a/hotspot/.hgtags b/hotspot/.hgtags index dcd6fc2574e..ada9a1ad431 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -533,3 +533,4 @@ adc8c84b7cf8c540d920182f78a2bc982366432a jdk-9+126 22bf6db9767b1b3a1994cbf32eb3331f31ae2093 jdk-9+128 e96b34b76d863ed1fa04e0eeb3f297ac17b490fd jdk-9+129 7d54c7056328b6a2bf4877458b8f4d8cd870f93b jdk-9+130 +943bf73b49c33c2d7cbd796f6a4ae3c7a00ae932 jdk-9+131 diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java index c4eab6cda82..f6aa30241e2 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java @@ -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; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java index 83085fe08d2..81689cf00be 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java @@ -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); diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index 92bf8fe4856..2cb586f1f54 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -140,7 +140,7 @@ PerfCounter* ClassLoader::_unsafe_defineClassCallCounter = NULL; PerfCounter* ClassLoader::_isUnsyncloadClass = NULL; PerfCounter* ClassLoader::_load_instance_class_failCounter = NULL; -GrowableArray* ClassLoader::_xpatch_entries = NULL; +GrowableArray* ClassLoader::_patch_mod_entries = NULL; GrowableArray* 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* xpatch_args = Arguments::get_xpatchprefix(); - int num_of_entries = xpatch_args->length(); + GrowableArray* 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(num_of_entries, true); + // Set up the boot loader's _patch_mod_entries list + _patch_mod_entries = new (ResourceObj::C_HEAP, mtModule) GrowableArray(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* 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 GrowableArraylength(); 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 GrowableArrayopen_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:=()*]; [jimage | exploded module build] + // [--patch-module==()*]; [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. diff --git a/hotspot/src/share/vm/classfile/classLoader.hpp b/hotspot/src/share/vm/classfile/classLoader.hpp index 045bfab715c..e0d56862b95 100644 --- a/hotspot/src/share/vm/classfile/classLoader.hpp +++ b/hotspot/src/share/vm/classfile/classLoader.hpp @@ -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 { 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:=()* + // 1. the module/path pairs specified to --patch-module + // --patch-module==()* // 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* _xpatch_entries; + // 1. Contains the module/path pairs specified to --patch-module + static GrowableArray* _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* const module_list, const char* const class_name, const char* const file_name, TRAPS); diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp index e4ec1c1a155..6dc7d1fb1c6 100644 --- a/hotspot/src/share/vm/memory/filemap.cpp +++ b/hotspot/src/share/vm/memory/filemap.cpp @@ -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; } diff --git a/hotspot/src/share/vm/prims/jvmtiEnv.cpp b/hotspot/src/share/vm/prims/jvmtiEnv.cpp index 2a5b202d93f..5b44ee01085 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp @@ -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; jnext()) { + 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 *Arguments::_xpatchprefix = NULL; +GrowableArray *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==()* + 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==()* + 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.#==()* - // 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(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(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 diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp index e72c492e0b1..dbac4f710b0 100644 --- a/hotspot/src/share/vm/runtime/arguments.hpp +++ b/hotspot/src/share/vm/runtime/arguments.hpp @@ -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 { protected: @@ -107,13 +107,13 @@ class PathString : public CHeapObj { } }; -// ModuleXPatchPath records the module/path pair as specified to -Xpatch. -class ModuleXPatchPath : public CHeapObj { +// ModulePatchPath records the module/path pair as specified to --patch-module. +class ModulePatchPath : public CHeapObj { 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=()* + // --patch-module=module=()* // Each element contains the associated module name, path - // string pair as specified to -Xpatch. - static GrowableArray* _xpatchprefix; + // string pair as specified to --patch-module. + static GrowableArray* _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* get_xpatchprefix() { return _xpatchprefix; } + static GrowableArray* 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; } diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp index e9cc5fc2f08..e909222cf23 100644 --- a/hotspot/src/share/vm/utilities/ostream.cpp +++ b/hotspot/src/share/vm/utilities/ostream.cpp @@ -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"); } diff --git a/hotspot/test/TEST.ROOT b/hotspot/test/TEST.ROOT index d604c52e930..9074b149ea1 100644 --- a/hotspot/test/TEST.ROOT +++ b/hotspot/test/TEST.ROOT @@ -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 diff --git a/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java index d897ba9370a..82661b28271 100644 --- a/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java +++ b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java @@ -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 */ diff --git a/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java b/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java index 85d0fcd6031..3d26f946937 100644 --- a/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java +++ b/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java @@ -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()])); diff --git a/hotspot/test/gc/arguments/TestSurvivorRatioFlag.java b/hotspot/test/gc/arguments/TestSurvivorRatioFlag.java index 2891eb1daa5..b18da4b3cf6 100644 --- a/hotspot/test/gc/arguments/TestSurvivorRatioFlag.java +++ b/hotspot/test/gc/arguments/TestSurvivorRatioFlag.java @@ -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", diff --git a/hotspot/test/gc/arguments/TestTargetSurvivorRatioFlag.java b/hotspot/test/gc/arguments/TestTargetSurvivorRatioFlag.java index e2df1d7e866..dd254e0e7a2 100644 --- a/hotspot/test/gc/arguments/TestTargetSurvivorRatioFlag.java +++ b/hotspot/test/gc/arguments/TestTargetSurvivorRatioFlag.java @@ -132,7 +132,7 @@ public class TestTargetSurvivorRatioFlag { LinkedList 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", diff --git a/hotspot/test/gc/g1/TestShrinkAuxiliaryData.java b/hotspot/test/gc/g1/TestShrinkAuxiliaryData.java index 83ef798f0bb..3b0907c6663 100644 --- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData.java +++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData.java @@ -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:.", }; diff --git a/hotspot/test/runtime/BadObjectClass/BootstrapRedefine.java b/hotspot/test/runtime/BadObjectClass/BootstrapRedefine.java index e23a6920796..fe77452c4a5 100644 --- a/hotspot/test/runtime/BadObjectClass/BootstrapRedefine.java +++ b/hotspot/test/runtime/BadObjectClass/BootstrapRedefine.java @@ -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); diff --git a/hotspot/test/runtime/BootClassAppendProp/BootClassPathAppendProp.java b/hotspot/test/runtime/BootClassAppendProp/BootClassPathAppendProp.java index 1d18c3ababd..0fd7830f46a 100644 --- a/hotspot/test/runtime/BootClassAppendProp/BootClassPathAppendProp.java +++ b/hotspot/test/runtime/BootClassAppendProp/BootClassPathAppendProp.java @@ -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 */ diff --git a/hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java b/hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java index a864f4d3c90..e4f0f94bdb2 100644 --- a/hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java +++ b/hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java @@ -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()); } } diff --git a/hotspot/test/runtime/ErrorHandling/ProblematicFrameTest.java b/hotspot/test/runtime/ErrorHandling/ProblematicFrameTest.java index 117c4839207..3ee548d2575 100644 --- a/hotspot/test/runtime/ErrorHandling/ProblematicFrameTest.java +++ b/hotspot/test/runtime/ErrorHandling/ProblematicFrameTest.java @@ -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\\)"); diff --git a/hotspot/test/runtime/SharedArchiveFile/BootAppendTests.java b/hotspot/test/runtime/SharedArchiveFile/BootAppendTests.java index 502adcf24be..b354fcbf355 100644 --- a/hotspot/test/runtime/SharedArchiveFile/BootAppendTests.java +++ b/hotspot/test/runtime/SharedArchiveFile/BootAppendTests.java @@ -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); diff --git a/hotspot/test/runtime/SharedArchiveFile/SASymbolTableTest.java b/hotspot/test/runtime/SharedArchiveFile/SASymbolTableTest.java index b9f2e52ab46..2ba4f6d139d 100644 --- a/hotspot/test/runtime/SharedArchiveFile/SASymbolTableTest.java +++ b/hotspot/test/runtime/SharedArchiveFile/SASymbolTableTest.java @@ -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); diff --git a/hotspot/test/runtime/Unsafe/RangeCheck.java b/hotspot/test/runtime/Unsafe/RangeCheck.java index 0e9b914234b..172af2a467d 100644 --- a/hotspot/test/runtime/Unsafe/RangeCheck.java +++ b/hotspot/test/runtime/Unsafe/RangeCheck.java @@ -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 diff --git a/hotspot/test/runtime/getSysPackage/GetSysPkgTest.java b/hotspot/test/runtime/getSysPackage/GetSysPkgTest.java index 04916a3e7b8..cce37fa72ff 100644 --- a/hotspot/test/runtime/getSysPackage/GetSysPkgTest.java +++ b/hotspot/test/runtime/getSysPackage/GetSysPkgTest.java @@ -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); diff --git a/hotspot/test/runtime/modules/IgnoreModulePropertiesTest.java b/hotspot/test/runtime/modules/IgnoreModulePropertiesTest.java new file mode 100644 index 00000000000..833182b09b3 --- /dev/null +++ b/hotspot/test/runtime/modules/IgnoreModulePropertiesTest.java @@ -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"); + } +} diff --git a/hotspot/test/runtime/modules/ModuleOptionsTest.java b/hotspot/test/runtime/modules/ModuleOptionsTest.java new file mode 100644 index 00000000000..2efb8bc0ad5 --- /dev/null +++ b/hotspot/test/runtime/modules/ModuleOptionsTest.java @@ -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); + } +} diff --git a/hotspot/test/runtime/modules/ModuleOptionsWarn.java b/hotspot/test/runtime/modules/ModuleOptionsWarn.java new file mode 100644 index 00000000000..e595c555e17 --- /dev/null +++ b/hotspot/test/runtime/modules/ModuleOptionsWarn.java @@ -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); + } +} diff --git a/hotspot/test/runtime/modules/ModuleStress/ExportModuleStressTest.java b/hotspot/test/runtime/modules/ModuleStress/ExportModuleStressTest.java index 49c75b1d211..e170d5eabb1 100644 --- a/hotspot/test/runtime/modules/ModuleStress/ExportModuleStressTest.java +++ b/hotspot/test/runtime/modules/ModuleStress/ExportModuleStressTest.java @@ -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") diff --git a/hotspot/test/runtime/modules/ModuleStress/ModuleStressGC.java b/hotspot/test/runtime/modules/ModuleStress/ModuleStressGC.java index 1ebb198ba5c..8ee2fb8a6f3 100644 --- a/hotspot/test/runtime/modules/ModuleStress/ModuleStressGC.java +++ b/hotspot/test/runtime/modules/ModuleStress/ModuleStressGC.java @@ -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") diff --git a/hotspot/test/runtime/modules/Xpatch/BasicJarBuilder.java b/hotspot/test/runtime/modules/PatchModule/BasicJarBuilder.java similarity index 100% rename from hotspot/test/runtime/modules/Xpatch/BasicJarBuilder.java rename to hotspot/test/runtime/modules/PatchModule/BasicJarBuilder.java diff --git a/hotspot/test/runtime/modules/Xpatch/Xpatch2Dirs.java b/hotspot/test/runtime/modules/PatchModule/PatchModule2Dirs.java similarity index 87% rename from hotspot/test/runtime/modules/Xpatch/Xpatch2Dirs.java rename to hotspot/test/runtime/modules/PatchModule/PatchModule2Dirs.java index d874d10fb04..8b04db22632 100644 --- a/hotspot/test/runtime/modules/Xpatch/Xpatch2Dirs.java +++ b/hotspot/test/runtime/modules/PatchModule/PatchModule2Dirs.java @@ -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!"); diff --git a/hotspot/test/runtime/modules/Xpatch/Xpatch2DirsMain.java b/hotspot/test/runtime/modules/PatchModule/PatchModule2DirsMain.java similarity index 80% rename from hotspot/test/runtime/modules/Xpatch/Xpatch2DirsMain.java rename to hotspot/test/runtime/modules/PatchModule/PatchModule2DirsMain.java index 9691156030b..466d11c9bcc 100644 --- a/hotspot/test/runtime/modules/Xpatch/Xpatch2DirsMain.java +++ b/hotspot/test/runtime/modules/PatchModule/PatchModule2DirsMain.java @@ -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]); diff --git a/hotspot/test/runtime/modules/XpatchCDS.java b/hotspot/test/runtime/modules/PatchModule/PatchModuleCDS.java similarity index 81% rename from hotspot/test/runtime/modules/XpatchCDS.java rename to hotspot/test/runtime/modules/PatchModule/PatchModuleCDS.java index 53ef3cf74e6..3ad5dab8014 100644 --- a/hotspot/test/runtime/modules/XpatchCDS.java +++ b/hotspot/test/runtime/modules/PatchModule/PatchModuleCDS.java @@ -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); } diff --git a/hotspot/test/runtime/modules/Xpatch/XpatchDupJavaBase.java b/hotspot/test/runtime/modules/PatchModule/PatchModuleDupJavaBase.java similarity index 87% rename from hotspot/test/runtime/modules/Xpatch/XpatchDupJavaBase.java rename to hotspot/test/runtime/modules/PatchModule/PatchModuleDupJavaBase.java index 69448a62796..e1d29adfc8b 100644 --- a/hotspot/test/runtime/modules/Xpatch/XpatchDupJavaBase.java +++ b/hotspot/test/runtime/modules/PatchModule/PatchModuleDupJavaBase.java @@ -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); } } diff --git a/hotspot/test/runtime/modules/Xpatch/XpatchDupModule.java b/hotspot/test/runtime/modules/PatchModule/PatchModuleDupModule.java similarity index 86% rename from hotspot/test/runtime/modules/Xpatch/XpatchDupModule.java rename to hotspot/test/runtime/modules/PatchModule/PatchModuleDupModule.java index 9fcffa4157a..2b56665de2b 100644 --- a/hotspot/test/runtime/modules/Xpatch/XpatchDupModule.java +++ b/hotspot/test/runtime/modules/PatchModule/PatchModuleDupModule.java @@ -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); } } - diff --git a/hotspot/test/runtime/modules/Xpatch/XpatchJavaBase.java b/hotspot/test/runtime/modules/PatchModule/PatchModuleJavaBase.java similarity index 88% rename from hotspot/test/runtime/modules/Xpatch/XpatchJavaBase.java rename to hotspot/test/runtime/modules/PatchModule/PatchModuleJavaBase.java index 3c0e50a58fb..c9d957f96f3 100644 --- a/hotspot/test/runtime/modules/Xpatch/XpatchJavaBase.java +++ b/hotspot/test/runtime/modules/PatchModule/PatchModuleJavaBase.java @@ -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!") diff --git a/hotspot/test/runtime/modules/Xpatch/XpatchMain.java b/hotspot/test/runtime/modules/PatchModule/PatchModuleMain.java similarity index 85% rename from hotspot/test/runtime/modules/Xpatch/XpatchMain.java rename to hotspot/test/runtime/modules/PatchModule/PatchModuleMain.java index 5509cbc7621..daa9001e72f 100644 --- a/hotspot/test/runtime/modules/Xpatch/XpatchMain.java +++ b/hotspot/test/runtime/modules/PatchModule/PatchModuleMain.java @@ -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]); } diff --git a/hotspot/test/runtime/modules/Xpatch/XpatchTest.java b/hotspot/test/runtime/modules/PatchModule/PatchModuleTest.java similarity index 87% rename from hotspot/test/runtime/modules/Xpatch/XpatchTest.java rename to hotspot/test/runtime/modules/PatchModule/PatchModuleTest.java index 6c67a4fe514..c85c88e99dd 100644 --- a/hotspot/test/runtime/modules/Xpatch/XpatchTest.java +++ b/hotspot/test/runtime/modules/PatchModule/PatchModuleTest.java @@ -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!") diff --git a/hotspot/test/runtime/modules/Xpatch/XpatchTestJar.java b/hotspot/test/runtime/modules/PatchModule/PatchModuleTestJar.java similarity index 90% rename from hotspot/test/runtime/modules/Xpatch/XpatchTestJar.java rename to hotspot/test/runtime/modules/PatchModule/PatchModuleTestJar.java index ad1675a15f0..c9ed80939a5 100644 --- a/hotspot/test/runtime/modules/Xpatch/XpatchTestJar.java +++ b/hotspot/test/runtime/modules/PatchModule/PatchModuleTestJar.java @@ -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!") diff --git a/hotspot/test/runtime/modules/Xpatch/XpatchTestJarDir.java b/hotspot/test/runtime/modules/PatchModule/PatchModuleTestJarDir.java similarity index 93% rename from hotspot/test/runtime/modules/Xpatch/XpatchTestJarDir.java rename to hotspot/test/runtime/modules/PatchModule/PatchModuleTestJarDir.java index a5329b6349d..4220816b322 100644 --- a/hotspot/test/runtime/modules/Xpatch/XpatchTestJarDir.java +++ b/hotspot/test/runtime/modules/PatchModule/PatchModuleTestJarDir.java @@ -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"); diff --git a/hotspot/test/runtime/modules/Xpatch/XpatchTraceCL.java b/hotspot/test/runtime/modules/PatchModule/PatchModuleTraceCL.java similarity index 76% rename from hotspot/test/runtime/modules/Xpatch/XpatchTraceCL.java rename to hotspot/test/runtime/modules/PatchModule/PatchModuleTraceCL.java index c3484971407..0d3bdeac0d1 100644 --- a/hotspot/test/runtime/modules/Xpatch/XpatchTraceCL.java +++ b/hotspot/test/runtime/modules/PatchModule/PatchModuleTraceCL.java @@ -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); } } diff --git a/hotspot/test/runtime/modules/Visibility/XpatchVisibility.java b/hotspot/test/runtime/modules/Visibility/PatchModuleVisibility.java similarity index 84% rename from hotspot/test/runtime/modules/Visibility/XpatchVisibility.java rename to hotspot/test/runtime/modules/Visibility/PatchModuleVisibility.java index a49fd997515..89afde3376d 100644 --- a/hotspot/test/runtime/modules/Visibility/XpatchVisibility.java +++ b/hotspot/test/runtime/modules/Visibility/PatchModuleVisibility.java @@ -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); } diff --git a/hotspot/test/runtime/modules/Visibility/XbootcpNoVisibility.java b/hotspot/test/runtime/modules/Visibility/XbootcpNoVisibility.java index 70cfa71f25a..3f92fd3dfe1 100644 --- a/hotspot/test/runtime/modules/Visibility/XbootcpNoVisibility.java +++ b/hotspot/test/runtime/modules/Visibility/XbootcpNoVisibility.java @@ -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. diff --git a/hotspot/test/runtime/modules/java.base/java/lang/reflect/ModuleHelper.java b/hotspot/test/runtime/modules/java.base/java/lang/reflect/ModuleHelper.java index ca7977aee8d..19bbff48a76 100644 --- a/hotspot/test/runtime/modules/java.base/java/lang/reflect/ModuleHelper.java +++ b/hotspot/test/runtime/modules/java.base/java/lang/reflect/ModuleHelper.java @@ -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. */ diff --git a/hotspot/test/serviceability/sa/TestInstanceKlassSize.java b/hotspot/test/serviceability/sa/TestInstanceKlassSize.java index 5d13df401df..6ab0a921609 100644 --- a/hotspot/test/serviceability/sa/TestInstanceKlassSize.java +++ b/hotspot/test/serviceability/sa/TestInstanceKlassSize.java @@ -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()) }; diff --git a/hotspot/test/serviceability/sa/TestInstanceKlassSizeForInterface.java b/hotspot/test/serviceability/sa/TestInstanceKlassSizeForInterface.java index 085ac246664..c2c0c61b9a9 100644 --- a/hotspot/test/serviceability/sa/TestInstanceKlassSizeForInterface.java +++ b/hotspot/test/serviceability/sa/TestInstanceKlassSizeForInterface.java @@ -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()) }; diff --git a/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java b/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java index 459686ee71c..a1b297adc06 100644 --- a/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java +++ b/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java @@ -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(); diff --git a/hotspot/test/testlibrary/ctw/Makefile b/hotspot/test/testlibrary/ctw/Makefile index ed63271e91a..0c642c63256 100644 --- a/hotspot/test/testlibrary/ctw/Makefile +++ b/hotspot/test/testlibrary/ctw/Makefile @@ -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 diff --git a/hotspot/test/testlibrary/jittester/Makefile b/hotspot/test/testlibrary/jittester/Makefile index 49470f7df71..4068d9d0af5 100644 --- a/hotspot/test/testlibrary/jittester/Makefile +++ b/hotspot/test/testlibrary/jittester/Makefile @@ -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) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index ac9804aad0a..bfe5860fa48 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -373,3 +373,4 @@ bdc3c0b737efbf899709eb3121ce760dcfb51151 jdk-9+127 8a7681a9d70640ac7fbf05c28f53c1d51d8d00a1 jdk-9+128 74241304e87b0d463391a8ecab40979b5af86dc2 jdk-9+129 e66cdc2de6b02443911d386fc9217b0d824d0686 jdk-9+130 +874082a9b565a7092a40bfa934a6e3e3c3455a60 jdk-9+131 diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/message.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/message.properties index 01f475b6ed8..48e15b05488 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/message.properties +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xpath/regex/message.properties @@ -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 diff --git a/jaxp/test/TEST.ROOT b/jaxp/test/TEST.ROOT index 190bdf5ccae..11ad18dbae6 100644 --- a/jaxp/test/TEST.ROOT +++ b/jaxp/test/TEST.ROOT @@ -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 diff --git a/jaxp/test/javax/xml/jaxp/libs/jaxp/library/BasePolicy.java b/jaxp/test/javax/xml/jaxp/libs/jaxp/library/BasePolicy.java index 5289148ad74..8305f54af74 100644 --- a/jaxp/test/javax/xml/jaxp/libs/jaxp/library/BasePolicy.java +++ b/jaxp/test/javax/xml/jaxp/libs/jaxp/library/BasePolicy.java @@ -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); } } diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport2.java b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport2.java index 50cb26e3c60..10159d3567c 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport2.java +++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport2.java @@ -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) diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport3.java b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport3.java index 6a9b04da148..6760b1981e1 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport3.java +++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupport3.java @@ -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) diff --git a/jaxp/test/javax/xml/jaxp/unittest/validation/Bug6773084Test.java b/jaxp/test/javax/xml/jaxp/unittest/validation/Bug6773084Test.java index 4ac7b5b977b..b50fa08e529 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/validation/Bug6773084Test.java +++ b/jaxp/test/javax/xml/jaxp/unittest/validation/Bug6773084Test.java @@ -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) { diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 0d23a61cd3e..0b957319e81 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -376,3 +376,4 @@ c42decd28bbfa817347112ed6053b5fbd30517a2 jdk-9+123 fe4e11bd2423635dc0f5f5cb9a64eb2f2cce7f4c jdk-9+128 46a02f57218e4a8c334dbccf656fb048f823f163 jdk-9+129 39c6293131d91aec7f2f5120395e070a937b8858 jdk-9+130 +783e7e2c587f2c7e1b9998a46d90ec196ab2a195 jdk-9+131 diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/SchemaGenerator.java b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/SchemaGenerator.java index 1fdf164f717..d19b7a70321 100644 --- a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/SchemaGenerator.java +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/SchemaGenerator.java @@ -140,7 +140,7 @@ public class SchemaGenerator { aptargs.add("-cp"); aptargs.add(setClasspath(options.classpath)); // set original classpath + jaxb-api to be visible to annotation processor - aptargs.add("-addmods"); + aptargs.add("--add-modules"); aptargs.add("java.xml.bind"); if(options.targetDir!=null) { diff --git a/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/wscompile/WsgenTool.java b/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/wscompile/WsgenTool.java index a325b3455a1..ebbaa2c8385 100644 --- a/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/wscompile/WsgenTool.java +++ b/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/wscompile/WsgenTool.java @@ -162,7 +162,7 @@ public class WsgenTool { boolean bootCP = useBootClasspath(EndpointReference.class) || useBootClasspath(XmlSeeAlso.class); List args = new ArrayList(6 + (bootCP ? 1 : 0) + (options.nocompile ? 1 : 0) + (options.encoding != null ? 2 : 0)); - args.add("-addmods"); + args.add("--add-modules"); args.add("java.xml.ws"); args.add("-d"); args.add(options.destDir.getAbsolutePath()); diff --git a/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/wscompile/WsimportTool.java b/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/wscompile/WsimportTool.java index 410cf89904d..a1b18541291 100644 --- a/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/wscompile/WsimportTool.java +++ b/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/wscompile/WsimportTool.java @@ -525,7 +525,7 @@ public class WsimportTool { String classpathString = createClasspathString(); boolean bootCP = useBootClasspath(EndpointContext.class) || useBootClasspath(JAXBPermission.class); List args = new ArrayList(); - args.add("-addmods"); + args.add("--add-modules"); args.add("java.xml.ws"); args.add("-d"); args.add(classDir); diff --git a/jdk/.hgtags b/jdk/.hgtags index b82ddf4e57c..d0c1a581878 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -374,3 +374,4 @@ c40c8739bcdc88892ff58ebee3fd8a3f287be94d jdk-9+123 47699aa2e69ec2702542dc73eb01de3bfb61aea0 jdk-9+129 6c827500e34587061af97ad6fef0e859280255c5 jdk-9+130 8c57f4c293bbc5609928308a6d91ba765760b5f9 jdk-9+131 +d5c70818cd8a82e76632c8c815bdb4f75f53aeaf jdk-9+132 diff --git a/jdk/make/copy/Copy-java.base.gmk b/jdk/make/copy/Copy-java.base.gmk index 5fb26d4b4d2..c023e8cfbed 100644 --- a/jdk/make/copy/Copy-java.base.gmk +++ b/jdk/make/copy/Copy-java.base.gmk @@ -183,7 +183,7 @@ DEF_POLICY_DST := $(LIB_DST_DIR)/security/default.policy DEF_POLICY_SRC_LIST := $(DEF_POLICY_SRC) -ifeq ($(OPENJDK_TARGET_OS), windows) +ifneq ($(filter $(OPENJDK_TARGET_OS), windows solaris), ) DEF_POLICY_SRC_LIST += $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/lib/security/default.policy endif diff --git a/jdk/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java b/jdk/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java index 134a60096c2..87c3da39c8c 100644 --- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java +++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -107,7 +107,7 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey { throw new InvalidKeySpecException("Key length is negative"); } try { - this.prf = Mac.getInstance(prfAlgo, SunJCE.getInstance()); + this.prf = Mac.getInstance(prfAlgo); } catch (NoSuchAlgorithmException nsae) { // not gonna happen; re-throw just in case InvalidKeySpecException ike = new InvalidKeySpecException(); diff --git a/jdk/src/java.base/share/classes/java/io/BufferedReader.java b/jdk/src/java.base/share/classes/java/io/BufferedReader.java index 3940b3b8776..1f6a66490cd 100644 --- a/jdk/src/java.base/share/classes/java/io/BufferedReader.java +++ b/jdk/src/java.base/share/classes/java/io/BufferedReader.java @@ -560,7 +560,7 @@ public class BufferedReader extends Reader { * @since 1.8 */ public Stream lines() { - Iterator iter = new Iterator() { + Iterator iter = new Iterator<>() { String nextLine = null; @Override diff --git a/jdk/src/java.base/share/classes/java/io/ByteArrayOutputStream.java b/jdk/src/java.base/share/classes/java/io/ByteArrayOutputStream.java index 61a147d1c4d..bd867c08d76 100644 --- a/jdk/src/java.base/share/classes/java/io/ByteArrayOutputStream.java +++ b/jdk/src/java.base/share/classes/java/io/ByteArrayOutputStream.java @@ -187,7 +187,7 @@ public class ByteArrayOutputStream extends OutputStream { * @return the current contents of this output stream, as a byte array. * @see java.io.ByteArrayOutputStream#size() */ - public synchronized byte toByteArray()[] { + public synchronized byte[] toByteArray() { return Arrays.copyOf(buf, count); } diff --git a/jdk/src/java.base/share/classes/java/io/CharArrayWriter.java b/jdk/src/java.base/share/classes/java/io/CharArrayWriter.java index 773b59614d9..e8bf2c36167 100644 --- a/jdk/src/java.base/share/classes/java/io/CharArrayWriter.java +++ b/jdk/src/java.base/share/classes/java/io/CharArrayWriter.java @@ -165,7 +165,7 @@ class CharArrayWriter extends Writer { * * @param csq * The character sequence to append. If {@code csq} is - * {@code null}, then the four characters "{@code null}" are + * {@code null}, then the four characters {@code "null"} are * appended to this writer. * * @return This writer @@ -173,7 +173,7 @@ class CharArrayWriter extends Writer { * @since 1.5 */ public CharArrayWriter append(CharSequence csq) { - String s = (csq == null ? "null" : csq.toString()); + String s = String.valueOf(csq); write(s, 0, s.length()); return this; } @@ -193,7 +193,7 @@ class CharArrayWriter extends Writer { * The character sequence from which a subsequence will be * appended. If {@code csq} is {@code null}, then characters * will be appended as if {@code csq} contained the four - * characters "{@code null}". + * characters {@code "null"}. * * @param start * The index of the first character in the subsequence @@ -212,9 +212,8 @@ class CharArrayWriter extends Writer { * @since 1.5 */ public CharArrayWriter append(CharSequence csq, int start, int end) { - String s = (csq == null ? "null" : csq).subSequence(start, end).toString(); - write(s, 0, s.length()); - return this; + if (csq == null) csq = "null"; + return append(csq.subSequence(start, end)); } /** @@ -251,7 +250,7 @@ class CharArrayWriter extends Writer { * * @return an array of chars copied from the input data. */ - public char toCharArray()[] { + public char[] toCharArray() { synchronized (lock) { return Arrays.copyOf(buf, count); } diff --git a/jdk/src/java.base/share/classes/java/io/FileSystem.java b/jdk/src/java.base/share/classes/java/io/FileSystem.java index 9d73e79ed40..a7528a9b5ca 100644 --- a/jdk/src/java.base/share/classes/java/io/FileSystem.java +++ b/jdk/src/java.base/share/classes/java/io/FileSystem.java @@ -228,13 +228,8 @@ abstract class FileSystem { static boolean useCanonPrefixCache = true; private static boolean getBooleanProperty(String prop, boolean defaultVal) { - String val = System.getProperty(prop); - if (val == null) return defaultVal; - if (val.equalsIgnoreCase("true")) { - return true; - } else { - return false; - } + return Boolean.parseBoolean(System.getProperty(prop, + String.valueOf(defaultVal))); } static { diff --git a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java index 9f13c9216a3..1895203cd11 100644 --- a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -1265,22 +1265,21 @@ public class ObjectInputStream WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue); Boolean result = Caches.subclassAudits.get(key); if (result == null) { - result = Boolean.valueOf(auditSubclass(cl)); + result = auditSubclass(cl); Caches.subclassAudits.putIfAbsent(key, result); } - if (result.booleanValue()) { - return; + if (!result) { + sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); } - sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); } /** * Performs reflective checks on given subclass to verify that it doesn't - * override security-sensitive non-final methods. Returns true if subclass - * is "safe", false otherwise. + * override security-sensitive non-final methods. Returns TRUE if subclass + * is "safe", FALSE otherwise. */ - private static boolean auditSubclass(final Class subcl) { - Boolean result = AccessController.doPrivileged( + private static Boolean auditSubclass(Class subcl) { + return AccessController.doPrivileged( new PrivilegedAction<>() { public Boolean run() { for (Class cl = subcl; @@ -1303,7 +1302,6 @@ public class ObjectInputStream } } ); - return result.booleanValue(); } /** diff --git a/jdk/src/java.base/share/classes/java/io/ObjectOutputStream.java b/jdk/src/java.base/share/classes/java/io/ObjectOutputStream.java index 2fc905e2dd3..bff6f8311ee 100644 --- a/jdk/src/java.base/share/classes/java/io/ObjectOutputStream.java +++ b/jdk/src/java.base/share/classes/java/io/ObjectOutputStream.java @@ -1050,22 +1050,21 @@ public class ObjectOutputStream WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue); Boolean result = Caches.subclassAudits.get(key); if (result == null) { - result = Boolean.valueOf(auditSubclass(cl)); + result = auditSubclass(cl); Caches.subclassAudits.putIfAbsent(key, result); } - if (result.booleanValue()) { - return; + if (!result) { + sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); } - sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); } /** * Performs reflective checks on given subclass to verify that it doesn't - * override security-sensitive non-final methods. Returns true if subclass - * is "safe", false otherwise. + * override security-sensitive non-final methods. Returns TRUE if subclass + * is "safe", FALSE otherwise. */ - private static boolean auditSubclass(final Class subcl) { - Boolean result = AccessController.doPrivileged( + private static Boolean auditSubclass(Class subcl) { + return AccessController.doPrivileged( new PrivilegedAction<>() { public Boolean run() { for (Class cl = subcl; @@ -1088,7 +1087,6 @@ public class ObjectOutputStream } } ); - return result.booleanValue(); } /** diff --git a/jdk/src/java.base/share/classes/java/io/ObjectStreamClass.java b/jdk/src/java.base/share/classes/java/io/ObjectStreamClass.java index cca42a71bbf..7ae45cae8c4 100644 --- a/jdk/src/java.base/share/classes/java/io/ObjectStreamClass.java +++ b/jdk/src/java.base/share/classes/java/io/ObjectStreamClass.java @@ -1509,11 +1509,9 @@ public class ObjectStreamClass implements Serializable { private static String getPackageName(Class cl) { String s = cl.getName(); int i = s.lastIndexOf('['); - if (i >= 0) { - s = s.substring(i + 2); - } - i = s.lastIndexOf('.'); - return (i >= 0) ? s.substring(0, i) : ""; + i = (i < 0) ? 0 : i + 2; + int j = s.lastIndexOf('.'); + return (i < j) ? s.substring(i, j) : ""; } /** @@ -1535,14 +1533,14 @@ public class ObjectStreamClass implements Serializable { private static String getMethodSignature(Class[] paramTypes, Class retType) { - StringBuilder sbuf = new StringBuilder(); - sbuf.append('('); + StringBuilder sb = new StringBuilder(); + sb.append('('); for (int i = 0; i < paramTypes.length; i++) { - appendClassSignature(sbuf, paramTypes[i]); + appendClassSignature(sb, paramTypes[i]); } - sbuf.append(')'); - appendClassSignature(sbuf, retType); - return sbuf.toString(); + sb.append(')'); + appendClassSignature(sb, retType); + return sb.toString(); } /** diff --git a/jdk/src/java.base/share/classes/java/io/OutputStreamWriter.java b/jdk/src/java.base/share/classes/java/io/OutputStreamWriter.java index 4fdb148baaf..3d44f443b82 100644 --- a/jdk/src/java.base/share/classes/java/io/OutputStreamWriter.java +++ b/jdk/src/java.base/share/classes/java/io/OutputStreamWriter.java @@ -233,22 +233,16 @@ public class OutputStreamWriter extends Writer { @Override public Writer append(CharSequence csq, int start, int end) throws IOException { - if (csq == null) { - write("null".subSequence(start, end).toString()); - return this; - } else { - return append(csq.subSequence(start, end)); - } + if (csq == null) csq = "null"; + return append(csq.subSequence(start, end)); } @Override public Writer append(CharSequence csq) throws IOException { - if (csq == null) { - se.write("null"); - } else if (csq instanceof CharBuffer) { + if (csq instanceof CharBuffer) { se.write((CharBuffer) csq); } else { - se.write(csq.toString()); + se.write(String.valueOf(csq)); } return this; } diff --git a/jdk/src/java.base/share/classes/java/io/PrintStream.java b/jdk/src/java.base/share/classes/java/io/PrintStream.java index 36a271e804d..09028de7358 100644 --- a/jdk/src/java.base/share/classes/java/io/PrintStream.java +++ b/jdk/src/java.base/share/classes/java/io/PrintStream.java @@ -568,7 +568,7 @@ public class PrintStream extends FilterOutputStream * @param b The {@code boolean} to be printed */ public void print(boolean b) { - write(b ? "true" : "false"); + write(String.valueOf(b)); } /** @@ -663,10 +663,7 @@ public class PrintStream extends FilterOutputStream * @param s The {@code String} to be printed */ public void print(String s) { - if (s == null) { - s = "null"; - } - write(s); + write(String.valueOf(s)); } /** @@ -1068,10 +1065,7 @@ public class PrintStream extends FilterOutputStream * @since 1.5 */ public PrintStream append(CharSequence csq) { - if (csq == null) - print("null"); - else - print(csq.toString()); + print(String.valueOf(csq)); return this; } @@ -1111,9 +1105,8 @@ public class PrintStream extends FilterOutputStream * @since 1.5 */ public PrintStream append(CharSequence csq, int start, int end) { - CharSequence cs = (csq == null ? "null" : csq); - write(cs.subSequence(start, end).toString()); - return this; + if (csq == null) csq = "null"; + return append(csq.subSequence(start, end)); } /** diff --git a/jdk/src/java.base/share/classes/java/io/PrintWriter.java b/jdk/src/java.base/share/classes/java/io/PrintWriter.java index d516b8ef404..0513312781b 100644 --- a/jdk/src/java.base/share/classes/java/io/PrintWriter.java +++ b/jdk/src/java.base/share/classes/java/io/PrintWriter.java @@ -504,7 +504,7 @@ public class PrintWriter extends Writer { * @param b The {@code boolean} to be printed */ public void print(boolean b) { - write(b ? "true" : "false"); + write(String.valueOf(b)); } /** @@ -599,10 +599,7 @@ public class PrintWriter extends Writer { * @param s The {@code String} to be printed */ public void print(String s) { - if (s == null) { - s = "null"; - } - write(s); + write(String.valueOf(s)); } /** @@ -1005,10 +1002,7 @@ public class PrintWriter extends Writer { * @since 1.5 */ public PrintWriter append(CharSequence csq) { - if (csq == null) - write("null"); - else - write(csq.toString()); + write(String.valueOf(csq)); return this; } @@ -1047,9 +1041,8 @@ public class PrintWriter extends Writer { * @since 1.5 */ public PrintWriter append(CharSequence csq, int start, int end) { - CharSequence cs = (csq == null ? "null" : csq); - write(cs.subSequence(start, end).toString()); - return this; + if (csq == null) csq = "null"; + return append(csq.subSequence(start, end)); } /** diff --git a/jdk/src/java.base/share/classes/java/io/SequenceInputStream.java b/jdk/src/java.base/share/classes/java/io/SequenceInputStream.java index f68f7d25265..b2caa11bca9 100644 --- a/jdk/src/java.base/share/classes/java/io/SequenceInputStream.java +++ b/jdk/src/java.base/share/classes/java/io/SequenceInputStream.java @@ -65,12 +65,7 @@ class SequenceInputStream extends InputStream { */ public SequenceInputStream(Enumeration e) { this.e = e; - try { - nextStream(); - } catch (IOException ex) { - // This should never happen - throw new Error("panic"); - } + peekNextStream(); } /** @@ -86,16 +81,10 @@ class SequenceInputStream extends InputStream { */ public SequenceInputStream(InputStream s1, InputStream s2) { Vector v = new Vector<>(2); - v.addElement(s1); v.addElement(s2); e = v.elements(); - try { - nextStream(); - } catch (IOException ex) { - // This should never happen - throw new Error("panic"); - } + peekNextStream(); } /** @@ -105,14 +94,17 @@ class SequenceInputStream extends InputStream { if (in != null) { in.close(); } + peekNextStream(); + } + private void peekNextStream() { if (e.hasMoreElements()) { in = (InputStream) e.nextElement(); if (in == null) throw new NullPointerException(); + } else { + in = null; } - else in = null; - } /** diff --git a/jdk/src/java.base/share/classes/java/io/StringBufferInputStream.java b/jdk/src/java.base/share/classes/java/io/StringBufferInputStream.java index 787cbb9c45e..11c230ff932 100644 --- a/jdk/src/java.base/share/classes/java/io/StringBufferInputStream.java +++ b/jdk/src/java.base/share/classes/java/io/StringBufferInputStream.java @@ -108,6 +108,7 @@ class StringBufferInputStream extends InputStream { * -1 if there is no more data because the end of * the stream has been reached. */ + @SuppressWarnings("deprecation") public synchronized int read(byte b[], int off, int len) { if (b == null) { throw new NullPointerException(); @@ -126,12 +127,8 @@ class StringBufferInputStream extends InputStream { if (len <= 0) { return 0; } - String s = buffer; - int cnt = len; - while (--cnt >= 0) { - b[off++] = (byte)s.charAt(pos++); - } - + buffer.getBytes(pos, pos + len, b, off); + pos += len; return len; } diff --git a/jdk/src/java.base/share/classes/java/io/StringReader.java b/jdk/src/java.base/share/classes/java/io/StringReader.java index 2dd72ff5357..9cfe5412993 100644 --- a/jdk/src/java.base/share/classes/java/io/StringReader.java +++ b/jdk/src/java.base/share/classes/java/io/StringReader.java @@ -142,8 +142,8 @@ public class StringReader extends Reader { */ public boolean ready() throws IOException { synchronized (lock) { - ensureOpen(); - return true; + ensureOpen(); + return true; } } diff --git a/jdk/src/java.base/share/classes/java/io/StringWriter.java b/jdk/src/java.base/share/classes/java/io/StringWriter.java index 15022b353a8..16eed62d7bb 100644 --- a/jdk/src/java.base/share/classes/java/io/StringWriter.java +++ b/jdk/src/java.base/share/classes/java/io/StringWriter.java @@ -139,7 +139,7 @@ public class StringWriter extends Writer { * * @param csq * The character sequence to append. If {@code csq} is - * {@code null}, then the four characters "{@code null}" are + * {@code null}, then the four characters {@code "null"} are * appended to this writer. * * @return This writer @@ -147,10 +147,7 @@ public class StringWriter extends Writer { * @since 1.5 */ public StringWriter append(CharSequence csq) { - if (csq == null) - write("null"); - else - write(csq.toString()); + write(String.valueOf(csq)); return this; } @@ -170,7 +167,7 @@ public class StringWriter extends Writer { * The character sequence from which a subsequence will be * appended. If {@code csq} is {@code null}, then characters * will be appended as if {@code csq} contained the four - * characters "{@code null}". + * characters {@code "null"}. * * @param start * The index of the first character in the subsequence @@ -189,9 +186,8 @@ public class StringWriter extends Writer { * @since 1.5 */ public StringWriter append(CharSequence csq, int start, int end) { - CharSequence cs = (csq == null ? "null" : csq); - write(cs.subSequence(start, end).toString()); - return this; + if (csq == null) csq = "null"; + return append(csq.subSequence(start, end)); } /** diff --git a/jdk/src/java.base/share/classes/java/io/Writer.java b/jdk/src/java.base/share/classes/java/io/Writer.java index 17e8de3ef8a..cd9aded358f 100644 --- a/jdk/src/java.base/share/classes/java/io/Writer.java +++ b/jdk/src/java.base/share/classes/java/io/Writer.java @@ -221,7 +221,7 @@ public abstract class Writer implements Appendable, Closeable, Flushable { * * @param csq * The character sequence to append. If {@code csq} is - * {@code null}, then the four characters "{@code null}" are + * {@code null}, then the four characters {@code "null"} are * appended to this writer. * * @return This writer @@ -232,10 +232,7 @@ public abstract class Writer implements Appendable, Closeable, Flushable { * @since 1.5 */ public Writer append(CharSequence csq) throws IOException { - if (csq == null) - write("null"); - else - write(csq.toString()); + write(String.valueOf(csq)); return this; } @@ -256,7 +253,7 @@ public abstract class Writer implements Appendable, Closeable, Flushable { * The character sequence from which a subsequence will be * appended. If {@code csq} is {@code null}, then characters * will be appended as if {@code csq} contained the four - * characters "{@code null}". + * characters {@code "null"}. * * @param start * The index of the first character in the subsequence @@ -278,9 +275,8 @@ public abstract class Writer implements Appendable, Closeable, Flushable { * @since 1.5 */ public Writer append(CharSequence csq, int start, int end) throws IOException { - CharSequence cs = (csq == null ? "null" : csq); - write(cs.subSequence(start, end).toString()); - return this; + if (csq == null) csq = "null"; + return append(csq.subSequence(start, end)); } /** diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java index 3b6fad7a636..91071a2b3b4 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java @@ -36,7 +36,6 @@ import sun.invoke.util.Wrapper; import java.lang.invoke.LambdaForm.NamedFunction; import java.lang.invoke.MethodHandles.Lookup; import java.lang.reflect.Field; -import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.function.Function; @@ -308,7 +307,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; /*non-public*/ char fieldTypeChar(int i) { return typeChars.charAt(i); } - Object fieldSignature() { + String fieldSignature() { return typeChars; } public Class fieldHolder() { diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java index 2e4baec0857..d11012e6487 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java @@ -27,6 +27,7 @@ package java.lang.invoke; import java.util.Arrays; import static java.lang.invoke.LambdaForm.*; +import static java.lang.invoke.LambdaForm.Kind.*; import static java.lang.invoke.MethodHandleStatics.*; /** @@ -96,14 +97,8 @@ abstract class DelegatingMethodHandle extends MethodHandle { int whichCache, Object constraint, NamedFunction getTargetFn) { - String debugString; - switch(whichCache) { - case MethodTypeForm.LF_REBIND: debugString = "BMH.reinvoke"; break; - case MethodTypeForm.LF_DELEGATE: debugString = "MH.delegate"; break; - default: debugString = "MH.reinvoke"; break; - } // No pre-action needed. - return makeReinvokerForm(target, whichCache, constraint, debugString, true, getTargetFn, null); + return makeReinvokerForm(target, whichCache, constraint, null, true, getTargetFn, null); } /** Create a LF which simply reinvokes a target of the given basic type. */ static LambdaForm makeReinvokerForm(MethodHandle target, @@ -114,6 +109,10 @@ abstract class DelegatingMethodHandle extends MethodHandle { NamedFunction getTargetFn, NamedFunction preActionFn) { MethodType mtype = target.type().basicType(); + Kind kind = whichKind(whichCache); + if (debugString == null) { + debugString = kind.defaultLambdaName; + } boolean customized = (whichCache < 0 || mtype.parameterSlotCount() > MethodType.MAX_MH_INVOKER_ARITY); boolean hasPreAction = (preActionFn != null); @@ -145,13 +144,21 @@ abstract class DelegatingMethodHandle extends MethodHandle { targetArgs[0] = names[NEXT_MH]; // overwrite this MH with next MH names[REINVOKE] = new LambdaForm.Name(mtype, targetArgs); } - form = new LambdaForm(debugString, ARG_LIMIT, names, forceInline); + form = new LambdaForm(debugString, ARG_LIMIT, names, forceInline, kind); if (!customized) { form = mtype.form().setCachedLambdaForm(whichCache, form); } return form; } + private static Kind whichKind(int whichCache) { + switch(whichCache) { + case MethodTypeForm.LF_REBIND: return BOUND_REINVOKER; + case MethodTypeForm.LF_DELEGATE: return DELEGATE; + default: return REINVOKER; + } + } + static final NamedFunction NF_getTarget; static { try { @@ -160,5 +167,13 @@ abstract class DelegatingMethodHandle extends MethodHandle { } catch (ReflectiveOperationException ex) { throw newInternalError(ex); } + // The Holder class will contain pre-generated DelegatingMethodHandles resolved + // speculatively using MemberName.getFactory().resolveOrNull. However, that + // doesn't initialize the class, which subtly breaks inlining etc. By forcing + // initialization of the Holder class we avoid these issues. + UNSAFE.ensureClassInitialized(Holder.class); } + + /* Placeholder class for DelegatingMethodHandles generated ahead of time */ + final class Holder {} } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java index 494103f57cc..174e914f805 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java @@ -38,6 +38,7 @@ import java.util.Arrays; import java.util.Objects; import static java.lang.invoke.LambdaForm.*; +import static java.lang.invoke.LambdaForm.Kind.*; import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandleStatics.UNSAFE; import static java.lang.invoke.MethodHandleStatics.newInternalError; @@ -189,14 +190,15 @@ class DirectMethodHandle extends MethodHandle { static LambdaForm makePreparedLambdaForm(MethodType mtype, int which) { boolean needsInit = (which == LF_INVSTATIC_INIT); boolean doesAlloc = (which == LF_NEWINVSPECIAL); - String linkerName, lambdaName; + String linkerName; + LambdaForm.Kind kind; switch (which) { - case LF_INVVIRTUAL: linkerName = "linkToVirtual"; lambdaName = "DMH.invokeVirtual"; break; - case LF_INVSTATIC: linkerName = "linkToStatic"; lambdaName = "DMH.invokeStatic"; break; - case LF_INVSTATIC_INIT:linkerName = "linkToStatic"; lambdaName = "DMH.invokeStaticInit"; break; - case LF_INVSPECIAL: linkerName = "linkToSpecial"; lambdaName = "DMH.invokeSpecial"; break; - case LF_INVINTERFACE: linkerName = "linkToInterface"; lambdaName = "DMH.invokeInterface"; break; - case LF_NEWINVSPECIAL: linkerName = "linkToSpecial"; lambdaName = "DMH.newInvokeSpecial"; break; + case LF_INVVIRTUAL: linkerName = "linkToVirtual"; kind = DIRECT_INVOKE_VIRTUAL; break; + case LF_INVSTATIC: linkerName = "linkToStatic"; kind = DIRECT_INVOKE_STATIC; break; + case LF_INVSTATIC_INIT:linkerName = "linkToStatic"; kind = DIRECT_INVOKE_STATIC_INIT; break; + case LF_INVSPECIAL: linkerName = "linkToSpecial"; kind = DIRECT_INVOKE_SPECIAL; break; + case LF_INVINTERFACE: linkerName = "linkToInterface"; kind = DIRECT_INVOKE_INTERFACE; break; + case LF_NEWINVSPECIAL: linkerName = "linkToSpecial"; kind = DIRECT_NEW_INVOKE_SPECIAL; break; default: throw new InternalError("which="+which); } @@ -240,11 +242,11 @@ class DirectMethodHandle extends MethodHandle { result = NEW_OBJ; } names[LINKER_CALL] = new Name(linker, outArgs); - lambdaName += "_" + shortenSignature(basicTypeSignature(mtype)); - LambdaForm lform = new LambdaForm(lambdaName, ARG_LIMIT, names, result); + String lambdaName = kind.defaultLambdaName + "_" + shortenSignature(basicTypeSignature(mtype)); + LambdaForm lform = new LambdaForm(lambdaName, ARG_LIMIT, names, result, kind); // This is a tricky bit of code. Don't send it through the LF interpreter. - lform.compileToBytecode(Holder.class); + lform.compileToBytecode(); return lform; } @@ -705,7 +707,7 @@ class DirectMethodHandle extends MethodHandle { } static { - // The DMH class will contain pre-generated DirectMethodHandles resolved + // The Holder class will contain pre-generated DirectMethodHandles resolved // speculatively using MemberName.getFactory().resolveOrNull. However, that // doesn't initialize the class, which subtly breaks inlining etc. By forcing // initialization of the Holder class we avoid these issues. @@ -713,5 +715,5 @@ class DirectMethodHandle extends MethodHandle { } /* Placeholder class for DirectMethodHandles generated ahead of time */ - private final class Holder {} + final class Holder {} } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java b/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java index 5edf33c8c60..1f1b50d67c5 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java @@ -29,21 +29,56 @@ import java.util.Map; import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.Opcodes; +import java.util.ArrayList; +import java.util.HashSet; + /** * Helper class to assist the GenerateJLIClassesPlugin to get access to * generate classes ahead of time. */ class GenerateJLIClassesHelper { - static byte[] generateDMHClassBytes(String className, + static byte[] generateDirectMethodHandleHolderClassBytes(String className, MethodType[] methodTypes, int[] types) { LambdaForm[] forms = new LambdaForm[methodTypes.length]; + String[] names = new String[methodTypes.length]; for (int i = 0; i < forms.length; i++) { forms[i] = DirectMethodHandle.makePreparedLambdaForm(methodTypes[i], types[i]); - methodTypes[i] = forms[i].methodType(); + names[i] = forms[i].kind.defaultLambdaName; } - return generateCodeBytesForLFs(className, forms, methodTypes); + return generateCodeBytesForLFs(className, names, forms); + } + + static byte[] generateDelegatingMethodHandleHolderClassBytes(String className, + MethodType[] methodTypes) { + + HashSet dedupSet = new HashSet<>(); + ArrayList forms = new ArrayList<>(); + ArrayList names = new ArrayList<>(); + for (int i = 0; i < methodTypes.length; i++) { + // generate methods representing the DelegatingMethodHandle + if (dedupSet.add(methodTypes[i])) { + // reinvokers are variant with the associated SpeciesData + // and shape of the target LF, but we can easily pregenerate + // the basic reinvokers associated with Species_L. Ultimately we + // may want to consider pregenerating more of these, which will + // require an even more complex naming scheme + LambdaForm reinvoker = makeReinvokerFor(methodTypes[i]); + forms.add(reinvoker); + String speciesSig = BoundMethodHandle + .speciesData(reinvoker).fieldSignature(); + assert(speciesSig.equals("L")); + names.add(reinvoker.kind.defaultLambdaName + "_" + speciesSig); + + LambdaForm delegate = makeDelegateFor(methodTypes[i]); + forms.add(delegate); + names.add(delegate.kind.defaultLambdaName); + } + } + return generateCodeBytesForLFs(className, + names.toArray(new String[0]), + forms.toArray(new LambdaForm[0])); } /* @@ -51,22 +86,45 @@ class GenerateJLIClassesHelper { * a class with a specified name. */ private static byte[] generateCodeBytesForLFs(String className, - LambdaForm[] forms, MethodType[] types) { - assert(forms.length == types.length); + String[] names, LambdaForm[] forms) { 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(); + addMethod(className, names[i], forms[i], + forms[i].methodType(), cw); } return cw.toByteArray(); } + private static void addMethod(String className, String methodName, LambdaForm form, + MethodType type, ClassWriter cw) { + InvokerBytecodeGenerator g + = new InvokerBytecodeGenerator(className, methodName, form, type); + g.setClassWriter(cw); + g.addMethod(); + } + + private static LambdaForm makeReinvokerFor(MethodType type) { + MethodHandle emptyHandle = MethodHandles.empty(type); + return DelegatingMethodHandle.makeReinvokerForm(emptyHandle, + MethodTypeForm.LF_REBIND, + BoundMethodHandle.speciesData_L(), + BoundMethodHandle.speciesData_L().getterFunction(0)); + } + + private static LambdaForm makeDelegateFor(MethodType type) { + MethodHandle handle = MethodHandles.empty(type); + return DelegatingMethodHandle.makeReinvokerForm( + handle, + MethodTypeForm.LF_DELEGATE, + DelegatingMethodHandle.class, + DelegatingMethodHandle.NF_getTarget); + } + static Map.Entry generateConcreteBMHClassBytes( final String types) { for (char c : types.toCharArray()) { diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index 3508a11b049..ebfe415fbf1 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -46,6 +46,7 @@ import java.util.stream.Stream; import static java.lang.invoke.LambdaForm.*; import static java.lang.invoke.LambdaForm.BasicType.*; +import static java.lang.invoke.LambdaForm.Kind.*; import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandleStatics.*; @@ -125,9 +126,15 @@ class InvokerBytecodeGenerator { } /** For generating customized code for a single LambdaForm. */ - InvokerBytecodeGenerator(String className, LambdaForm form, MethodType invokerType) { + private InvokerBytecodeGenerator(String className, LambdaForm form, MethodType invokerType) { + this(className, form.debugName, form, invokerType); + } + + /** For generating customized code for a single LambdaForm. */ + InvokerBytecodeGenerator(String className, String invokerName, + LambdaForm form, MethodType invokerType) { this(form, form.names.length, - className, form.debugName, invokerType); + className, invokerName, invokerType); // Create an array to map name indexes to locals indexes. Name[] names = form.names; for (int i = 0, index = 0; i < localsMap.length; i++) { @@ -597,10 +604,42 @@ class InvokerBytecodeGenerator { return c.getName().replace('.', '/'); } + private static MemberName resolveFrom(String name, MethodType type, Class holder) { + MemberName member = new MemberName(holder, name, type, REF_invokeStatic); + MemberName resolvedMember = MemberName.getFactory().resolveOrNull(REF_invokeStatic, member, holder); + + return resolvedMember; + } + + private static MemberName lookupPregenerated(LambdaForm form) { + if (form.customized != null) { + // No pre-generated version for customized LF + return null; + } + MethodType invokerType = form.methodType(); + String name = form.kind.methodName; + switch (form.kind) { + case BOUND_REINVOKER: { + name = name + "_" + BoundMethodHandle.speciesData(form).fieldSignature(); + return resolveFrom(name, invokerType, DelegatingMethodHandle.Holder.class); + } + case DELEGATE: return resolveFrom(name, invokerType, DelegatingMethodHandle.Holder.class); + case DIRECT_INVOKE_INTERFACE: // fall-through + case DIRECT_INVOKE_SPECIAL: // fall-through + case DIRECT_INVOKE_STATIC: // fall-through + case DIRECT_INVOKE_STATIC_INIT: // fall-through + case DIRECT_INVOKE_VIRTUAL: return resolveFrom(name, invokerType, DirectMethodHandle.Holder.class); + } + return null; + } + /** * Generate customized bytecode for a given LambdaForm. */ static MemberName generateCustomizedCode(LambdaForm form, MethodType invokerType) { + MemberName pregenerated = lookupPregenerated(form); + if (pregenerated != null) return pregenerated; // pre-generated bytecode + InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("MH", form, invokerType); return g.loadMethod(g.generateCustomizedCodeBytes()); } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java index a007881252f..c70d6c4163a 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java @@ -41,6 +41,7 @@ import java.util.HashMap; import static java.lang.invoke.LambdaForm.BasicType.*; import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic; import static java.lang.invoke.MethodHandleStatics.*; +import java.util.Objects; /** * The symbolic, non-executable form of a method handle's invocation semantics. @@ -127,6 +128,7 @@ class LambdaForm { final MethodHandle customized; @Stable final Name[] names; final String debugName; + final Kind kind; MemberName vmentry; // low-level behavior, or null if not yet prepared private boolean isCompiled; @@ -266,12 +268,46 @@ class LambdaForm { } } + enum Kind { + GENERIC(""), + BOUND_REINVOKER("BMH.reinvoke"), + REINVOKER("MH.reinvoke"), + DELEGATE("MH.delegate"), + DIRECT_INVOKE_VIRTUAL("DMH.invokeVirtual"), + DIRECT_INVOKE_SPECIAL("DMH.invokeSpecial"), + DIRECT_INVOKE_STATIC("DMH.invokeStatic"), + DIRECT_NEW_INVOKE_SPECIAL("DMH.newInvokeSpecial"), + DIRECT_INVOKE_INTERFACE("DMH.invokeInterface"), + DIRECT_INVOKE_STATIC_INIT("DMH.invokeStaticInit"); + + final String defaultLambdaName; + final String methodName; + + private Kind(String defaultLambdaName) { + this.defaultLambdaName = defaultLambdaName; + int p = defaultLambdaName.indexOf('.'); + if (p > -1) { + this.methodName = defaultLambdaName.substring(p + 1); + } else { + this.methodName = defaultLambdaName; + } + } + } + LambdaForm(String debugName, int arity, Name[] names, int result) { - this(debugName, arity, names, result, /*forceInline=*/true, /*customized=*/null); + this(debugName, arity, names, result, /*forceInline=*/true, /*customized=*/null, Kind.GENERIC); + } + LambdaForm(String debugName, + int arity, Name[] names, int result, Kind kind) { + this(debugName, arity, names, result, /*forceInline=*/true, /*customized=*/null, kind); } LambdaForm(String debugName, int arity, Name[] names, int result, boolean forceInline, MethodHandle customized) { + this(debugName, arity, names, result, forceInline, customized, Kind.GENERIC); + } + LambdaForm(String debugName, + int arity, Name[] names, int result, boolean forceInline, MethodHandle customized, Kind kind) { assert(namesOK(arity, names)); this.arity = arity; this.result = fixResult(result, names); @@ -279,6 +315,7 @@ class LambdaForm { this.debugName = fixDebugName(debugName); this.forceInline = forceInline; this.customized = customized; + this.kind = kind; int maxOutArity = normalize(); if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) { // Cannot use LF interpreter on very high arity expressions. @@ -288,11 +325,15 @@ class LambdaForm { } LambdaForm(String debugName, int arity, Name[] names) { - this(debugName, arity, names, LAST_RESULT, /*forceInline=*/true, /*customized=*/null); + this(debugName, arity, names, LAST_RESULT, /*forceInline=*/true, /*customized=*/null, Kind.GENERIC); } LambdaForm(String debugName, int arity, Name[] names, boolean forceInline) { - this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null); + this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null, Kind.GENERIC); + } + LambdaForm(String debugName, + int arity, Name[] names, boolean forceInline, Kind kind) { + this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null, kind); } LambdaForm(String debugName, Name[] formals, Name[] temps, Name result) { @@ -325,6 +366,7 @@ class LambdaForm { this.debugName = "LF.zero"; this.forceInline = true; this.customized = null; + this.kind = Kind.GENERIC; assert(nameRefsAreLegal()); assert(isEmpty()); String sig = null; @@ -395,7 +437,7 @@ class LambdaForm { /** Customize LambdaForm for a particular MethodHandle */ LambdaForm customize(MethodHandle mh) { - LambdaForm customForm = new LambdaForm(debugName, arity, names, result, forceInline, mh); + LambdaForm customForm = new LambdaForm(debugName, arity, names, result, forceInline, mh, kind); if (COMPILE_THRESHOLD >= 0 && isCompiled) { // If shared LambdaForm has been compiled, compile customized version as well. customForm.compileToBytecode(); @@ -773,28 +815,6 @@ class LambdaForm { } } - /** - * Generate optimizable bytecode for this form after first looking for a - * pregenerated version in a specified class. - */ - void compileToBytecode(Class lookupClass) { - if (vmentry != null && isCompiled) { - return; // already compiled somehow - } - MethodType invokerType = methodType(); - assert(vmentry == null || vmentry.getMethodType().basicType().equals(invokerType)); - int dot = debugName.indexOf('.'); - String methodName = (dot > 0) ? debugName.substring(dot + 1) : debugName; - MemberName member = new MemberName(lookupClass, methodName, invokerType, REF_invokeStatic); - MemberName resolvedMember = MemberName.getFactory().resolveOrNull(REF_invokeStatic, member, lookupClass); - if (resolvedMember != null) { - vmentry = resolvedMember; - isCompiled = true; - } else { - compileToBytecode(); - } - } - private static void computeInitialPreparedForms() { // Find all predefined invokers and associate them with canonical empty lambda forms. for (MemberName m : MemberName.getFactory().getMethods(LambdaForm.class, false, null, null, null)) { diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java index 60dc84f65ed..a0561589beb 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -1718,10 +1718,19 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; } @Override - public byte[] generateDMHClassBytes(String className, - MethodType[] methodTypes, int[] types) { + public byte[] generateDirectMethodHandleHolderClassBytes( + String className, MethodType[] methodTypes, int[] types) { return GenerateJLIClassesHelper - .generateDMHClassBytes(className, methodTypes, types); + .generateDirectMethodHandleHolderClassBytes( + className, methodTypes, types); + } + + @Override + public byte[] generateDelegatingMethodHandleHolderClassBytes( + String className, MethodType[] methodTypes) { + return GenerateJLIClassesHelper + .generateDelegatingMethodHandleHolderClassBytes( + className, methodTypes); } @Override diff --git a/jdk/src/java.base/share/classes/java/security/Provider.java b/jdk/src/java.base/share/classes/java/security/Provider.java index f9b0583df84..1d9d072b700 100644 --- a/jdk/src/java.base/share/classes/java/security/Provider.java +++ b/jdk/src/java.base/share/classes/java/security/Provider.java @@ -601,7 +601,7 @@ public abstract class Provider extends Properties { public synchronized Object compute(Object key, BiFunction remappingFunction) { check("putProviderProperty." + name); - check("removeProviderProperty" + name); + check("removeProviderProperty." + name); if (debug != null) { debug.println("Compute " + name + " provider property " + key); @@ -632,7 +632,7 @@ public abstract class Provider extends Properties { public synchronized Object computeIfAbsent(Object key, Function mappingFunction) { check("putProviderProperty." + name); - check("removeProviderProperty" + name); + check("removeProviderProperty." + name); if (debug != null) { debug.println("ComputeIfAbsent " + name + " provider property " + @@ -662,7 +662,7 @@ public abstract class Provider extends Properties { public synchronized Object computeIfPresent(Object key, BiFunction remappingFunction) { check("putProviderProperty." + name); - check("removeProviderProperty" + name); + check("removeProviderProperty." + name); if (debug != null) { debug.println("ComputeIfPresent " + name + " provider property " + @@ -695,7 +695,7 @@ public abstract class Provider extends Properties { public synchronized Object merge(Object key, Object value, BiFunction remappingFunction) { check("putProviderProperty." + name); - check("removeProviderProperty" + name); + check("removeProviderProperty." + name); if (debug != null) { debug.println("Merge " + name + " provider property " + key); @@ -904,8 +904,8 @@ public abstract class Provider extends Properties { if (!checkLegacy(key)) { return null; } - legacyStrings.computeIfAbsent((String) key, - (Function) remappingFunction); + legacyStrings.compute((String) key, + (BiFunction) remappingFunction); } return super.compute(key, remappingFunction); } diff --git a/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java b/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java index 5284bcd3907..0c9b50ae152 100644 --- a/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java +++ b/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java @@ -399,7 +399,10 @@ public class DateFormatSymbols implements Serializable, Cloneable { * Calendar Elements in the Unicode Locale Data Markup Language * (LDML) specification for more details. * - * @return the month strings. + * @return the month strings. Use + * {@link java.util.Calendar#JANUARY Calendar.JANUARY}, + * {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY}, + * etc. to index the result array. */ public String[] getMonths() { return Arrays.copyOf(months, months.length); @@ -407,7 +410,9 @@ public class DateFormatSymbols implements Serializable, Cloneable { /** * Sets month strings. For example: "January", "February", etc. - * @param newMonths the new month strings. + * @param newMonths the new month strings. The array should + * be indexed by {@link java.util.Calendar#JANUARY Calendar.JANUARY}, + * {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY}, etc. */ public void setMonths(String[] newMonths) { months = Arrays.copyOf(newMonths, newMonths.length); @@ -427,7 +432,10 @@ public class DateFormatSymbols implements Serializable, Cloneable { * Calendar Elements in the Unicode Locale Data Markup Language * (LDML) specification for more details. * - * @return the short month strings. + * @return the short month strings. Use + * {@link java.util.Calendar#JANUARY Calendar.JANUARY}, + * {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY}, + * etc. to index the result array. */ public String[] getShortMonths() { return Arrays.copyOf(shortMonths, shortMonths.length); @@ -435,7 +443,9 @@ public class DateFormatSymbols implements Serializable, Cloneable { /** * Sets short month strings. For example: "Jan", "Feb", etc. - * @param newShortMonths the new short month strings. + * @param newShortMonths the new short month strings. The array should + * be indexed by {@link java.util.Calendar#JANUARY Calendar.JANUARY}, + * {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY}, etc. */ public void setShortMonths(String[] newShortMonths) { shortMonths = Arrays.copyOf(newShortMonths, newShortMonths.length); @@ -444,8 +454,10 @@ public class DateFormatSymbols implements Serializable, Cloneable { /** * Gets weekday strings. For example: "Sunday", "Monday", etc. - * @return the weekday strings. Use Calendar.SUNDAY, - * Calendar.MONDAY, etc. to index the result array. + * @return the weekday strings. Use + * {@link java.util.Calendar#SUNDAY Calendar.SUNDAY}, + * {@link java.util.Calendar#MONDAY Calendar.MONDAY}, etc. to index + * the result array. */ public String[] getWeekdays() { return Arrays.copyOf(weekdays, weekdays.length); @@ -454,8 +466,8 @@ public class DateFormatSymbols implements Serializable, Cloneable { /** * Sets weekday strings. For example: "Sunday", "Monday", etc. * @param newWeekdays the new weekday strings. The array should - * be indexed by Calendar.SUNDAY, - * Calendar.MONDAY, etc. + * be indexed by {@link java.util.Calendar#SUNDAY Calendar.SUNDAY}, + * {@link java.util.Calendar#MONDAY Calendar.MONDAY}, etc. */ public void setWeekdays(String[] newWeekdays) { weekdays = Arrays.copyOf(newWeekdays, newWeekdays.length); @@ -464,8 +476,10 @@ public class DateFormatSymbols implements Serializable, Cloneable { /** * Gets short weekday strings. For example: "Sun", "Mon", etc. - * @return the short weekday strings. Use Calendar.SUNDAY, - * Calendar.MONDAY, etc. to index the result array. + * @return the short weekday strings. Use + * {@link java.util.Calendar#SUNDAY Calendar.SUNDAY}, + * {@link java.util.Calendar#MONDAY Calendar.MONDAY}, etc. to index + * the result array. */ public String[] getShortWeekdays() { return Arrays.copyOf(shortWeekdays, shortWeekdays.length); @@ -474,8 +488,8 @@ public class DateFormatSymbols implements Serializable, Cloneable { /** * Sets short weekday strings. For example: "Sun", "Mon", etc. * @param newShortWeekdays the new short weekday strings. The array should - * be indexed by Calendar.SUNDAY, - * Calendar.MONDAY, etc. + * be indexed by {@link java.util.Calendar#SUNDAY Calendar.SUNDAY}, + * {@link java.util.Calendar#MONDAY Calendar.MONDAY}, etc. */ public void setShortWeekdays(String[] newShortWeekdays) { shortWeekdays = Arrays.copyOf(newShortWeekdays, newShortWeekdays.length); diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java index d32624aaab7..44b9e5aea68 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java @@ -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; } /** diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java b/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java index b007db93d88..24be8fbe580 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java @@ -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; - } } } } diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/SSLEngine.java b/jdk/src/java.base/share/classes/javax/net/ssl/SSLEngine.java index 3b222cf6ad7..300265cbcd4 100644 --- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLEngine.java +++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLEngine.java @@ -861,6 +861,13 @@ public abstract class SSLEngine { * be enabled by default, since this list may include cipher suites which * do not meet quality of service requirements for those defaults. Such * cipher suites might be useful in specialized applications. + *

+ * The returned array includes cipher suites from the list of standard + * cipher suite names in the + * JSSE Cipher Suite Names section of the Java Cryptography + * Architecture Standard Algorithm Name Documentation, and may also + * include other cipher suites that the provider supports. * * @return an array of cipher suite names * @see #getEnabledCipherSuites() @@ -880,6 +887,13 @@ public abstract class SSLEngine { * or the requisite certificates (and private keys) for the suite are * not available, or an anonymous suite is enabled but authentication * is required. + *

+ * The returned array includes cipher suites from the list of standard + * cipher suite names in the + * JSSE Cipher Suite Names section of the Java Cryptography + * Architecture Standard Algorithm Name Documentation, and may also + * include other cipher suites that the provider supports. * * @return an array of cipher suite names * @see #getSupportedCipherSuites() @@ -896,6 +910,14 @@ public abstract class SSLEngine { * fail. Following a successful call to this method, only suites * listed in the {@code suites} parameter are enabled for use. *

+ * Note that the standard list of cipher suite names may be found in the + * + * JSSE Cipher Suite Names section of the Java Cryptography + * Architecture Standard Algorithm Name Documentation. Providers + * may support cipher suite names not found in this list or might not + * use the recommended name for a certain cipher suite. + *

* See {@link #getEnabledCipherSuites()} for more information * on why a specific cipher suite may never be used on a engine. * diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/SSLParameters.java b/jdk/src/java.base/share/classes/javax/net/ssl/SSLParameters.java index 5d47d37b909..5207c3c1f84 100644 --- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLParameters.java +++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -108,7 +108,12 @@ public class SSLParameters { *

* Calling this constructor is equivalent to calling the no-args * constructor followed by - * {@code setCipherSuites(cipherSuites);}. + * {@code setCipherSuites(cipherSuites);}. Note that the + * standard list of cipher suite names may be found in the + * JSSE Cipher Suite Names section of the Java Cryptography + * Architecture Standard Algorithm Name Documentation. Providers + * may support cipher suite names not found in this list. * * @param cipherSuites the array of ciphersuites (or null) */ @@ -123,6 +128,12 @@ public class SSLParameters { * Calling this constructor is equivalent to calling the no-args * constructor followed by * {@code setCipherSuites(cipherSuites); setProtocols(protocols);}. + * Note that the standard list of cipher suite names may be found in the + * + * JSSE Cipher Suite Names section of the Java Cryptography + * Architecture Standard Algorithm Name Documentation. Providers + * may support cipher suite names not found in this list. * * @param cipherSuites the array of ciphersuites (or null) * @param protocols the array of protocols (or null) @@ -139,6 +150,13 @@ public class SSLParameters { /** * Returns a copy of the array of ciphersuites or null if none * have been set. + *

+ * The returned array includes cipher suites from the list of standard + * cipher suite names in the + * JSSE Cipher Suite Names section of the Java Cryptography + * Architecture Standard Algorithm Name Documentation, and may also + * include other cipher suites that the provider supports. * * @return a copy of the array of ciphersuites or null if none * have been set. @@ -150,7 +168,13 @@ public class SSLParameters { /** * Sets the array of ciphersuites. * - * @param cipherSuites the array of ciphersuites (or null) + * @param cipherSuites the array of ciphersuites (or null). Note that the + * standard list of cipher suite names may be found in the + * JSSE Cipher Suite Names section of the Java Cryptography + * Architecture Standard Algorithm Name Documentation. Providers + * may support cipher suite names not found in this list or might not + * use the recommended name for a certain cipher suite. */ public void setCipherSuites(String[] cipherSuites) { this.cipherSuites = clone(cipherSuites); diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/SSLServerSocket.java b/jdk/src/java.base/share/classes/javax/net/ssl/SSLServerSocket.java index 8c7d9dc3031..ead7d20ae58 100644 --- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLServerSocket.java +++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLServerSocket.java @@ -195,6 +195,13 @@ public abstract class SSLServerSocket extends ServerSocket { * or the requisite certificates (and private keys) for the suite are * not available, or an anonymous suite is enabled but authentication * is required. + *

+ * The returned array includes cipher suites from the list of standard + * cipher suite names in the + * JSSE Cipher Suite Names section of the Java Cryptography + * Architecture Standard Algorithm Name Documentation, and may also + * include other cipher suites that the provider supports. * * @return an array of cipher suites enabled * @see #getSupportedCipherSuites() @@ -215,6 +222,14 @@ public abstract class SSLServerSocket extends ServerSocket { * in this ServerSocket's authentication context will not be used * in any case, even if they are enabled. *

+ * Note that the standard list of cipher suite names may be found in the + * + * JSSE Cipher Suite Names section of the Java Cryptography + * Architecture Standard Algorithm Name Documentation. Providers + * may support cipher suite names not found in this list or might not + * use the recommended name for a certain cipher suite. + *

* SSLSockets returned from accept() * inherit this setting. * @@ -236,6 +251,13 @@ public abstract class SSLServerSocket extends ServerSocket { * be enabled by default, since this list may include cipher suites which * do not meet quality of service requirements for those defaults. Such * cipher suites are useful in specialized applications. + *

+ * The returned array includes cipher suites from the list of standard + * cipher suite names in the + * JSSE Cipher Suite Names section of the Java Cryptography + * Architecture Standard Algorithm Name Documentation, and may also + * include other cipher suites that the provider supports. * * @return an array of cipher suite names * @see #getEnabledCipherSuites() diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java b/jdk/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java index fea47ba0cd3..3629aaef3c7 100644 --- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java +++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -123,6 +123,13 @@ public abstract class SSLServerSocketFactory extends ServerSocketFactory * will use one of these cipher suites. The minimum quality of service * for these defaults requires confidentiality protection and server * authentication (that is, no anonymous cipher suites). + *

+ * The returned array includes cipher suites from the list of standard + * cipher suite names in the + * JSSE Cipher Suite Names section of the Java Cryptography + * Architecture Standard Algorithm Name Documentation, and may also + * include other cipher suites that the provider supports. * * @see #getSupportedCipherSuites() * @return array of the cipher suites enabled by default @@ -137,6 +144,13 @@ public abstract class SSLServerSocketFactory extends ServerSocketFactory * be enabled by default, since this list may include cipher suites which * do not meet quality of service requirements for those defaults. Such * cipher suites are useful in specialized applications. + *

+ * The returned array includes cipher suites from the list of standard + * cipher suite names in the + * JSSE Cipher Suite Names section of the Java Cryptography + * Architecture Standard Algorithm Name Documentation, and may also + * include other cipher suites that the provider supports. * * @return an array of cipher suite names * @see #getDefaultCipherSuites() diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocket.java b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocket.java index 93c7ec01ab7..daaefe08ec7 100644 --- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocket.java +++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocket.java @@ -265,6 +265,13 @@ public abstract class SSLSocket extends Socket * be enabled by default, since this list may include cipher suites which * do not meet quality of service requirements for those defaults. Such * cipher suites might be useful in specialized applications. + *

+ * The returned array includes cipher suites from the list of standard + * cipher suite names in the + * JSSE Cipher Suite Names section of the Java Cryptography + * Architecture Standard Algorithm Name Documentation, and may also + * include other cipher suites that the provider supports. * * @return an array of cipher suite names * @see #getEnabledCipherSuites() @@ -284,6 +291,13 @@ public abstract class SSLSocket extends Socket * or the requisite certificates (and private keys) for the suite are * not available, or an anonymous suite is enabled but authentication * is required. + *

+ * The returned array includes cipher suites from the list of standard + * cipher suite names in the + * JSSE Cipher Suite Names section of the Java Cryptography + * Architecture Standard Algorithm Name Documentation, and may also + * include other cipher suites that the provider supports. * * @return an array of cipher suite names * @see #getSupportedCipherSuites() @@ -300,6 +314,14 @@ public abstract class SSLSocket extends Socket * fail. Following a successful call to this method, only suites * listed in the suites parameter are enabled for use. *

+ * Note that the standard list of cipher suite names may be found in the + * + * JSSE Cipher Suite Names section of the Java Cryptography + * Architecture Standard Algorithm Name Documentation. Providers + * may support cipher suite names not found in this list or might not + * use the recommended name for a certain cipher suite. + *

* See {@link #getEnabledCipherSuites()} for more information * on why a specific ciphersuite may never be used on a connection. * diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java index 6375a52a1b0..d504e1d7a3d 100644 --- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java +++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -148,6 +148,13 @@ public abstract class SSLSocketFactory extends SocketFactory * will use one of these cipher suites. The minimum quality of service * for these defaults requires confidentiality protection and server * authentication (that is, no anonymous cipher suites). + *

+ * The returned array includes cipher suites from the list of standard + * cipher suite names in the + * JSSE Cipher Suite Names section of the Java Cryptography + * Architecture Standard Algorithm Name Documentation, and may also + * include other cipher suites that the provider supports. * * @see #getSupportedCipherSuites() * @return array of the cipher suites enabled by default @@ -160,6 +167,13 @@ public abstract class SSLSocketFactory extends SocketFactory * be enabled by default, since this list may include cipher suites which * do not meet quality of service requirements for those defaults. Such * cipher suites are useful in specialized applications. + *

+ * The returned array includes cipher suites from the list of standard + * cipher suite names in the + * JSSE Cipher Suite Names section of the Java Cryptography + * Architecture Standard Algorithm Name Documentation, and may also + * include other cipher suites that the provider supports. * * @see #getDefaultCipherSuites() * @return an array of cipher suite names diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java index e514e5c95c0..ea941316b4e 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java @@ -51,8 +51,17 @@ public interface JavaLangInvokeAccess { * 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); + byte[] generateDirectMethodHandleHolderClassBytes(String className, + MethodType[] methodTypes, int[] types); + + /** + * Returns a {@code byte[]} containing the bytecode for a class implementing + * DelegatingMethodHandles of each {@code MethodType} kind in the + * {@code methodTypes} argument. Used by GenerateJLIClassesPlugin to + * generate such a class during the jlink phase. + */ + byte[] generateDelegatingMethodHandleHolderClassBytes(String className, + MethodType[] methodTypes); /** * Returns a {@code byte[]} containing the bytecode for a BoundMethodHandle diff --git a/jdk/src/java.base/share/classes/module-info.java b/jdk/src/java.base/share/classes/module-info.java index 044f43b2877..ae5ebbbb070 100644 --- a/jdk/src/java.base/share/classes/module-info.java +++ b/jdk/src/java.base/share/classes/module-info.java @@ -24,9 +24,8 @@ */ /** - * java.base defines and exports the core APIs of the Java SE platform. + * Defines the foundational APIs of the Java SE Platform. */ - module java.base { exports java.io; diff --git a/jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java b/jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java index 1c176f9fa24..4e7d546583f 100644 --- a/jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java +++ b/jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java @@ -580,6 +580,9 @@ public final class PKCS12KeyStore extends KeyStoreSpi { Entry entry; if (key instanceof PrivateKey) { + // Check that all the certs are X.509 certs + checkX509Certs(chain); + PrivateKeyEntry keyEntry = new PrivateKeyEntry(); keyEntry.date = new Date(); @@ -690,6 +693,9 @@ public final class PKCS12KeyStore extends KeyStoreSpi { Certificate[] chain) throws KeyStoreException { + // Check that all the certs are X.509 certs + checkX509Certs(chain); + // Private key must be encoded as EncryptedPrivateKeyInfo // as defined in PKCS#8 try { @@ -960,6 +966,13 @@ public final class PKCS12KeyStore extends KeyStoreSpi { private void setCertEntry(String alias, Certificate cert, Set attributes) throws KeyStoreException { + // Check that the cert is an X.509 cert + if (cert != null && (!(cert instanceof X509Certificate))) { + throw new KeyStoreException( + "Only X.509 certificates are supported - rejecting class: " + + cert.getClass().getName()); + } + Entry entry = entries.get(alias.toLowerCase(Locale.ENGLISH)); if (entry != null && entry instanceof KeyEntry) { throw new KeyStoreException("Cannot overwrite own certificate"); @@ -1505,6 +1518,21 @@ public final class PKCS12KeyStore extends KeyStoreSpi { return set.size() == certChain.length; } + /* + * Check that all the certificates are X.509 certificates + */ + private static void checkX509Certs(Certificate[] certs) + throws KeyStoreException { + if (certs != null) { + for (Certificate cert : certs) { + if (!(cert instanceof X509Certificate)) { + throw new KeyStoreException( + "Only X.509 certificates are supported - " + + "rejecting class: " + cert.getClass().getName()); + } + } + } + } /* * Create PKCS#12 Attributes, friendlyName, localKeyId and trustedKeyUsage. diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java b/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java index 3eb4ae86d4c..764f04cd545 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java @@ -59,6 +59,11 @@ public abstract class SSLContextImpl extends SSLContextSpi { "jdk.tls.client.enableStatusRequestExtension", true); private final boolean serverEnableStapling = Debug.getBooleanProperty( "jdk.tls.server.enableStatusRequestExtension", false); + private final static Collection clientCustomizedCipherSuites = + getCustomizedCipherSuites("jdk.tls.client.cipherSuites"); + private final static Collection serverCustomizedCipherSuites = + getCustomizedCipherSuites("jdk.tls.server.cipherSuites"); + private volatile StatusResponseManager statusResponseManager; SSLContextImpl() { @@ -336,20 +341,52 @@ public abstract class SSLContextImpl extends SSLContextSpi { return isClient ? clientEnableStapling : serverEnableStapling; } - /* - * Return the list of all available CipherSuites with a priority of - * minPriority or above. - */ - private static CipherSuiteList getApplicableCipherSuiteList( - ProtocolList protocols, boolean onlyEnabled) { - int minPriority = CipherSuite.SUPPORTED_SUITES_PRIORITY; - if (onlyEnabled) { - minPriority = CipherSuite.DEFAULT_SUITES_PRIORITY; + /* + * Return the list of all available CipherSuites that are supported + * using currently installed providers. + */ + private static CipherSuiteList getApplicableSupportedCipherSuiteList( + ProtocolList protocols) { + + return getApplicableCipherSuiteList( + CipherSuite.allowedCipherSuites(), + protocols, CipherSuite.SUPPORTED_SUITES_PRIORITY); + } + + /* + * Return the list of all available CipherSuites that are default enabled + * in client or server side. + */ + private static CipherSuiteList getApplicableEnabledCipherSuiteList( + ProtocolList protocols, boolean isClient) { + + if (isClient) { + if (!clientCustomizedCipherSuites.isEmpty()) { + return getApplicableCipherSuiteList( + clientCustomizedCipherSuites, + protocols, CipherSuite.SUPPORTED_SUITES_PRIORITY); + } + } else { + if (!serverCustomizedCipherSuites.isEmpty()) { + return getApplicableCipherSuiteList( + serverCustomizedCipherSuites, + protocols, CipherSuite.SUPPORTED_SUITES_PRIORITY); + } } - Collection allowedCipherSuites = - CipherSuite.allowedCipherSuites(); + return getApplicableCipherSuiteList( + CipherSuite.allowedCipherSuites(), + protocols, CipherSuite.DEFAULT_SUITES_PRIORITY); + } + + /* + * Return the list of available CipherSuites which are applicable to + * the specified protocols. + */ + private static CipherSuiteList getApplicableCipherSuiteList( + Collection allowedCipherSuites, + ProtocolList protocols, int minPriority) { TreeSet suites = new TreeSet<>(); if (!(protocols.collection().isEmpty()) && @@ -386,6 +423,67 @@ public abstract class SSLContextImpl extends SSLContextSpi { return new CipherSuiteList(suites); } + /* + * Get the customized cipher suites specified by the given system property. + */ + private static Collection getCustomizedCipherSuites( + String propertyName) { + + String property = GetPropertyAction.privilegedGetProperty(propertyName); + if (debug != null && Debug.isOn("sslctx")) { + System.out.println( + "System property " + propertyName + " is set to '" + + property + "'"); + } + if (property != null && property.length() != 0) { + // remove double quote marks from beginning/end of the property + if (property.length() > 1 && property.charAt(0) == '"' && + property.charAt(property.length() - 1) == '"') { + property = property.substring(1, property.length() - 1); + } + } + + if (property != null && property.length() != 0) { + String[] cipherSuiteNames = property.split(","); + Collection cipherSuites = + new ArrayList<>(cipherSuiteNames.length); + for (int i = 0; i < cipherSuiteNames.length; i++) { + cipherSuiteNames[i] = cipherSuiteNames[i].trim(); + if (cipherSuiteNames[i].isEmpty()) { + continue; + } + + CipherSuite suite; + try { + suite = CipherSuite.valueOf(cipherSuiteNames[i]); + } catch (IllegalArgumentException iae) { + if (debug != null && Debug.isOn("sslctx")) { + System.out.println( + "Unknown or unsupported cipher suite name: " + + cipherSuiteNames[i]); + } + + continue; + } + + if (suite.isAvailable()) { + cipherSuites.add(suite); + } else { + if (debug != null && Debug.isOn("sslctx")) { + System.out.println( + "The current installed providers do not " + + "support cipher suite: " + cipherSuiteNames[i]); + } + } + } + + return cipherSuites; + } + + return Collections.emptyList(); + } + + private static String[] getAvailableProtocols( ProtocolVersion[] protocolCandidates) { @@ -481,10 +579,10 @@ public abstract class SSLContextImpl extends SSLContextSpi { })); } - supportedCipherSuiteList = getApplicableCipherSuiteList( - supportedProtocolList, false); // all supported - serverDefaultCipherSuiteList = getApplicableCipherSuiteList( - serverDefaultProtocolList, true); // enabled only + supportedCipherSuiteList = getApplicableSupportedCipherSuiteList( + supportedProtocolList); + serverDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList( + serverDefaultProtocolList, false); } @Override @@ -541,8 +639,8 @@ public abstract class SSLContextImpl extends SSLContextSpi { })); } - clientDefaultCipherSuiteList = getApplicableCipherSuiteList( - clientDefaultProtocolList, true); // enabled only + clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList( + clientDefaultProtocolList, true); } @Override @@ -581,8 +679,9 @@ public abstract class SSLContextImpl extends SSLContextSpi { })); } - clientDefaultCipherSuiteList = getApplicableCipherSuiteList( - clientDefaultProtocolList, true); // enabled only + clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList( + clientDefaultProtocolList, true); + } @Override @@ -623,8 +722,8 @@ public abstract class SSLContextImpl extends SSLContextSpi { })); } - clientDefaultCipherSuiteList = getApplicableCipherSuiteList( - clientDefaultProtocolList, true); // enabled only + clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList( + clientDefaultProtocolList, true); } @Override @@ -757,8 +856,9 @@ public abstract class SSLContextImpl extends SSLContextSpi { clientDefaultProtocolList = new ProtocolList( getAvailableProtocols(candidates)); - clientDefaultCipherSuiteList = getApplicableCipherSuiteList( - clientDefaultProtocolList, true); // enabled only + clientDefaultCipherSuiteList = + getApplicableEnabledCipherSuiteList( + clientDefaultProtocolList, true); } else { clientDefaultProtocolList = null; // unlikely to be used clientDefaultCipherSuiteList = null; // unlikely to be used @@ -1032,10 +1132,10 @@ public abstract class SSLContextImpl extends SSLContextSpi { ProtocolVersion.DTLS12 })); - supportedCipherSuiteList = getApplicableCipherSuiteList( - supportedProtocolList, false); // all supported - serverDefaultCipherSuiteList = getApplicableCipherSuiteList( - serverDefaultProtocolList, true); // enabled only + supportedCipherSuiteList = getApplicableSupportedCipherSuiteList( + supportedProtocolList); + serverDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList( + serverDefaultProtocolList, false); } @Override @@ -1090,8 +1190,8 @@ public abstract class SSLContextImpl extends SSLContextSpi { ProtocolVersion.DTLS10 })); - clientDefaultCipherSuiteList = getApplicableCipherSuiteList( - clientDefaultProtocolList, true); // enabled only + clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList( + clientDefaultProtocolList, true); } @Override @@ -1122,8 +1222,8 @@ public abstract class SSLContextImpl extends SSLContextSpi { ProtocolVersion.DTLS12 })); - clientDefaultCipherSuiteList = getApplicableCipherSuiteList( - clientDefaultProtocolList, true); // enabled only + clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList( + clientDefaultProtocolList, true); } @Override @@ -1187,8 +1287,9 @@ public abstract class SSLContextImpl extends SSLContextSpi { clientDefaultProtocolList = new ProtocolList( getAvailableProtocols(candidates)); - clientDefaultCipherSuiteList = getApplicableCipherSuiteList( - clientDefaultProtocolList, true); // enabled only + clientDefaultCipherSuiteList = + getApplicableEnabledCipherSuiteList( + clientDefaultProtocolList, true); } else { clientDefaultProtocolList = null; // unlikely to be used clientDefaultCipherSuiteList = null; // unlikely to be used diff --git a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java index 12b5041ea41..6e26cc62128 100644 --- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java +++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java @@ -3631,8 +3631,8 @@ public final class Main { if (time != null) { if (time.matches("\\d\\d:\\d\\d:\\d\\d")) { c.set(Calendar.HOUR_OF_DAY, Integer.valueOf(time.substring(0, 2))); - c.set(Calendar.MINUTE, Integer.valueOf(time.substring(0, 2))); - c.set(Calendar.SECOND, Integer.valueOf(time.substring(0, 2))); + c.set(Calendar.MINUTE, Integer.valueOf(time.substring(3, 5))); + c.set(Calendar.SECOND, Integer.valueOf(time.substring(6, 8))); c.set(Calendar.MILLISECOND, 0); } else { throw ioe; diff --git a/jdk/src/java.compact1/share/classes/module-info.java b/jdk/src/java.compact1/share/classes/module-info.java index 8c604682cd4..112c71b66e0 100644 --- a/jdk/src/java.compact1/share/classes/module-info.java +++ b/jdk/src/java.compact1/share/classes/module-info.java @@ -23,6 +23,9 @@ * questions. */ +/** + * Aggregates {@code java.base}, {@code java.logging}, and {@code java.scripting}. + */ module java.compact1 { requires public java.logging; requires public java.scripting; diff --git a/jdk/src/java.compact2/share/classes/module-info.java b/jdk/src/java.compact2/share/classes/module-info.java index 31a738dcd8b..b19902435d7 100644 --- a/jdk/src/java.compact2/share/classes/module-info.java +++ b/jdk/src/java.compact2/share/classes/module-info.java @@ -23,6 +23,9 @@ * questions. */ +/** + * Supplements {@code java.compact1} with JDBC, JAXP, and RMI. + */ module java.compact2 { requires public java.compact1; requires public java.rmi; diff --git a/jdk/src/java.compact3/share/classes/module-info.java b/jdk/src/java.compact3/share/classes/module-info.java index cbc67be6319..05f33c0da0e 100644 --- a/jdk/src/java.compact3/share/classes/module-info.java +++ b/jdk/src/java.compact3/share/classes/module-info.java @@ -23,6 +23,10 @@ * questions. */ +/** + * Supplements {@code java.compact2} with JDBC RowSet, JMX, JNDI, Compiler, + * Instrumentation, Preferences, Security, and XML cryptography APIs. + */ module java.compact3 { requires public java.compact2; requires public java.compiler; diff --git a/jdk/src/java.datatransfer/share/classes/module-info.java b/jdk/src/java.datatransfer/share/classes/module-info.java index 2a19571e3b4..ea3f9c2a53c 100644 --- a/jdk/src/java.datatransfer/share/classes/module-info.java +++ b/jdk/src/java.datatransfer/share/classes/module-info.java @@ -24,10 +24,8 @@ */ /** - * Provides interfaces and classes for transferring data between and - * within applications. + * Defines an API for transferring data between and within applications. */ - module java.datatransfer { exports java.awt.datatransfer; exports sun.datatransfer to java.desktop; diff --git a/jdk/src/java.desktop/share/classes/module-info.java b/jdk/src/java.desktop/share/classes/module-info.java index 504c0c25451..93ab9a46aa2 100644 --- a/jdk/src/java.desktop/share/classes/module-info.java +++ b/jdk/src/java.desktop/share/classes/module-info.java @@ -24,9 +24,9 @@ */ /** - * java.desktop defines and exports the user interface, graphics - * and imaging APIs of the Java SE platform. - */ + * Defines the AWT and Swing user interface toolkits, plus APIs for + * accessibility, audio, imaging, printing, and JavaBeans. + */ module java.desktop { requires public java.datatransfer; requires public java.xml; diff --git a/jdk/src/java.httpclient/share/classes/module-info.java b/jdk/src/java.httpclient/share/classes/module-info.java index 5adf7f6e5b2..f24416d1dfb 100644 --- a/jdk/src/java.httpclient/share/classes/module-info.java +++ b/jdk/src/java.httpclient/share/classes/module-info.java @@ -23,6 +23,9 @@ * questions. */ +/** + * Defines the high-level HTTP and WebSocket API. + */ module java.httpclient { requires java.base; exports java.net.http; diff --git a/jdk/src/java.instrument/share/classes/module-info.java b/jdk/src/java.instrument/share/classes/module-info.java index 3eb704c6eab..27587d2c250 100644 --- a/jdk/src/java.instrument/share/classes/module-info.java +++ b/jdk/src/java.instrument/share/classes/module-info.java @@ -23,6 +23,10 @@ * questions. */ +/** + * Defines services that allow agents to + * instrument programs running on the JVM. + */ module java.instrument { exports java.lang.instrument; } diff --git a/jdk/src/java.logging/share/classes/module-info.java b/jdk/src/java.logging/share/classes/module-info.java index 47456e5ef5b..293d3873da1 100644 --- a/jdk/src/java.logging/share/classes/module-info.java +++ b/jdk/src/java.logging/share/classes/module-info.java @@ -23,6 +23,9 @@ * questions. */ +/** + * Defines the Java Logging API. + */ module java.logging { exports java.util.logging; provides jdk.internal.logger.DefaultLoggerFinder with diff --git a/jdk/src/java.management/share/classes/module-info.java b/jdk/src/java.management/share/classes/module-info.java index 8f7bd1b909e..6772da9d8ee 100644 --- a/jdk/src/java.management/share/classes/module-info.java +++ b/jdk/src/java.management/share/classes/module-info.java @@ -23,6 +23,12 @@ * questions. */ +/** + * Defines the Java Management Extensions (JMX) API. + *

+ * The JMX API consists of interfaces for monitoring and management of the + * JVM and other components in the Java runtime. + */ module java.management { requires public java.rmi; requires java.logging; diff --git a/jdk/src/java.naming/share/classes/module-info.java b/jdk/src/java.naming/share/classes/module-info.java index fb2e1018d76..b8964699610 100644 --- a/jdk/src/java.naming/share/classes/module-info.java +++ b/jdk/src/java.naming/share/classes/module-info.java @@ -23,6 +23,9 @@ * questions. */ +/** + * Defines the Java Naming and Directory Interface (JNDI) API. + */ module java.naming { requires java.security.sasl; diff --git a/jdk/src/java.prefs/share/classes/module-info.java b/jdk/src/java.prefs/share/classes/module-info.java index 3556b8eb395..4826cd2241b 100644 --- a/jdk/src/java.prefs/share/classes/module-info.java +++ b/jdk/src/java.prefs/share/classes/module-info.java @@ -23,6 +23,9 @@ * questions. */ +/** + * Defines the Preferences API. + */ module java.prefs { requires java.xml; diff --git a/jdk/src/java.rmi/share/classes/module-info.java b/jdk/src/java.rmi/share/classes/module-info.java index 44bd7288ca2..76195b6ec81 100644 --- a/jdk/src/java.rmi/share/classes/module-info.java +++ b/jdk/src/java.rmi/share/classes/module-info.java @@ -23,6 +23,9 @@ * questions. */ +/** + * Defines the Remote Method Invocation (RMI) API. + */ module java.rmi { requires java.logging; diff --git a/jdk/src/java.scripting/share/classes/module-info.java b/jdk/src/java.scripting/share/classes/module-info.java index b713ad0873b..b0a5baffc39 100644 --- a/jdk/src/java.scripting/share/classes/module-info.java +++ b/jdk/src/java.scripting/share/classes/module-info.java @@ -23,6 +23,9 @@ * questions. */ +/** + * Defines the Scripting API. + */ module java.scripting { exports javax.script; uses javax.script.ScriptEngineFactory; diff --git a/jdk/src/java.se/share/classes/module-info.java b/jdk/src/java.se/share/classes/module-info.java index 73d5d05c093..26aeb030675 100644 --- a/jdk/src/java.se/share/classes/module-info.java +++ b/jdk/src/java.se/share/classes/module-info.java @@ -23,6 +23,13 @@ * questions. */ +/** + * Defines the core Java SE API. + *

+ * The modules defining + * CORBA and Java EE APIs are not required by this module, but they are + * required by {@code java.se.ee}. + */ module java.se { requires public java.compact3; requires public java.datatransfer; diff --git a/jdk/src/java.security.jgss/share/classes/module-info.java b/jdk/src/java.security.jgss/share/classes/module-info.java index 0a1e6c02f7c..6380721852c 100644 --- a/jdk/src/java.security.jgss/share/classes/module-info.java +++ b/jdk/src/java.security.jgss/share/classes/module-info.java @@ -23,6 +23,11 @@ * questions. */ +/** + * Defines the Java binding of the IETF Generic Security Services API (GSS-API). + *

+ * This module also contains GSS-API mechanisms including Kerberos v5 and SPNEGO. + */ module java.security.jgss { requires java.naming; exports javax.security.auth.kerberos; diff --git a/jdk/src/java.security.sasl/share/classes/module-info.java b/jdk/src/java.security.sasl/share/classes/module-info.java index ca06592ac70..70f860b3ce9 100644 --- a/jdk/src/java.security.sasl/share/classes/module-info.java +++ b/jdk/src/java.security.sasl/share/classes/module-info.java @@ -23,6 +23,13 @@ * questions. */ +/** + * Defines Java support for the IETF Simple Authentication and Security Layer + * (SASL). + *

+ * This module also contains SASL mechanisms including DIGEST-MD5, + * CRAM-MD5, and NTLM. + */ module java.security.sasl { requires java.logging; diff --git a/jdk/src/java.smartcardio/share/classes/module-info.java b/jdk/src/java.smartcardio/share/classes/module-info.java index 18f39988cc8..05f4588cbf6 100644 --- a/jdk/src/java.smartcardio/share/classes/module-info.java +++ b/jdk/src/java.smartcardio/share/classes/module-info.java @@ -23,6 +23,9 @@ * questions. */ +/** + * Defines the Java Smart Card I/O API. + */ module java.smartcardio { exports javax.smartcardio; provides java.security.Provider with sun.security.smartcardio.SunPCSC; diff --git a/jdk/src/java.sql.rowset/share/classes/module-info.java b/jdk/src/java.sql.rowset/share/classes/module-info.java index a1cd9ce5772..8d24418b6f2 100644 --- a/jdk/src/java.sql.rowset/share/classes/module-info.java +++ b/jdk/src/java.sql.rowset/share/classes/module-info.java @@ -23,6 +23,9 @@ * questions. */ +/** + * Defines the JDBC RowSet API. + */ module java.sql.rowset { requires public java.logging; requires public java.naming; diff --git a/jdk/src/java.sql/share/classes/javax/sql/DataSource.java b/jdk/src/java.sql/share/classes/javax/sql/DataSource.java index dbdfd4c07de..4c3274d22d9 100644 --- a/jdk/src/java.sql/share/classes/javax/sql/DataSource.java +++ b/jdk/src/java.sql/share/classes/javax/sql/DataSource.java @@ -64,7 +64,7 @@ import java.sql.Wrapper; *

* A driver that is accessed via a {@code DataSource} object does not * register itself with the {@code DriverManager}. Rather, a - * {@code DataSource} object is retrieved though a lookup operation + * {@code DataSource} object is retrieved through a lookup operation * and then used to create a {@code Connection} object. With a basic * implementation, the connection obtained through a {@code DataSource} * object is identical to a connection obtained through the diff --git a/jdk/src/java.sql/share/classes/module-info.java b/jdk/src/java.sql/share/classes/module-info.java index 30683d94b06..70764a06d73 100644 --- a/jdk/src/java.sql/share/classes/module-info.java +++ b/jdk/src/java.sql/share/classes/module-info.java @@ -23,6 +23,9 @@ * questions. */ +/** + * Defines the JDBC API. + */ module java.sql { requires public java.logging; requires public java.xml; diff --git a/jdk/src/java.transaction/share/classes/module-info.java b/jdk/src/java.transaction/share/classes/module-info.java index de572d90cb5..84daf74a27d 100644 --- a/jdk/src/java.transaction/share/classes/module-info.java +++ b/jdk/src/java.transaction/share/classes/module-info.java @@ -23,6 +23,12 @@ * questions. */ +/** + * Defines a subset of the Java Transaction API (JTA) to support CORBA interop. + *

+ * The subset consists of RMI exception types which are mapped to CORBA system + * exceptions by the 'Java Language to IDL Mapping Specification'. + */ module java.transaction { requires public java.rmi; exports javax.transaction; diff --git a/jdk/src/java.xml.crypto/share/classes/module-info.java b/jdk/src/java.xml.crypto/share/classes/module-info.java index 1c92d07ad80..62694bba195 100644 --- a/jdk/src/java.xml.crypto/share/classes/module-info.java +++ b/jdk/src/java.xml.crypto/share/classes/module-info.java @@ -23,6 +23,9 @@ * questions. */ +/** + * Defines an API for XML cryptography. + */ module java.xml.crypto { requires public java.xml; requires java.logging; diff --git a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/Key.java b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/Key.java index 0124ffb3a40..8154c489a95 100644 --- a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/Key.java +++ b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/Key.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,6 @@ import sun.security.util.Length; /** * The handle for an RSA or DSA key using the Microsoft Crypto API. * - * @see DSAPrivateKey * @see RSAPrivateKey * @see RSAPublicKey * @@ -41,9 +40,35 @@ abstract class Key implements java.security.Key, Length { private static final long serialVersionUID = -1088859394025049194L; - // Native handle - protected long hCryptProv = 0; - protected long hCryptKey = 0; + static class NativeHandles { + long hCryptProv = 0; + long hCryptKey = 0; + + public NativeHandles(long hCryptProv, long hCryptKey) { + this.hCryptProv = hCryptProv; + this.hCryptKey = hCryptKey; + } + + /** + * Finalization method + */ + protected void finalize() throws Throwable + { + try { + synchronized(this) + { + cleanUp(hCryptProv, hCryptKey); + hCryptProv = 0; + hCryptKey = 0; + } + + } finally { + super.finalize(); + } + } + } + + protected NativeHandles handles; // Key length protected int keyLength = 0; @@ -51,31 +76,12 @@ abstract class Key implements java.security.Key, Length /** * Construct a Key object. */ - protected Key(long hCryptProv, long hCryptKey, int keyLength) + protected Key(NativeHandles handles, int keyLength) { - this.hCryptProv = hCryptProv; - this.hCryptKey = hCryptKey; + this.handles = handles; this.keyLength = keyLength; } - /** - * Finalization method - */ - protected void finalize() throws Throwable - { - try { - synchronized(this) - { - cleanUp(hCryptProv, hCryptKey); - hCryptProv = 0; - hCryptKey = 0; - } - - } finally { - super.finalize(); - } - } - /** * Native method to cleanup the key handle. */ @@ -96,7 +102,7 @@ abstract class Key implements java.security.Key, Length */ public long getHCryptKey() { - return hCryptKey; + return handles.hCryptKey; } /** @@ -104,12 +110,12 @@ abstract class Key implements java.security.Key, Length */ public long getHCryptProvider() { - return hCryptProv; + return handles.hCryptProv; } /** * Returns the standard algorithm name for this key. For - * example, "DSA" would indicate that this key is a DSA key. + * example, "RSA" would indicate that this key is a RSA key. * See Appendix A in the * Java Cryptography Architecture API Specification & Reference diff --git a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/KeyStore.java b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/KeyStore.java index 84828c156bf..c4888bf3049 100644 --- a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/KeyStore.java +++ b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/KeyStore.java @@ -168,7 +168,7 @@ abstract class KeyStore extends KeyStoreSpi { } certChain = chain; } - }; + } /* * An X.509 certificate factory. @@ -798,7 +798,8 @@ abstract class KeyStore extends KeyStoreSpi { } storeWithUniqueAlias(alias, new KeyEntry(alias, - new RSAPrivateKey(hCryptProv, hCryptKey, keyLength), + new RSAPrivateKey(new Key.NativeHandles(hCryptProv, + hCryptKey), keyLength), certChain)); } catch (Throwable e) @@ -854,7 +855,6 @@ abstract class KeyStore extends KeyStoreSpi { * Load keys and/or certificates from keystore into Collection. * * @param name Name of keystore. - * @param entries Collection of key/certificate. */ private native void loadKeysOrCertificateChains(String name) throws KeyStoreException; diff --git a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPair.java b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPair.java index 6fba2a23cd8..0880c20d85d 100644 --- a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPair.java +++ b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPair.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,8 +41,9 @@ class RSAKeyPair { */ RSAKeyPair(long hCryptProv, long hCryptKey, int keyLength) { - privateKey = new RSAPrivateKey(hCryptProv, hCryptKey, keyLength); - publicKey = new RSAPublicKey(hCryptProv, hCryptKey, keyLength); + Key.NativeHandles handles = new Key.NativeHandles(hCryptProv, hCryptKey); + privateKey = new RSAPrivateKey(handles, keyLength); + publicKey = new RSAPublicKey(handles, keyLength); } public RSAPrivateKey getPrivate() { diff --git a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAPrivateKey.java b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAPrivateKey.java index bc530f5372b..ca692dfa2f3 100644 --- a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAPrivateKey.java +++ b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAPrivateKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,15 @@ class RSAPrivateKey extends Key implements PrivateKey */ RSAPrivateKey(long hCryptProv, long hCryptKey, int keyLength) { - super(hCryptProv, hCryptKey, keyLength); + super(new NativeHandles(hCryptProv, hCryptKey), keyLength); + } + + /** + * Construct an RSAPrivateKey object. + */ + RSAPrivateKey(NativeHandles handles, int keyLength) + { + super(handles, keyLength); } /** @@ -63,8 +71,8 @@ class RSAPrivateKey extends Key implements PrivateKey public String toString() { return "RSAPrivateKey [size=" + keyLength + " bits, type=" + - getKeyType(hCryptKey) + ", container=" + - getContainerName(hCryptProv) + "]"; + getKeyType(handles.hCryptKey) + ", container=" + + getContainerName(handles.hCryptProv) + "]"; } // This class is not serializable diff --git a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAPublicKey.java b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAPublicKey.java index a62d783aa7c..52081abb5aa 100644 --- a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAPublicKey.java +++ b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAPublicKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,15 @@ class RSAPublicKey extends Key implements java.security.interfaces.RSAPublicKey */ RSAPublicKey(long hCryptProv, long hCryptKey, int keyLength) { - super(hCryptProv, hCryptKey, keyLength); + super(new NativeHandles(hCryptProv, hCryptKey), keyLength); + } + + /** + * Construct an RSAPublicKey object. + */ + RSAPublicKey(NativeHandles handles, int keyLength) + { + super(handles, keyLength); } /** @@ -77,8 +85,8 @@ class RSAPublicKey extends Key implements java.security.interfaces.RSAPublicKey StringBuffer sb = new StringBuffer(); sb.append("RSAPublicKey [size=").append(keyLength) - .append(" bits, type=").append(getKeyType(hCryptKey)) - .append(", container=").append(getContainerName(hCryptProv)) + .append(" bits, type=").append(getKeyType(handles.hCryptKey)) + .append(", container=").append(getContainerName(handles.hCryptProv)) .append("]\n modulus: ").append(getModulus()) .append("\n public exponent: ").append(getPublicExponent()); @@ -93,7 +101,7 @@ class RSAPublicKey extends Key implements java.security.interfaces.RSAPublicKey if (exponent == null) { try { - publicKeyBlob = getPublicKeyBlob(hCryptKey); + publicKeyBlob = getPublicKeyBlob(handles.hCryptKey); exponent = new BigInteger(1, getExponent(publicKeyBlob)); } catch (KeyException e) { @@ -112,7 +120,7 @@ class RSAPublicKey extends Key implements java.security.interfaces.RSAPublicKey if (modulus == null) { try { - publicKeyBlob = getPublicKeyBlob(hCryptKey); + publicKeyBlob = getPublicKeyBlob(handles.hCryptKey); modulus = new BigInteger(1, getModulus(publicKeyBlob)); } catch (KeyException e) { diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java index 1697e988b53..3866c95c2dc 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java @@ -55,7 +55,7 @@ public final class GenerateJLIClassesPlugin implements Plugin { private static final String DESCRIPTION = PluginsResourceBundle.getDescription(NAME); - private static final String DMH = "java/lang/invoke/DirectMethodHandle$Holder"; + private static final String DIRECT_METHOD_HANDLE = "java/lang/invoke/DirectMethodHandle$Holder"; private static final String DMH_INVOKE_VIRTUAL = "invokeVirtual"; private static final String DMH_INVOKE_STATIC = "invokeStatic"; private static final String DMH_INVOKE_SPECIAL = "invokeSpecial"; @@ -63,6 +63,8 @@ public final class GenerateJLIClassesPlugin implements Plugin { private static final String DMH_INVOKE_INTERFACE = "invokeInterface"; private static final String DMH_INVOKE_STATIC_INIT = "invokeStaticInit"; + private static final String DELEGATING_METHOD_HANDLE = "java/lang/invoke/DelegatingMethodHandle$Holder"; + private static final JavaLangInvokeAccess JLIA = SharedSecrets.getJavaLangInvokeAccess(); @@ -222,7 +224,15 @@ public final class GenerateJLIClassesPlugin implements Plugin { @Override public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) { // Copy all but DMH_ENTRY to out - in.transformAndCopy(entry -> entry.path().equals(DMH_ENTRY) ? null : entry, out); + in.transformAndCopy(entry -> { + // filter out placeholder entries + if (entry.path().equals(DIRECT_METHOD_HANDLE_ENTRY) || + entry.path().equals(DELEGATING_METHOD_HANDLE_ENTRY)) { + return null; + } else { + return entry; + } + }, out); speciesTypes.forEach(types -> generateBMHClass(types, out)); generateDMHClass(out); return out.build(); @@ -264,15 +274,24 @@ public final class GenerateJLIClassesPlugin implements Plugin { } } try { - byte[] bytes = - JLIA.generateDMHClassBytes(DMH, methodTypes, dmhTypes); - ResourcePoolEntry ndata = ResourcePoolEntry.create(DMH_ENTRY, bytes); + byte[] bytes = JLIA.generateDirectMethodHandleHolderClassBytes( + DIRECT_METHOD_HANDLE, methodTypes, dmhTypes); + ResourcePoolEntry ndata = ResourcePoolEntry + .create(DIRECT_METHOD_HANDLE_ENTRY, bytes); + out.add(ndata); + + bytes = JLIA.generateDelegatingMethodHandleHolderClassBytes( + DELEGATING_METHOD_HANDLE, methodTypes); + ndata = ResourcePoolEntry.create(DELEGATING_METHOD_HANDLE_ENTRY, bytes); out.add(ndata); } catch (Exception ex) { throw new PluginException(ex); } } - private static final String DMH_ENTRY = "/java.base/" + DMH + ".class"; + private static final String DIRECT_METHOD_HANDLE_ENTRY = + "/java.base/" + DIRECT_METHOD_HANDLE + ".class"; + private static final String DELEGATING_METHOD_HANDLE_ENTRY = + "/java.base/" + DELEGATING_METHOD_HANDLE + ".class"; // Convert LL -> LL, L3 -> LLL private static String expandSignature(String signature) { @@ -310,15 +329,19 @@ public final class GenerateJLIClassesPlugin implements Plugin { assert(parts.length == 2); assert(parts[1].length() == 1); String parameters = expandSignature(parts[0]); - Class rtype = primitiveType(parts[1].charAt(0)); - Class[] ptypes = new Class[parameters.length()]; - for (int i = 0; i < ptypes.length; i++) { - ptypes[i] = primitiveType(parameters.charAt(i)); + Class rtype = simpleType(parts[1].charAt(0)); + if (parameters.isEmpty()) { + return MethodType.methodType(rtype); + } else { + Class[] ptypes = new Class[parameters.length()]; + for (int i = 0; i < ptypes.length; i++) { + ptypes[i] = simpleType(parameters.charAt(i)); + } + return MethodType.methodType(rtype, ptypes); } - return MethodType.methodType(rtype, ptypes); } - private static Class primitiveType(char c) { + private static Class simpleType(char c) { switch (c) { case 'F': return float.class; diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 5bad9db84d4..50eb6e6b321 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -211,6 +211,8 @@ sun/rmi/rmic/newrmic/equivalence/run.sh 8145980 generic- java/rmi/transport/dgcDeadLock/DGCDeadLock.java 8029360 macosx-all +sun/rmi/runtime/Log/6409194/NoConsoleOutput.java 8164124 windows-all + ############################################################################ # jdk_security diff --git a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java b/jdk/test/java/lang/StackWalker/VerifyStackTrace.java index eb4a5085a5a..2c70a6d02dc 100644 --- a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java +++ b/jdk/test/java/lang/StackWalker/VerifyStackTrace.java @@ -205,8 +205,12 @@ public class VerifyStackTrace { .replaceAll("java.base@(\\d+\\.){0,3}(\\d+)/", "java.base/") .replaceAll("/[0-9]+\\.run", "/xxxxxxxx.run") .replaceAll("/[0-9]+\\.invoke", "/xxxxxxxx.invoke") + // DMHs may or may not be pre-generated, making frames differ .replaceAll("DirectMethodHandle\\$Holder", "LambdaForm\\$DMH") .replaceAll("DMH\\.invoke", "DMH/xxxxxxxx.invoke") + // invoke frames may or may not have basic method type + // information encoded for diagnostic purposes + .replaceAll("xx\\.invoke([A-Za-z]*)_[A-Z]+_[A-Z]", "xx.invoke$1") .replaceAll("\\$[0-9]+", "\\$??"); } else { return produced; diff --git a/jdk/test/java/security/KeyPairGenerator/FinalizeHalf.java b/jdk/test/java/security/KeyPairGenerator/FinalizeHalf.java new file mode 100644 index 00000000000..a2a1eb36194 --- /dev/null +++ b/jdk/test/java/security/KeyPairGenerator/FinalizeHalf.java @@ -0,0 +1,90 @@ +/* + * 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 8163896 + * @summary Finalizing one key of a KeyPair invalidates the other key + */ + +import java.security.Key; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.ProviderException; +import java.security.Security; +import java.util.function.Consumer; +import java.util.ArrayList; +import java.util.List; + +public class FinalizeHalf { + + static int failures = 0; + + public static void main(String[] args) throws Throwable { + List> methods = new ArrayList<>(); + methods.add((Key k) -> k.getEncoded()); + methods.add((Key k) -> k.toString()); + + for (String algo : new String[] {"DiffieHellman", "DSA", "RSA"}) { + for (Provider provider : Security.getProviders()) { + for (boolean priv : new boolean[] {true, false}) { + for (Consumer method : methods) { + test(algo, provider, priv, method); + } + } + } + } + + if (failures > 0) { + throw new RuntimeException(failures + " test(s) failed."); + } + } + + static void test(String algo, Provider provider, boolean priv, + Consumer method) throws Exception { + KeyPairGenerator generator; + try { + generator = KeyPairGenerator.getInstance(algo, provider); + } catch (NoSuchAlgorithmException nsae) { + return; + } + + System.out.println("Checking " + provider.getName() + ", " + algo); + + KeyPair pair = generator.generateKeyPair(); + Key key = priv ? pair.getPrivate() : pair.getPublic(); + + pair = null; + for (int i = 0; i < 32; ++i) { + System.gc(); + } + + try { + method.accept(key); + } catch (ProviderException pe) { + failures++; + } + } +} diff --git a/jdk/test/java/security/Security/ClassLoader/DeprivilegedModuleLoaderTest.java b/jdk/test/java/security/Security/ClassLoader/DeprivilegedModuleLoaderTest.java new file mode 100644 index 00000000000..b12259b6833 --- /dev/null +++ b/jdk/test/java/security/Security/ClassLoader/DeprivilegedModuleLoaderTest.java @@ -0,0 +1,90 @@ +/* + * 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. + */ + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import javax.security.auth.kerberos.KeyTab; +import javax.xml.crypto.KeySelectorException; +import javax.xml.crypto.dsig.XMLSignatureFactory; +import com.sun.security.auth.callback.TextCallbackHandler; +import com.sun.security.jgss.AuthorizationDataEntry; + +/* + * @test + * @bug 8159964 + * @summary Classes from deprivileged modules should get loaded through + * Platform Classloader. + * @run main DeprivilegedModuleLoaderTest + */ +public class DeprivilegedModuleLoaderTest { + + public static void main(String[] args) { + + boolean pass = true; + List> classes = getDeprivilegedClasses(); + for (Class cls : classes) { + try { + pass &= testPlatformClassLoader(cls); + } catch (Exception exc) { + exc.printStackTrace(System.out); + pass = false; + } + } + + if (!pass) { + throw new RuntimeException("Atleast one test failed."); + } + } + + private static List> getDeprivilegedClasses() { + + List> classes = new ArrayList>(); + // Test from java.xml.crypto/javax/xml/crypto/dsig package + classes.add(XMLSignatureFactory.class); + // Test from java.xml.crypto/javax/xml/crypto package + classes.add(KeySelectorException.class); + // Test From java.security.jgss/javax/security/auth/kerberos package + classes.add(KeyTab.class); + // Test from jdk.security.jgss/com/sun/security/jgss package + classes.add(AuthorizationDataEntry.class); + // Test from jdk.security.auth/com/sun/security/auth/callback package + classes.add(TextCallbackHandler.class); + return classes; + } + + private static boolean testPlatformClassLoader(Class cls) { + + ClassLoader loader = cls.getClassLoader(); + if (loader == null) { + throw new RuntimeException(String.format( + "Loaded through Bootstrap Classloader: '%s'", cls)); + } else if (!loader.toString().contains("PlatformClassLoader")) { + throw new RuntimeException(String.format( + "Not loaded through Platform ClassLoader: '%s'", cls)); + } + System.out.println(String.format( + "Pass: '%s' get loaded through PlatformClassLoader", cls)); + return true; + } +} diff --git a/jdk/test/java/security/testlibrary/SimpleOCSPServer.java b/jdk/test/java/security/testlibrary/SimpleOCSPServer.java index 77b8bb44642..4901e6f2651 100644 --- a/jdk/test/java/security/testlibrary/SimpleOCSPServer.java +++ b/jdk/test/java/security/testlibrary/SimpleOCSPServer.java @@ -64,6 +64,8 @@ public class SimpleOCSPServer { private static final SimpleDateFormat utcDateFmt = new SimpleDateFormat("MMM dd yyyy, HH:mm:ss z"); + static final int FREE_PORT = 0; + // CertStatus values public static enum CertStatus { CERT_STATUS_GOOD, @@ -88,7 +90,8 @@ public class SimpleOCSPServer { private volatile boolean started = false; private volatile boolean serverReady = false; private volatile boolean receivedShutdown = false; - private long delayMsec = 0; + private volatile boolean acceptConnections = true; + private volatile long delayMsec = 0; // Fields used in the generation of responses private long nextUpdateInterval = -1; @@ -116,7 +119,7 @@ public class SimpleOCSPServer { */ public SimpleOCSPServer(KeyStore ks, String password, String issuerAlias, String signerAlias) throws GeneralSecurityException, IOException { - this(null, 0, ks, password, issuerAlias, signerAlias); + this(null, FREE_PORT, ks, password, issuerAlias, signerAlias); } /** @@ -230,6 +233,15 @@ public class SimpleOCSPServer { while (!receivedShutdown) { try { Socket newConnection = servSocket.accept(); + if (!acceptConnections) { + try { + log("Reject connection"); + newConnection.close(); + } catch (IOException e) { + // ignore + } + continue; + } threadPool.submit(new OcspHandler(newConnection)); } catch (SocketTimeoutException timeout) { // Nothing to do here. If receivedShutdown @@ -256,6 +268,23 @@ public class SimpleOCSPServer { }); } + /** + * Make the OCSP server reject incoming connections. + */ + public synchronized void rejectConnections() { + log("Reject OCSP connections"); + acceptConnections = false; + } + + /** + * Make the OCSP server accept incoming connections. + */ + public synchronized void acceptConnections() { + log("Accept OCSP connections"); + acceptConnections = true; + } + + /** * Stop the OCSP server. */ @@ -499,13 +528,11 @@ public class SimpleOCSPServer { * on the incoming request. */ public void setDelay(long delayMillis) { - if (!started) { - delayMsec = delayMillis > 0 ? delayMillis : 0; - if (delayMsec > 0) { - log("OCSP latency set to " + delayMsec + " milliseconds."); - } else { - log("OCSP latency disabled"); - } + delayMsec = delayMillis > 0 ? delayMillis : 0; + if (delayMsec > 0) { + log("OCSP latency set to " + delayMsec + " milliseconds."); + } else { + log("OCSP latency disabled"); } } diff --git a/jdk/test/java/util/concurrent/BlockingQueue/PollMemoryLeak.java b/jdk/test/java/util/concurrent/BlockingQueue/PollMemoryLeak.java index f5a70ecf77f..070ee1e002d 100644 --- a/jdk/test/java/util/concurrent/BlockingQueue/PollMemoryLeak.java +++ b/jdk/test/java/util/concurrent/BlockingQueue/PollMemoryLeak.java @@ -26,43 +26,133 @@ * However, the following notice accompanied the original version of this * file: * - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at + * Written by Doug Lea and Martin Buchholz with assistance from + * members of JCP JSR-166 Expert Group and released to the public + * domain, as explained at * http://creativecommons.org/publicdomain/zero/1.0/ */ /* * @test * @bug 6236036 6264015 - * @compile PollMemoryLeak.java - * @run main/othervm -Xmx8m PollMemoryLeak - * @summary Checks for OutOfMemoryError when an unbounded - * number of aborted timed waits occur without a signal. + * @summary Checks for a memory leak when a sequence of aborted timed + * waits occur without a signal. Uses the strategy of detecting + * changes in the size of the object graph retained by a root object. */ +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.Set; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedTransferQueue; +import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.TimeUnit; public class PollMemoryLeak { - public static void main(String[] args) throws InterruptedException { - final BlockingQueue[] qs = { - new LinkedBlockingDeque(10), - new LinkedBlockingQueue(10), - new LinkedTransferQueue(), - new ArrayBlockingQueue(10), - new ArrayBlockingQueue(10, true), - new SynchronousQueue(), - new SynchronousQueue(true), - }; - final long start = System.currentTimeMillis(); - final long end = start + 10 * 1000; - while (System.currentTimeMillis() < end) - for (BlockingQueue q : qs) - q.poll(1, TimeUnit.NANOSECONDS); + public static void main(String[] args) throws Throwable { + new PollMemoryLeak().main(); + } + + void main() throws Throwable { + test(new LinkedBlockingDeque(10)); + test(new LinkedBlockingQueue(10)); + test(new LinkedTransferQueue()); + test(new ArrayBlockingQueue(10)); + test(new PriorityBlockingQueue()); + test(new SynchronousQueue()); + test(new SynchronousQueue(true)); + } + + void test(BlockingQueue q) throws Throwable { + assertNoLeak(q, () -> timedPoll(q)); + + // A demo that the leak detection infrastructure works + // assertNoLeak(q, () -> q.add(1)); + // printRetainedObjects(q); + } + + static void timedPoll(BlockingQueue q) { + try { q.poll(1, TimeUnit.NANOSECONDS); } + catch (InterruptedException ex) { throw new AssertionError(ex); } + } + + // -------- leak detection infrastructure --------------- + void assertNoLeak(Object root, Runnable r) { + int prev = retainedObjects(root).size(); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) r.run(); + int next = retainedObjects(root).size(); + if (next <= prev) + return; + prev = next; + } + throw new AssertionError( + String.format("probable memory leak in %s: %s", + root.getClass().getSimpleName(), root)); + } + + ConcurrentHashMap, Collection> classFields + = new ConcurrentHashMap, Collection>(); + + Collection referenceFieldsOf(Class k) { + Collection fields = classFields.get(k); + if (fields == null) { + fields = new ArrayDeque(); + ArrayDeque allFields = new ArrayDeque(); + for (Class c = k; c != null; c = c.getSuperclass()) + for (Field field : c.getDeclaredFields()) + if (!Modifier.isStatic(field.getModifiers()) + && !field.getType().isPrimitive()) + fields.add(field); + AccessibleObject.setAccessible( + fields.toArray(new AccessibleObject[0]), true); + classFields.put(k, fields); + } + return fields; + } + + static Object get(Field field, Object x) { + try { return field.get(x); } + catch (IllegalAccessException ex) { throw new AssertionError(ex); } + } + + Set retainedObjects(Object x) { + ArrayDeque todo = new ArrayDeque() { + public void push(Object x) { if (x != null) super.push(x); }}; + Set uniqueObjects = Collections.newSetFromMap( + new IdentityHashMap()); + todo.push(x); + while (!todo.isEmpty()) { + Object y = todo.pop(); + if (uniqueObjects.contains(y)) + continue; + uniqueObjects.add(y); + Class k = y.getClass(); + if (k.isArray() && !k.getComponentType().isPrimitive()) { + for (int i = 0, len = Array.getLength(y); i < len; i++) + todo.push(Array.get(y, i)); + } else { + for (Field field : referenceFieldsOf(k)) + todo.push(get(field, y)); + } + } + return uniqueObjects; + } + + /** for debugging the retained object graph */ + void printRetainedObjects(Object x) { + for (Object y : retainedObjects(x)) + System.out.printf("%s : %s%n", y.getClass().getSimpleName(), y); } } diff --git a/jdk/test/java/util/concurrent/ConcurrentLinkedQueue/RemoveLeak.java b/jdk/test/java/util/concurrent/ConcurrentLinkedQueue/RemoveLeak.java index fd1e52d197b..558cfb60981 100644 --- a/jdk/test/java/util/concurrent/ConcurrentLinkedQueue/RemoveLeak.java +++ b/jdk/test/java/util/concurrent/ConcurrentLinkedQueue/RemoveLeak.java @@ -35,26 +35,120 @@ * @test * @bug 8054446 8137184 8137185 * @summary Regression test for memory leak in remove(Object) - * @run main/othervm -Xmx2200k RemoveLeak */ +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.Set; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.LinkedTransferQueue; +import java.util.concurrent.PriorityBlockingQueue; public class RemoveLeak { - public static void main(String[] args) { - int i = 0; - // Without bug fix, OutOfMemoryError was observed at iteration 65120 - int iterations = 10 * 65120; - try { - ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>(); - queue.add(0L); - while (i++ < iterations) { - queue.add(1L); - queue.remove(1L); - } - } catch (Error t) { - System.err.printf("failed at iteration %d/%d%n", i, iterations); - throw t; + public static void main(String[] args) throws Throwable { + new RemoveLeak().main(); + } + + void main() throws Throwable { + test(new ConcurrentLinkedDeque()); + test(new ConcurrentLinkedQueue()); + test(new LinkedBlockingDeque(10)); + test(new LinkedBlockingQueue(10)); + test(new LinkedTransferQueue()); + test(new ArrayBlockingQueue(10)); + test(new PriorityBlockingQueue()); + } + + void test(Collection c) throws Throwable { + assertNoLeak(c, () -> addRemove(c)); + + // A demo that the leak detection infrastructure works + // assertNoLeak(c, () -> c.add(1)); + // printRetainedObjects(c); + } + + static void addRemove(Collection c) { + c.add(1); + c.remove(1); + } + + // -------- leak detection infrastructure --------------- + void assertNoLeak(Object root, Runnable r) { + int prev = retainedObjects(root).size(); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) r.run(); + int next = retainedObjects(root).size(); + if (next <= prev) + return; + prev = next; } + throw new AssertionError( + String.format("probable memory leak in %s: %s", + root.getClass().getSimpleName(), root)); + } + + ConcurrentHashMap, Collection> classFields + = new ConcurrentHashMap, Collection>(); + + Collection referenceFieldsOf(Class k) { + Collection fields = classFields.get(k); + if (fields == null) { + fields = new ArrayDeque(); + ArrayDeque allFields = new ArrayDeque(); + for (Class c = k; c != null; c = c.getSuperclass()) + for (Field field : c.getDeclaredFields()) + if (!Modifier.isStatic(field.getModifiers()) + && !field.getType().isPrimitive()) + fields.add(field); + AccessibleObject.setAccessible( + fields.toArray(new AccessibleObject[0]), true); + classFields.put(k, fields); + } + return fields; + } + + static Object get(Field field, Object x) { + try { return field.get(x); } + catch (IllegalAccessException ex) { throw new AssertionError(ex); } + } + + Set retainedObjects(Object x) { + ArrayDeque todo = new ArrayDeque() { + public void push(Object x) { if (x != null) super.push(x); }}; + Set uniqueObjects = Collections.newSetFromMap( + new IdentityHashMap()); + todo.push(x); + while (!todo.isEmpty()) { + Object y = todo.pop(); + if (uniqueObjects.contains(y)) + continue; + uniqueObjects.add(y); + Class k = y.getClass(); + if (k.isArray() && !k.getComponentType().isPrimitive()) { + for (int i = 0, len = Array.getLength(y); i < len; i++) + todo.push(Array.get(y, i)); + } else { + for (Field field : referenceFieldsOf(k)) + todo.push(get(field, y)); + } + } + return uniqueObjects; + } + + /** for debugging the retained object graph */ + void printRetainedObjects(Object x) { + for (Object y : retainedObjects(x)) + System.out.printf("%s : %s%n", y.getClass().getSimpleName(), y); } } diff --git a/jdk/test/java/util/concurrent/forkjoin/FJExceptionTableLeak.java b/jdk/test/java/util/concurrent/forkjoin/FJExceptionTableLeak.java index f2c728c2a71..b218aded0f8 100644 --- a/jdk/test/java/util/concurrent/forkjoin/FJExceptionTableLeak.java +++ b/jdk/test/java/util/concurrent/forkjoin/FJExceptionTableLeak.java @@ -26,51 +26,117 @@ * However, the following notice accompanied the original version of this * file: * - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at + * Written by Doug Lea and Martin Buchholz with assistance from + * members of JCP JSR-166 Expert Group and released to the public + * domain, as explained at * http://creativecommons.org/publicdomain/zero/1.0/ */ /* * @test - * @author Doug Lea * @bug 8004138 - * @key intermittent - * @summary Check if ForkJoinPool table leaks thrown exceptions. - * @run main/othervm -Xmx8m -Djava.util.concurrent.ForkJoinPool.common.parallelism=4 FJExceptionTableLeak + * @summary Checks that ForkJoinTask thrown exceptions are not leaked. + * This whitebox test is sensitive to forkjoin implementation details. */ +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.lang.ref.WeakReference; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; import java.util.concurrent.RecursiveAction; +import java.util.function.BooleanSupplier; public class FJExceptionTableLeak { - // This test was observed to fail with pre-bug-fix jdk7 -Xmx8m, - // using STEPS = 220 and TASKS_PER_STEP = 100 - static final int PRE_BUG_FIX_FAILURE_STEPS = 220; - static final int STEPS = 10 * PRE_BUG_FIX_FAILURE_STEPS; - static final int TASKS_PER_STEP = 100; - static class FailingTaskException extends RuntimeException {} static class FailingTask extends RecursiveAction { - public void compute() { - throw new FailingTaskException(); - } + public void compute() { throw new FailingTaskException(); } } - public static void main(String[] args) throws InterruptedException { - ForkJoinPool pool = new ForkJoinPool(4); - FailingTask[] tasks = new FailingTask[TASKS_PER_STEP]; - for (int k = 0; k < STEPS; ++k) { - for (int i = 0; i < tasks.length; ++i) - tasks[i] = new FailingTask(); - for (int i = 0; i < tasks.length; ++i) - pool.execute(tasks[i]); - for (int i = 0; i < tasks.length; ++i) { + static int bucketsInuse(Object[] exceptionTable) { + int count = 0; + for (Object x : exceptionTable) + if (x != null) count++; + return count; + } + + public static void main(String[] args) throws Exception { + final ForkJoinPool pool = new ForkJoinPool(4); + final Field exceptionTableField = + ForkJoinTask.class.getDeclaredField("exceptionTable"); + exceptionTableField.setAccessible(true); + final Object[] exceptionTable = (Object[]) exceptionTableField.get(null); + + if (bucketsInuse(exceptionTable) != 0) throw new AssertionError(); + + final ArrayList tasks = new ArrayList<>(); + + // Keep submitting failing tasks until most of the exception + // table buckets are in use + do { + for (int i = 0; i < exceptionTable.length; i++) { + FailingTask task = new FailingTask(); + pool.execute(task); + tasks.add(task); // retain strong refs to all tasks, for now + } + for (FailingTask task : tasks) { try { - tasks[i].join(); + task.join(); throw new AssertionError("should throw"); } catch (FailingTaskException success) {} } + } while (bucketsInuse(exceptionTable) < exceptionTable.length * 3 / 4); + + // Retain a strong ref to one last failing task; + // task.join() will trigger exception table expunging. + FailingTask lastTask = tasks.get(0); + + // Clear all other strong refs, making exception table cleanable + tasks.clear(); + + BooleanSupplier exceptionTableIsClean = () -> { + try { + lastTask.join(); + throw new AssertionError("should throw"); + } catch (FailingTaskException expected) {} + int count = bucketsInuse(exceptionTable); + if (count == 0) + throw new AssertionError("expected to find last task"); + return count == 1; + }; + gcAwait(exceptionTableIsClean); + } + + // --------------- GC finalization infrastructure --------------- + + /** No guarantees, but effective in practice. */ + static void forceFullGc() { + CountDownLatch finalizeDone = new CountDownLatch(1); + WeakReference ref = new WeakReference(new Object() { + protected void finalize() { finalizeDone.countDown(); }}); + try { + for (int i = 0; i < 10; i++) { + System.gc(); + if (finalizeDone.await(1L, SECONDS) && ref.get() == null) { + System.runFinalization(); // try to pick up stragglers + return; + } + } + } catch (InterruptedException unexpected) { + throw new AssertionError("unexpected InterruptedException"); } + throw new AssertionError("failed to do a \"full\" gc"); + } + + static void gcAwait(BooleanSupplier s) { + for (int i = 0; i < 10; i++) { + if (s.getAsBoolean()) + return; + forceFullGc(); + } + throw new AssertionError("failed to satisfy condition"); } } diff --git a/jdk/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java b/jdk/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java index e7fa0316197..9df1603ad46 100644 --- a/jdk/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java +++ b/jdk/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java @@ -492,7 +492,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase { }}); await(aboutToWait); - waitForThreadToEnterWaitState(t, LONG_DELAY_MS); + waitForThreadToEnterWaitState(t); t.interrupt(); awaitTermination(t); checkEmpty(q); diff --git a/jdk/test/java/util/concurrent/tck/AtomicBooleanTest.java b/jdk/test/java/util/concurrent/tck/AtomicBooleanTest.java index 91b5cfa8c1f..be136357ff1 100644 --- a/jdk/test/java/util/concurrent/tck/AtomicBooleanTest.java +++ b/jdk/test/java/util/concurrent/tck/AtomicBooleanTest.java @@ -136,11 +136,14 @@ public class AtomicBooleanTest extends JSR166TestCase { * getAndSet returns previous value and sets to given value */ public void testGetAndSet() { - AtomicBoolean ai = new AtomicBoolean(true); - assertEquals(true, ai.getAndSet(false)); - assertEquals(false, ai.getAndSet(false)); - assertEquals(false, ai.getAndSet(true)); - assertTrue(ai.get()); + AtomicBoolean ai = new AtomicBoolean(); + boolean[] booleans = { false, true }; + for (boolean before : booleans) + for (boolean after : booleans) { + ai.set(before); + assertEquals(before, ai.getAndSet(after)); + assertEquals(after, ai.get()); + } } /** diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java b/jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java index 518fab33170..18695548129 100644 --- a/jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java +++ b/jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java @@ -433,7 +433,7 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { Integer[] elements = new Integer[size]; for (int i = 0; i < size; i++) elements[i] = i; - Collections.shuffle(Arrays.asList(elements)); + shuffle(elements); Collection full = populatedSet(elements); Iterator it = full.iterator(); @@ -523,7 +523,7 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { Integer[] elements = new Integer[size]; for (int i = 0; i < size; i++) elements[i] = i; - Collections.shuffle(Arrays.asList(elements)); + shuffle(elements); Collection full = populatedSet(elements); assertTrue(Arrays.asList(elements).containsAll(Arrays.asList(full.toArray()))); @@ -553,7 +553,7 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { Integer[] elements = new Integer[size]; for (int i = 0; i < size; i++) elements[i] = i; - Collections.shuffle(Arrays.asList(elements)); + shuffle(elements); Collection full = populatedSet(elements); Arrays.fill(a, 42); diff --git a/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java b/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java index 75cfb1435fc..e8be651d53d 100644 --- a/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java +++ b/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java @@ -291,7 +291,7 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase { Integer[] elements = new Integer[SIZE]; for (int i = 0; i < SIZE; i++) elements[i] = i; - Collections.shuffle(Arrays.asList(elements)); + shuffle(elements); Collection full = populatedArray(elements); Iterator it = full.iterator(); @@ -459,7 +459,7 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase { Integer[] elements = new Integer[SIZE]; for (int i = 0; i < SIZE; i++) elements[i] = i; - Collections.shuffle(Arrays.asList(elements)); + shuffle(elements); Collection full = populatedArray(elements); assertTrue(Arrays.equals(elements, full.toArray())); @@ -487,7 +487,7 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase { Integer[] elements = new Integer[SIZE]; for (int i = 0; i < SIZE; i++) elements[i] = i; - Collections.shuffle(Arrays.asList(elements)); + shuffle(elements); Collection full = populatedArray(elements); Arrays.fill(a, 42); diff --git a/jdk/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java b/jdk/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java index bd9a7e3da43..21f932e09a3 100644 --- a/jdk/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java +++ b/jdk/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java @@ -251,7 +251,7 @@ public class CopyOnWriteArraySetTest extends JSR166TestCase { Integer[] elements = new Integer[SIZE]; for (int i = 0; i < SIZE; i++) elements[i] = i; - Collections.shuffle(Arrays.asList(elements)); + shuffle(elements); Collection full = populatedSet(elements); Iterator it = full.iterator(); @@ -338,7 +338,7 @@ public class CopyOnWriteArraySetTest extends JSR166TestCase { Integer[] elements = new Integer[SIZE]; for (int i = 0; i < SIZE; i++) elements[i] = i; - Collections.shuffle(Arrays.asList(elements)); + shuffle(elements); Collection full = populatedSet(elements); assertTrue(Arrays.equals(elements, full.toArray())); @@ -366,7 +366,7 @@ public class CopyOnWriteArraySetTest extends JSR166TestCase { Integer[] elements = new Integer[SIZE]; for (int i = 0; i < SIZE; i++) elements[i] = i; - Collections.shuffle(Arrays.asList(elements)); + shuffle(elements); Collection full = populatedSet(elements); Arrays.fill(a, 42); diff --git a/jdk/test/java/util/concurrent/tck/ForkJoinTask8Test.java b/jdk/test/java/util/concurrent/tck/ForkJoinTask8Test.java index c8fe1bb9986..54e944b54d0 100644 --- a/jdk/test/java/util/concurrent/tck/ForkJoinTask8Test.java +++ b/jdk/test/java/util/concurrent/tck/ForkJoinTask8Test.java @@ -948,7 +948,7 @@ public class ForkJoinTask8Test extends JSR166TestCase { AsyncFib f = new AsyncFib(8); FailingAsyncFib g = new FailingAsyncFib(9); ForkJoinTask[] tasks = { f, g }; - Collections.shuffle(Arrays.asList(tasks)); + shuffle(tasks); try { invokeAll(tasks[0], tasks[1]); shouldThrow(); @@ -975,7 +975,7 @@ public class ForkJoinTask8Test extends JSR166TestCase { FailingAsyncFib g = new FailingAsyncFib(9); AsyncFib h = new AsyncFib(7); ForkJoinTask[] tasks = { f, g, h }; - Collections.shuffle(Arrays.asList(tasks)); + shuffle(tasks); try { invokeAll(tasks[0], tasks[1], tasks[2]); shouldThrow(); @@ -1002,7 +1002,7 @@ public class ForkJoinTask8Test extends JSR166TestCase { AsyncFib g = new AsyncFib(9); AsyncFib h = new AsyncFib(7); ForkJoinTask[] tasks = { f, g, h }; - Collections.shuffle(Arrays.asList(tasks)); + shuffle(tasks); try { invokeAll(Arrays.asList(tasks)); shouldThrow(); diff --git a/jdk/test/java/util/concurrent/tck/ForkJoinTaskTest.java b/jdk/test/java/util/concurrent/tck/ForkJoinTaskTest.java index 7000c1a4bb5..c3e1c1802a5 100644 --- a/jdk/test/java/util/concurrent/tck/ForkJoinTaskTest.java +++ b/jdk/test/java/util/concurrent/tck/ForkJoinTaskTest.java @@ -924,7 +924,7 @@ public class ForkJoinTaskTest extends JSR166TestCase { AsyncFib f = new AsyncFib(8); FailingAsyncFib g = new FailingAsyncFib(9); ForkJoinTask[] tasks = { f, g }; - Collections.shuffle(Arrays.asList(tasks)); + shuffle(tasks); try { invokeAll(tasks); shouldThrow(); @@ -962,7 +962,7 @@ public class ForkJoinTaskTest extends JSR166TestCase { FailingAsyncFib g = new FailingAsyncFib(9); AsyncFib h = new AsyncFib(7); ForkJoinTask[] tasks = { f, g, h }; - Collections.shuffle(Arrays.asList(tasks)); + shuffle(tasks); try { invokeAll(tasks); shouldThrow(); @@ -983,10 +983,9 @@ public class ForkJoinTaskTest extends JSR166TestCase { AsyncFib g = new AsyncFib(9); AsyncFib h = new AsyncFib(7); ForkJoinTask[] tasks = { f, g, h }; - List taskList = Arrays.asList(tasks); - Collections.shuffle(taskList); + shuffle(tasks); try { - invokeAll(taskList); + invokeAll(Arrays.asList(tasks)); shouldThrow(); } catch (FJException success) { checkCompletedAbnormally(f, success); @@ -1594,7 +1593,7 @@ public class ForkJoinTaskTest extends JSR166TestCase { AsyncFib f = new AsyncFib(8); FailingAsyncFib g = new FailingAsyncFib(9); ForkJoinTask[] tasks = { f, g }; - Collections.shuffle(Arrays.asList(tasks)); + shuffle(tasks); try { invokeAll(tasks); shouldThrow(); @@ -1632,7 +1631,7 @@ public class ForkJoinTaskTest extends JSR166TestCase { FailingAsyncFib g = new FailingAsyncFib(9); AsyncFib h = new AsyncFib(7); ForkJoinTask[] tasks = { f, g, h }; - Collections.shuffle(Arrays.asList(tasks)); + shuffle(tasks); try { invokeAll(tasks); shouldThrow(); @@ -1653,10 +1652,9 @@ public class ForkJoinTaskTest extends JSR166TestCase { AsyncFib g = new AsyncFib(9); AsyncFib h = new AsyncFib(7); ForkJoinTask[] tasks = { f, g, h }; - List taskList = Arrays.asList(tasks); - Collections.shuffle(taskList); + shuffle(tasks); try { - invokeAll(taskList); + invokeAll(Arrays.asList(tasks)); shouldThrow(); } catch (FJException success) { checkCompletedAbnormally(f, success); diff --git a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java index a1e0b7bc1c9..f6c3e2a930c 100644 --- a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java +++ b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java @@ -68,6 +68,7 @@ import java.security.ProtectionDomain; import java.security.SecurityPermission; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.Enumeration; import java.util.Iterator; @@ -89,6 +90,7 @@ import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.Semaphore; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; @@ -1278,7 +1280,7 @@ public class JSR166TestCase extends TestCase { * thread to enter a wait state: BLOCKED, WAITING, or TIMED_WAITING. */ void waitForThreadToEnterWaitState(Thread thread, long timeoutMillis) { - long startTime = System.nanoTime(); + long startTime = 0L; for (;;) { Thread.State s = thread.getState(); if (s == Thread.State.BLOCKED || @@ -1287,6 +1289,8 @@ public class JSR166TestCase extends TestCase { return; else if (s == Thread.State.TERMINATED) fail("Unexpected thread termination"); + else if (startTime == 0L) + startTime = System.nanoTime(); else if (millisElapsedSince(startTime) > timeoutMillis) { threadAssertTrue(thread.isAlive()); return; @@ -1900,4 +1904,7 @@ public class JSR166TestCase extends TestCase { 1000L, MILLISECONDS, new SynchronousQueue()); + static void shuffle(T[] array) { + Collections.shuffle(Arrays.asList(array), ThreadLocalRandom.current()); + } } diff --git a/jdk/test/java/util/concurrent/tck/LinkedBlockingDequeTest.java b/jdk/test/java/util/concurrent/tck/LinkedBlockingDequeTest.java index 138799035cb..4950584833d 100644 --- a/jdk/test/java/util/concurrent/tck/LinkedBlockingDequeTest.java +++ b/jdk/test/java/util/concurrent/tck/LinkedBlockingDequeTest.java @@ -792,7 +792,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase { }}); aboutToWait.await(); - waitForThreadToEnterWaitState(t, LONG_DELAY_MS); + waitForThreadToEnterWaitState(t); t.interrupt(); awaitTermination(t); checkEmpty(q); diff --git a/jdk/test/java/util/concurrent/tck/LinkedBlockingQueueTest.java b/jdk/test/java/util/concurrent/tck/LinkedBlockingQueueTest.java index 51246e903a6..125e6a54571 100644 --- a/jdk/test/java/util/concurrent/tck/LinkedBlockingQueueTest.java +++ b/jdk/test/java/util/concurrent/tck/LinkedBlockingQueueTest.java @@ -481,7 +481,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase { }}); await(aboutToWait); - waitForThreadToEnterWaitState(t, LONG_DELAY_MS); + waitForThreadToEnterWaitState(t); t.interrupt(); awaitTermination(t); checkEmpty(q); diff --git a/jdk/test/java/util/concurrent/tck/PriorityBlockingQueueTest.java b/jdk/test/java/util/concurrent/tck/PriorityBlockingQueueTest.java index 2c4dbd0fe98..7b22c6ed7b4 100644 --- a/jdk/test/java/util/concurrent/tck/PriorityBlockingQueueTest.java +++ b/jdk/test/java/util/concurrent/tck/PriorityBlockingQueueTest.java @@ -437,7 +437,7 @@ public class PriorityBlockingQueueTest extends JSR166TestCase { }}); aboutToWait.await(); - waitForThreadToEnterWaitState(t, LONG_DELAY_MS); + waitForThreadToEnterWaitState(t); t.interrupt(); awaitTermination(t); } diff --git a/jdk/test/java/util/concurrent/tck/StampedLockTest.java b/jdk/test/java/util/concurrent/tck/StampedLockTest.java index d71d6546aca..5ced6c93d4d 100644 --- a/jdk/test/java/util/concurrent/tck/StampedLockTest.java +++ b/jdk/test/java/util/concurrent/tck/StampedLockTest.java @@ -34,10 +34,12 @@ import static java.util.concurrent.TimeUnit.DAYS; import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.StampedLock; @@ -56,208 +58,189 @@ public class StampedLockTest extends JSR166TestCase { return new TestSuite(StampedLockTest.class); } - /** - * A runnable calling writeLockInterruptibly - */ - class InterruptibleLockRunnable extends CheckedRunnable { - final StampedLock lock; - InterruptibleLockRunnable(StampedLock l) { lock = l; } - public void realRun() throws InterruptedException { - lock.writeLockInterruptibly(); - } - } - - /** - * A runnable calling writeLockInterruptibly that expects to be - * interrupted - */ - class InterruptedLockRunnable extends CheckedInterruptedRunnable { - final StampedLock lock; - InterruptedLockRunnable(StampedLock l) { lock = l; } - public void realRun() throws InterruptedException { - lock.writeLockInterruptibly(); - } - } - /** * Releases write lock, checking isWriteLocked before and after */ - void releaseWriteLock(StampedLock lock, long s) { + void releaseWriteLock(StampedLock lock, long stamp) { assertTrue(lock.isWriteLocked()); - lock.unlockWrite(s); + assertValid(lock, stamp); + lock.unlockWrite(stamp); assertFalse(lock.isWriteLocked()); + assertFalse(lock.validate(stamp)); + } + + /** + * Releases read lock, checking isReadLocked before and after + */ + void releaseReadLock(StampedLock lock, long stamp) { + assertTrue(lock.isReadLocked()); + assertValid(lock, stamp); + lock.unlockRead(stamp); + assertFalse(lock.isReadLocked()); + assertTrue(lock.validate(stamp)); + } + + long assertNonZero(long v) { + assertTrue(v != 0L); + return v; + } + + long assertValid(StampedLock lock, long stamp) { + assertTrue(stamp != 0L); + assertTrue(lock.validate(stamp)); + return stamp; + } + + void assertUnlocked(StampedLock lock) { + assertFalse(lock.isReadLocked()); + assertFalse(lock.isWriteLocked()); + assertEquals(0, lock.getReadLockCount()); + assertValid(lock, lock.tryOptimisticRead()); + } + + List lockLockers(Lock lock) { + List lockers = new ArrayList<>(); + lockers.add(() -> lock.lock()); + lockers.add(() -> lock.lockInterruptibly()); + lockers.add(() -> lock.tryLock()); + lockers.add(() -> lock.tryLock(Long.MIN_VALUE, DAYS)); + lockers.add(() -> lock.tryLock(0L, DAYS)); + lockers.add(() -> lock.tryLock(Long.MAX_VALUE, DAYS)); + return lockers; + } + + List> readLockers() { + List> readLockers = new ArrayList<>(); + readLockers.add((sl) -> sl.readLock()); + readLockers.add((sl) -> sl.tryReadLock()); + readLockers.add((sl) -> readLockInterruptiblyUninterrupted(sl)); + readLockers.add((sl) -> tryReadLockUninterrupted(sl, Long.MIN_VALUE, DAYS)); + readLockers.add((sl) -> tryReadLockUninterrupted(sl, 0L, DAYS)); + readLockers.add((sl) -> sl.tryConvertToReadLock(sl.tryOptimisticRead())); + return readLockers; + } + + List> readUnlockers() { + List> readUnlockers = new ArrayList<>(); + readUnlockers.add((sl, stamp) -> sl.unlockRead(stamp)); + readUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockRead())); + readUnlockers.add((sl, stamp) -> sl.asReadLock().unlock()); + readUnlockers.add((sl, stamp) -> sl.unlock(stamp)); + readUnlockers.add((sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp))); + return readUnlockers; + } + + List> writeLockers() { + List> writeLockers = new ArrayList<>(); + writeLockers.add((sl) -> sl.writeLock()); + writeLockers.add((sl) -> sl.tryWriteLock()); + writeLockers.add((sl) -> writeLockInterruptiblyUninterrupted(sl)); + writeLockers.add((sl) -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS)); + writeLockers.add((sl) -> tryWriteLockUninterrupted(sl, 0L, DAYS)); + writeLockers.add((sl) -> sl.tryConvertToWriteLock(sl.tryOptimisticRead())); + return writeLockers; + } + + List> writeUnlockers() { + List> writeUnlockers = new ArrayList<>(); + writeUnlockers.add((sl, stamp) -> sl.unlockWrite(stamp)); + writeUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockWrite())); + writeUnlockers.add((sl, stamp) -> sl.asWriteLock().unlock()); + writeUnlockers.add((sl, stamp) -> sl.unlock(stamp)); + writeUnlockers.add((sl, stamp) -> assertValid(sl, sl.tryConvertToOptimisticRead(stamp))); + return writeUnlockers; } /** * Constructed StampedLock is in unlocked state */ public void testConstructor() { - StampedLock lock; - lock = new StampedLock(); - assertFalse(lock.isWriteLocked()); - assertFalse(lock.isReadLocked()); - assertEquals(lock.getReadLockCount(), 0); + assertUnlocked(new StampedLock()); } /** - * write-locking and read-locking an unlocked lock succeed + * write-locking, then unlocking, an unlocked lock succeed */ - public void testLock() { + public void testWriteLock_lockUnlock() { StampedLock lock = new StampedLock(); - assertFalse(lock.isWriteLocked()); - assertFalse(lock.isReadLocked()); - assertEquals(lock.getReadLockCount(), 0); - long s = lock.writeLock(); - assertTrue(lock.isWriteLocked()); - assertFalse(lock.isReadLocked()); - assertEquals(lock.getReadLockCount(), 0); - lock.unlockWrite(s); - assertFalse(lock.isWriteLocked()); - assertFalse(lock.isReadLocked()); - assertEquals(lock.getReadLockCount(), 0); - long rs = lock.readLock(); - assertFalse(lock.isWriteLocked()); - assertTrue(lock.isReadLocked()); - assertEquals(lock.getReadLockCount(), 1); - lock.unlockRead(rs); - assertFalse(lock.isWriteLocked()); - assertFalse(lock.isReadLocked()); - assertEquals(lock.getReadLockCount(), 0); + + for (Function writeLocker : writeLockers()) + for (BiConsumer writeUnlocker : writeUnlockers()) { + assertFalse(lock.isWriteLocked()); + assertFalse(lock.isReadLocked()); + assertEquals(0, lock.getReadLockCount()); + + long s = writeLocker.apply(lock); + assertValid(lock, s); + assertTrue(lock.isWriteLocked()); + assertFalse(lock.isReadLocked()); + assertEquals(0, lock.getReadLockCount()); + writeUnlocker.accept(lock, s); + assertUnlocked(lock); + } } /** - * unlock releases either a read or write lock + * read-locking, then unlocking, an unlocked lock succeed */ - public void testUnlock() { + public void testReadLock_lockUnlock() { StampedLock lock = new StampedLock(); - assertFalse(lock.isWriteLocked()); - assertFalse(lock.isReadLocked()); - assertEquals(lock.getReadLockCount(), 0); - long s = lock.writeLock(); - assertTrue(lock.isWriteLocked()); - assertFalse(lock.isReadLocked()); - assertEquals(lock.getReadLockCount(), 0); - lock.unlock(s); - assertFalse(lock.isWriteLocked()); - assertFalse(lock.isReadLocked()); - assertEquals(lock.getReadLockCount(), 0); - long rs = lock.readLock(); - assertFalse(lock.isWriteLocked()); - assertTrue(lock.isReadLocked()); - assertEquals(lock.getReadLockCount(), 1); - lock.unlock(rs); - assertFalse(lock.isWriteLocked()); - assertFalse(lock.isReadLocked()); - assertEquals(lock.getReadLockCount(), 0); + + for (Function readLocker : readLockers()) + for (BiConsumer readUnlocker : readUnlockers()) { + long s = 42; + for (int i = 0; i < 2; i++) { + s = assertValid(lock, readLocker.apply(lock)); + assertFalse(lock.isWriteLocked()); + assertTrue(lock.isReadLocked()); + assertEquals(i + 1, lock.getReadLockCount()); + } + for (int i = 0; i < 2; i++) { + assertFalse(lock.isWriteLocked()); + assertTrue(lock.isReadLocked()); + assertEquals(2 - i, lock.getReadLockCount()); + readUnlocker.accept(lock, s); + } + assertUnlocked(lock); + } } /** - * tryUnlockRead/Write succeeds if locked in associated mode else - * returns false + * tryUnlockWrite fails if not write locked */ - public void testTryUnlock() { + public void testTryUnlockWrite_failure() { StampedLock lock = new StampedLock(); - assertFalse(lock.isWriteLocked()); - assertFalse(lock.isReadLocked()); - assertEquals(lock.getReadLockCount(), 0); - long s = lock.writeLock(); - assertTrue(lock.isWriteLocked()); - assertFalse(lock.isReadLocked()); - assertEquals(lock.getReadLockCount(), 0); - assertFalse(lock.tryUnlockRead()); - assertTrue(lock.tryUnlockWrite()); assertFalse(lock.tryUnlockWrite()); + + for (Function readLocker : readLockers()) + for (BiConsumer readUnlocker : readUnlockers()) { + long s = assertValid(lock, readLocker.apply(lock)); + assertFalse(lock.tryUnlockWrite()); + assertTrue(lock.isReadLocked()); + readUnlocker.accept(lock, s); + assertUnlocked(lock); + } + } + + /** + * tryUnlockRead fails if not read locked + */ + public void testTryUnlockRead_failure() { + StampedLock lock = new StampedLock(); assertFalse(lock.tryUnlockRead()); - assertFalse(lock.isWriteLocked()); - assertFalse(lock.isReadLocked()); - assertEquals(lock.getReadLockCount(), 0); - long rs = lock.readLock(); - assertFalse(lock.isWriteLocked()); - assertTrue(lock.isReadLocked()); - assertEquals(lock.getReadLockCount(), 1); - assertFalse(lock.tryUnlockWrite()); - assertTrue(lock.tryUnlockRead()); - assertFalse(lock.tryUnlockRead()); - assertFalse(lock.tryUnlockWrite()); - assertFalse(lock.isWriteLocked()); - assertFalse(lock.isReadLocked()); - assertEquals(lock.getReadLockCount(), 0); + + for (Function writeLocker : writeLockers()) + for (BiConsumer writeUnlocker : writeUnlockers()) { + long s = writeLocker.apply(lock); + assertFalse(lock.tryUnlockRead()); + assertTrue(lock.isWriteLocked()); + writeUnlocker.accept(lock, s); + assertUnlocked(lock); + } } /** - * write-unlocking an unlocked lock throws IllegalMonitorStateException - */ - public void testWriteUnlock_IMSE() { - StampedLock lock = new StampedLock(); - try { - lock.unlockWrite(0L); - shouldThrow(); - } catch (IllegalMonitorStateException success) {} - } - - /** - * write-unlocking an unlocked lock throws IllegalMonitorStateException - */ - public void testWriteUnlock_IMSE2() { - StampedLock lock = new StampedLock(); - long s = lock.writeLock(); - lock.unlockWrite(s); - try { - lock.unlockWrite(s); - shouldThrow(); - } catch (IllegalMonitorStateException success) {} - } - - /** - * write-unlocking after readlock throws IllegalMonitorStateException - */ - public void testWriteUnlock_IMSE3() { - StampedLock lock = new StampedLock(); - long s = lock.readLock(); - try { - lock.unlockWrite(s); - shouldThrow(); - } catch (IllegalMonitorStateException success) {} - } - - /** - * read-unlocking an unlocked lock throws IllegalMonitorStateException - */ - public void testReadUnlock_IMSE() { - StampedLock lock = new StampedLock(); - long s = lock.readLock(); - lock.unlockRead(s); - try { - lock.unlockRead(s); - shouldThrow(); - } catch (IllegalMonitorStateException success) {} - } - - /** - * read-unlocking an unlocked lock throws IllegalMonitorStateException - */ - public void testReadUnlock_IMSE2() { - StampedLock lock = new StampedLock(); - try { - lock.unlockRead(0L); - shouldThrow(); - } catch (IllegalMonitorStateException success) {} - } - - /** - * read-unlocking after writeLock throws IllegalMonitorStateException - */ - public void testReadUnlock_IMSE3() { - StampedLock lock = new StampedLock(); - long s = lock.writeLock(); - try { - lock.unlockRead(s); - shouldThrow(); - } catch (IllegalMonitorStateException success) {} - } - - /** - * validate(0) fails + * validate(0L) fails */ public void testValidate0() { StampedLock lock = new StampedLock(); @@ -265,29 +248,24 @@ public class StampedLockTest extends JSR166TestCase { } /** - * A stamp obtained from a successful lock operation validates + * A stamp obtained from a successful lock operation validates while the lock is held */ public void testValidate() throws InterruptedException { StampedLock lock = new StampedLock(); - long s = lock.writeLock(); - assertTrue(lock.validate(s)); - lock.unlockWrite(s); - s = lock.readLock(); - assertTrue(lock.validate(s)); - lock.unlockRead(s); - assertTrue((s = lock.tryWriteLock()) != 0L); - assertTrue(lock.validate(s)); - lock.unlockWrite(s); - assertTrue((s = lock.tryReadLock()) != 0L); - assertTrue(lock.validate(s)); - lock.unlockRead(s); - assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L); - assertTrue(lock.validate(s)); - lock.unlockWrite(s); - assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L); - assertTrue(lock.validate(s)); - lock.unlockRead(s); - assertTrue((s = lock.tryOptimisticRead()) != 0L); + + for (Function readLocker : readLockers()) + for (BiConsumer readUnlocker : readUnlockers()) { + long s = assertNonZero(readLocker.apply(lock)); + assertTrue(lock.validate(s)); + readUnlocker.accept(lock, s); + } + + for (Function writeLocker : writeLockers()) + for (BiConsumer writeUnlocker : writeUnlockers()) { + long s = assertNonZero(writeLocker.apply(lock)); + assertTrue(lock.validate(s)); + writeUnlocker.accept(lock, s); + } } /** @@ -295,124 +273,190 @@ public class StampedLockTest extends JSR166TestCase { */ public void testValidate2() throws InterruptedException { StampedLock lock = new StampedLock(); - long s; - assertTrue((s = lock.writeLock()) != 0L); + long s = assertNonZero(lock.writeLock()); assertTrue(lock.validate(s)); assertFalse(lock.validate(lock.tryWriteLock())); - assertFalse(lock.validate(lock.tryWriteLock(10L, MILLISECONDS))); + assertFalse(lock.validate(lock.tryWriteLock(0L, SECONDS))); assertFalse(lock.validate(lock.tryReadLock())); - assertFalse(lock.validate(lock.tryReadLock(10L, MILLISECONDS))); + assertFalse(lock.validate(lock.tryReadLock(0L, SECONDS))); assertFalse(lock.validate(lock.tryOptimisticRead())); lock.unlockWrite(s); } - /** - * writeLockInterruptibly is interruptible - */ - public void testWriteLockInterruptibly_Interruptible() - throws InterruptedException { - final CountDownLatch running = new CountDownLatch(1); - final StampedLock lock = new StampedLock(); - long s = lock.writeLock(); - Thread t = newStartedThread(new CheckedInterruptedRunnable() { - public void realRun() throws InterruptedException { - running.countDown(); - lock.writeLockInterruptibly(); - }}); - - running.await(); - waitForThreadToEnterWaitState(t, 100); - t.interrupt(); - awaitTermination(t); - releaseWriteLock(lock, s); + void assertThrowInterruptedExceptionWhenPreInterrupted(Action[] actions) { + for (Action action : actions) { + Thread.currentThread().interrupt(); + try { + action.run(); + shouldThrow(); + } + catch (InterruptedException success) {} + catch (Throwable fail) { threadUnexpectedException(fail); } + assertFalse(Thread.interrupted()); + } } /** - * timed tryWriteLock is interruptible + * interruptible operations throw InterruptedException when pre-interrupted */ - public void testWriteTryLock_Interruptible() throws InterruptedException { + public void testInterruptibleOperationsThrowInterruptedExceptionWhenPreInterrupted() { final CountDownLatch running = new CountDownLatch(1); final StampedLock lock = new StampedLock(); - long s = lock.writeLock(); - Thread t = newStartedThread(new CheckedInterruptedRunnable() { - public void realRun() throws InterruptedException { - running.countDown(); - lock.tryWriteLock(2 * LONG_DELAY_MS, MILLISECONDS); - }}); - running.await(); - waitForThreadToEnterWaitState(t, 100); - t.interrupt(); - awaitTermination(t); - releaseWriteLock(lock, s); + Action[] interruptibleLockActions = { + () -> lock.writeLockInterruptibly(), + () -> lock.tryWriteLock(Long.MIN_VALUE, DAYS), + () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS), + () -> lock.readLockInterruptibly(), + () -> lock.tryReadLock(Long.MIN_VALUE, DAYS), + () -> lock.tryReadLock(Long.MAX_VALUE, DAYS), + () -> lock.asWriteLock().lockInterruptibly(), + () -> lock.asWriteLock().tryLock(0L, DAYS), + () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS), + () -> lock.asReadLock().lockInterruptibly(), + () -> lock.asReadLock().tryLock(0L, DAYS), + () -> lock.asReadLock().tryLock(Long.MAX_VALUE, DAYS), + }; + shuffle(interruptibleLockActions); + + assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions); + { + long s = lock.writeLock(); + assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions); + lock.unlockWrite(s); + } + { + long s = lock.readLock(); + assertThrowInterruptedExceptionWhenPreInterrupted(interruptibleLockActions); + lock.unlockRead(s); + } + } + + void assertThrowInterruptedExceptionWhenInterrupted(Action[] actions) { + int n = actions.length; + Future[] futures = new Future[n]; + CountDownLatch threadsStarted = new CountDownLatch(n); + CountDownLatch done = new CountDownLatch(n); + + for (int i = 0; i < n; i++) { + Action action = actions[i]; + futures[i] = cachedThreadPool.submit(new CheckedRunnable() { + public void realRun() throws Throwable { + threadsStarted.countDown(); + try { + action.run(); + shouldThrow(); + } + catch (InterruptedException success) {} + catch (Throwable fail) { threadUnexpectedException(fail); } + assertFalse(Thread.interrupted()); + done.countDown(); + }}); + } + + await(threadsStarted); + assertEquals(n, done.getCount()); + for (Future future : futures) // Interrupt all the tasks + future.cancel(true); + await(done); } /** - * readLockInterruptibly is interruptible + * interruptible operations throw InterruptedException when write locked and interrupted */ - public void testReadLockInterruptibly_Interruptible() - throws InterruptedException { + public void testInterruptibleOperationsThrowInterruptedExceptionWriteLockedInterrupted() { final CountDownLatch running = new CountDownLatch(1); final StampedLock lock = new StampedLock(); long s = lock.writeLock(); - Thread t = newStartedThread(new CheckedInterruptedRunnable() { - public void realRun() throws InterruptedException { - running.countDown(); - lock.readLockInterruptibly(); - }}); - running.await(); - waitForThreadToEnterWaitState(t, 100); - t.interrupt(); - awaitTermination(t); - releaseWriteLock(lock, s); + Action[] interruptibleLockBlockingActions = { + () -> lock.writeLockInterruptibly(), + () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS), + () -> lock.readLockInterruptibly(), + () -> lock.tryReadLock(Long.MAX_VALUE, DAYS), + () -> lock.asWriteLock().lockInterruptibly(), + () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS), + () -> lock.asReadLock().lockInterruptibly(), + () -> lock.asReadLock().tryLock(Long.MAX_VALUE, DAYS), + }; + shuffle(interruptibleLockBlockingActions); + + assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions); } /** - * timed tryReadLock is interruptible + * interruptible operations throw InterruptedException when read locked and interrupted */ - public void testReadTryLock_Interruptible() throws InterruptedException { + public void testInterruptibleOperationsThrowInterruptedExceptionReadLockedInterrupted() { final CountDownLatch running = new CountDownLatch(1); final StampedLock lock = new StampedLock(); - long s = lock.writeLock(); - Thread t = newStartedThread(new CheckedInterruptedRunnable() { - public void realRun() throws InterruptedException { - running.countDown(); - lock.tryReadLock(2 * LONG_DELAY_MS, MILLISECONDS); - }}); + long s = lock.readLock(); - running.await(); - waitForThreadToEnterWaitState(t, 100); - t.interrupt(); - awaitTermination(t); - releaseWriteLock(lock, s); + Action[] interruptibleLockBlockingActions = { + () -> lock.writeLockInterruptibly(), + () -> lock.tryWriteLock(Long.MAX_VALUE, DAYS), + () -> lock.asWriteLock().lockInterruptibly(), + () -> lock.asWriteLock().tryLock(Long.MAX_VALUE, DAYS), + }; + shuffle(interruptibleLockBlockingActions); + + assertThrowInterruptedExceptionWhenInterrupted(interruptibleLockBlockingActions); + } + + /** + * Non-interruptible operations ignore and preserve interrupt status + */ + public void testNonInterruptibleOperationsIgnoreInterrupts() { + final StampedLock lock = new StampedLock(); + Thread.currentThread().interrupt(); + + for (BiConsumer readUnlocker : readUnlockers()) { + long s = assertValid(lock, lock.readLock()); + readUnlocker.accept(lock, s); + s = assertValid(lock, lock.tryReadLock()); + readUnlocker.accept(lock, s); + } + + lock.asReadLock().lock(); + lock.asReadLock().unlock(); + + for (BiConsumer writeUnlocker : writeUnlockers()) { + long s = assertValid(lock, lock.writeLock()); + writeUnlocker.accept(lock, s); + s = assertValid(lock, lock.tryWriteLock()); + writeUnlocker.accept(lock, s); + } + + lock.asWriteLock().lock(); + lock.asWriteLock().unlock(); + + assertTrue(Thread.interrupted()); } /** * tryWriteLock on an unlocked lock succeeds */ - public void testWriteTryLock() { + public void testTryWriteLock() { final StampedLock lock = new StampedLock(); long s = lock.tryWriteLock(); assertTrue(s != 0L); assertTrue(lock.isWriteLocked()); - long s2 = lock.tryWriteLock(); - assertEquals(s2, 0L); + assertEquals(0L, lock.tryWriteLock()); releaseWriteLock(lock, s); } /** * tryWriteLock fails if locked */ - public void testWriteTryLockWhenLocked() { + public void testTryWriteLockWhenLocked() { final StampedLock lock = new StampedLock(); long s = lock.writeLock(); Thread t = newStartedThread(new CheckedRunnable() { public void realRun() { - long ws = lock.tryWriteLock(); - assertTrue(ws == 0L); + assertEquals(0L, lock.tryWriteLock()); }}); + assertEquals(0L, lock.tryWriteLock()); awaitTermination(t); releaseWriteLock(lock, s); } @@ -420,15 +464,15 @@ public class StampedLockTest extends JSR166TestCase { /** * tryReadLock fails if write-locked */ - public void testReadTryLockWhenLocked() { + public void testTryReadLockWhenLocked() { final StampedLock lock = new StampedLock(); long s = lock.writeLock(); Thread t = newStartedThread(new CheckedRunnable() { public void realRun() { - long rs = lock.tryReadLock(); - assertEquals(rs, 0L); + assertEquals(0L, lock.tryReadLock()); }}); + assertEquals(0L, lock.tryReadLock()); awaitTermination(t); releaseWriteLock(lock, s); } @@ -442,13 +486,20 @@ public class StampedLockTest extends JSR166TestCase { Thread t = newStartedThread(new CheckedRunnable() { public void realRun() throws InterruptedException { long s2 = lock.tryReadLock(); - assertTrue(s2 != 0L); + assertValid(lock, s2); lock.unlockRead(s2); long s3 = lock.tryReadLock(LONG_DELAY_MS, MILLISECONDS); - assertTrue(s3 != 0L); + assertValid(lock, s3); lock.unlockRead(s3); long s4 = lock.readLock(); + assertValid(lock, s4); lock.unlockRead(s4); + lock.asReadLock().lock(); + lock.asReadLock().unlock(); + lock.asReadLock().lockInterruptibly(); + lock.asReadLock().unlock(); + lock.asReadLock().tryLock(Long.MIN_VALUE, DAYS); + lock.asReadLock().unlock(); }}); awaitTermination(t); @@ -470,7 +521,7 @@ public class StampedLockTest extends JSR166TestCase { }}); running.await(); - waitForThreadToEnterWaitState(t, 100); + waitForThreadToEnterWaitState(t, MEDIUM_DELAY_MS); assertFalse(lock.isWriteLocked()); lock.unlockRead(rs); awaitTermination(t); @@ -497,6 +548,7 @@ public class StampedLockTest extends JSR166TestCase { lock.unlockWrite(ws); }}); + assertTrue(lock.isReadLocked()); assertFalse(lock.isWriteLocked()); lock.unlockRead(s); awaitTermination(t2); @@ -508,25 +560,31 @@ public class StampedLockTest extends JSR166TestCase { */ public void testReadAfterWriteLock() { final StampedLock lock = new StampedLock(); + final CountDownLatch threadsStarted = new CountDownLatch(2); final long s = lock.writeLock(); Thread t1 = newStartedThread(new CheckedRunnable() { public void realRun() { + threadsStarted.countDown(); long rs = lock.readLock(); lock.unlockRead(rs); }}); Thread t2 = newStartedThread(new CheckedRunnable() { public void realRun() { + threadsStarted.countDown(); long rs = lock.readLock(); lock.unlockRead(rs); }}); + await(threadsStarted); + waitForThreadToEnterWaitState(t1, MEDIUM_DELAY_MS); + waitForThreadToEnterWaitState(t2, MEDIUM_DELAY_MS); releaseWriteLock(lock, s); awaitTermination(t1); awaitTermination(t2); } /** - * tryReadLock succeeds if readlocked but not writelocked + * tryReadLock succeeds if read locked but not write locked */ public void testTryLockWhenReadLocked() { final StampedLock lock = new StampedLock(); @@ -534,7 +592,7 @@ public class StampedLockTest extends JSR166TestCase { Thread t = newStartedThread(new CheckedRunnable() { public void realRun() { long rs = lock.tryReadLock(); - threadAssertTrue(rs != 0L); + assertValid(lock, rs); lock.unlockRead(rs); }}); @@ -543,15 +601,14 @@ public class StampedLockTest extends JSR166TestCase { } /** - * tryWriteLock fails when readlocked + * tryWriteLock fails when read locked */ - public void testWriteTryLockWhenReadLocked() { + public void testTryWriteLockWhenReadLocked() { final StampedLock lock = new StampedLock(); long s = lock.readLock(); Thread t = newStartedThread(new CheckedRunnable() { public void realRun() { - long ws = lock.tryWriteLock(); - threadAssertEquals(ws, 0L); + threadAssertEquals(0L, lock.tryWriteLock()); }}); awaitTermination(t); @@ -559,86 +616,82 @@ public class StampedLockTest extends JSR166TestCase { } /** - * timed tryWriteLock times out if locked + * timed lock operations time out if lock not available */ - public void testWriteTryLock_Timeout() { + public void testTimedLock_Timeout() throws Exception { + ArrayList> futures = new ArrayList<>(); + + // Write locked final StampedLock lock = new StampedLock(); - long s = lock.writeLock(); - Thread t = newStartedThread(new CheckedRunnable() { + long stamp = lock.writeLock(); + assertEquals(0L, lock.tryReadLock(0L, DAYS)); + assertEquals(0L, lock.tryReadLock(Long.MIN_VALUE, DAYS)); + assertFalse(lock.asReadLock().tryLock(0L, DAYS)); + assertFalse(lock.asReadLock().tryLock(Long.MIN_VALUE, DAYS)); + assertEquals(0L, lock.tryWriteLock(0L, DAYS)); + assertEquals(0L, lock.tryWriteLock(Long.MIN_VALUE, DAYS)); + assertFalse(lock.asWriteLock().tryLock(0L, DAYS)); + assertFalse(lock.asWriteLock().tryLock(Long.MIN_VALUE, DAYS)); + + futures.add(cachedThreadPool.submit(new CheckedRunnable() { public void realRun() throws InterruptedException { long startTime = System.nanoTime(); - long timeoutMillis = 10; - long ws = lock.tryWriteLock(timeoutMillis, MILLISECONDS); - assertEquals(ws, 0L); - assertTrue(millisElapsedSince(startTime) >= timeoutMillis); - }}); + assertEquals(0L, lock.tryWriteLock(timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + }})); - awaitTermination(t); - releaseWriteLock(lock, s); + futures.add(cachedThreadPool.submit(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + assertEquals(0L, lock.tryReadLock(timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + }})); + + // Read locked + final StampedLock lock2 = new StampedLock(); + long stamp2 = lock2.readLock(); + assertEquals(0L, lock2.tryWriteLock(0L, DAYS)); + assertEquals(0L, lock2.tryWriteLock(Long.MIN_VALUE, DAYS)); + assertFalse(lock2.asWriteLock().tryLock(0L, DAYS)); + assertFalse(lock2.asWriteLock().tryLock(Long.MIN_VALUE, DAYS)); + + futures.add(cachedThreadPool.submit(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + assertEquals(0L, lock2.tryWriteLock(timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + }})); + + for (Future future : futures) + assertNull(future.get()); + + releaseWriteLock(lock, stamp); + releaseReadLock(lock2, stamp2); } /** - * timed tryReadLock times out if write-locked - */ - public void testReadTryLock_Timeout() { - final StampedLock lock = new StampedLock(); - long s = lock.writeLock(); - Thread t = newStartedThread(new CheckedRunnable() { - public void realRun() throws InterruptedException { - long startTime = System.nanoTime(); - long timeoutMillis = 10; - long rs = lock.tryReadLock(timeoutMillis, MILLISECONDS); - assertEquals(rs, 0L); - assertTrue(millisElapsedSince(startTime) >= timeoutMillis); - }}); - - awaitTermination(t); - assertTrue(lock.isWriteLocked()); - lock.unlockWrite(s); - } - - /** - * writeLockInterruptibly succeeds if unlocked, else is interruptible + * writeLockInterruptibly succeeds if unlocked */ public void testWriteLockInterruptibly() throws InterruptedException { - final CountDownLatch running = new CountDownLatch(1); final StampedLock lock = new StampedLock(); long s = lock.writeLockInterruptibly(); - Thread t = newStartedThread(new CheckedInterruptedRunnable() { - public void realRun() throws InterruptedException { - running.countDown(); - lock.writeLockInterruptibly(); - }}); - - running.await(); - waitForThreadToEnterWaitState(t, 100); - t.interrupt(); assertTrue(lock.isWriteLocked()); - awaitTermination(t); releaseWriteLock(lock, s); } /** - * readLockInterruptibly succeeds if lock free else is interruptible + * readLockInterruptibly succeeds if lock free */ public void testReadLockInterruptibly() throws InterruptedException { - final CountDownLatch running = new CountDownLatch(1); final StampedLock lock = new StampedLock(); - long s; - s = lock.readLockInterruptibly(); - lock.unlockRead(s); - s = lock.writeLockInterruptibly(); - Thread t = newStartedThread(new CheckedInterruptedRunnable() { - public void realRun() throws InterruptedException { - running.countDown(); - lock.readLockInterruptibly(); - }}); - running.await(); - waitForThreadToEnterWaitState(t, 100); - t.interrupt(); - awaitTermination(t); - releaseWriteLock(lock, s); + long s = assertValid(lock, lock.readLockInterruptibly()); + assertTrue(lock.isReadLocked()); + lock.unlockRead(s); + + lock.asReadLock().lockInterruptibly(); + assertTrue(lock.isReadLocked()); + lock.asReadLock().unlock(); } /** @@ -670,54 +723,39 @@ public class StampedLockTest extends JSR166TestCase { } /** - * tryOptimisticRead succeeds and validates if unlocked, fails if locked + * tryOptimisticRead succeeds and validates if unlocked, fails if + * exclusively locked */ public void testValidateOptimistic() throws InterruptedException { StampedLock lock = new StampedLock(); - long s, p; - assertTrue((p = lock.tryOptimisticRead()) != 0L); - assertTrue(lock.validate(p)); - assertTrue((s = lock.writeLock()) != 0L); - assertFalse((p = lock.tryOptimisticRead()) != 0L); - assertTrue(lock.validate(s)); - lock.unlockWrite(s); - assertTrue((p = lock.tryOptimisticRead()) != 0L); - assertTrue(lock.validate(p)); - assertTrue((s = lock.readLock()) != 0L); - assertTrue(lock.validate(s)); - assertTrue((p = lock.tryOptimisticRead()) != 0L); - assertTrue(lock.validate(p)); - lock.unlockRead(s); - assertTrue((s = lock.tryWriteLock()) != 0L); - assertTrue(lock.validate(s)); - assertFalse((p = lock.tryOptimisticRead()) != 0L); - lock.unlockWrite(s); - assertTrue((s = lock.tryReadLock()) != 0L); - assertTrue(lock.validate(s)); - assertTrue((p = lock.tryOptimisticRead()) != 0L); - lock.unlockRead(s); - assertTrue(lock.validate(p)); - assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L); - assertFalse((p = lock.tryOptimisticRead()) != 0L); - assertTrue(lock.validate(s)); - lock.unlockWrite(s); - assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L); - assertTrue(lock.validate(s)); - assertTrue((p = lock.tryOptimisticRead()) != 0L); - lock.unlockRead(s); - assertTrue((p = lock.tryOptimisticRead()) != 0L); + + assertValid(lock, lock.tryOptimisticRead()); + + for (Function writeLocker : writeLockers()) { + long s = assertValid(lock, writeLocker.apply(lock)); + assertEquals(0L, lock.tryOptimisticRead()); + releaseWriteLock(lock, s); + } + + for (Function readLocker : readLockers()) { + long s = assertValid(lock, readLocker.apply(lock)); + long p = assertValid(lock, lock.tryOptimisticRead()); + releaseReadLock(lock, s); + assertTrue(lock.validate(p)); + } + + assertValid(lock, lock.tryOptimisticRead()); } /** * tryOptimisticRead stamp does not validate if a write lock intervenes */ public void testValidateOptimisticWriteLocked() { - StampedLock lock = new StampedLock(); - long s, p; - assertTrue((p = lock.tryOptimisticRead()) != 0L); - assertTrue((s = lock.writeLock()) != 0L); + final StampedLock lock = new StampedLock(); + final long p = assertValid(lock, lock.tryOptimisticRead()); + final long s = assertValid(lock, lock.writeLock()); assertFalse(lock.validate(p)); - assertFalse((p = lock.tryOptimisticRead()) != 0L); + assertEquals(0L, lock.tryOptimisticRead()); assertTrue(lock.validate(s)); lock.unlockWrite(s); } @@ -730,8 +768,8 @@ public class StampedLockTest extends JSR166TestCase { throws InterruptedException { final CountDownLatch running = new CountDownLatch(1); final StampedLock lock = new StampedLock(); - long s, p; - assertTrue((p = lock.tryOptimisticRead()) != 0L); + final long p = assertValid(lock, lock.tryOptimisticRead()); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { public void realRun() throws InterruptedException { lock.writeLockInterruptibly(); @@ -741,228 +779,209 @@ public class StampedLockTest extends JSR166TestCase { running.await(); assertFalse(lock.validate(p)); - assertFalse((p = lock.tryOptimisticRead()) != 0L); + assertEquals(0L, lock.tryOptimisticRead()); t.interrupt(); awaitTermination(t); } /** - * tryConvertToOptimisticRead succeeds and validates if successfully locked, + * tryConvertToOptimisticRead succeeds and validates if successfully locked */ public void testTryConvertToOptimisticRead() throws InterruptedException { StampedLock lock = new StampedLock(); - long s, p; + long s, p, q; assertEquals(0L, lock.tryConvertToOptimisticRead(0L)); - assertTrue((s = lock.tryOptimisticRead()) != 0L); + s = assertValid(lock, lock.tryOptimisticRead()); assertEquals(s, lock.tryConvertToOptimisticRead(s)); assertTrue(lock.validate(s)); - assertTrue((p = lock.readLock()) != 0L); - assertTrue((s = lock.tryOptimisticRead()) != 0L); - assertEquals(s, lock.tryConvertToOptimisticRead(s)); - assertTrue(lock.validate(s)); - lock.unlockRead(p); + for (Function writeLocker : writeLockers()) { + s = assertValid(lock, writeLocker.apply(lock)); + p = assertValid(lock, lock.tryConvertToOptimisticRead(s)); + assertFalse(lock.validate(s)); + assertTrue(lock.validate(p)); + assertUnlocked(lock); + } - assertTrue((s = lock.writeLock()) != 0L); - assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L); - assertTrue(lock.validate(p)); - - assertTrue((s = lock.readLock()) != 0L); - assertTrue(lock.validate(s)); - assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L); - assertTrue(lock.validate(p)); - - assertTrue((s = lock.tryWriteLock()) != 0L); - assertTrue(lock.validate(s)); - assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L); - assertTrue(lock.validate(p)); - - assertTrue((s = lock.tryReadLock()) != 0L); - assertTrue(lock.validate(s)); - assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L); - assertTrue(lock.validate(p)); - - assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L); - assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L); - assertTrue(lock.validate(p)); - - assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L); - assertTrue(lock.validate(s)); - assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L); - assertTrue(lock.validate(p)); + for (Function readLocker : readLockers()) { + s = assertValid(lock, readLocker.apply(lock)); + q = assertValid(lock, lock.tryOptimisticRead()); + assertEquals(q, lock.tryConvertToOptimisticRead(q)); + assertTrue(lock.validate(q)); + assertTrue(lock.isReadLocked()); + p = assertValid(lock, lock.tryConvertToOptimisticRead(s)); + assertTrue(lock.validate(p)); + assertTrue(lock.validate(s)); + assertUnlocked(lock); + assertEquals(q, lock.tryConvertToOptimisticRead(q)); + assertTrue(lock.validate(q)); + } } /** - * tryConvertToReadLock succeeds and validates if successfully locked - * or lock free; + * tryConvertToReadLock succeeds for valid stamps */ public void testTryConvertToReadLock() throws InterruptedException { StampedLock lock = new StampedLock(); long s, p; - assertFalse((p = lock.tryConvertToReadLock(0L)) != 0L); + assertEquals(0L, lock.tryConvertToReadLock(0L)); - assertTrue((s = lock.tryOptimisticRead()) != 0L); - assertTrue((p = lock.tryConvertToReadLock(s)) != 0L); + s = assertValid(lock, lock.tryOptimisticRead()); + p = assertValid(lock, lock.tryConvertToReadLock(s)); assertTrue(lock.isReadLocked()); assertEquals(1, lock.getReadLockCount()); + assertTrue(lock.validate(s)); lock.unlockRead(p); - assertTrue((s = lock.tryOptimisticRead()) != 0L); + s = assertValid(lock, lock.tryOptimisticRead()); lock.readLock(); - assertTrue((p = lock.tryConvertToReadLock(s)) != 0L); + p = assertValid(lock, lock.tryConvertToReadLock(s)); assertTrue(lock.isReadLocked()); assertEquals(2, lock.getReadLockCount()); lock.unlockRead(p); lock.unlockRead(p); + assertUnlocked(lock); - assertTrue((s = lock.writeLock()) != 0L); - assertTrue((p = lock.tryConvertToReadLock(s)) != 0L); - assertTrue(lock.validate(p)); - assertTrue(lock.isReadLocked()); - assertEquals(1, lock.getReadLockCount()); - lock.unlockRead(p); + for (BiConsumer readUnlocker : readUnlockers()) { + for (Function writeLocker : writeLockers()) { + s = assertValid(lock, writeLocker.apply(lock)); + p = assertValid(lock, lock.tryConvertToReadLock(s)); + assertFalse(lock.validate(s)); + assertTrue(lock.isReadLocked()); + assertEquals(1, lock.getReadLockCount()); + readUnlocker.accept(lock, p); + } - assertTrue((s = lock.readLock()) != 0L); - assertTrue(lock.validate(s)); - assertEquals(s, lock.tryConvertToReadLock(s)); - assertTrue(lock.validate(s)); - assertTrue(lock.isReadLocked()); - assertEquals(1, lock.getReadLockCount()); - lock.unlockRead(s); - - assertTrue((s = lock.tryWriteLock()) != 0L); - assertTrue(lock.validate(s)); - assertTrue((p = lock.tryConvertToReadLock(s)) != 0L); - assertTrue(lock.validate(p)); - assertEquals(1, lock.getReadLockCount()); - lock.unlockRead(p); - - assertTrue((s = lock.tryReadLock()) != 0L); - assertTrue(lock.validate(s)); - assertEquals(s, lock.tryConvertToReadLock(s)); - assertTrue(lock.validate(s)); - assertTrue(lock.isReadLocked()); - assertEquals(1, lock.getReadLockCount()); - lock.unlockRead(s); - - assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L); - assertTrue((p = lock.tryConvertToReadLock(s)) != 0L); - assertTrue(lock.validate(p)); - assertTrue(lock.isReadLocked()); - assertEquals(1, lock.getReadLockCount()); - lock.unlockRead(p); - - assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L); - assertTrue(lock.validate(s)); - assertEquals(s, lock.tryConvertToReadLock(s)); - assertTrue(lock.validate(s)); - assertTrue(lock.isReadLocked()); - assertEquals(1, lock.getReadLockCount()); - lock.unlockRead(s); + for (Function readLocker : readLockers()) { + s = assertValid(lock, readLocker.apply(lock)); + assertEquals(s, lock.tryConvertToReadLock(s)); + assertTrue(lock.validate(s)); + assertTrue(lock.isReadLocked()); + assertEquals(1, lock.getReadLockCount()); + readUnlocker.accept(lock, s); + } + } } /** - * tryConvertToWriteLock succeeds and validates if successfully locked - * or lock free; + * tryConvertToWriteLock succeeds if lock available; fails if multiply read locked */ public void testTryConvertToWriteLock() throws InterruptedException { StampedLock lock = new StampedLock(); long s, p; - assertFalse((p = lock.tryConvertToWriteLock(0L)) != 0L); + assertEquals(0L, lock.tryConvertToWriteLock(0L)); assertTrue((s = lock.tryOptimisticRead()) != 0L); assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); assertTrue(lock.isWriteLocked()); lock.unlockWrite(p); - assertTrue((s = lock.writeLock()) != 0L); - assertEquals(s, lock.tryConvertToWriteLock(s)); - assertTrue(lock.validate(s)); - assertTrue(lock.isWriteLocked()); - lock.unlockWrite(s); + for (BiConsumer writeUnlocker : writeUnlockers()) { + for (Function writeLocker : writeLockers()) { + s = assertValid(lock, writeLocker.apply(lock)); + assertEquals(s, lock.tryConvertToWriteLock(s)); + assertTrue(lock.validate(s)); + assertTrue(lock.isWriteLocked()); + writeUnlocker.accept(lock, s); + } - assertTrue((s = lock.readLock()) != 0L); - assertTrue(lock.validate(s)); - assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); - assertTrue(lock.validate(p)); - assertTrue(lock.isWriteLocked()); - lock.unlockWrite(p); + for (Function readLocker : readLockers()) { + s = assertValid(lock, readLocker.apply(lock)); + p = assertValid(lock, lock.tryConvertToWriteLock(s)); + assertFalse(lock.validate(s)); + assertTrue(lock.validate(p)); + assertTrue(lock.isWriteLocked()); + writeUnlocker.accept(lock, p); + } + } - assertTrue((s = lock.tryWriteLock()) != 0L); - assertTrue(lock.validate(s)); - assertEquals(s, lock.tryConvertToWriteLock(s)); - assertTrue(lock.validate(s)); - assertTrue(lock.isWriteLocked()); - lock.unlockWrite(s); - - assertTrue((s = lock.tryReadLock()) != 0L); - assertTrue(lock.validate(s)); - assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); - assertTrue(lock.validate(p)); - assertTrue(lock.isWriteLocked()); - lock.unlockWrite(p); - - assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L); - assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); - assertTrue(lock.validate(p)); - assertTrue(lock.isWriteLocked()); - lock.unlockWrite(p); - - assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L); - assertTrue(lock.validate(s)); - assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); - assertTrue(lock.validate(p)); - assertTrue(lock.isWriteLocked()); - lock.unlockWrite(p); + // failure if multiply read locked + for (Function readLocker : readLockers()) { + s = assertValid(lock, readLocker.apply(lock)); + p = assertValid(lock, readLocker.apply(lock)); + assertEquals(0L, lock.tryConvertToWriteLock(s)); + assertTrue(lock.validate(s)); + assertTrue(lock.validate(p)); + assertEquals(2, lock.getReadLockCount()); + lock.unlock(p); + lock.unlock(s); + assertUnlocked(lock); + } } /** * asWriteLock can be locked and unlocked */ - public void testAsWriteLock() { + public void testAsWriteLock() throws Throwable { StampedLock sl = new StampedLock(); Lock lock = sl.asWriteLock(); - lock.lock(); - assertFalse(lock.tryLock()); - lock.unlock(); - assertTrue(lock.tryLock()); + for (Action locker : lockLockers(lock)) { + locker.run(); + assertTrue(sl.isWriteLocked()); + assertFalse(sl.isReadLocked()); + assertFalse(lock.tryLock()); + lock.unlock(); + assertUnlocked(sl); + } } /** * asReadLock can be locked and unlocked */ - public void testAsReadLock() { + public void testAsReadLock() throws Throwable { StampedLock sl = new StampedLock(); Lock lock = sl.asReadLock(); - lock.lock(); - lock.unlock(); - assertTrue(lock.tryLock()); + for (Action locker : lockLockers(lock)) { + locker.run(); + assertTrue(sl.isReadLocked()); + assertFalse(sl.isWriteLocked()); + assertEquals(1, sl.getReadLockCount()); + locker.run(); + assertTrue(sl.isReadLocked()); + assertEquals(2, sl.getReadLockCount()); + lock.unlock(); + lock.unlock(); + assertUnlocked(sl); + } } /** * asReadWriteLock.writeLock can be locked and unlocked */ - public void testAsReadWriteLockWriteLock() { + public void testAsReadWriteLockWriteLock() throws Throwable { StampedLock sl = new StampedLock(); Lock lock = sl.asReadWriteLock().writeLock(); - lock.lock(); - assertFalse(lock.tryLock()); - lock.unlock(); - assertTrue(lock.tryLock()); + for (Action locker : lockLockers(lock)) { + locker.run(); + assertTrue(sl.isWriteLocked()); + assertFalse(sl.isReadLocked()); + assertFalse(lock.tryLock()); + lock.unlock(); + assertUnlocked(sl); + } } /** * asReadWriteLock.readLock can be locked and unlocked */ - public void testAsReadWriteLockReadLock() { + public void testAsReadWriteLockReadLock() throws Throwable { StampedLock sl = new StampedLock(); Lock lock = sl.asReadWriteLock().readLock(); - lock.lock(); - lock.unlock(); - assertTrue(lock.tryLock()); + for (Action locker : lockLockers(lock)) { + locker.run(); + assertTrue(sl.isReadLocked()); + assertFalse(sl.isWriteLocked()); + assertEquals(1, sl.getReadLockCount()); + locker.run(); + assertTrue(sl.isReadLocked()); + assertEquals(2, sl.getReadLockCount()); + lock.unlock(); + lock.unlock(); + assertUnlocked(sl); + } } /** @@ -985,8 +1004,7 @@ public class StampedLockTest extends JSR166TestCase { Runnable[] actions = { () -> { StampedLock sl = new StampedLock(); - long stamp = sl.tryOptimisticRead(); - assertTrue(stamp != 0); + long stamp = assertValid(sl, sl.tryOptimisticRead()); sl.unlockRead(stamp); }, () -> { @@ -1003,21 +1021,21 @@ public class StampedLockTest extends JSR166TestCase { }, () -> { StampedLock sl = new StampedLock(); - long stamp = sl.tryOptimisticRead(); sl.readLock(); + long stamp = assertValid(sl, sl.tryOptimisticRead()); sl.unlockRead(stamp); }, () -> { StampedLock sl = new StampedLock(); - long stamp = sl.tryOptimisticRead(); sl.readLock(); + long stamp = assertValid(sl, sl.tryOptimisticRead()); sl.unlock(stamp); }, () -> { StampedLock sl = new StampedLock(); long stamp = sl.tryConvertToOptimisticRead(sl.writeLock()); - assertTrue(stamp != 0); + assertValid(sl, stamp); sl.writeLock(); sl.unlockWrite(stamp); }, @@ -1043,7 +1061,7 @@ public class StampedLockTest extends JSR166TestCase { () -> { StampedLock sl = new StampedLock(); long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); - assertTrue(stamp != 0); + assertValid(sl, stamp); sl.writeLock(); sl.unlockWrite(stamp); }, @@ -1063,7 +1081,7 @@ public class StampedLockTest extends JSR166TestCase { StampedLock sl = new StampedLock(); sl.readLock(); long stamp = sl.tryConvertToOptimisticRead(sl.readLock()); - assertTrue(stamp != 0); + assertValid(sl, stamp); sl.readLock(); sl.unlockRead(stamp); }, @@ -1106,100 +1124,84 @@ public class StampedLockTest extends JSR166TestCase { } /** - * Invalid write stamps result in IllegalMonitorStateException + * Invalid stamps result in IllegalMonitorStateException */ - public void testInvalidWriteStampsThrowIllegalMonitorStateException() { - List> writeLockers = new ArrayList<>(); - writeLockers.add((sl) -> sl.writeLock()); - writeLockers.add((sl) -> writeLockInterruptiblyUninterrupted(sl)); - writeLockers.add((sl) -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS)); - writeLockers.add((sl) -> tryWriteLockUninterrupted(sl, 0, DAYS)); + public void testInvalidStampsThrowIllegalMonitorStateException() { + final StampedLock sl = new StampedLock(); - List> writeUnlockers = new ArrayList<>(); - writeUnlockers.add((sl, stamp) -> sl.unlockWrite(stamp)); - writeUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockWrite())); - writeUnlockers.add((sl, stamp) -> sl.asWriteLock().unlock()); - writeUnlockers.add((sl, stamp) -> sl.unlock(stamp)); + assertThrows(IllegalMonitorStateException.class, + () -> sl.unlockWrite(0L), + () -> sl.unlockRead(0L), + () -> sl.unlock(0L)); - List> mutaters = new ArrayList<>(); - mutaters.add((sl) -> {}); - mutaters.add((sl) -> sl.readLock()); - for (Function writeLocker : writeLockers) - mutaters.add((sl) -> writeLocker.apply(sl)); + final long optimisticStamp = sl.tryOptimisticRead(); + final long readStamp = sl.readLock(); + sl.unlockRead(readStamp); + final long writeStamp = sl.writeLock(); + sl.unlockWrite(writeStamp); + assertTrue(optimisticStamp != 0L && readStamp != 0L && writeStamp != 0L); + final long[] noLongerValidStamps = { optimisticStamp, readStamp, writeStamp }; + final Runnable assertNoLongerValidStampsThrow = () -> { + for (long noLongerValidStamp : noLongerValidStamps) + assertThrows(IllegalMonitorStateException.class, + () -> sl.unlockWrite(noLongerValidStamp), + () -> sl.unlockRead(noLongerValidStamp), + () -> sl.unlock(noLongerValidStamp)); + }; + assertNoLongerValidStampsThrow.run(); - for (Function writeLocker : writeLockers) - for (BiConsumer writeUnlocker : writeUnlockers) - for (Consumer mutater : mutaters) { - final StampedLock sl = new StampedLock(); + for (Function readLocker : readLockers()) + for (BiConsumer readUnlocker : readUnlockers()) { + final long stamp = readLocker.apply(sl); + assertValid(sl, stamp); + assertNoLongerValidStampsThrow.run(); + assertThrows(IllegalMonitorStateException.class, + () -> sl.unlockWrite(stamp), + () -> sl.unlockRead(sl.tryOptimisticRead()), + () -> sl.unlockRead(0L)); + readUnlocker.accept(sl, stamp); + assertUnlocked(sl); + assertNoLongerValidStampsThrow.run(); + } + + for (Function writeLocker : writeLockers()) + for (BiConsumer writeUnlocker : writeUnlockers()) { final long stamp = writeLocker.apply(sl); - assertTrue(stamp != 0L); + assertValid(sl, stamp); + assertNoLongerValidStampsThrow.run(); assertThrows(IllegalMonitorStateException.class, - () -> sl.unlockRead(stamp)); - writeUnlocker.accept(sl, stamp); - mutater.accept(sl); - assertThrows(IllegalMonitorStateException.class, - () -> sl.unlock(stamp), () -> sl.unlockRead(stamp), - () -> sl.unlockWrite(stamp)); + () -> sl.unlockWrite(0L)); + writeUnlocker.accept(sl, stamp); + assertUnlocked(sl); + assertNoLongerValidStampsThrow.run(); } } /** - * Invalid read stamps result in IllegalMonitorStateException + * Read locks can be very deeply nested */ - public void testInvalidReadStampsThrowIllegalMonitorStateException() { - List> readLockers = new ArrayList<>(); - readLockers.add((sl) -> sl.readLock()); - readLockers.add((sl) -> readLockInterruptiblyUninterrupted(sl)); - readLockers.add((sl) -> tryReadLockUninterrupted(sl, Long.MIN_VALUE, DAYS)); - readLockers.add((sl) -> tryReadLockUninterrupted(sl, 0, DAYS)); - - List> readUnlockers = new ArrayList<>(); - readUnlockers.add((sl, stamp) -> sl.unlockRead(stamp)); - readUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockRead())); - readUnlockers.add((sl, stamp) -> sl.asReadLock().unlock()); - readUnlockers.add((sl, stamp) -> sl.unlock(stamp)); - - List> writeLockers = new ArrayList<>(); - writeLockers.add((sl) -> sl.writeLock()); - writeLockers.add((sl) -> writeLockInterruptiblyUninterrupted(sl)); - writeLockers.add((sl) -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS)); - writeLockers.add((sl) -> tryWriteLockUninterrupted(sl, 0, DAYS)); - - List> writeUnlockers = new ArrayList<>(); - writeUnlockers.add((sl, stamp) -> sl.unlockWrite(stamp)); - writeUnlockers.add((sl, stamp) -> assertTrue(sl.tryUnlockWrite())); - writeUnlockers.add((sl, stamp) -> sl.asWriteLock().unlock()); - writeUnlockers.add((sl, stamp) -> sl.unlock(stamp)); - - - for (Function readLocker : readLockers) - for (BiConsumer readUnlocker : readUnlockers) - for (Function writeLocker : writeLockers) - for (BiConsumer writeUnlocker : writeUnlockers) { - final StampedLock sl = new StampedLock(); - final long stamp = readLocker.apply(sl); - assertTrue(stamp != 0L); - assertThrows(IllegalMonitorStateException.class, - () -> sl.unlockWrite(stamp)); - readUnlocker.accept(sl, stamp); - assertThrows(IllegalMonitorStateException.class, - () -> sl.unlock(stamp), - () -> sl.unlockRead(stamp), - () -> sl.unlockWrite(stamp)); - final long writeStamp = writeLocker.apply(sl); - assertTrue(writeStamp != 0L); - assertTrue(writeStamp != stamp); - assertThrows(IllegalMonitorStateException.class, - () -> sl.unlock(stamp), - () -> sl.unlockRead(stamp), - () -> sl.unlockWrite(stamp)); - writeUnlocker.accept(sl, writeStamp); - assertThrows(IllegalMonitorStateException.class, - () -> sl.unlock(stamp), - () -> sl.unlockRead(stamp), - () -> sl.unlockWrite(stamp)); + public void testDeeplyNestedReadLocks() { + final StampedLock lock = new StampedLock(); + final int depth = 300; + final long[] stamps = new long[depth]; + final List> readLockers = readLockers(); + final List> readUnlockers = readUnlockers(); + for (int i = 0; i < depth; i++) { + Function readLocker + = readLockers.get(i % readLockers.size()); + long stamp = readLocker.apply(lock); + assertEquals(i + 1, lock.getReadLockCount()); + assertTrue(lock.isReadLocked()); + stamps[i] = stamp; } + for (int i = 0; i < depth; i++) { + BiConsumer readUnlocker + = readUnlockers.get(i % readUnlockers.size()); + assertEquals(depth - i, lock.getReadLockCount()); + assertTrue(lock.isReadLocked()); + readUnlocker.accept(lock, stamps[depth - 1 - i]); + } + assertUnlocked(lock); } - } diff --git a/jdk/test/javax/net/ssl/Stapling/SSLSocketWithStapling.java b/jdk/test/javax/net/ssl/Stapling/SSLSocketWithStapling.java index f1e5f1da945..aaa8ce35396 100644 --- a/jdk/test/javax/net/ssl/Stapling/SSLSocketWithStapling.java +++ b/jdk/test/javax/net/ssl/Stapling/SSLSocketWithStapling.java @@ -119,20 +119,22 @@ public class SSLSocketWithStapling { System.setProperty("javax.net.debug", "ssl"); } - // Create the PKI we will use for the test and start the OCSP servers - createPKI(); + try { + // Create the PKI we will use for the test and start the OCSP servers + createPKI(); - testAllDefault(); - testPKIXParametersRevEnabled(); - testRevokedCertificate(); - testHardFailFallback(); - testSoftFailFallback(); - testLatencyNoStaple(false); - testLatencyNoStaple(true); - - // shut down the OCSP responders before finishing the test - intOcsp.stop(); - rootOcsp.stop(); + testAllDefault(); + testPKIXParametersRevEnabled(); + testRevokedCertificate(); + testHardFailFallback(); + testSoftFailFallback(); + testLatencyNoStaple(false); + testLatencyNoStaple(true); + } finally { + // shut down the OCSP responders before finishing the test + intOcsp.stop(); + rootOcsp.stop(); + } } /** @@ -281,11 +283,9 @@ public class SSLSocketWithStapling { ServerParameters servParams = new ServerParameters(); serverReady = false; - // Stop the OCSP responders and give a 1 second delay before - // running the test. - intOcsp.stop(); - rootOcsp.stop(); - Thread.sleep(1000); + // make OCSP responders reject connections + intOcsp.rejectConnections(); + rootOcsp.rejectConnections(); System.out.println("======================================="); System.out.println("Stapling enbled in client and server,"); @@ -315,9 +315,9 @@ public class SSLSocketWithStapling { System.out.println(" PASS"); System.out.println("=======================================\n"); - // Start the OCSP responders up again - intOcsp.start(); - rootOcsp.start(); + // Make OCSP responders accept connections + intOcsp.acceptConnections(); + rootOcsp.acceptConnections(); // Wait 5 seconds for server ready for (int i = 0; (i < 100 && (!intOcsp.isServerReady() || !rootOcsp.isServerReady())); i++) { @@ -338,11 +338,9 @@ public class SSLSocketWithStapling { ServerParameters servParams = new ServerParameters(); serverReady = false; - // Stop the OCSP responders and give a 1 second delay before - // running the test. - intOcsp.stop(); - rootOcsp.stop(); - Thread.sleep(1000); + // make OCSP responders reject connections + intOcsp.rejectConnections(); + rootOcsp.rejectConnections(); System.out.println("======================================="); System.out.println("Stapling enbled in client and server,"); @@ -372,9 +370,9 @@ public class SSLSocketWithStapling { System.out.println(" PASS"); System.out.println("=======================================\n"); - // Start the OCSP responders up again - intOcsp.start(); - rootOcsp.start(); + // Make OCSP responders accept connections + intOcsp.acceptConnections(); + rootOcsp.acceptConnections(); // Wait 5 seconds for server ready for (int i = 0; (i < 100 && (!intOcsp.isServerReady() || !rootOcsp.isServerReady())); i++) { @@ -401,15 +399,10 @@ public class SSLSocketWithStapling { ServerParameters servParams = new ServerParameters(); serverReady = false; - // Stop the OCSP responders and give a 1 second delay before - // running the test. - intOcsp.stop(); - rootOcsp.stop(); - Thread.sleep(1000); + // Give a 1 second delay before running the test. intOcsp.setDelay(3000); rootOcsp.setDelay(3000); - rootOcsp.start(); - intOcsp.start(); + Thread.sleep(1000); // Wait 5 seconds for server ready for (int i = 0; (i < 100 && (!intOcsp.isServerReady() || !rootOcsp.isServerReady())); i++) { @@ -458,13 +451,9 @@ public class SSLSocketWithStapling { System.out.println("========================================\n"); // Remove the OCSP responder latency - intOcsp.stop(); - rootOcsp.stop(); - Thread.sleep(1000); intOcsp.setDelay(0); rootOcsp.setDelay(0); - rootOcsp.start(); - intOcsp.start(); + Thread.sleep(1000); // Wait 5 seconds for server ready for (int i = 0; (i < 100 && (!intOcsp.isServerReady() || !rootOcsp.isServerReady())); i++) { @@ -676,6 +665,7 @@ public class SSLSocketWithStapling { * Release the client, if not active already... */ System.err.println("Server died..."); + e.printStackTrace(System.err); serverReady = true; serverException = e; } diff --git a/jdk/test/javax/xml/crypto/dsig/TransformService/NullParent.java b/jdk/test/javax/xml/crypto/dsig/TransformService/NullParent.java index 79c03174d20..1205cce8beb 100644 --- a/jdk/test/javax/xml/crypto/dsig/TransformService/NullParent.java +++ b/jdk/test/javax/xml/crypto/dsig/TransformService/NullParent.java @@ -26,6 +26,7 @@ * @bug 8022120 * @summary check that the init and marshalParams methods throw * NullPointerException when the parent parameter is null + * @run main/othervm/java.security.policy==test.policy NullParent */ import javax.xml.crypto.dsig.CanonicalizationMethod; diff --git a/jdk/test/javax/xml/crypto/dsig/TransformService/test.policy b/jdk/test/javax/xml/crypto/dsig/TransformService/test.policy new file mode 100644 index 00000000000..ccc41e5f1ab --- /dev/null +++ b/jdk/test/javax/xml/crypto/dsig/TransformService/test.policy @@ -0,0 +1,3 @@ +grant { + +}; diff --git a/jdk/test/javax/xml/crypto/dsig/keyinfo/KeyInfo/Marshal.java b/jdk/test/javax/xml/crypto/dsig/keyinfo/KeyInfo/Marshal.java index f03cbf3ac99..159fc4ef627 100644 --- a/jdk/test/javax/xml/crypto/dsig/keyinfo/KeyInfo/Marshal.java +++ b/jdk/test/javax/xml/crypto/dsig/keyinfo/KeyInfo/Marshal.java @@ -27,7 +27,7 @@ * @summary Test that KeyInfo.marshal works correctly * @modules java.xml.crypto/org.jcp.xml.dsig.internal.dom * @compile -XDignore.symbol.file Marshal.java - * @run main Marshal + * @run main/othervm/java.security.policy==test.policy Marshal * @author Sean Mullan */ diff --git a/jdk/test/javax/xml/crypto/dsig/keyinfo/KeyInfo/test.policy b/jdk/test/javax/xml/crypto/dsig/keyinfo/KeyInfo/test.policy new file mode 100644 index 00000000000..a6a4709bbae --- /dev/null +++ b/jdk/test/javax/xml/crypto/dsig/keyinfo/KeyInfo/test.policy @@ -0,0 +1,3 @@ +grant { + permission java.lang.RuntimePermission "accessClassInPackage.org.jcp.xml.dsig.internal.dom"; +}; diff --git a/jdk/test/sun/misc/URLClassPath/ClassnameCharTest.java b/jdk/test/sun/misc/URLClassPath/ClassnameCharTest.java index aba760aded1..ea873180b78 100644 --- a/jdk/test/sun/misc/URLClassPath/ClassnameCharTest.java +++ b/jdk/test/sun/misc/URLClassPath/ClassnameCharTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -103,16 +103,60 @@ public class ClassnameCharTest { //--------------------- Infrastructure --------------------------- static volatile int passed = 0, failed = 0; - static boolean pass() {passed++; return true;} - static boolean fail() {failed++; server.stop(0); Thread.dumpStack(); return false;} - static boolean fail(String msg) {System.out.println(msg); return fail();} - static void unexpected(Throwable t) {failed++; server.stop(0); t.printStackTrace();} - static boolean check(boolean cond) {if (cond) pass(); else fail(); return cond;} + + static boolean pass() { + passed++; + return true; + } + + static boolean fail() { + failed++; + if (server != null) { + server.stop(0); + } + Thread.dumpStack(); + return false; + } + + static boolean fail(String msg) { + System.out.println(msg); + return fail(); + } + + static void unexpected(Throwable t) { + failed++; + if (server != null) { + server.stop(0); + } + t.printStackTrace(); + } + + static boolean check(boolean cond) { + if (cond) { + pass(); + } else { + fail(); + } + return cond; + } + static boolean equal(Object x, Object y) { - if (x == null ? y == null : x.equals(y)) return pass(); - else return fail(x + " not equal to " + y);} + if (x == null ? y == null : x.equals(y)) { + return pass(); + } else { + return fail(x + " not equal to " + y); + } + } + public static void main(String[] args) throws Throwable { - try {realMain(args);} catch (Throwable t) {unexpected(t);} + try { + realMain(args); + } catch (Throwable t) { + unexpected(t); + } System.out.println("\nPassed = " + passed + " failed = " + failed); - if (failed > 0) throw new AssertionError("Some tests failed");} + if (failed > 0) { + throw new AssertionError("Some tests failed"); + } + } } diff --git a/jdk/test/sun/security/krb5/auto/CommMatcher.java b/jdk/test/sun/security/krb5/auto/CommMatcher.java new file mode 100644 index 00000000000..1cfe25a5d4d --- /dev/null +++ b/jdk/test/sun/security/krb5/auto/CommMatcher.java @@ -0,0 +1,86 @@ +/* + * 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. + */ + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Matches the krb5 debug output: + * >>> KDCCommunication: kdc=host UDP:11555, timeout=100,Attempt =1, #bytes=138 + * + * Example: + * CommMatcher cm = new CommMatcher(); + * cm.addPort(12345).addPort(23456); + * for (String line : debugOutput) { + * if (cm.match(line)) { + * println("KDC: %c, %s, Timeout: %d\n", + * cm.kdc(), cm.protocol(), cm.timeout()); + * } + * } + */ +public class CommMatcher { + + static final Pattern re = Pattern.compile( + ">>> KDCCommunication: kdc=\\S+ (TCP|UDP):(\\d+), " + + "timeout=(\\d+),Attempt\\s*=(\\d+)"); + + List kdcPorts = new ArrayList<>(); + Matcher matcher; + + /** + * Add KDC ports one by one. The 1st KDC will be 'a' in {@link #kdc()}, + * 2nd is 'b', etc, etc. + */ + public CommMatcher addPort(int port) { + if (port > 0) { + kdcPorts.add(port); + } else { + kdcPorts.clear(); + } + return this; + } + + public boolean match(String line) { + matcher = re.matcher(line); + return matcher.find(); + } + + public String protocol() { + return matcher.group(1); + } + + public char kdc() { + int port = Integer.parseInt(matcher.group(2)); + return (char)(kdcPorts.indexOf(port) + 'a'); + } + + public int timeout() { + return BadKdc.toSymbolicSec(Integer.parseInt(matcher.group(3))); + } + + public int attempt() { + return Integer.parseInt(matcher.group(4)); + } +} diff --git a/jdk/test/sun/security/krb5/auto/MaxRetries.java b/jdk/test/sun/security/krb5/auto/MaxRetries.java index d23cd1043b5..b732becd169 100644 --- a/jdk/test/sun/security/krb5/auto/MaxRetries.java +++ b/jdk/test/sun/security/krb5/auto/MaxRetries.java @@ -30,6 +30,7 @@ * @summary support max_retries in krb5.conf */ +import javax.security.auth.login.LoginException; import java.io.*; import java.net.DatagramSocket; import java.security.Security; @@ -37,46 +38,86 @@ import java.security.Security; public class MaxRetries { static int idlePort = -1; + static CommMatcher cm = new CommMatcher(); public static void main(String[] args) throws Exception { System.setProperty("sun.security.krb5.debug", "true"); - new OneKDC(null).writeJAASConf(); + OneKDC kdc = new OneKDC(null).writeJAASConf(); // An idle UDP socket to prevent PortUnreachableException DatagramSocket ds = new DatagramSocket(); idlePort = ds.getLocalPort(); + cm.addPort(idlePort); + cm.addPort(kdc.getPort()); + System.setProperty("java.security.krb5.conf", "alternative-krb5.conf"); - // For tryLast Security.setProperty("krb5.kdc.bad.policy", "trylast"); + + // We always make the real timeout to be 1 second + BadKdc.setRatio(0.25f); rewriteMaxRetries(4); - test1(4000, 6); // 1 1 1 1 2 2 - test1(4000, 2); // 2 2 + // Explanation: In this case, max_retries=4 and timeout=4s. + // For AS-REQ without preauth, we will see 4 4s timeout on kdc#1 + // ("a4" repeat 4 times), and one 4s timeout on kdc#2 ("b4"). For + // AS-REQ with preauth, one 4s timeout on kdc#2 (second "b4"). + // we tolerate 4 real timeout on kdc#2, so make it "(b4){2,6}". + test1("a4a4a4a4b4b4", "a4a4a4a4(b4){2,6}"); + test1("b4b4", "(b4){2,6}"); + + BadKdc.setRatio(1f); rewriteMaxRetries(1); - test1(1000, 3); // 1 2 2 - test1(1000, 2); // 2 2 + // Explanation: Since max_retries=1 only, we could fail in 1st or 2nd + // AS-REQ to kdc#2. + String actual = test1("a1b1b1", "(a1b1b1|a1b1x|a1b1b1x)"); + if (actual.endsWith("x")) { + // If 1st attempt fails, all bads are back available + test1("a1b1b1", "(a1b1b1|a1b1x|a1b1b1x)"); + } else { + test1("b1b1", "(b1b1|b1x|b1b1x)"); + } + BadKdc.setRatio(0.2f); rewriteMaxRetries(-1); - test1(5000, 4); // 1 1 2 2 - test1(5000, 2); // 2 2 + test1("a5a5a5b5b5", "a5a5a5(b5){2,4}"); + test1("b5b5", "(b5){2,4}"); - // For tryLess - Security.setProperty("krb5.kdc.bad.policy", "tryless:1," + BadKdc.toReal(5000)); + BadKdc.setRatio(0.25f); + Security.setProperty("krb5.kdc.bad.policy", + "tryless:1,1000"); rewriteMaxRetries(4); - test1(4000, 7); // 1 1 1 1 2 1 2 - test1(4000, 4); // 1 2 1 2 + test1("a4a4a4a4b4a4b4", "a4a4a4a4(b4){1,3}a4(b4){1,3}"); + test1("a4b4a4b4", "a4(b4){1,3}a4(b4){1,3}"); + BadKdc.setRatio(1f); rewriteMaxRetries(1); - test1(1000, 4); // 1 2 1 2 - test1(1000, 4); // 1 2 1 2 + actual = test1("a1b1a1b1", "(a1b1|a1b1x|a1b1a1b1|a1b1a1b1x)"); + if (actual.endsWith("x")) { + test1("a1b1a1b1", "(a1b1|a1b1x|a1b1a1b1|a1b1a1b1x)"); + } else { + test1("a1b1a1b1", "(a1b1|a1b1x|a1b1a1b1|a1b1a1b1x)"); + } + BadKdc.setRatio(.2f); rewriteMaxRetries(-1); - test1(5000, 5); // 1 1 2 1 2 - test1(5000, 4); // 1 2 1 2 + test1("a5a5a5b5a5b5", "a5a5a5(b5){1,2}a5(b5){1,2}"); + test1("a5b5a5b5", "a5(b5){1,2}a5(b5){1,2}"); + + BadKdc.setRatio(1f); + rewriteMaxRetries(2); + if (BadKdc.toReal(2000) > 1000) { + // Explanation: if timeout is longer than 1s in tryLess, + // we will see "a1" at 2nd kdc#1 access + test1("a2a2b2a1b2", "a2a2(b2){1,2}a1(b2){1,2}"); + } else { + test1("a2a2b2a2b2", "a2a2(b2){1,2}a2(b2){1,2}"); + } + + BadKdc.setRatio(1f); rewriteUdpPrefLimit(-1, -1); // default, no limit test2("UDP"); @@ -95,32 +136,52 @@ public class MaxRetries { /** * One round of test for max_retries and timeout. - * @param timeout the expected timeout - * @param count the expected total try + * + * @param exact the expected exact match, where no timeout + * happens for real KDCs + * @param relaxed the expected relaxed match, where some timeout + * could happen for real KDCs + * @return the actual result */ - private static void test1(int timeout, int count) throws Exception { - String timeoutTag = "timeout=" + BadKdc.toReal(timeout); + private static String test1(String exact, String relaxed) throws Exception { ByteArrayOutputStream bo = new ByteArrayOutputStream(); PrintStream oldout = System.out; System.setOut(new PrintStream(bo)); - Context c = Context.fromJAAS("client"); + boolean failed = false; + long start = System.nanoTime(); + try { + Context c = Context.fromJAAS("client"); + } catch (LoginException e) { + failed = true; + } System.setOut(oldout); String[] lines = new String(bo.toByteArray()).split("\n"); - System.out.println("----------------- TEST (" + timeout + "," + - count + ") -----------------"); + System.out.println("----------------- TEST (" + exact + + ") -----------------"); + + // Result, a series of timeout + kdc# + StringBuilder sb = new StringBuilder(); for (String line: lines) { - if (line.startsWith(">>> KDCCommunication")) { + if (cm.match(line)) { System.out.println(line); - if (line.indexOf(timeoutTag) < 0) { - throw new Exception("Wrong timeout value" + timeoutTag); - } - count--; + sb.append(cm.kdc()).append(cm.timeout()); } } - if (count != 0) { - throw new Exception("Retry count is " + count + " less"); + if (failed) { + sb.append("x"); } + System.out.println("Time: " + (System.nanoTime() - start) / 1000000000d); + String actual = sb.toString(); + System.out.println("Actual: " + actual); + if (actual.equals(exact)) { + System.out.println("Exact match: " + exact); + } else if (actual.matches(relaxed)) { + System.out.println("!!!! Tolerant match: " + relaxed); + } else { + throw new Exception("Match neither " + exact + " nor " + relaxed); + } + return actual; } /** @@ -138,11 +199,11 @@ public class MaxRetries { String[] lines = new String(bo.toByteArray()).split("\n"); System.out.println("----------------- TEST -----------------"); for (String line: lines) { - if (line.startsWith(">>> KDCCommunication")) { + if (cm.match(line)) { System.out.println(line); count--; - if (line.indexOf(proto) < 0) { - throw new Exception("Wrong timeout value"); + if (!cm.protocol().equals(proto)) { + throw new Exception("Wrong protocol value"); } } } @@ -165,6 +226,7 @@ public class MaxRetries { } if (s.startsWith("[realms]")) { // Reconfig global setting + fw.write("kdc_timeout = 5000\n"); if (global != -1) { fw.write("udp_preference_limit = " + global + "\n"); } @@ -183,7 +245,8 @@ public class MaxRetries { /** * Set max_retries and timeout value for realm. The global value is always - * 2 and 5000. + * 3 and 5000. + * * @param value max_retries and timeout/1000 for a realm, -1 means none. */ private static void rewriteMaxRetries(int value) throws Exception { @@ -196,7 +259,7 @@ public class MaxRetries { } if (s.startsWith("[realms]")) { // Reconfig global setting - fw.write("max_retries = 2\n"); + fw.write("max_retries = 3\n"); fw.write("kdc_timeout = " + BadKdc.toReal(5000) + "\n"); } else if (s.trim().startsWith("kdc = ")) { if (value != -1) { diff --git a/jdk/test/sun/security/ssl/SSLContextImpl/CustomizedCipherSuites.java b/jdk/test/sun/security/ssl/SSLContextImpl/CustomizedCipherSuites.java new file mode 100644 index 00000000000..e19b8f29b83 --- /dev/null +++ b/jdk/test/sun/security/ssl/SSLContextImpl/CustomizedCipherSuites.java @@ -0,0 +1,270 @@ +/* + * 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. + */ + +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. + +/* + * @test + * @bug 8162362 + * @summary Cannot enable previously default enabled cipher suites + * @run main/othervm + * CustomizedCipherSuites Default true + * TLS_RSA_WITH_AES_128_CBC_SHA + * SSL_RSA_WITH_DES_CBC_SHA + * @run main/othervm + * -Djdk.tls.client.cipherSuites="unknown" + * CustomizedCipherSuites Default true + * TLS_RSA_WITH_AES_128_CBC_SHA + * SSL_RSA_WITH_DES_CBC_SHA + * @run main/othervm + * -Djdk.tls.client.cipherSuites="" + * CustomizedCipherSuites Default true + * TLS_RSA_WITH_AES_128_CBC_SHA + * SSL_RSA_WITH_DES_CBC_SHA + * @run main/othervm + * -Djdk.tls.client.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA" + * CustomizedCipherSuites Default true + * SSL_RSA_WITH_DES_CBC_SHA + * TLS_RSA_WITH_AES_128_CBC_SHA + * @run main/othervm + * -Djdk.tls.server.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA" + * CustomizedCipherSuites Default false + * SSL_RSA_WITH_DES_CBC_SHA + * TLS_RSA_WITH_AES_128_CBC_SHA + * @run main/othervm + * -Djdk.tls.client.cipherSuites="TLS_RSA_WITH_AES_128_CBC_SHA,unknown,SSL_RSA_WITH_DES_CBC_SHA" + * CustomizedCipherSuites Default true + * SSL_RSA_WITH_DES_CBC_SHA + * "" + * @run main/othervm + * -Djdk.tls.server.cipherSuites="TLS_RSA_WITH_AES_128_CBC_SHA,unknown,SSL_RSA_WITH_DES_CBC_SHA" + * CustomizedCipherSuites Default false + * TLS_RSA_WITH_AES_128_CBC_SHA + * "" + * @run main/othervm + * -Djdk.tls.server.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA" + * CustomizedCipherSuites Default true + * TLS_RSA_WITH_AES_128_CBC_SHA + * SSL_RSA_WITH_DES_CBC_SHA + * @run main/othervm + * -Djdk.tls.client.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA" + * CustomizedCipherSuites Default false + * TLS_RSA_WITH_AES_128_CBC_SHA + * SSL_RSA_WITH_DES_CBC_SHA + */ + +import javax.net.ssl.*; + +/** + * Test the customized default cipher suites. + * + * This test is based on the behavior that SSL_RSA_WITH_DES_CBC_SHA is + * disabled by default, and TLS_RSA_WITH_AES_128_CBC_SHA is enabled by + * default in JDK. If the behavior is changed in the future, please + * update the test cases above accordingly. + */ +public class CustomizedCipherSuites { + + private static String contextProtocol; + private static boolean isClientMode; + + private static String enabledCipherSuite; + private static String disabledCipherSuite; + + public static void main(String[] args) throws Exception { + + contextProtocol = trimQuotes(args[0]); + isClientMode = Boolean.parseBoolean(args[1]); + enabledCipherSuite = trimQuotes(args[2]); + disabledCipherSuite = trimQuotes(args[3]); + + // + // Create instance of SSLContext with the specified protocol. + // + SSLContext context = SSLContext.getInstance(contextProtocol); + + // Default SSLContext is initialized automatically. + if (!contextProtocol.equals("Default")) { + // Use default TK, KM and random. + context.init((KeyManager[])null, (TrustManager[])null, null); + } + + // SSLContext default parameters is client mode in JDK. + if (isClientMode) { + // + // Check default parameters of the specified SSLContext protocol + // + SSLParameters parameters = context.getDefaultSSLParameters(); + System.out.println("Checking SSLContext default parameters ..."); + checkEnabledCiphers(parameters.getCipherSuites()); + } + + // + // Check supported parameters of the specified SSLContext protocol + // + SSLParameters parameters = context.getSupportedSSLParameters(); + System.out.println("Checking SSLContext suppport parameters ..."); + checkSupportedCiphers(parameters.getCipherSuites()); + + + // + // Check the default cipher suites of SSLEngine. + // + SSLEngine engine = context.createSSLEngine(); + engine.setUseClientMode(isClientMode); + + System.out.println("Checking SSLEngine default cipher suites ..."); + checkEnabledCiphers(engine.getEnabledCipherSuites()); + + // + // Check the supported cipher suites of SSLEngine. + // + System.out.println("Checking SSLEngine supported cipher suites ..."); + checkSupportedCiphers(engine.getSupportedCipherSuites()); + + if (isClientMode) { + SSLSocketFactory factory = context.getSocketFactory(); + // Use an unconnected socket. + try (SSLSocket socket = (SSLSocket)factory.createSocket()) { + // + // Check the default cipher suites of SSLSocket. + // + System.out.println( + "Checking SSLSocket default cipher suites ..."); + checkEnabledCiphers(socket.getEnabledCipherSuites()); + + // + // Check the supported cipher suites of SSLSocket. + // + System.out.println( + "Checking SSLSocket supported cipher suites ..."); + checkSupportedCiphers(socket.getSupportedCipherSuites()); + } + } else { + SSLServerSocketFactory factory = context.getServerSocketFactory(); + // Use an unbound server socket. + try (SSLServerSocket socket = + (SSLServerSocket)factory.createServerSocket()) { + // + // Check the default cipher suites of SSLServerSocket. + // + System.out.println( + "Checking SSLServerSocket default cipher suites ..."); + checkEnabledCiphers(socket.getEnabledCipherSuites()); + + // + // Check the supported cipher suites of SSLServerSocket. + // + System.out.println( + "Checking SSLServerSocket supported cipher suites ..."); + checkSupportedCiphers(socket.getSupportedCipherSuites()); + } + } + + System.out.println("\t... Success"); + } + + private static void checkEnabledCiphers( + String[] ciphers) throws Exception { + + if (ciphers.length == 0) { + throw new Exception("No default cipher suites"); + } + + boolean isMatch = false; + if (enabledCipherSuite.isEmpty()) { + // Don't check if not specify the expected cipher suite. + isMatch = true; + } + + boolean isBroken = false; + for (String cipher : ciphers) { + System.out.println("\tdefault cipher suite " + cipher); + if (!enabledCipherSuite.isEmpty() && + cipher.equals(enabledCipherSuite)) { + isMatch = true; + } + + if (!disabledCipherSuite.isEmpty() && + cipher.equals(disabledCipherSuite)) { + isBroken = true; + } + } + + if (!isMatch) { + throw new Exception( + "Cipher suite " + enabledCipherSuite + " should be enabled"); + } + + if (isBroken) { + throw new Exception( + "Cipher suite " + disabledCipherSuite + " should be disabled"); + } + } + + private static void checkSupportedCiphers( + String[] ciphers) throws Exception { + + if (ciphers.length == 0) { + throw new Exception("No supported cipher suites"); + } + + boolean hasEnabledCipherSuite = enabledCipherSuite.isEmpty(); + boolean hasDisabledCipherSuite = disabledCipherSuite.isEmpty(); + for (String cipher : ciphers) { + System.out.println("\tsupported cipher suite " + cipher); + if (!enabledCipherSuite.isEmpty() && + cipher.equals(enabledCipherSuite)) { + hasEnabledCipherSuite = true; + } + + if (!disabledCipherSuite.isEmpty() && + cipher.equals(disabledCipherSuite)) { + hasDisabledCipherSuite = true; + } + } + + if (!hasEnabledCipherSuite) { + throw new Exception( + "Cipher suite " + enabledCipherSuite + " should be supported"); + } + + if (!hasDisabledCipherSuite) { + throw new Exception( + "Cipher suite " + disabledCipherSuite + " should be supported"); + } + } + + private static String trimQuotes(String candidate) { + if (candidate != null && candidate.length() != 0) { + // Remove double quote marks from beginning/end of the string. + if (candidate.length() > 1 && candidate.charAt(0) == '"' && + candidate.charAt(candidate.length() - 1) == '"') { + return candidate.substring(1, candidate.length() - 1); + } + } + + return candidate; + } +} diff --git a/jdk/test/sun/security/tools/keytool/StartDateTest.java b/jdk/test/sun/security/tools/keytool/StartDateTest.java index a1180eac4f2..d558ff6a49f 100644 --- a/jdk/test/sun/security/tools/keytool/StartDateTest.java +++ b/jdk/test/sun/security/tools/keytool/StartDateTest.java @@ -49,23 +49,31 @@ public class StartDateTest { new File("jks").delete(); - run("-keystore jks -storetype jks -storepass changeit -keypass changeit -alias me " + - "-keyalg rsa -genkeypair -dname CN=Haha -startdate +1y"); - cal.setTime(getIssueDate()); + run("one", "+1y"); + cal.setTime(getIssueDate("one")); System.out.println(cal); if (cal.get(Calendar.YEAR) != year + 1) { throw new Exception("Function check #1 fails"); } - run("-keystore jks -storetype jks -storepass changeit -keypass changeit -alias me " + - "-selfcert -startdate +1m"); - cal.setTime(getIssueDate()); + run("two", "+1m"); + cal.setTime(getIssueDate("two")); System.out.println(cal); if (cal.get(Calendar.MONTH) != (month + 1) % 12) { throw new Exception("Function check #2 fails"); } - new File("jks").delete(); + run("three", "2009/10/11 12:34:56"); + cal.setTime(getIssueDate("three")); + System.out.println(cal); + if (cal.get(Calendar.YEAR) != 2009 || + cal.get(Calendar.MONTH) != Calendar.OCTOBER || + cal.get(Calendar.DAY_OF_MONTH) != 11 || + cal.get(Calendar.HOUR_OF_DAY) != 12 || + cal.get(Calendar.MINUTE) != 34 || + cal.get(Calendar.SECOND) != 56) { + throw new Exception("Function check #3 fails"); + } // Part 2: Test format Method m = sun.security.tools.keytool.Main.class.getDeclaredMethod( @@ -129,16 +137,23 @@ public class StartDateTest { } } - static void run(String s) throws Exception { - sun.security.tools.keytool.Main.main((s+" -debug").split(" ")); + // The keytool command line template, alias and startdate TBD + static String[] cmd = ("-alias tbd -startdate tbd -keystore jks " + + "-storetype jks -storepass changeit -keypass changeit " + + "-keyalg rsa -genkeypair -dname CN=Haha -debug").split(" "); + + static void run(String alias, String startDate) throws Exception { + cmd[1] = alias; + cmd[3] = startDate; + sun.security.tools.keytool.Main.main(cmd); } - static Date getIssueDate() throws Exception { + static Date getIssueDate(String alias) throws Exception { KeyStore ks = KeyStore.getInstance("jks"); try (FileInputStream fis = new FileInputStream("jks")) { ks.load(fis, "changeit".toCharArray()); } - X509Certificate cert = (X509Certificate)ks.getCertificate("me"); + X509Certificate cert = (X509Certificate)ks.getCertificate(alias); return cert.getNotBefore(); } } diff --git a/langtools/.hgtags b/langtools/.hgtags index c950141141e..9314ae7e9bd 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -373,3 +373,4 @@ a42768b48cb0c5af9063e12093975baeeca3b5fa jdk-9+127 2764986661b6d339ba73af52d69d3506ce12e648 jdk-9+128 e181909291981038b041ed4d22714c4760e049cd jdk-9+129 3665ebc22a42c8f33777ee025ba0e300e6086a8c jdk-9+130 +aebfafc43714d5a27d5064d8a0011eaccde633cf jdk-9+131 diff --git a/langtools/make/tools/crules/MutableFieldsAnalyzer.java b/langtools/make/tools/crules/MutableFieldsAnalyzer.java index 5609556be5c..538f7827dfa 100644 --- a/langtools/make/tools/crules/MutableFieldsAnalyzer.java +++ b/langtools/make/tools/crules/MutableFieldsAnalyzer.java @@ -107,6 +107,8 @@ public class MutableFieldsAnalyzer extends AbstractCodingRulesAnalyzer { "layerClass", "bootMethod", "defineModulesWithOneLoaderMethod", "configurationMethod"); ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$ServiceLoaderHelper", "loadMethod"); + ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$VMHelper", + "vmClass", "getRuntimeArgumentsMethod"); ignoreFields("com.sun.tools.javac.util.ModuleHelper", "addExportsMethod", "getUnnamedModuleMethod", "getModuleMethod"); } diff --git a/langtools/src/java.compiler/share/classes/javax/tools/DocumentationTool.java b/langtools/src/java.compiler/share/classes/javax/tools/DocumentationTool.java index 163c2a56fc3..aeb7b98f9d7 100644 --- a/langtools/src/java.compiler/share/classes/javax/tools/DocumentationTool.java +++ b/langtools/src/java.compiler/share/classes/javax/tools/DocumentationTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ public interface DocumentationTool extends Tool, OptionChecker { * use the tool's default method for reporting diagnostics * * @param docletClass a class providing the necessary methods required - * of a doclet + * of a doclet; a value of {@code null} means to use the standard doclet. * * @param options documentation tool options and doclet options, * {@code null} means no options diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTool.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTool.java index fba01f1be5a..69615ce6af5 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTool.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTool.java @@ -179,10 +179,10 @@ public final class JavacTool implements JavaCompiler { args.init("javac", options, classes, compilationUnits); // init multi-release jar handling - if (fileManager.isSupportedOption(Option.MULTIRELEASE.text) == 1) { + if (fileManager.isSupportedOption(Option.MULTIRELEASE.primaryName) == 1) { Target target = Target.instance(context); List list = List.of(target.multiReleaseValue()); - fileManager.handleOption(Option.MULTIRELEASE.text, list.iterator()); + fileManager.handleOption(Option.MULTIRELEASE.primaryName, list.iterator()); } return new JavacTaskImpl(context); @@ -212,8 +212,9 @@ public final class JavacTool implements JavaCompiler { public int isSupportedOption(String option) { Set