diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 3d8197a6c2b..b1a11dc3634 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -270,3 +270,4 @@ ee4fd72b2ec3d92497f37163352f294aa695c6fb jdk9-b20 aefd8899a8d6615fb34ba99b2e38996a7145baa8 jdk9-b25 d3ec8d048e6c3c46b6e0ee011cc551ad386dfba5 jdk9-b26 ba5645f2735b41ed085d07ba20fa7b322afff318 jdk9-b27 +ea2f7981236f3812436958748ab3d26e80a35130 jdk9-b28 diff --git a/Makefile b/Makefile index 1e574940964..6827fd615f3 100644 --- a/Makefile +++ b/Makefile @@ -136,10 +136,12 @@ help: $(info . make docs # Create all docs) $(info . make docs-javadoc # Create just javadocs, depends on less than full docs) $(info . make profiles # Create complete j2re compact profile images) - $(info . make bootcycle-images # Build images twice, second time with newly build JDK) + $(info . make bootcycle-images # Build images twice, second time with newly built JDK) $(info . make install # Install the generated images locally) $(info . make clean # Remove all files generated by make, but not those) - $(info . # generated by configure) + $(info . # generated by configure. Do not run clean and other) + $(info . # targets together as that might behave in an) + $(info . # unexpected way.) $(info . make dist-clean # Remove all files, including configuration) $(info . make help # Give some help on using make) $(info . make test # Run tests, default is all tests (see TEST below)) diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4 index ca88e9f14fa..1a8cb100d94 100644 --- a/common/autoconf/basics.m4 +++ b/common/autoconf/basics.m4 @@ -849,7 +849,12 @@ AC_DEFUN([BASIC_CHECK_FIND_DELETE], if test -f $DELETEDIR/TestIfFindSupportsDelete; then # No, it does not. rm $DELETEDIR/TestIfFindSupportsDelete - FIND_DELETE="-exec rm \{\} \+" + if test "x$OPENJDK_TARGET_OS" = "xaix"; then + # AIX 'find' is buggy if called with '-exec {} \+' and an empty file list + FIND_DELETE="-print | xargs rm" + else + FIND_DELETE="-exec rm \{\} \+" + fi AC_MSG_RESULT([no]) else AC_MSG_RESULT([yes]) diff --git a/common/autoconf/boot-jdk.m4 b/common/autoconf/boot-jdk.m4 index 872e33fb609..fbfa15c7b06 100644 --- a/common/autoconf/boot-jdk.m4 +++ b/common/autoconf/boot-jdk.m4 @@ -370,18 +370,27 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS], # Maximum amount of heap memory. # Maximum stack size. + JVM_MAX_HEAP=`expr $MEMORY_SIZE / 2` if test "x$BUILD_NUM_BITS" = x32; then - JVM_MAX_HEAP=1100M + if test "$JVM_MAX_HEAP" -gt "1100"; then + JVM_MAX_HEAP=1100 + elif test "$JVM_MAX_HEAP" -lt "512"; then + JVM_MAX_HEAP=512 + fi STACK_SIZE=768 else # Running Javac on a JVM on a 64-bit machine, takes more space since 64-bit # pointers are used. Apparently, we need to increase the heap and stack # space for the jvm. More specifically, when running javac to build huge # jdk batch - JVM_MAX_HEAP=1600M + if test "$JVM_MAX_HEAP" -gt "1600"; then + JVM_MAX_HEAP=1600 + elif test "$JVM_MAX_HEAP" -lt "512"; then + JVM_MAX_HEAP=512 + fi STACK_SIZE=1536 fi - ADD_JVM_ARG_IF_OK([-Xmx$JVM_MAX_HEAP],boot_jdk_jvmargs_big,[$JAVA]) + ADD_JVM_ARG_IF_OK([-Xmx${JVM_MAX_HEAP}M],boot_jdk_jvmargs_big,[$JAVA]) ADD_JVM_ARG_IF_OK([-XX:ThreadStackSize=$STACK_SIZE],boot_jdk_jvmargs_big,[$JAVA]) AC_MSG_RESULT([$boot_jdk_jvmargs_big]) diff --git a/common/autoconf/build-performance.m4 b/common/autoconf/build-performance.m4 index 7d4b8abb8da..8425d744990 100644 --- a/common/autoconf/build-performance.m4 +++ b/common/autoconf/build-performance.m4 @@ -131,8 +131,8 @@ AC_DEFUN_ONCE([BPERF_SETUP_BUILD_JOBS], if test "x$with_jobs" = x; then # Number of jobs was not specified, calculate. AC_MSG_CHECKING([for appropriate number of jobs to run in parallel]) - # Approximate memory in GB, rounding up a bit. - memory_gb=`expr $MEMORY_SIZE / 1100` + # Approximate memory in GB. + memory_gb=`expr $MEMORY_SIZE / 1024` # Pick the lowest of memory in gb and number of cores. if test "$memory_gb" -lt "$NUM_CORES"; then JOBS="$memory_gb" @@ -291,16 +291,11 @@ AC_DEFUN_ONCE([BPERF_SETUP_SMART_JAVAC], AC_MSG_ERROR([Could not execute server java: $SJAVAC_SERVER_JAVA]) fi else - SJAVAC_SERVER_JAVA="" - # Hotspot specific options. - ADD_JVM_ARG_IF_OK([-verbosegc],SJAVAC_SERVER_JAVA,[$JAVA]) - # JRockit specific options. - ADD_JVM_ARG_IF_OK([-Xverbose:gc],SJAVAC_SERVER_JAVA,[$JAVA]) - SJAVAC_SERVER_JAVA="$JAVA $SJAVAC_SERVER_JAVA" + SJAVAC_SERVER_JAVA="$JAVA" fi AC_SUBST(SJAVAC_SERVER_JAVA) - if test "$MEMORY_SIZE" -gt "2500"; then + if test "$MEMORY_SIZE" -gt "3000"; then ADD_JVM_ARG_IF_OK([-d64],SJAVAC_SERVER_JAVA,[$SJAVAC_SERVER_JAVA]) if test "$JVM_ARG_OK" = true; then JVM_64BIT=true @@ -308,34 +303,33 @@ AC_DEFUN_ONCE([BPERF_SETUP_SMART_JAVAC], fi fi + MX_VALUE=`expr $MEMORY_SIZE / 2` if test "$JVM_64BIT" = true; then - if test "$MEMORY_SIZE" -gt "17000"; then - ADD_JVM_ARG_IF_OK([-Xms10G -Xmx10G],SJAVAC_SERVER_JAVA,[$SJAVAC_SERVER_JAVA]) + # Set ms lower than mx since more than one instance of the server might + # get launched at the same time before they figure out which instance won. + MS_VALUE=512 + if test "$MX_VALUE" -gt "2048"; then + MX_VALUE=2048 fi - if test "$MEMORY_SIZE" -gt "10000" && test "$JVM_ARG_OK" = false; then - ADD_JVM_ARG_IF_OK([-Xms6G -Xmx6G],SJAVAC_SERVER_JAVA,[$SJAVAC_SERVER_JAVA]) - fi - if test "$MEMORY_SIZE" -gt "5000" && test "$JVM_ARG_OK" = false; then - ADD_JVM_ARG_IF_OK([-Xms1G -Xmx3G],SJAVAC_SERVER_JAVA,[$SJAVAC_SERVER_JAVA]) - fi - if test "$MEMORY_SIZE" -gt "3800" && test "$JVM_ARG_OK" = false; then - ADD_JVM_ARG_IF_OK([-Xms1G -Xmx2500M],SJAVAC_SERVER_JAVA,[$SJAVAC_SERVER_JAVA]) + else + MS_VALUE=256 + if test "$MX_VALUE" -gt "1500"; then + MX_VALUE=1500 fi fi - if test "$MEMORY_SIZE" -gt "2500" && test "$JVM_ARG_OK" = false; then - ADD_JVM_ARG_IF_OK([-Xms1000M -Xmx1500M],SJAVAC_SERVER_JAVA,[$SJAVAC_SERVER_JAVA]) - fi - if test "$MEMORY_SIZE" -gt "1000" && test "$JVM_ARG_OK" = false; then - ADD_JVM_ARG_IF_OK([-Xms400M -Xmx1100M],SJAVAC_SERVER_JAVA,[$SJAVAC_SERVER_JAVA]) - fi - if test "$JVM_ARG_OK" = false; then - ADD_JVM_ARG_IF_OK([-Xms256M -Xmx512M],SJAVAC_SERVER_JAVA,[$SJAVAC_SERVER_JAVA]) + if test "$MX_VALUE" -lt "512"; then + MX_VALUE=512 fi + ADD_JVM_ARG_IF_OK([-Xms${MS_VALUE}M -Xmx${MX_VALUE}M],SJAVAC_SERVER_JAVA,[$SJAVAC_SERVER_JAVA]) - AC_MSG_CHECKING([whether to use sjavac]) AC_ARG_ENABLE([sjavac], [AS_HELP_STRING([--enable-sjavac], [use sjavac to do fast incremental compiles @<:@disabled@:>@])], [ENABLE_SJAVAC="${enableval}"], [ENABLE_SJAVAC='no']) + if test "x$JVM_ARG_OK" = "xfalse"; then + AC_MSG_WARN([Could not set -Xms${MS_VALUE}M -Xmx${MX_VALUE}M, disabling sjavac]) + ENABLE_SJAVAC=no; + fi + AC_MSG_CHECKING([whether to use sjavac]) AC_MSG_RESULT([$ENABLE_SJAVAC]) AC_SUBST(ENABLE_SJAVAC) diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac index ec0d7490d59..ca373c859f1 100644 --- a/common/autoconf/configure.ac +++ b/common/autoconf/configure.ac @@ -142,7 +142,6 @@ JDKOPT_SETUP_JDK_VERSION_NUMBERS ############################################################################### BOOTJDK_SETUP_BOOT_JDK -BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS ############################################################################### # @@ -233,6 +232,9 @@ BPERF_SETUP_BUILD_CORES BPERF_SETUP_BUILD_MEMORY BPERF_SETUP_BUILD_JOBS +# Setup arguments for the boot jdk (after cores and memory have been setup) +BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS + # Setup smart javac (after cores and memory have been setup) BPERF_SETUP_SMART_JAVAC diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4 index 45006928e01..7a62d93ea7f 100644 --- a/common/autoconf/flags.m4 +++ b/common/autoconf/flags.m4 @@ -342,17 +342,15 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION], # no adjustment ;; fastdebug ) - # Add compile time bounds checks. - CFLAGS_DEBUG_OPTIONS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1" - CXXFLAGS_DEBUG_OPTIONS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1" + # no adjustment ;; slowdebug ) - # Add runtime bounds checks and symbol info. - CFLAGS_DEBUG_OPTIONS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector-all --param ssp-buffer-size=1" - CXXFLAGS_DEBUG_OPTIONS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector-all --param ssp-buffer-size=1" + # Add runtime stack smashing and undefined behavior checks + CFLAGS_DEBUG_OPTIONS="-fstack-protector-all --param ssp-buffer-size=1" + CXXFLAGS_DEBUG_OPTIONS="-fstack-protector-all --param ssp-buffer-size=1" if test "x$HAS_CFLAG_DETECT_UNDEFINED_BEHAVIOR" = "xtrue"; then CFLAGS_DEBUG_OPTIONS="$CFLAGS_DEBUG_OPTIONS $CFLAG_DETECT_UNDEFINED_BEHAVIOR_FLAG" - CXXFLAGS_DEBUG_OPTIONS="$CXXFLAGS_DEBUG_OPTIONS $CFLAG_DETECT_UNDEFINED_BEHAVIOR_FLAG" + CXXFLAGS_DEBUG_OPTIONS="$CXXFLAGS_DEBUG_OPTIONS $CFLAG_DETECT_UNDEFINED_BEHAVIsOR_FLAG" fi ;; esac diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 4dd04bd4cf2..d24edd39c20 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -634,6 +634,10 @@ USE_PRECOMPILED_HEADER SJAVAC_SERVER_DIR ENABLE_SJAVAC SJAVAC_SERVER_JAVA +JAVA_TOOL_FLAGS_SMALL +JAVA_FLAGS_SMALL +JAVA_FLAGS_BIG +JAVA_FLAGS JOBS MEMORY_SIZE NUM_CORES @@ -805,10 +809,6 @@ JAXWS_TOPDIR JAXP_TOPDIR CORBA_TOPDIR LANGTOOLS_TOPDIR -JAVA_TOOL_FLAGS_SMALL -JAVA_FLAGS_SMALL -JAVA_FLAGS_BIG -JAVA_FLAGS JAVAC_FLAGS BOOT_JDK_SOURCETARGET JARSIGNER @@ -1064,7 +1064,6 @@ with_update_version with_user_release_suffix with_build_number with_boot_jdk -with_boot_jdk_jvmargs with_add_source_root with_override_source_root with_adds_and_overrides @@ -1106,6 +1105,7 @@ with_dxsdk_include with_num_cores with_memory_size with_jobs +with_boot_jdk_jvmargs with_sjavac_server_java enable_sjavac enable_precompiled_headers @@ -1904,10 +1904,6 @@ Optional Packages: number is not set.[username_builddateb00] --with-build-number Set build number value for build [b00] --with-boot-jdk path to Boot JDK (used to bootstrap build) [probed] - --with-boot-jdk-jvmargs specify JVM arguments to be passed to all java - invocations of boot JDK, overriding the default - values, e.g --with-boot-jdk-jvmargs="-Xmx8G - -enableassertions" --with-add-source-root for each and every source directory, look in this additional source root for the same directory; if it exists and have files in it, include it in the build @@ -1979,6 +1975,10 @@ Optional Packages: --with-memory-size=1024 [probed] --with-jobs number of parallel jobs to let make run [calculated based on cores and memory] + --with-boot-jdk-jvmargs specify JVM arguments to be passed to all java + invocations of boot JDK, overriding the default + values, e.g --with-boot-jdk-jvmargs="-Xmx8G + -enableassertions" --with-sjavac-server-java use this java binary for running the sjavac background server [Boot JDK java] @@ -4321,7 +4321,7 @@ TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++" #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1408448519 +DATE_WHEN_GENERATED=1409311712 ############################################################################### # @@ -17284,7 +17284,12 @@ $as_echo_n "checking if find supports -delete... " >&6; } if test -f $DELETEDIR/TestIfFindSupportsDelete; then # No, it does not. rm $DELETEDIR/TestIfFindSupportsDelete - FIND_DELETE="-exec rm \{\} \+" + if test "x$OPENJDK_TARGET_OS" = "xaix"; then + # AIX 'find' is buggy if called with '-exec {} \+' and an empty file list + FIND_DELETE="-print | xargs rm" + else + FIND_DELETE="-exec rm \{\} \+" + fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else @@ -26315,197 +26320,6 @@ $as_echo "$tool_specified" >&6; } - ############################################################################## - # - # Specify jvm options for anything that is run with the Boot JDK. - # Not all JVM:s accept the same arguments on the command line. - # - -# Check whether --with-boot-jdk-jvmargs was given. -if test "${with_boot_jdk_jvmargs+set}" = set; then : - withval=$with_boot_jdk_jvmargs; -fi - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking flags for boot jdk java command " >&5 -$as_echo_n "checking flags for boot jdk java command ... " >&6; } - - # Disable special log output when a debug build is used as Boot JDK... - - $ECHO "Check if jvm arg is ok: -XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput" >&5 - $ECHO "Command: $JAVA -XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput -version" >&5 - OUTPUT=`$JAVA -XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput -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 - boot_jdk_jvmargs="$boot_jdk_jvmargs -XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - - # Apply user provided options. - - $ECHO "Check if jvm arg is ok: $with_boot_jdk_jvmargs" >&5 - $ECHO "Command: $JAVA $with_boot_jdk_jvmargs -version" >&5 - OUTPUT=`$JAVA $with_boot_jdk_jvmargs -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 - boot_jdk_jvmargs="$boot_jdk_jvmargs $with_boot_jdk_jvmargs" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $boot_jdk_jvmargs" >&5 -$as_echo "$boot_jdk_jvmargs" >&6; } - - # For now, general JAVA_FLAGS are the same as the boot jdk jvmargs - JAVA_FLAGS=$boot_jdk_jvmargs - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking flags for boot jdk java command for big workloads" >&5 -$as_echo_n "checking flags for boot jdk java command for big workloads... " >&6; } - - # Starting amount of heap memory. - - $ECHO "Check if jvm arg is ok: -Xms64M" >&5 - $ECHO "Command: $JAVA -Xms64M -version" >&5 - OUTPUT=`$JAVA -Xms64M -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 - boot_jdk_jvmargs_big="$boot_jdk_jvmargs_big -Xms64M" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - - # Maximum amount of heap memory. - # Maximum stack size. - if test "x$BUILD_NUM_BITS" = x32; then - JVM_MAX_HEAP=1100M - STACK_SIZE=768 - else - # Running Javac on a JVM on a 64-bit machine, takes more space since 64-bit - # pointers are used. Apparently, we need to increase the heap and stack - # space for the jvm. More specifically, when running javac to build huge - # jdk batch - JVM_MAX_HEAP=1600M - STACK_SIZE=1536 - fi - - $ECHO "Check if jvm arg is ok: -Xmx$JVM_MAX_HEAP" >&5 - $ECHO "Command: $JAVA -Xmx$JVM_MAX_HEAP -version" >&5 - OUTPUT=`$JAVA -Xmx$JVM_MAX_HEAP -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 - boot_jdk_jvmargs_big="$boot_jdk_jvmargs_big -Xmx$JVM_MAX_HEAP" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - - $ECHO "Check if jvm arg is ok: -XX:ThreadStackSize=$STACK_SIZE" >&5 - $ECHO "Command: $JAVA -XX:ThreadStackSize=$STACK_SIZE -version" >&5 - OUTPUT=`$JAVA -XX:ThreadStackSize=$STACK_SIZE -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 - boot_jdk_jvmargs_big="$boot_jdk_jvmargs_big -XX:ThreadStackSize=$STACK_SIZE" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $boot_jdk_jvmargs_big" >&5 -$as_echo "$boot_jdk_jvmargs_big" >&6; } - - JAVA_FLAGS_BIG=$boot_jdk_jvmargs_big - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking flags for boot jdk java command for small workloads" >&5 -$as_echo_n "checking flags for boot jdk java command for small workloads... " >&6; } - - # Use serial gc for small short lived tools if possible - - $ECHO "Check if jvm arg is ok: -XX:+UseSerialGC" >&5 - $ECHO "Command: $JAVA -XX:+UseSerialGC -version" >&5 - OUTPUT=`$JAVA -XX:+UseSerialGC -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 - boot_jdk_jvmargs_small="$boot_jdk_jvmargs_small -XX:+UseSerialGC" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - - $ECHO "Check if jvm arg is ok: -Xms32M" >&5 - $ECHO "Command: $JAVA -Xms32M -version" >&5 - OUTPUT=`$JAVA -Xms32M -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 - boot_jdk_jvmargs_small="$boot_jdk_jvmargs_small -Xms32M" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - - $ECHO "Check if jvm arg is ok: -Xmx512M" >&5 - $ECHO "Command: $JAVA -Xmx512M -version" >&5 - OUTPUT=`$JAVA -Xmx512M -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 - boot_jdk_jvmargs_small="$boot_jdk_jvmargs_small -Xmx512M" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $boot_jdk_jvmargs_small" >&5 -$as_echo "$boot_jdk_jvmargs_small" >&6; } - - JAVA_FLAGS_SMALL=$boot_jdk_jvmargs_small - - - JAVA_TOOL_FLAGS_SMALL="" - for f in $JAVA_FLAGS_SMALL; do - JAVA_TOOL_FLAGS_SMALL="$JAVA_TOOL_FLAGS_SMALL -J$f" - done - - - ############################################################################### # # Configure the sources to use. We can add or override individual directories. @@ -42515,17 +42329,15 @@ $as_echo "$ac_cv_c_bigendian" >&6; } # no adjustment ;; fastdebug ) - # Add compile time bounds checks. - CFLAGS_DEBUG_OPTIONS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1" - CXXFLAGS_DEBUG_OPTIONS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1" + # no adjustment ;; slowdebug ) - # Add runtime bounds checks and symbol info. - CFLAGS_DEBUG_OPTIONS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector-all --param ssp-buffer-size=1" - CXXFLAGS_DEBUG_OPTIONS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector-all --param ssp-buffer-size=1" + # Add runtime stack smashing and undefined behavior checks + CFLAGS_DEBUG_OPTIONS="-fstack-protector-all --param ssp-buffer-size=1" + CXXFLAGS_DEBUG_OPTIONS="-fstack-protector-all --param ssp-buffer-size=1" if test "x$HAS_CFLAG_DETECT_UNDEFINED_BEHAVIOR" = "xtrue"; then CFLAGS_DEBUG_OPTIONS="$CFLAGS_DEBUG_OPTIONS $CFLAG_DETECT_UNDEFINED_BEHAVIOR_FLAG" - CXXFLAGS_DEBUG_OPTIONS="$CXXFLAGS_DEBUG_OPTIONS $CFLAG_DETECT_UNDEFINED_BEHAVIOR_FLAG" + CXXFLAGS_DEBUG_OPTIONS="$CXXFLAGS_DEBUG_OPTIONS $CFLAG_DETECT_UNDEFINED_BEHAVIsOR_FLAG" fi ;; esac @@ -49884,8 +49696,8 @@ fi # Number of jobs was not specified, calculate. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for appropriate number of jobs to run in parallel" >&5 $as_echo_n "checking for appropriate number of jobs to run in parallel... " >&6; } - # Approximate memory in GB, rounding up a bit. - memory_gb=`expr $MEMORY_SIZE / 1100` + # Approximate memory in GB. + memory_gb=`expr $MEMORY_SIZE / 1024` # Pick the lowest of memory in gb and number of cores. if test "$memory_gb" -lt "$NUM_CORES"; then JOBS="$memory_gb" @@ -49911,6 +49723,208 @@ $as_echo "$JOBS" >&6; } +# Setup arguments for the boot jdk (after cores and memory have been setup) + + ############################################################################## + # + # Specify jvm options for anything that is run with the Boot JDK. + # Not all JVM:s accept the same arguments on the command line. + # + +# Check whether --with-boot-jdk-jvmargs was given. +if test "${with_boot_jdk_jvmargs+set}" = set; then : + withval=$with_boot_jdk_jvmargs; +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking flags for boot jdk java command " >&5 +$as_echo_n "checking flags for boot jdk java command ... " >&6; } + + # Disable special log output when a debug build is used as Boot JDK... + + $ECHO "Check if jvm arg is ok: -XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput" >&5 + $ECHO "Command: $JAVA -XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput -version" >&5 + OUTPUT=`$JAVA -XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput -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 + boot_jdk_jvmargs="$boot_jdk_jvmargs -XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput" + JVM_ARG_OK=true + else + $ECHO "Arg failed:" >&5 + $ECHO "$OUTPUT" >&5 + JVM_ARG_OK=false + fi + + + # Apply user provided options. + + $ECHO "Check if jvm arg is ok: $with_boot_jdk_jvmargs" >&5 + $ECHO "Command: $JAVA $with_boot_jdk_jvmargs -version" >&5 + OUTPUT=`$JAVA $with_boot_jdk_jvmargs -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 + boot_jdk_jvmargs="$boot_jdk_jvmargs $with_boot_jdk_jvmargs" + JVM_ARG_OK=true + else + $ECHO "Arg failed:" >&5 + $ECHO "$OUTPUT" >&5 + JVM_ARG_OK=false + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $boot_jdk_jvmargs" >&5 +$as_echo "$boot_jdk_jvmargs" >&6; } + + # For now, general JAVA_FLAGS are the same as the boot jdk jvmargs + JAVA_FLAGS=$boot_jdk_jvmargs + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking flags for boot jdk java command for big workloads" >&5 +$as_echo_n "checking flags for boot jdk java command for big workloads... " >&6; } + + # Starting amount of heap memory. + + $ECHO "Check if jvm arg is ok: -Xms64M" >&5 + $ECHO "Command: $JAVA -Xms64M -version" >&5 + OUTPUT=`$JAVA -Xms64M -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 + boot_jdk_jvmargs_big="$boot_jdk_jvmargs_big -Xms64M" + JVM_ARG_OK=true + else + $ECHO "Arg failed:" >&5 + $ECHO "$OUTPUT" >&5 + JVM_ARG_OK=false + fi + + + # Maximum amount of heap memory. + # Maximum stack size. + JVM_MAX_HEAP=`expr $MEMORY_SIZE / 2` + if test "x$BUILD_NUM_BITS" = x32; then + if test "$JVM_MAX_HEAP" -gt "1100"; then + JVM_MAX_HEAP=1100 + elif test "$JVM_MAX_HEAP" -lt "512"; then + JVM_MAX_HEAP=512 + fi + STACK_SIZE=768 + else + # Running Javac on a JVM on a 64-bit machine, takes more space since 64-bit + # pointers are used. Apparently, we need to increase the heap and stack + # space for the jvm. More specifically, when running javac to build huge + # jdk batch + if test "$JVM_MAX_HEAP" -gt "1600"; then + JVM_MAX_HEAP=1600 + elif test "$JVM_MAX_HEAP" -lt "512"; then + JVM_MAX_HEAP=512 + fi + STACK_SIZE=1536 + fi + + $ECHO "Check if jvm arg is ok: -Xmx${JVM_MAX_HEAP}M" >&5 + $ECHO "Command: $JAVA -Xmx${JVM_MAX_HEAP}M -version" >&5 + OUTPUT=`$JAVA -Xmx${JVM_MAX_HEAP}M -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 + boot_jdk_jvmargs_big="$boot_jdk_jvmargs_big -Xmx${JVM_MAX_HEAP}M" + JVM_ARG_OK=true + else + $ECHO "Arg failed:" >&5 + $ECHO "$OUTPUT" >&5 + JVM_ARG_OK=false + fi + + + $ECHO "Check if jvm arg is ok: -XX:ThreadStackSize=$STACK_SIZE" >&5 + $ECHO "Command: $JAVA -XX:ThreadStackSize=$STACK_SIZE -version" >&5 + OUTPUT=`$JAVA -XX:ThreadStackSize=$STACK_SIZE -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 + boot_jdk_jvmargs_big="$boot_jdk_jvmargs_big -XX:ThreadStackSize=$STACK_SIZE" + JVM_ARG_OK=true + else + $ECHO "Arg failed:" >&5 + $ECHO "$OUTPUT" >&5 + JVM_ARG_OK=false + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $boot_jdk_jvmargs_big" >&5 +$as_echo "$boot_jdk_jvmargs_big" >&6; } + + JAVA_FLAGS_BIG=$boot_jdk_jvmargs_big + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking flags for boot jdk java command for small workloads" >&5 +$as_echo_n "checking flags for boot jdk java command for small workloads... " >&6; } + + # Use serial gc for small short lived tools if possible + + $ECHO "Check if jvm arg is ok: -XX:+UseSerialGC" >&5 + $ECHO "Command: $JAVA -XX:+UseSerialGC -version" >&5 + OUTPUT=`$JAVA -XX:+UseSerialGC -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 + boot_jdk_jvmargs_small="$boot_jdk_jvmargs_small -XX:+UseSerialGC" + JVM_ARG_OK=true + else + $ECHO "Arg failed:" >&5 + $ECHO "$OUTPUT" >&5 + JVM_ARG_OK=false + fi + + + $ECHO "Check if jvm arg is ok: -Xms32M" >&5 + $ECHO "Command: $JAVA -Xms32M -version" >&5 + OUTPUT=`$JAVA -Xms32M -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 + boot_jdk_jvmargs_small="$boot_jdk_jvmargs_small -Xms32M" + JVM_ARG_OK=true + else + $ECHO "Arg failed:" >&5 + $ECHO "$OUTPUT" >&5 + JVM_ARG_OK=false + fi + + + $ECHO "Check if jvm arg is ok: -Xmx512M" >&5 + $ECHO "Command: $JAVA -Xmx512M -version" >&5 + OUTPUT=`$JAVA -Xmx512M -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 + boot_jdk_jvmargs_small="$boot_jdk_jvmargs_small -Xmx512M" + JVM_ARG_OK=true + else + $ECHO "Arg failed:" >&5 + $ECHO "$OUTPUT" >&5 + JVM_ARG_OK=false + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $boot_jdk_jvmargs_small" >&5 +$as_echo "$boot_jdk_jvmargs_small" >&6; } + + JAVA_FLAGS_SMALL=$boot_jdk_jvmargs_small + + + JAVA_TOOL_FLAGS_SMALL="" + for f in $JAVA_FLAGS_SMALL; do + JAVA_TOOL_FLAGS_SMALL="$JAVA_TOOL_FLAGS_SMALL -J$f" + done + + + # Setup smart javac (after cores and memory have been setup) @@ -49927,44 +49941,11 @@ fi as_fn_error $? "Could not execute server java: $SJAVAC_SERVER_JAVA" "$LINENO" 5 fi else - SJAVAC_SERVER_JAVA="" - # Hotspot specific options. - - $ECHO "Check if jvm arg is ok: -verbosegc" >&5 - $ECHO "Command: $JAVA -verbosegc -version" >&5 - OUTPUT=`$JAVA -verbosegc -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 - SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -verbosegc" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - # JRockit specific options. - - $ECHO "Check if jvm arg is ok: -Xverbose:gc" >&5 - $ECHO "Command: $JAVA -Xverbose:gc -version" >&5 - OUTPUT=`$JAVA -Xverbose:gc -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 - SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -Xverbose:gc" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - SJAVAC_SERVER_JAVA="$JAVA $SJAVAC_SERVER_JAVA" + SJAVAC_SERVER_JAVA="$JAVA" fi - if test "$MEMORY_SIZE" -gt "2500"; then + if test "$MEMORY_SIZE" -gt "3000"; then $ECHO "Check if jvm arg is ok: -d64" >&5 $ECHO "Command: $SJAVAC_SERVER_JAVA -d64 -version" >&5 @@ -49986,85 +49967,31 @@ fi fi fi + MX_VALUE=`expr $MEMORY_SIZE / 2` if test "$JVM_64BIT" = true; then - if test "$MEMORY_SIZE" -gt "17000"; then - - $ECHO "Check if jvm arg is ok: -Xms10G -Xmx10G" >&5 - $ECHO "Command: $SJAVAC_SERVER_JAVA -Xms10G -Xmx10G -version" >&5 - OUTPUT=`$SJAVAC_SERVER_JAVA -Xms10G -Xmx10G -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 - SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -Xms10G -Xmx10G" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - + # Set ms lower than mx since more than one instance of the server might + # get launched at the same time before they figure out which instance won. + MS_VALUE=512 + if test "$MX_VALUE" -gt "2048"; then + MX_VALUE=2048 fi - if test "$MEMORY_SIZE" -gt "10000" && test "$JVM_ARG_OK" = false; then - - $ECHO "Check if jvm arg is ok: -Xms6G -Xmx6G" >&5 - $ECHO "Command: $SJAVAC_SERVER_JAVA -Xms6G -Xmx6G -version" >&5 - OUTPUT=`$SJAVAC_SERVER_JAVA -Xms6G -Xmx6G -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 - SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -Xms6G -Xmx6G" - JVM_ARG_OK=true else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - fi - if test "$MEMORY_SIZE" -gt "5000" && test "$JVM_ARG_OK" = false; then - - $ECHO "Check if jvm arg is ok: -Xms1G -Xmx3G" >&5 - $ECHO "Command: $SJAVAC_SERVER_JAVA -Xms1G -Xmx3G -version" >&5 - OUTPUT=`$SJAVAC_SERVER_JAVA -Xms1G -Xmx3G -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 - SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -Xms1G -Xmx3G" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - fi - if test "$MEMORY_SIZE" -gt "3800" && test "$JVM_ARG_OK" = false; then - - $ECHO "Check if jvm arg is ok: -Xms1G -Xmx2500M" >&5 - $ECHO "Command: $SJAVAC_SERVER_JAVA -Xms1G -Xmx2500M -version" >&5 - OUTPUT=`$SJAVAC_SERVER_JAVA -Xms1G -Xmx2500M -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 - SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -Xms1G -Xmx2500M" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - + MS_VALUE=256 + if test "$MX_VALUE" -gt "1500"; then + MX_VALUE=1500 fi fi - if test "$MEMORY_SIZE" -gt "2500" && test "$JVM_ARG_OK" = false; then + if test "$MX_VALUE" -lt "512"; then + MX_VALUE=512 + fi - $ECHO "Check if jvm arg is ok: -Xms1000M -Xmx1500M" >&5 - $ECHO "Command: $SJAVAC_SERVER_JAVA -Xms1000M -Xmx1500M -version" >&5 - OUTPUT=`$SJAVAC_SERVER_JAVA -Xms1000M -Xmx1500M -version 2>&1` + $ECHO "Check if jvm arg is ok: -Xms${MS_VALUE}M -Xmx${MX_VALUE}M" >&5 + $ECHO "Command: $SJAVAC_SERVER_JAVA -Xms${MS_VALUE}M -Xmx${MX_VALUE}M -version" >&5 + OUTPUT=`$SJAVAC_SERVER_JAVA -Xms${MS_VALUE}M -Xmx${MX_VALUE}M -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 - SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -Xms1000M -Xmx1500M" + SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -Xms${MS_VALUE}M -Xmx${MX_VALUE}M" JVM_ARG_OK=true else $ECHO "Arg failed:" >&5 @@ -50072,44 +49999,7 @@ fi JVM_ARG_OK=false fi - fi - if test "$MEMORY_SIZE" -gt "1000" && test "$JVM_ARG_OK" = false; then - $ECHO "Check if jvm arg is ok: -Xms400M -Xmx1100M" >&5 - $ECHO "Command: $SJAVAC_SERVER_JAVA -Xms400M -Xmx1100M -version" >&5 - OUTPUT=`$SJAVAC_SERVER_JAVA -Xms400M -Xmx1100M -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 - SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -Xms400M -Xmx1100M" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - fi - if test "$JVM_ARG_OK" = false; then - - $ECHO "Check if jvm arg is ok: -Xms256M -Xmx512M" >&5 - $ECHO "Command: $SJAVAC_SERVER_JAVA -Xms256M -Xmx512M -version" >&5 - OUTPUT=`$SJAVAC_SERVER_JAVA -Xms256M -Xmx512M -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 - SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -Xms256M -Xmx512M" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use sjavac" >&5 -$as_echo_n "checking whether to use sjavac... " >&6; } # Check whether --enable-sjavac was given. if test "${enable_sjavac+set}" = set; then : enableval=$enable_sjavac; ENABLE_SJAVAC="${enableval}" @@ -50117,6 +50007,13 @@ else ENABLE_SJAVAC='no' fi + if test "x$JVM_ARG_OK" = "xfalse"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Could not set -Xms${MS_VALUE}M -Xmx${MX_VALUE}M, disabling sjavac" >&5 +$as_echo "$as_me: WARNING: Could not set -Xms${MS_VALUE}M -Xmx${MX_VALUE}M, disabling sjavac" >&2;} + ENABLE_SJAVAC=no; + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use sjavac" >&5 +$as_echo_n "checking whether to use sjavac... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ENABLE_SJAVAC" >&5 $as_echo "$ENABLE_SJAVAC" >&6; } diff --git a/common/bin/hgforest.sh b/common/bin/hgforest.sh index e7fbd1fe13f..5bf586bc13c 100644 --- a/common/bin/hgforest.sh +++ b/common/bin/hgforest.sh @@ -77,6 +77,11 @@ do shift done +# debug mode +if [ "${HGFOREST_DEBUG:-false}" = "true" ] ; then + global_opts="${global_opts} --debug" +fi + # silence standard output? if [ ${qflag} = "true" ] ; then global_opts="${global_opts} -q" @@ -89,14 +94,26 @@ if [ ${vflag} = "true" ] ; then fi # Make sure we have a command. -if [ $# -lt 1 -o -z "${1:-}" ] ; then - echo "ERROR: No command to hg supplied!" - usage +if [ ${#} -lt 1 -o -z "${1:-}" ] ; then + echo "ERROR: No command to hg supplied!" > ${status_output} + usage > ${status_output} fi -command="$1"; shift +# grab command +command="${1}"; shift + +if [ ${vflag} = "true" ] ; then + echo "# Mercurial command: ${command}" > ${status_output} +fi + + +# capture command options and arguments (if any) command_args="${@:-}" +if [ ${vflag} = "true" ] ; then + echo "# Mercurial command arguments: ${command_args}" > ${status_output} +fi + # Clean out the temporary directory that stores the pid files. tmp=/tmp/forest.$$ rm -f -r ${tmp} @@ -104,7 +121,8 @@ mkdir -p ${tmp} if [ "${HGFOREST_DEBUG:-false}" = "true" ] ; then - echo "DEBUG: temp files are in: ${tmp}" + # ignores redirection. + echo "DEBUG: temp files are in: ${tmp}" >&2 fi # Check if we can use fifos for monitoring sub-process completion. @@ -377,21 +395,33 @@ else fi fi done + + if [ ${have_fifos} = "true" ]; then + # done with the fifo + exec 3>&- + fi fi # Wait for all subprocesses to complete wait # Terminate with exit 0 only if all subprocesses were successful +# Terminate with highest exit code of subprocesses ec=0 if [ -d ${tmp} ]; then rcfiles="`(ls -a ${tmp}/*.pid.rc 2> /dev/null) || echo ''`" for rc in ${rcfiles} ; do exit_code=`cat ${rc} | tr -d ' \n\r'` if [ "${exit_code}" != "0" ] ; then + if [ ${exit_code} -gt 1 ]; then + # mercurial exit codes greater than "1" signal errors. repo="`echo ${rc} | sed -e 's@^'${tmp}'@@' -e 's@/*\([^/]*\)\.pid\.rc$@\1@' -e 's@_@/@g'`" echo "WARNING: ${repo} exited abnormally (${exit_code})" > ${status_output} - ec=1 + fi + if [ ${exit_code} -gt ${ec} ]; then + # assume that larger exit codes are more significant + ec=${exit_code} + fi fi done fi diff --git a/corba/.hgtags b/corba/.hgtags index 6b8724a977f..346a38ca219 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -270,3 +270,4 @@ ddc07abf4307855c0dc904cc5c96cc764023a930 jdk9-b22 da08cca6b97f41b7081a3e176dcb400af6e4bb26 jdk9-b25 6c777df597bbf5abba3488d44c401edfe73c74af jdk9-b26 7e06bf1dcb0907b80ddf59315426ce9ce775e56d jdk9-b27 +a00b04ef067e39f50b9a0fea6f1904e35d632a73 jdk9-b28 diff --git a/corba/make/GensrcCorba.gmk b/corba/make/GensrcCorba.gmk index 8b814238272..1951cd43e37 100644 --- a/corba/make/GensrcCorba.gmk +++ b/corba/make/GensrcCorba.gmk @@ -50,8 +50,9 @@ $(eval $(call SetupJavaCompilation,BUILD_IDLJ, \ INCLUDES := com/sun/tools/corba/se/idl, \ EXCLUDE_FILES := ResourceBundleUtil.java)) +# Force the language to english for predictable source code generation. TOOL_IDLJ_CMD := $(JAVA) -cp $(CORBA_OUTPUTDIR)/idlj_classes \ - com.sun.tools.corba.se.idl.toJavaPortable.Compile + -Duser.language=en com.sun.tools.corba.se.idl.toJavaPortable.Compile ################################################################################ diff --git a/get_source.sh b/get_source.sh index 5e874d1cb51..72049bdec8a 100644 --- a/get_source.sh +++ b/get_source.sh @@ -67,7 +67,7 @@ if [ "x$hgwhere" = "x" ]; then error "Could not locate Mercurial command" fi -hgversion="`hg --version 2> /dev/null | sed -n -e 's@^Mercurial Distributed SCM (version \([^+]*\).*)\$@\1@p'`" +hgversion="`LANGUAGE=en hg --version 2> /dev/null | sed -n -e 's@^Mercurial Distributed SCM (version \([^+]*\).*)\$@\1@p'`" if [ "x${hgversion}" = "x" ] ; then error "Could not determine Mercurial version of $hgwhere" fi diff --git a/hotspot/.hgtags b/hotspot/.hgtags index eada5bf5c92..cf882b4f365 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -430,3 +430,4 @@ dde2d03b0ea46a27650839e3a1d212c7c1f7b4c8 jdk9-b24 6de94e8693240cec8aae11f6b42f43433456a733 jdk9-b25 48b95a073d752d6891cc0d1d2836b321ecf3ce0c jdk9-b26 f95347244306affc32ce3056f27ceff7b2100810 jdk9-b27 +657294869d7ff063e055f5492cab7ce5612ca851 jdk9-b28 diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java index eea5e4b7271..9ba1d2ba72b 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java @@ -45,8 +45,8 @@ import sun.jvm.hotspot.types.TypeDataBase; public class G1CollectedHeap extends SharedHeap { // HeapRegionSeq _seq; static private long hrsFieldOffset; - // MemRegion _g1_committed; - static private long g1CommittedFieldOffset; + // MemRegion _g1_reserved; + static private long g1ReservedFieldOffset; // size_t _summary_bytes_used; static private CIntegerField summaryBytesUsedField; // G1MonitoringSupport* _g1mm; @@ -68,7 +68,6 @@ public class G1CollectedHeap extends SharedHeap { Type type = db.lookupType("G1CollectedHeap"); hrsFieldOffset = type.getField("_hrs").getOffset(); - g1CommittedFieldOffset = type.getField("_g1_committed").getOffset(); summaryBytesUsedField = type.getCIntegerField("_summary_bytes_used"); g1mmField = type.getAddressField("_g1mm"); oldSetFieldOffset = type.getField("_old_set").getOffset(); @@ -76,9 +75,7 @@ public class G1CollectedHeap extends SharedHeap { } public long capacity() { - Address g1CommittedAddr = addr.addOffsetTo(g1CommittedFieldOffset); - MemRegion g1Committed = new MemRegion(g1CommittedAddr); - return g1Committed.byteSize(); + return hrs().capacity(); } public long used() { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1HeapRegionTable.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1HeapRegionTable.java index cfbea40435c..e8bbaaa0553 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1HeapRegionTable.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1HeapRegionTable.java @@ -93,19 +93,35 @@ public class G1HeapRegionTable extends VMObject { private class HeapRegionIterator implements Iterator { private long index; private long length; + private HeapRegion next; + + public HeapRegion positionToNext() { + HeapRegion result = next; + while (index < length && at(index) == null) { + index++; + } + if (index < length) { + next = at(index); + index++; // restart search at next element + } else { + next = null; + } + return result; + } @Override - public boolean hasNext() { return index < length; } + public boolean hasNext() { return next != null; } @Override - public HeapRegion next() { return at(index++); } + public HeapRegion next() { return positionToNext(); } @Override - public void remove() { /* not supported */ } + public void remove() { /* not supported */ } - HeapRegionIterator(long committedLength) { + HeapRegionIterator(long totalLength) { index = 0; - length = committedLength; + length = totalLength; + positionToNext(); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSeq.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSeq.java index 190bf56a17f..8d011ed61ea 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSeq.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSeq.java @@ -43,7 +43,7 @@ public class HeapRegionSeq extends VMObject { // G1HeapRegionTable _regions static private long regionsFieldOffset; // uint _committed_length - static private CIntegerField committedLengthField; + static private CIntegerField numCommittedField; static { VM.registerVMInitializedObserver(new Observer() { @@ -57,7 +57,7 @@ public class HeapRegionSeq extends VMObject { Type type = db.lookupType("HeapRegionSeq"); regionsFieldOffset = type.getField("_regions").getOffset(); - committedLengthField = type.getCIntegerField("_committed_length"); + numCommittedField = type.getCIntegerField("_num_committed"); } private G1HeapRegionTable regions() { @@ -66,16 +66,20 @@ public class HeapRegionSeq extends VMObject { regionsAddr); } + public long capacity() { + return length() * HeapRegion.grainBytes(); + } + public long length() { return regions().length(); } public long committedLength() { - return committedLengthField.getValue(addr); + return numCommittedField.getValue(addr); } public Iterator heapRegionIterator() { - return regions().heapRegionIterator(committedLength()); + return regions().heapRegionIterator(length()); } public HeapRegionSeq(Address addr) { diff --git a/hotspot/make/bsd/makefiles/gcc.make b/hotspot/make/bsd/makefiles/gcc.make index 54d319bb1eb..b31b0cd17a1 100644 --- a/hotspot/make/bsd/makefiles/gcc.make +++ b/hotspot/make/bsd/makefiles/gcc.make @@ -508,13 +508,9 @@ endif ifeq ($(USE_CLANG),) # Enable bounds checking. - # _FORTIFY_SOURCE appears in GCC 4.0+ ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) )" "1" - # compile time size bounds checks - FASTDEBUG_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 - - # and runtime size bounds checks and paranoid stack smashing checks. - DEBUG_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector-all --param ssp-buffer-size=1 + # stack smashing checks. + DEBUG_CFLAGS += -fstack-protector-all --param ssp-buffer-size=1 endif endif diff --git a/hotspot/make/excludeSrc.make b/hotspot/make/excludeSrc.make index 5aabf4c52ac..c28f3b9745e 100644 --- a/hotspot/make/excludeSrc.make +++ b/hotspot/make/excludeSrc.make @@ -70,7 +70,8 @@ ifeq ($(INCLUDE_CDS), false) CXXFLAGS += -DINCLUDE_CDS=0 CFLAGS += -DINCLUDE_CDS=0 - Src_Files_EXCLUDE += filemap.cpp metaspaceShared.cpp + Src_Files_EXCLUDE += filemap.cpp metaspaceShared*.cpp sharedPathsMiscInfo.cpp \ + systemDictionaryShared.cpp classLoaderExt.cpp sharedClassUtil.cpp endif ifeq ($(INCLUDE_ALL_GCS), false) diff --git a/hotspot/make/jprt.properties b/hotspot/make/jprt.properties index 252216f32b5..47df3e779a1 100644 --- a/hotspot/make/jprt.properties +++ b/hotspot/make/jprt.properties @@ -374,6 +374,7 @@ jprt.make.rule.test.targets.standard = \ ${jprt.make.rule.test.targets.standard.reg.group:GROUP=hotspot_compiler}, \ ${jprt.make.rule.test.targets.standard.reg.group:GROUP=hotspot_gc}, \ ${jprt.make.rule.test.targets.standard.reg.group:GROUP=hotspot_runtime}, \ + ${jprt.make.rule.test.targets.standard.reg.group:GROUP=hotspot_runtime_closed}, \ ${jprt.make.rule.test.targets.standard.reg.group:GROUP=hotspot_serviceability} jprt.make.rule.test.targets.embedded = \ diff --git a/hotspot/make/linux/makefiles/gcc.make b/hotspot/make/linux/makefiles/gcc.make index a20e7a1c18b..2447c8d3dd6 100644 --- a/hotspot/make/linux/makefiles/gcc.make +++ b/hotspot/make/linux/makefiles/gcc.make @@ -365,16 +365,13 @@ endif ifeq ($(USE_CLANG),) # Enable bounds checking. - # _FORTIFY_SOURCE appears in GCC 4.0+ ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) )" "1" - # compile time size bounds checks - FASTDEBUG_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 - - # and runtime size bounds checks and paranoid stack smashing checks. - DEBUG_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector-all --param ssp-buffer-size=1 + # stack smashing checks. + DEBUG_CFLAGS += -fstack-protector-all --param ssp-buffer-size=1 endif endif + # If we are building HEADLESS, pass on to VM # so it can set the java.awt.headless property ifdef HEADLESS diff --git a/hotspot/make/solaris/makefiles/gcc.make b/hotspot/make/solaris/makefiles/gcc.make index 9ea05411166..03ba4458c12 100644 --- a/hotspot/make/solaris/makefiles/gcc.make +++ b/hotspot/make/solaris/makefiles/gcc.make @@ -240,11 +240,7 @@ ifeq ($(DEBUG_CFLAGS/$(BUILDARCH)),) endif # Enable bounds checking. -# _FORTIFY_SOURCE appears in GCC 4.0+ ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) )" "1" - # compile time size bounds checks - FASTDEBUG_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 - - # and runtime size bounds checks and paranoid stack smashing checks. - DEBUG_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector-all --param ssp-buffer-size=1 + # stack smashing checks. + DEBUG_CFLAGS += -fstack-protector-all --param ssp-buffer-size=1 endif diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp index 929481c3fbf..068cc4f9ffe 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp @@ -731,7 +731,7 @@ InterpreterFrame *InterpreterFrame::build(Method* const method, TRAPS) { if (method->is_static()) object = method->constants()->pool_holder()->java_mirror(); else - object = (oop) locals[0]; + object = (oop) (void*)locals[0]; monitor->set_obj(object); } diff --git a/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp b/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp index 64e7f5fdf1f..0ea5bbc4f77 100644 --- a/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp +++ b/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp @@ -26,6 +26,8 @@ #ifndef CPU_ZERO_VM_FRAME_ZERO_INLINE_HPP #define CPU_ZERO_VM_FRAME_ZERO_INLINE_HPP +#include "code/codeCache.hpp" + // Constructors inline frame::frame() { diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 9668cb17d7d..586f46a26b3 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -2246,7 +2246,7 @@ void os::print_siginfo(outputStream* st, void* siginfo) { const siginfo_t* si = (const siginfo_t*)siginfo; os::Posix::print_siginfo_brief(st, si); - +#if INCLUDE_CDS if (si && (si->si_signo == SIGBUS || si->si_signo == SIGSEGV) && UseSharedSpaces) { FileMapInfo* mapinfo = FileMapInfo::current_info(); @@ -2256,6 +2256,7 @@ void os::print_siginfo(outputStream* st, void* siginfo) { " possible disk/network problem."); } } +#endif st->cr(); } diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp index 56ccc721fa0..f30ad48669a 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp @@ -66,129 +66,92 @@ static void do_sysinfo(int si, const char* string, int* features, int mask) { } int VM_Version::platform_features(int features) { - // getisax(2), SI_ARCHITECTURE_32, and SI_ARCHITECTURE_64 are - // supported on Solaris 10 and later. - if (os::Solaris::supports_getisax()) { + assert(os::Solaris::supports_getisax(), "getisax() must be available"); - // Check 32-bit architecture. - do_sysinfo(SI_ARCHITECTURE_32, "sparc", &features, v8_instructions_m); + // Check 32-bit architecture. + do_sysinfo(SI_ARCHITECTURE_32, "sparc", &features, v8_instructions_m); - // Check 64-bit architecture. - do_sysinfo(SI_ARCHITECTURE_64, "sparcv9", &features, generic_v9_m); + // Check 64-bit architecture. + do_sysinfo(SI_ARCHITECTURE_64, "sparcv9", &features, generic_v9_m); - // Extract valid instruction set extensions. - uint_t avs[2]; - uint_t avn = os::Solaris::getisax(avs, 2); - assert(avn <= 2, "should return two or less av's"); - uint_t av = avs[0]; + // Extract valid instruction set extensions. + uint_t avs[2]; + uint_t avn = os::Solaris::getisax(avs, 2); + assert(avn <= 2, "should return two or less av's"); + uint_t av = avs[0]; #ifndef PRODUCT - if (PrintMiscellaneous && Verbose) { - tty->print("getisax(2) returned: " PTR32_FORMAT, av); - if (avn > 1) { - tty->print(", " PTR32_FORMAT, avs[1]); - } - tty->cr(); + if (PrintMiscellaneous && Verbose) { + tty->print("getisax(2) returned: " PTR32_FORMAT, av); + if (avn > 1) { + tty->print(", " PTR32_FORMAT, avs[1]); } + tty->cr(); + } #endif - if (av & AV_SPARC_MUL32) features |= hardware_mul32_m; - if (av & AV_SPARC_DIV32) features |= hardware_div32_m; - if (av & AV_SPARC_FSMULD) features |= hardware_fsmuld_m; - if (av & AV_SPARC_V8PLUS) features |= v9_instructions_m; - if (av & AV_SPARC_POPC) features |= hardware_popc_m; - if (av & AV_SPARC_VIS) features |= vis1_instructions_m; - if (av & AV_SPARC_VIS2) features |= vis2_instructions_m; - if (avn > 1) { - uint_t av2 = avs[1]; + if (av & AV_SPARC_MUL32) features |= hardware_mul32_m; + if (av & AV_SPARC_DIV32) features |= hardware_div32_m; + if (av & AV_SPARC_FSMULD) features |= hardware_fsmuld_m; + if (av & AV_SPARC_V8PLUS) features |= v9_instructions_m; + if (av & AV_SPARC_POPC) features |= hardware_popc_m; + if (av & AV_SPARC_VIS) features |= vis1_instructions_m; + if (av & AV_SPARC_VIS2) features |= vis2_instructions_m; + if (avn > 1) { + uint_t av2 = avs[1]; #ifndef AV2_SPARC_SPARC5 #define AV2_SPARC_SPARC5 0x00000008 /* The 29 new fp and sub instructions */ #endif - if (av2 & AV2_SPARC_SPARC5) features |= sparc5_instructions_m; - } + if (av2 & AV2_SPARC_SPARC5) features |= sparc5_instructions_m; + } - // Next values are not defined before Solaris 10 - // but Solaris 8 is used for jdk6 update builds. + // We only build on Solaris 10 and up, but some of the values below + // are not defined on all versions of Solaris 10, so we define them, + // if necessary. #ifndef AV_SPARC_ASI_BLK_INIT #define AV_SPARC_ASI_BLK_INIT 0x0080 /* ASI_BLK_INIT_xxx ASI */ #endif - if (av & AV_SPARC_ASI_BLK_INIT) features |= blk_init_instructions_m; + if (av & AV_SPARC_ASI_BLK_INIT) features |= blk_init_instructions_m; #ifndef AV_SPARC_FMAF #define AV_SPARC_FMAF 0x0100 /* Fused Multiply-Add */ #endif - if (av & AV_SPARC_FMAF) features |= fmaf_instructions_m; + if (av & AV_SPARC_FMAF) features |= fmaf_instructions_m; #ifndef AV_SPARC_FMAU -#define AV_SPARC_FMAU 0x0200 /* Unfused Multiply-Add */ +#define AV_SPARC_FMAU 0x0200 /* Unfused Multiply-Add */ #endif - if (av & AV_SPARC_FMAU) features |= fmau_instructions_m; + if (av & AV_SPARC_FMAU) features |= fmau_instructions_m; #ifndef AV_SPARC_VIS3 -#define AV_SPARC_VIS3 0x0400 /* VIS3 instruction set extensions */ +#define AV_SPARC_VIS3 0x0400 /* VIS3 instruction set extensions */ #endif - if (av & AV_SPARC_VIS3) features |= vis3_instructions_m; + if (av & AV_SPARC_VIS3) features |= vis3_instructions_m; #ifndef AV_SPARC_CBCOND #define AV_SPARC_CBCOND 0x10000000 /* compare and branch instrs supported */ #endif - if (av & AV_SPARC_CBCOND) features |= cbcond_instructions_m; + if (av & AV_SPARC_CBCOND) features |= cbcond_instructions_m; #ifndef AV_SPARC_AES #define AV_SPARC_AES 0x00020000 /* aes instrs supported */ #endif - if (av & AV_SPARC_AES) features |= aes_instructions_m; + if (av & AV_SPARC_AES) features |= aes_instructions_m; #ifndef AV_SPARC_SHA1 #define AV_SPARC_SHA1 0x00400000 /* sha1 instruction supported */ #endif - if (av & AV_SPARC_SHA1) features |= sha1_instruction_m; + if (av & AV_SPARC_SHA1) features |= sha1_instruction_m; #ifndef AV_SPARC_SHA256 #define AV_SPARC_SHA256 0x00800000 /* sha256 instruction supported */ #endif - if (av & AV_SPARC_SHA256) features |= sha256_instruction_m; + if (av & AV_SPARC_SHA256) features |= sha256_instruction_m; #ifndef AV_SPARC_SHA512 #define AV_SPARC_SHA512 0x01000000 /* sha512 instruction supported */ #endif - if (av & AV_SPARC_SHA512) features |= sha512_instruction_m; - - } else { - // getisax(2) failed, use the old legacy code. -#ifndef PRODUCT - if (PrintMiscellaneous && Verbose) - tty->print_cr("getisax(2) is not supported."); -#endif - - char tmp; - size_t bufsize = sysinfo(SI_ISALIST, &tmp, 1); - char* buf = (char*) os::malloc(bufsize, mtInternal); - - if (buf != NULL) { - if (sysinfo(SI_ISALIST, buf, bufsize) == bufsize) { - // Figure out what kind of sparc we have - char *sparc_string = strstr(buf, "sparc"); - if (sparc_string != NULL) { features |= v8_instructions_m; - if (sparc_string[5] == 'v') { - if (sparc_string[6] == '8') { - if (sparc_string[7] == '-') { features |= hardware_mul32_m; - features |= hardware_div32_m; - } else if (sparc_string[7] == 'p') features |= generic_v9_m; - else features |= generic_v8_m; - } else if (sparc_string[6] == '9') features |= generic_v9_m; - } - } - - // Check for visualization instructions - char *vis = strstr(buf, "vis"); - if (vis != NULL) { features |= vis1_instructions_m; - if (vis[3] == '2') features |= vis2_instructions_m; - } - } - os::free(buf); - } - } + if (av & AV_SPARC_SHA512) features |= sha512_instruction_m; // Determine the machine type. do_sysinfo(SI_MACHINE, "sun4v", &features, sun4v_m); @@ -203,27 +166,7 @@ int VM_Version::platform_features(int features) { kstat_named_t* knm = (kstat_named_t *)ksp->ks_data; for (int i = 0; i < ksp->ks_ndata; i++) { if (strcmp((const char*)&(knm[i].name),"implementation") == 0) { -#ifndef KSTAT_DATA_STRING -#define KSTAT_DATA_STRING 9 -#endif - if (knm[i].data_type == KSTAT_DATA_CHAR) { - // VM is running on Solaris 8 which does not have value.str. - implementation = &(knm[i].value.c[0]); - } else if (knm[i].data_type == KSTAT_DATA_STRING) { - // VM is running on Solaris 10. -#ifndef KSTAT_NAMED_STR_PTR - // Solaris 8 was used to build VM, define the structure it misses. - struct str_t { - union { - char *ptr; /* NULL-term string */ - char __pad[8]; /* 64-bit padding */ - } addr; - uint32_t len; /* # bytes for strlen + '\0' */ - }; -#define KSTAT_NAMED_STR_PTR(knptr) (( (str_t*)&((knptr)->value) )->addr.ptr) -#endif - implementation = KSTAT_NAMED_STR_PTR(&knm[i]); - } + implementation = KSTAT_NAMED_STR_PTR(&knm[i]); #ifndef PRODUCT if (PrintMiscellaneous && Verbose) { tty->print_cr("cpu_info.implementation: %s", implementation); @@ -234,6 +177,7 @@ int VM_Version::platform_features(int features) { for (int i = 0; impl[i] != 0; i++) impl[i] = (char)toupper((uint)impl[i]); + if (strstr(impl, "SPARC64") != NULL) { features |= sparc64_family_m; } else if (strstr(impl, "SPARC-M") != NULL) { @@ -248,8 +192,10 @@ int VM_Version::platform_features(int features) { if (strstr(impl, "SPARC") == NULL) { #ifndef PRODUCT // kstat on Solaris 8 virtual machines (branded zones) - // returns "(unsupported)" implementation. - warning("kstat cpu_info implementation = '%s', should contain SPARC", impl); + // returns "(unsupported)" implementation. Solaris 8 is not + // supported anymore, but include this check to be on the + // safe side. + warning("kstat cpu_info implementation = '%s', assume generic SPARC", impl); #endif implementation = "SPARC"; } diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c1_Runtime1.cpp index b8dd1bbfb83..d480a70838e 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp @@ -546,13 +546,18 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* t // normal bytecode execution. thread->clear_exception_oop_and_pc(); + Handle original_exception(thread, exception()); + continuation = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, false, false); // If an exception was thrown during exception dispatch, the exception oop may have changed thread->set_exception_oop(exception()); thread->set_exception_pc(pc); // the exception cache is used only by non-implicit exceptions - if (continuation != NULL) { + // Update the exception cache only when there didn't happen + // another exception during the computation of the compiled + // exception handler. + if (continuation != NULL && original_exception() == exception()) { nm->add_handler_for_exception_and_pc(exception, pc, continuation); } } diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index c6de3e2e4f7..8b3ef37d590 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -31,6 +31,9 @@ #include "classfile/javaClasses.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" +#if INCLUDE_CDS +#include "classfile/systemDictionaryShared.hpp" +#endif #include "classfile/verificationType.hpp" #include "classfile/verifier.hpp" #include "classfile/vmSymbols.hpp" @@ -60,6 +63,7 @@ #include "services/threadService.hpp" #include "utilities/array.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/ostream.hpp" // We generally try to create the oops directly when parsing, rather than // allocating temporary data structures and copying the bytes twice. A @@ -3786,7 +3790,15 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, instanceKlassHandle nullHandle; // Figure out whether we can skip format checking (matching classic VM behavior) - _need_verify = Verifier::should_verify_for(class_loader(), verify); + if (DumpSharedSpaces) { + // verify == true means it's a 'remote' class (i.e., non-boot class) + // Verification decision is based on BytecodeVerificationRemote flag + // for those classes. + _need_verify = (verify) ? BytecodeVerificationRemote : + BytecodeVerificationLocal; + } else { + _need_verify = Verifier::should_verify_for(class_loader(), verify); + } // Set the verify flag in stream cfs->set_verify(_need_verify); @@ -3805,6 +3817,18 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, u2 minor_version = cfs->get_u2_fast(); u2 major_version = cfs->get_u2_fast(); + if (DumpSharedSpaces && major_version < JAVA_1_5_VERSION) { + ResourceMark rm; + warning("Pre JDK 1.5 class not supported by CDS: %u.%u %s", + major_version, minor_version, name->as_C_string()); + Exceptions::fthrow( + THREAD_AND_LOCATION, + vmSymbols::java_lang_UnsupportedClassVersionError(), + "Unsupported major.minor version for dump time %u.%u", + major_version, + minor_version); + } + // Check version numbers - we check this even with verifier off if (!is_supported_version(major_version, minor_version)) { if (name == NULL) { @@ -3912,6 +3936,18 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, if (cfs->source() != NULL) tty->print(" from %s", cfs->source()); tty->print_cr("]"); } +#if INCLUDE_CDS + if (DumpLoadedClassList != NULL && cfs->source() != NULL && classlist_file->is_open()) { + // Only dump the classes that can be stored into CDS archive + if (SystemDictionaryShared::is_sharing_possible(loader_data)) { + if (name != NULL) { + ResourceMark rm(THREAD); + classlist_file->print_cr("%s", name->as_C_string()); + classlist_file->flush(); + } + } + } +#endif u2 super_class_index = cfs->get_u2_fast(); instanceKlassHandle super_klass = parse_super_class(super_class_index, diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index 1467462f1bf..19aec02c26f 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -26,8 +26,13 @@ #include "classfile/classFileParser.hpp" #include "classfile/classFileStream.hpp" #include "classfile/classLoader.hpp" +#include "classfile/classLoaderExt.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/javaClasses.hpp" +#if INCLUDE_CDS +#include "classfile/sharedPathsMiscInfo.hpp" +#include "classfile/sharedClassUtil.hpp" +#endif #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "compiler/compileBroker.hpp" @@ -35,6 +40,7 @@ #include "interpreter/bytecodeStream.hpp" #include "interpreter/oopMapCache.hpp" #include "memory/allocation.inline.hpp" +#include "memory/filemap.hpp" #include "memory/generation.hpp" #include "memory/oopFactory.hpp" #include "memory/universe.inline.hpp" @@ -114,8 +120,12 @@ PerfCounter* ClassLoader::_load_instance_class_failCounter = NULL; ClassPathEntry* ClassLoader::_first_entry = NULL; ClassPathEntry* ClassLoader::_last_entry = NULL; +int ClassLoader::_num_entries = 0; PackageHashtable* ClassLoader::_package_hash_table = NULL; +#if INCLUDE_CDS +SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL; +#endif // helper routines bool string_starts_with(const char* str, const char* str_to_find) { size_t str_len = strlen(str); @@ -194,6 +204,14 @@ ClassFileStream* ClassPathDirEntry::open_stream(const char* name, TRAPS) { // check if file exists struct stat st; if (os::stat(path, &st) == 0) { +#if INCLUDE_CDS + if (DumpSharedSpaces) { + // We have already check in ClassLoader::check_shared_classpath() that the directory is empty, so + // we should never find a file underneath it -- unless user has added a new file while we are running + // the dump, in which case let's quit! + ShouldNotReachHere(); + } +#endif // found file, open it int file_handle = os::open(path, 0, 0); if (file_handle != -1) { @@ -228,13 +246,13 @@ ClassPathZipEntry::~ClassPathZipEntry() { FREE_C_HEAP_ARRAY(char, _zip_name, mtClass); } -ClassFileStream* ClassPathZipEntry::open_stream(const char* name, TRAPS) { - // enable call to C land +u1* ClassPathZipEntry::open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS) { + // enable call to C land JavaThread* thread = JavaThread::current(); ThreadToNativeFromVM ttn(thread); // check whether zip archive contains name - jint filesize, name_len; - jzentry* entry = (*FindEntry)(_zip, name, &filesize, &name_len); + jint name_len; + jzentry* entry = (*FindEntry)(_zip, name, filesize, &name_len); if (entry == NULL) return NULL; u1* buffer; char name_buf[128]; @@ -245,19 +263,33 @@ ClassFileStream* ClassPathZipEntry::open_stream(const char* name, TRAPS) { filename = NEW_RESOURCE_ARRAY(char, name_len + 1); } - // file found, get pointer to class in mmaped jar file. + // file found, get pointer to the entry in mmapped jar file. if (ReadMappedEntry == NULL || !(*ReadMappedEntry)(_zip, entry, &buffer, filename)) { - // mmaped access not available, perhaps due to compression, + // mmapped access not available, perhaps due to compression, // read contents into resource array - buffer = NEW_RESOURCE_ARRAY(u1, filesize); + int size = (*filesize) + ((nul_terminate) ? 1 : 0); + buffer = NEW_RESOURCE_ARRAY(u1, size); if (!(*ReadEntry)(_zip, entry, buffer, filename)) return NULL; } + + // return result + if (nul_terminate) { + buffer[*filesize] = 0; + } + return buffer; +} + +ClassFileStream* ClassPathZipEntry::open_stream(const char* name, TRAPS) { + jint filesize; + u1* buffer = open_entry(name, &filesize, false, CHECK_NULL); + if (buffer == NULL) { + return NULL; + } if (UsePerfData) { ClassLoader::perf_sys_classfile_bytes_read()->inc(filesize); } - // return result - return new ClassFileStream(buffer, filesize, _zip_name); // Resource allocated + return new ClassFileStream(buffer, filesize, _zip_name); // Resource allocated } // invoke function for each entry in the zip file @@ -272,12 +304,13 @@ void ClassPathZipEntry::contents_do(void f(const char* name, void* context), voi } } -LazyClassPathEntry::LazyClassPathEntry(char* path, const struct stat* st) : ClassPathEntry() { +LazyClassPathEntry::LazyClassPathEntry(char* path, const struct stat* st, bool throw_exception) : ClassPathEntry() { _path = os::strdup_check_oom(path); _st = *st; _meta_index = NULL; _resolved_entry = NULL; _has_error = false; + _throw_exception = throw_exception; } LazyClassPathEntry::~LazyClassPathEntry() { @@ -293,7 +326,11 @@ ClassPathEntry* LazyClassPathEntry::resolve_entry(TRAPS) { return (ClassPathEntry*) _resolved_entry; } ClassPathEntry* new_entry = NULL; - new_entry = ClassLoader::create_class_path_entry(_path, &_st, false, CHECK_NULL); + new_entry = ClassLoader::create_class_path_entry(_path, &_st, false, _throw_exception, CHECK_NULL); + if (!_throw_exception && new_entry == NULL) { + assert(!HAS_PENDING_EXCEPTION, "must be"); + return NULL; + } { ThreadCritical tc; if (_resolved_entry == NULL) { @@ -327,6 +364,23 @@ bool LazyClassPathEntry::is_lazy() { return true; } +u1* LazyClassPathEntry::open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS) { + if (_has_error) { + return NULL; + } + ClassPathEntry* cpe = resolve_entry(THREAD); + if (cpe == NULL) { + _has_error = true; + return NULL; + } else if (cpe->is_jar_file()) { + return ((ClassPathZipEntry*)cpe)->open_entry(name, filesize, nul_terminate,THREAD); + } else { + ShouldNotReachHere(); + *filesize = 0; + return NULL; + } +} + static void print_meta_index(LazyClassPathEntry* entry, GrowableArray& meta_packages) { tty->print("[Meta index for %s=", entry->name()); @@ -337,15 +391,62 @@ static void print_meta_index(LazyClassPathEntry* entry, tty->print_cr("]"); } +#if INCLUDE_CDS +void ClassLoader::exit_with_path_failure(const char* error, const char* message) { + assert(DumpSharedSpaces, "only called at dump time"); + tty->print_cr("Hint: enable -XX:+TraceClassPaths to diagnose the failure"); + vm_exit_during_initialization(error, message); +} +#endif -void ClassLoader::setup_meta_index() { +void ClassLoader::trace_class_path(const char* msg, const char* name) { + if (!TraceClassPaths) { + return; + } + + if (msg) { + tty->print("%s", msg); + } + if (name) { + if (strlen(name) < 256) { + tty->print("%s", name); + } else { + // For very long paths, we need to print each character separately, + // as print_cr() has a length limit + while (name[0] != '\0') { + tty->print("%c", name[0]); + name++; + } + } + } + if (msg && msg[0] == '[') { + tty->print_cr("]"); + } else { + tty->cr(); + } +} + +void ClassLoader::setup_bootstrap_meta_index() { // Set up meta index which allows us to open boot jars lazily if // class data sharing is enabled + const char* meta_index_path = Arguments::get_meta_index_path(); + const char* meta_index_dir = Arguments::get_meta_index_dir(); + setup_meta_index(meta_index_path, meta_index_dir, 0); +} + +void ClassLoader::setup_meta_index(const char* meta_index_path, const char* meta_index_dir, int start_index) { const char* known_version = "% VERSION 2"; - char* meta_index_path = Arguments::get_meta_index_path(); - char* meta_index_dir = Arguments::get_meta_index_dir(); FILE* file = fopen(meta_index_path, "r"); int line_no = 0; +#if INCLUDE_CDS + if (DumpSharedSpaces) { + if (file != NULL) { + _shared_paths_misc_info->add_required_file(meta_index_path); + } else { + _shared_paths_misc_info->add_nonexist_path(meta_index_path); + } + } +#endif if (file != NULL) { ResourceMark rm; LazyClassPathEntry* cur_entry = NULL; @@ -380,7 +481,7 @@ void ClassLoader::setup_meta_index() { // Hand off current packages to current lazy entry (if any) if ((cur_entry != NULL) && (boot_class_path_packages.length() > 0)) { - if (TraceClassLoading && Verbose) { + if ((TraceClassLoading || TraceClassPaths) && Verbose) { print_meta_index(cur_entry, boot_class_path_packages); } MetaIndex* index = new MetaIndex(boot_class_path_packages.adr_at(0), @@ -391,8 +492,10 @@ void ClassLoader::setup_meta_index() { boot_class_path_packages.clear(); // Find lazy entry corresponding to this jar file - for (ClassPathEntry* entry = _first_entry; entry != NULL; entry = entry->next()) { - if (entry->is_lazy() && + int count = 0; + for (ClassPathEntry* entry = _first_entry; entry != NULL; entry = entry->next(), count++) { + if (count >= start_index && + entry->is_lazy() && string_starts_with(entry->name(), meta_index_dir) && string_ends_with(entry->name(), &package_name[2])) { cur_entry = (LazyClassPathEntry*) entry; @@ -429,7 +532,7 @@ void ClassLoader::setup_meta_index() { // Hand off current packages to current lazy entry (if any) if ((cur_entry != NULL) && (boot_class_path_packages.length() > 0)) { - if (TraceClassLoading && Verbose) { + if ((TraceClassLoading || TraceClassPaths) && Verbose) { print_meta_index(cur_entry, boot_class_path_packages); } MetaIndex* index = new MetaIndex(boot_class_path_packages.adr_at(0), @@ -440,37 +543,88 @@ void ClassLoader::setup_meta_index() { } } +#if INCLUDE_CDS +void ClassLoader::check_shared_classpath(const char *path) { + if (strcmp(path, "") == 0) { + exit_with_path_failure("Cannot have empty path in archived classpaths", NULL); + } + + struct stat st; + if (os::stat(path, &st) == 0) { + if ((st.st_mode & S_IFREG) != S_IFREG) { // is directory + if (!os::dir_is_empty(path)) { + tty->print_cr("Error: non-empty directory '%s'", path); + exit_with_path_failure("CDS allows only empty directories in archived classpaths", NULL); + } + } + } +} +#endif + void ClassLoader::setup_bootstrap_search_path() { assert(_first_entry == NULL, "should not setup bootstrap class search path twice"); char* sys_class_path = os::strdup_check_oom(Arguments::get_sysclasspath()); - if (TraceClassLoading && Verbose) { - tty->print_cr("[Bootstrap loader class path=%s]", sys_class_path); + if (!PrintSharedArchiveAndExit) { + trace_class_path("[Bootstrap loader class path=", sys_class_path); } +#if INCLUDE_CDS + if (DumpSharedSpaces) { + _shared_paths_misc_info->add_boot_classpath(Arguments::get_sysclasspath()); + } +#endif + setup_search_path(sys_class_path); + os::free(sys_class_path); +} - int len = (int)strlen(sys_class_path); +#if INCLUDE_CDS +int ClassLoader::get_shared_paths_misc_info_size() { + return _shared_paths_misc_info->get_used_bytes(); +} + +void* ClassLoader::get_shared_paths_misc_info() { + return _shared_paths_misc_info->buffer(); +} + +bool ClassLoader::check_shared_paths_misc_info(void *buf, int size) { + SharedPathsMiscInfo* checker = SharedClassUtil::allocate_shared_paths_misc_info((char*)buf, size); + bool result = checker->check(); + delete checker; + return result; +} +#endif + +void ClassLoader::setup_search_path(char *class_path) { + int offset = 0; + int len = (int)strlen(class_path); int end = 0; // Iterate over class path entries for (int start = 0; start < len; start = end) { - while (sys_class_path[end] && sys_class_path[end] != os::path_separator()[0]) { + while (class_path[end] && class_path[end] != os::path_separator()[0]) { end++; } - char* path = NEW_C_HEAP_ARRAY(char, end-start+1, mtClass); - strncpy(path, &sys_class_path[start], end-start); - path[end-start] = '\0'; + EXCEPTION_MARK; + ResourceMark rm(THREAD); + char* path = NEW_RESOURCE_ARRAY(char, end - start + 1); + strncpy(path, &class_path[start], end - start); + path[end - start] = '\0'; update_class_path_entry_list(path, false); - FREE_C_HEAP_ARRAY(char, path, mtClass); - while (sys_class_path[end] == os::path_separator()[0]) { +#if INCLUDE_CDS + if (DumpSharedSpaces) { + check_shared_classpath(path); + } +#endif + while (class_path[end] == os::path_separator()[0]) { end++; } } - os::free(sys_class_path); } -ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct stat* st, bool lazy, TRAPS) { +ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct stat* st, + bool lazy, bool throw_exception, TRAPS) { JavaThread* thread = JavaThread::current(); if (lazy) { - return new LazyClassPathEntry(path, st); + return new LazyClassPathEntry(path, st, throw_exception); } ClassPathEntry* new_entry = NULL; if ((st->st_mode & S_IFREG) == S_IFREG) { @@ -479,7 +633,11 @@ ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct st char canonical_path[JVM_MAXPATHLEN]; if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) { // This matches the classic VM - THROW_MSG_(vmSymbols::java_io_IOException(), "Bad pathname", NULL); + if (throw_exception) { + THROW_MSG_(vmSymbols::java_io_IOException(), "Bad pathname", NULL); + } else { + return NULL; + } } char* error_msg = NULL; jzfile* zip; @@ -491,7 +649,7 @@ ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct st } if (zip != NULL && error_msg == NULL) { new_entry = new ClassPathZipEntry(zip, path); - if (TraceClassLoading) { + if (TraceClassLoading || TraceClassPaths) { tty->print_cr("[Opened %s]", path); } } else { @@ -505,12 +663,16 @@ ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct st msg = NEW_RESOURCE_ARRAY(char, len); ; jio_snprintf(msg, len - 1, "error in opening JAR file <%s> %s", error_msg, path); } - THROW_MSG_(vmSymbols::java_lang_ClassNotFoundException(), msg, NULL); + if (throw_exception) { + THROW_MSG_(vmSymbols::java_lang_ClassNotFoundException(), msg, NULL); + } else { + return NULL; + } } } else { // Directory new_entry = new ClassPathDirEntry(path); - if (TraceClassLoading) { + if (TraceClassLoading || TraceClassPaths) { tty->print_cr("[Path %s]", path); } } @@ -571,23 +733,37 @@ void ClassLoader::add_to_list(ClassPathEntry *new_entry) { _last_entry = new_entry; } } + _num_entries ++; } -void ClassLoader::update_class_path_entry_list(char *path, - bool check_for_duplicates) { +// Returns true IFF the file/dir exists and the entry was successfully created. +bool ClassLoader::update_class_path_entry_list(char *path, + bool check_for_duplicates, + bool throw_exception) { struct stat st; if (os::stat(path, &st) == 0) { // File or directory found ClassPathEntry* new_entry = NULL; Thread* THREAD = Thread::current(); - new_entry = create_class_path_entry(path, &st, LazyBootClassLoader, CHECK); + new_entry = create_class_path_entry(path, &st, LazyBootClassLoader, throw_exception, CHECK_(false)); + if (new_entry == NULL) { + return false; + } // The kernel VM adds dynamically to the end of the classloader path and // doesn't reorder the bootclasspath which would break java.lang.Package // (see PackageInfo). // Add new entry to linked list if (!check_for_duplicates || !contains_entry(new_entry)) { - add_to_list(new_entry); + ClassLoaderExt::add_class_path_entry(path, check_for_duplicates, new_entry); } + return true; + } else { +#if INCLUDE_CDS + if (DumpSharedSpaces) { + _shared_paths_misc_info->add_nonexist_path(path); + } + return false; +#endif } } @@ -739,10 +915,10 @@ public: assert(n == number_of_entries(), "just checking"); } - void copy_table(char** top, char* end, PackageHashtable* table); + CDS_ONLY(void copy_table(char** top, char* end, PackageHashtable* table);) }; - +#if INCLUDE_CDS void PackageHashtable::copy_table(char** top, char* end, PackageHashtable* table) { // Copy (relocate) the table to the shared space. @@ -750,33 +926,30 @@ void PackageHashtable::copy_table(char** top, char* end, // Calculate the space needed for the package name strings. int i; - int n = 0; - for (i = 0; i < table_size(); ++i) { - for (PackageInfo* pp = table->bucket(i); - pp != NULL; - pp = pp->next()) { - n += (int)(strlen(pp->pkgname()) + 1); - } - } - if (*top + n + sizeof(intptr_t) >= end) { - report_out_of_shared_space(SharedMiscData); - } - - // Copy the table data (the strings) to the shared space. - n = align_size_up(n, sizeof(HeapWord)); - *(intptr_t*)(*top) = n; - *top += sizeof(intptr_t); + intptr_t* tableSize = (intptr_t*)(*top); + *top += sizeof(intptr_t); // For table size + char* tableStart = *top; for (i = 0; i < table_size(); ++i) { for (PackageInfo* pp = table->bucket(i); pp != NULL; pp = pp->next()) { int n1 = (int)(strlen(pp->pkgname()) + 1); + if (*top + n1 >= end) { + report_out_of_shared_space(SharedMiscData); + } pp->set_pkgname((char*)memcpy(*top, pp->pkgname(), n1)); *top += n1; } } *top = (char*)align_size_up((intptr_t)*top, sizeof(HeapWord)); + if (*top >= end) { + report_out_of_shared_space(SharedMiscData); + } + + // Write table size + intptr_t len = *top - (char*)tableStart; + *tableSize = len; } @@ -787,7 +960,7 @@ void ClassLoader::copy_package_info_buckets(char** top, char* end) { void ClassLoader::copy_package_info_table(char** top, char* end) { _package_hash_table->copy_table(top, end, _package_hash_table); } - +#endif PackageInfo* ClassLoader::lookup_package(const char *pkgname) { const char *cp = strrchr(pkgname, '/'); @@ -880,7 +1053,8 @@ objArrayOop ClassLoader::get_system_packages(TRAPS) { instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) { ResourceMark rm(THREAD); - EventMark m("loading class %s", h_name->as_C_string()); + const char* class_name = h_name->as_C_string(); + EventMark m("loading class %s", class_name); ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion); stringStream st; @@ -888,18 +1062,24 @@ instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) { // st.print("%s.class", h_name->as_utf8()); st.print_raw(h_name->as_utf8()); st.print_raw(".class"); - char* name = st.as_string(); + const char* file_name = st.as_string(); + ClassLoaderExt::Context context(class_name, file_name, THREAD); // Lookup stream for parsing .class file ClassFileStream* stream = NULL; int classpath_index = 0; + ClassPathEntry* e = NULL; + instanceKlassHandle h; { PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(), ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(), PerfClassTraceTime::CLASS_LOAD); - ClassPathEntry* e = _first_entry; + e = _first_entry; while (e != NULL) { - stream = e->open_stream(name, CHECK_NULL); + stream = e->open_stream(file_name, CHECK_NULL); + if (!context.check(stream, classpath_index)) { + return h; // NULL + } if (stream != NULL) { break; } @@ -908,9 +1088,7 @@ instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) { } } - instanceKlassHandle h; if (stream != NULL) { - // class file found, parse it ClassFileParser parser(stream); ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); @@ -920,12 +1098,19 @@ instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) { loader_data, protection_domain, parsed_name, - false, - CHECK_(h)); - - // add to package table - if (add_package(name, classpath_index, THREAD)) { - h = result; + context.should_verify(classpath_index), + THREAD); + if (HAS_PENDING_EXCEPTION) { + ResourceMark rm; + if (DumpSharedSpaces) { + tty->print_cr("Preload Error: Failed to load %s", class_name); + } + return h; + } + h = context.record_result(classpath_index, e, result, THREAD); + } else { + if (DumpSharedSpaces) { + tty->print_cr("Preload Error: Cannot find %s", class_name); } } @@ -1020,14 +1205,27 @@ void ClassLoader::initialize() { // lookup zip library entry points load_zip_library(); +#if INCLUDE_CDS // initialize search path + if (DumpSharedSpaces) { + _shared_paths_misc_info = SharedClassUtil::allocate_shared_paths_misc_info(); + } +#endif setup_bootstrap_search_path(); if (LazyBootClassLoader) { // set up meta index which makes boot classpath initialization lazier - setup_meta_index(); + setup_bootstrap_meta_index(); } } +#if INCLUDE_CDS +void ClassLoader::initialize_shared_path() { + if (DumpSharedSpaces) { + ClassLoaderExt::setup_search_paths(); + _shared_paths_misc_info->write_jint(0); // see comments in SharedPathsMiscInfo::check() + } +} +#endif jlong ClassLoader::classloader_time_ms() { return UsePerfData ? diff --git a/hotspot/src/share/vm/classfile/classLoader.hpp b/hotspot/src/share/vm/classfile/classLoader.hpp index 4a7a841705d..bd1fe24b6e2 100644 --- a/hotspot/src/share/vm/classfile/classLoader.hpp +++ b/hotspot/src/share/vm/classfile/classLoader.hpp @@ -107,6 +107,7 @@ class ClassPathZipEntry: public ClassPathEntry { const char* name() { return _zip_name; } ClassPathZipEntry(jzfile* zip, const char* zip_name); ~ClassPathZipEntry(); + u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS); ClassFileStream* open_stream(const char* name, TRAPS); void contents_do(void f(const char* name, void* context), void* context); // Debugging @@ -122,13 +123,15 @@ class LazyClassPathEntry: public ClassPathEntry { struct stat _st; MetaIndex* _meta_index; bool _has_error; + bool _throw_exception; volatile ClassPathEntry* _resolved_entry; ClassPathEntry* resolve_entry(TRAPS); public: bool is_jar_file(); const char* name() { return _path; } - LazyClassPathEntry(char* path, const struct stat* st); + LazyClassPathEntry(char* path, const struct stat* st, bool throw_exception); virtual ~LazyClassPathEntry(); + u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS); ClassFileStream* open_stream(const char* name, TRAPS); void set_meta_index(MetaIndex* meta_index) { _meta_index = meta_index; } @@ -140,6 +143,7 @@ class LazyClassPathEntry: public ClassPathEntry { class PackageHashtable; class PackageInfo; +class SharedPathsMiscInfo; template class HashtableBucket; class ClassLoader: AllStatic { @@ -147,7 +151,7 @@ class ClassLoader: AllStatic { enum SomeConstants { package_hash_table_size = 31 // Number of buckets }; - private: + protected: friend class LazyClassPathEntry; // Performance counters @@ -189,10 +193,15 @@ class ClassLoader: AllStatic { static ClassPathEntry* _first_entry; // Last entry in linked list of ClassPathEntry instances static ClassPathEntry* _last_entry; + static int _num_entries; + // Hash table used to keep track of loaded packages static PackageHashtable* _package_hash_table; static const char* _shared_archive; + // Info used by CDS + CDS_ONLY(static SharedPathsMiscInfo * _shared_paths_misc_info;) + // Hash function static unsigned int hash(const char *s, int n); // Returns the package file name corresponding to the specified package @@ -203,19 +212,23 @@ class ClassLoader: AllStatic { static bool add_package(const char *pkgname, int classpath_index, TRAPS); // Initialization - static void setup_meta_index(); + static void setup_bootstrap_meta_index(); + static void setup_meta_index(const char* meta_index_path, const char* meta_index_dir, + int start_index); static void setup_bootstrap_search_path(); + static void setup_search_path(char *class_path); + static void load_zip_library(); static ClassPathEntry* create_class_path_entry(char *path, const struct stat* st, - bool lazy, TRAPS); + bool lazy, bool throw_exception, TRAPS); // Canonicalizes path names, so strcmp will work properly. This is mainly // to avoid confusing the zip library static bool get_canonical_path(char* orig, char* out, int len); public: - // Used by the kernel jvm. - static void update_class_path_entry_list(char *path, - bool check_for_duplicates); + static bool update_class_path_entry_list(char *path, + bool check_for_duplicates, + bool throw_exception=true); static void print_bootclasspath(); // Timing @@ -298,6 +311,7 @@ class ClassLoader: AllStatic { // Initialization static void initialize(); + CDS_ONLY(static void initialize_shared_path();) static void create_package_info_table(); static void create_package_info_table(HashtableBucket *t, int length, int number_of_entries); @@ -312,10 +326,21 @@ class ClassLoader: AllStatic { return e; } +#if INCLUDE_CDS // Sharing dump and restore static void copy_package_info_buckets(char** top, char* end); static void copy_package_info_table(char** top, char* end); + static void check_shared_classpath(const char *path); + static void finalize_shared_paths_misc_info(); + static int get_shared_paths_misc_info_size(); + static void* get_shared_paths_misc_info(); + static bool check_shared_paths_misc_info(void* info, int size); + static void exit_with_path_failure(const char* error, const char* message); +#endif + + static void trace_class_path(const char* msg, const char* name = NULL); + // VM monitoring and management support static jlong classloader_time_ms(); static jlong class_method_total_size(); @@ -339,7 +364,7 @@ class ClassLoader: AllStatic { // Force compilation of all methods in all classes in bootstrap class path (stress test) #ifndef PRODUCT - private: + protected: static int _compile_the_world_class_counter; static int _compile_the_world_method_counter; public: diff --git a/hotspot/src/share/vm/classfile/classLoaderExt.hpp b/hotspot/src/share/vm/classfile/classLoaderExt.hpp new file mode 100644 index 00000000000..ed3eda08e9a --- /dev/null +++ b/hotspot/src/share/vm/classfile/classLoaderExt.hpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, 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. + * + */ + +#ifndef SHARE_VM_CLASSFILE_CLASSLOADEREXT_HPP +#define SHARE_VM_CLASSFILE_CLASSLOADEREXT_HPP + +#include "classfile/classLoader.hpp" + +class ClassLoaderExt: public ClassLoader { // AllStatic +public: + + class Context { + const char* _file_name; + public: + Context(const char* class_name, const char* file_name, TRAPS) { + _file_name = file_name; + } + + bool check(ClassFileStream* stream, const int classpath_index) { + return true; + } + + bool should_verify(int classpath_index) { + return false; + } + + instanceKlassHandle record_result(const int classpath_index, + ClassPathEntry* e, instanceKlassHandle result, TRAPS) { + if (ClassLoader::add_package(_file_name, classpath_index, THREAD)) { + if (DumpSharedSpaces) { + result->set_shared_classpath_index(classpath_index); + } + return result; + } else { + return instanceKlassHandle(); // NULL + } + } + }; + + + static void add_class_path_entry(char* path, bool check_for_duplicates, + ClassPathEntry* new_entry) { + ClassLoader::add_to_list(new_entry); + } + static void setup_search_paths() {} +}; + +#endif // SHARE_VM_CLASSFILE_CLASSLOADEREXT_HPP diff --git a/hotspot/src/share/vm/classfile/dictionary.cpp b/hotspot/src/share/vm/classfile/dictionary.cpp index dcb295687aa..37381afbd65 100644 --- a/hotspot/src/share/vm/classfile/dictionary.cpp +++ b/hotspot/src/share/vm/classfile/dictionary.cpp @@ -130,15 +130,13 @@ void DictionaryEntry::add_protection_domain(Dictionary* dict, oop protection_dom } -bool Dictionary::do_unloading() { +void Dictionary::do_unloading() { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); - bool class_was_unloaded = false; - int index = 0; // Defined here for portability! Do not move // Remove unloadable entries and classes from system dictionary // The placeholder array has been handled in always_strong_oops_do. DictionaryEntry* probe = NULL; - for (index = 0; index < table_size(); index++) { + for (int index = 0; index < table_size(); index++) { for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) { probe = *p; Klass* e = probe->klass(); @@ -158,16 +156,8 @@ bool Dictionary::do_unloading() { // Do we need to delete this system dictionary entry? if (loader_data->is_unloading()) { // If the loader is not live this entry should always be - // removed (will never be looked up again). Note that this is - // not the same as unloading the referred class. - if (k_def_class_loader_data == loader_data) { - // This is the defining entry, so the referred class is about - // to be unloaded. - class_was_unloaded = true; - } - // Also remove this system dictionary entry. + // removed (will never be looked up again). purge_entry = true; - } else { // The loader in this entry is alive. If the klass is dead, // (determined by checking the defining class loader) @@ -196,7 +186,6 @@ bool Dictionary::do_unloading() { p = probe->next_addr(); } } - return class_was_unloaded; } void Dictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) { @@ -220,6 +209,29 @@ void Dictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) { _pd_cache_table->roots_oops_do(strong, weak); } +void Dictionary::remove_classes_in_error_state() { + assert(DumpSharedSpaces, "supported only when dumping"); + DictionaryEntry* probe = NULL; + for (int index = 0; index < table_size(); index++) { + for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) { + probe = *p; + InstanceKlass* ik = InstanceKlass::cast(probe->klass()); + if (ik->is_in_error_state()) { // purge this entry + *p = probe->next(); + if (probe == _current_class_entry) { + _current_class_entry = NULL; + } + free_entry(probe); + ResourceMark rm; + tty->print_cr("Removed error class: %s", ik->external_name()); + continue; + } + + p = probe->next_addr(); + } + } +} + void Dictionary::always_strong_oops_do(OopClosure* blk) { // Follow all system classes and temporary placeholders in dictionary; only // protection domain oops contain references into the heap. In a first @@ -693,16 +705,17 @@ void SymbolPropertyTable::methods_do(void f(Method*)) { // ---------------------------------------------------------------------------- -#ifndef PRODUCT -void Dictionary::print() { +void Dictionary::print(bool details) { ResourceMark rm; HandleMark hm; - tty->print_cr("Java system dictionary (table_size=%d, classes=%d)", - table_size(), number_of_entries()); - tty->print_cr("^ indicates that initiating loader is different from " - "defining loader"); + if (details) { + tty->print_cr("Java system dictionary (table_size=%d, classes=%d)", + table_size(), number_of_entries()); + tty->print_cr("^ indicates that initiating loader is different from " + "defining loader"); + } for (int index = 0; index < table_size(); index++) { for (DictionaryEntry* probe = bucket(index); @@ -713,21 +726,28 @@ void Dictionary::print() { ClassLoaderData* loader_data = probe->loader_data(); bool is_defining_class = (loader_data == InstanceKlass::cast(e)->class_loader_data()); - tty->print("%s%s", is_defining_class ? " " : "^", + tty->print("%s%s", ((!details) || is_defining_class) ? " " : "^", e->external_name()); + if (details) { tty->print(", loader "); - loader_data->print_value(); + if (loader_data != NULL) { + loader_data->print_value(); + } else { + tty->print("NULL"); + } + } tty->cr(); } } - tty->cr(); - _pd_cache_table->print(); + + if (details) { + tty->cr(); + _pd_cache_table->print(); + } tty->cr(); } -#endif - void Dictionary::verify() { guarantee(number_of_entries() >= 0, "Verify of system dictionary failed"); diff --git a/hotspot/src/share/vm/classfile/dictionary.hpp b/hotspot/src/share/vm/classfile/dictionary.hpp index 042772f45cc..180f07e9e01 100644 --- a/hotspot/src/share/vm/classfile/dictionary.hpp +++ b/hotspot/src/share/vm/classfile/dictionary.hpp @@ -100,6 +100,7 @@ public: void methods_do(void f(Method*)); void unlink(BoolObjectClosure* is_alive); + void remove_classes_in_error_state(); // Classes loaded by the bootstrap loader are always strongly reachable. // If we're not doing class unloading, all classes are strongly reachable. @@ -108,9 +109,8 @@ public: return (loader_data->is_the_null_class_loader_data() || !ClassUnloading); } - // Unload (that is, break root links to) all unmarked classes and - // loaders. Returns "true" iff something was unloaded. - bool do_unloading(); + // Unload (that is, break root links to) all unmarked classes and loaders. + void do_unloading(); // Protection domains Klass* find(int index, unsigned int hash, Symbol* name, @@ -127,9 +127,7 @@ public: ProtectionDomainCacheEntry* cache_get(oop protection_domain); -#ifndef PRODUCT - void print(); -#endif + void print(bool details = true); void verify(); }; diff --git a/hotspot/src/share/vm/classfile/sharedClassUtil.hpp b/hotspot/src/share/vm/classfile/sharedClassUtil.hpp new file mode 100644 index 00000000000..13be2b1b5de --- /dev/null +++ b/hotspot/src/share/vm/classfile/sharedClassUtil.hpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, 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. + * + */ + +#ifndef SHARE_VM_CLASSFILE_SHAREDCLASSUTIL_HPP +#define SHARE_VM_CLASSFILE_SHAREDCLASSUTIL_HPP + +#include "classfile/sharedPathsMiscInfo.hpp" +#include "memory/filemap.hpp" + +class SharedClassUtil : AllStatic { +public: + + static SharedPathsMiscInfo* allocate_shared_paths_misc_info() { + return new SharedPathsMiscInfo(); + } + + static SharedPathsMiscInfo* allocate_shared_paths_misc_info(char* buf, int size) { + return new SharedPathsMiscInfo(buf, size); + } + + static FileMapInfo::FileMapHeader* allocate_file_map_header() { + return new FileMapInfo::FileMapHeader(); + } + + static size_t file_map_header_size() { + return sizeof(FileMapInfo::FileMapHeader); + } + + static size_t shared_class_path_entry_size() { + return sizeof(SharedClassPathEntry); + } + + static void update_shared_classpath(ClassPathEntry *cpe, + SharedClassPathEntry* ent, + time_t timestamp, + long filesize, TRAPS) { + ent->_timestamp = timestamp; + ent->_filesize = filesize; + } + + static void initialize(TRAPS) {} + + inline static bool is_shared_boot_class(Klass* klass) { + return (klass->_shared_class_path_index >= 0); + } +}; + +#endif // SHARE_VM_CLASSFILE_SHAREDCLASSUTIL_HPP diff --git a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp new file mode 100644 index 00000000000..c988abdf9da --- /dev/null +++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2014, 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. + * + */ + +#include "precompiled.hpp" +#include "classfile/classLoader.hpp" +#include "classfile/classLoaderData.inline.hpp" +#include "classfile/sharedPathsMiscInfo.hpp" +#include "memory/allocation.inline.hpp" +#include "memory/metaspaceShared.hpp" +#include "runtime/arguments.hpp" + +void SharedPathsMiscInfo::add_path(const char* path, int type) { + if (TraceClassPaths) { + tty->print("[type=%s] ", type_name(type)); + trace_class_path("[Add misc shared path ", path); + } + write(path, strlen(path) + 1); + write_jint(jint(type)); +} + +void SharedPathsMiscInfo::ensure_size(size_t needed_bytes) { + assert(_allocated, "cannot modify buffer during validation."); + int used = get_used_bytes(); + int target = used + int(needed_bytes); + if (target > _buf_size) { + _buf_size = _buf_size * 2 + (int)needed_bytes; + _buf_start = REALLOC_C_HEAP_ARRAY(char, _buf_start, _buf_size, mtClass); + _cur_ptr = _buf_start + used; + _end_ptr = _buf_start + _buf_size; + } +} + +void SharedPathsMiscInfo::write(const void* ptr, size_t size) { + ensure_size(size); + memcpy(_cur_ptr, ptr, size); + _cur_ptr += size; +} + +bool SharedPathsMiscInfo::read(void* ptr, size_t size) { + if (_cur_ptr + size <= _end_ptr) { + memcpy(ptr, _cur_ptr, size); + _cur_ptr += size; + return true; + } + return false; +} + +bool SharedPathsMiscInfo::fail(const char* msg, const char* name) { + ClassLoader::trace_class_path(msg, name); + MetaspaceShared::set_archive_loading_failed(); + return false; +} + +bool SharedPathsMiscInfo::check() { + // The whole buffer must be 0 terminated so that we can use strlen and strcmp + // without fear. + _end_ptr -= sizeof(jint); + if (_cur_ptr >= _end_ptr) { + return fail("Truncated archive file header"); + } + if (*_end_ptr != 0) { + return fail("Corrupted archive file header"); + } + + while (_cur_ptr < _end_ptr) { + jint type; + const char* path = _cur_ptr; + _cur_ptr += strlen(path) + 1; + if (!read_jint(&type)) { + return fail("Corrupted archive file header"); + } + if (TraceClassPaths) { + tty->print("[type=%s ", type_name(type)); + print_path(tty, type, path); + tty->print_cr("]"); + } + if (!check(type, path)) { + if (!PrintSharedArchiveAndExit) { + return false; + } + } else { + trace_class_path("[ok"); + } + } + + return true; +} + +bool SharedPathsMiscInfo::check(jint type, const char* path) { + switch (type) { + case BOOT: + if (strcmp(path, Arguments::get_sysclasspath()) != 0) { + return fail("[BOOT classpath mismatch, actual: -Dsun.boot.class.path=", Arguments::get_sysclasspath()); + } + break; + case NON_EXIST: // fall-through + case REQUIRED: + { + struct stat st; + if (os::stat(path, &st) != 0) { + // The file does not actually exist + if (type == REQUIRED) { + // but we require it to exist -> fail + return fail("Required file doesn't exist"); + } + } else { + // The file actually exists + if (type == NON_EXIST) { + // But we want it to not exist -> fail + return fail("File must not exist"); + } + time_t timestamp; + long filesize; + + if (!read_time(×tamp) || !read_long(&filesize)) { + return fail("Corrupted archive file header"); + } + if (timestamp != st.st_mtime) { + return fail("Timestamp mismatch"); + } + if (filesize != st.st_size) { + return fail("File size mismatch"); + } + } + } + break; + + default: + return fail("Corrupted archive file header"); + } + + return true; +} diff --git a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp new file mode 100644 index 00000000000..78b09256218 --- /dev/null +++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2014, 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. + * + */ + +#ifndef SHARE_VM_CLASSFILE_SHAREDPATHSMISCINFO_HPP +#define SHARE_VM_CLASSFILE_SHAREDPATHSMISCINFO_HPP + +#include "runtime/os.hpp" + +// During dumping time, when processing class paths, we build up the dump-time +// classpath. The JAR files that exist are stored in the list ClassLoader::_first_entry. +// However, we need to store other "misc" information for run-time checking, such as +// +// + The values of Arguments::get_sysclasspath() used during dumping. +// +// + The meta-index file(s) used during dumping (incl modification time and size) +// +// + The class path elements specified during dumping but did not exist -- +// these elements must also be specified at run time, and they also must not +// exist at run time. +// +// These misc items are stored in a linear buffer in SharedPathsMiscInfo. +// The storage format is stream oriented to minimize its size. +// +// When writing the information to the archive file, SharedPathsMiscInfo is stored in +// the archive file header. At run-time, this information is used only during initialization +// (accessed using read() instead of mmap()), and is deallocated afterwards to save space. +// +// The SharedPathsMiscInfo class is used for both creating the the information (during +// dumping time) and validation (at run time). Different constructors are used in the +// two situations. See below. + +class SharedPathsMiscInfo : public CHeapObj { +protected: + char* _buf_start; + char* _cur_ptr; + char* _end_ptr; + int _buf_size; + bool _allocated; // was _buf_start allocated by me? + void ensure_size(size_t needed_bytes); + void add_path(const char* path, int type); + + void write(const void* ptr, size_t size); + bool read(void* ptr, size_t size); + + static void trace_class_path(const char* msg, const char* name = NULL) { + ClassLoader::trace_class_path(msg, name); + } +protected: + static bool fail(const char* msg, const char* name = NULL); + virtual bool check(jint type, const char* path); + +public: + enum { + INITIAL_BUF_SIZE = 128 + }; + // This constructor is used when creating the misc information (during dump) + SharedPathsMiscInfo() { + _buf_size = INITIAL_BUF_SIZE; + _cur_ptr = _buf_start = NEW_C_HEAP_ARRAY(char, _buf_size, mtClass); + _allocated = true; + } + // This constructor is used when validating the misc info (during run time) + SharedPathsMiscInfo(char *buff, int size) { + _cur_ptr = _buf_start = buff; + _end_ptr = _buf_start + size; + _buf_size = size; + _allocated = false; + } + ~SharedPathsMiscInfo() { + if (_allocated) { + FREE_C_HEAP_ARRAY(char, _buf_start, mtClass); + } + } + int get_used_bytes() { + return _cur_ptr - _buf_start; + } + void* buffer() { + return _buf_start; + } + + // writing -- + + // The path must not exist at run-time + void add_nonexist_path(const char* path) { + add_path(path, NON_EXIST); + } + + // The path must exist and have required size and modification time + void add_required_file(const char* path) { + add_path(path, REQUIRED); + + struct stat st; + if (os::stat(path, &st) != 0) { + assert(0, "sanity"); + ClassLoader::exit_with_path_failure("failed to os::stat(%s)", path); // should not happen + } + write_time(st.st_mtime); + write_long(st.st_size); + } + + // The path must exist, and must contain exactly files/dirs + void add_boot_classpath(const char* path) { + add_path(path, BOOT); + } + int write_jint(jint num) { + write(&num, sizeof(num)); + return 0; + } + void write_time(time_t t) { + write(&t, sizeof(t)); + } + void write_long(long l) { + write(&l, sizeof(l)); + } + + bool dump_to_file(int fd) { + int n = get_used_bytes(); + return (os::write(fd, _buf_start, n) == (size_t)n); + } + + // reading -- + + enum { + BOOT = 1, + NON_EXIST = 2, + REQUIRED = 3 + }; + + virtual const char* type_name(int type) { + switch (type) { + case BOOT: return "BOOT"; + case NON_EXIST: return "NON_EXIST"; + case REQUIRED: return "REQUIRED"; + default: ShouldNotReachHere(); return "?"; + } + } + + virtual void print_path(outputStream* out, int type, const char* path) { + switch (type) { + case BOOT: + out->print("Expecting -Dsun.boot.class.path=%s", path); + break; + case NON_EXIST: + out->print("Expecting that %s does not exist", path); + break; + case REQUIRED: + out->print("Expecting that file %s must exist and not altered", path); + break; + default: + ShouldNotReachHere(); + } + } + + bool check(); + bool read_jint(jint *ptr) { + return read(ptr, sizeof(jint)); + } + bool read_long(long *ptr) { + return read(ptr, sizeof(long)); + } + bool read_time(time_t *ptr) { + return read(ptr, sizeof(time_t)); + } +}; + +#endif // SHARE_VM_CLASSFILE_SHAREDPATHSMISCINFO_HPP diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index 3b058b5a625..e794d93a778 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -31,10 +31,15 @@ #include "classfile/resolutionErrors.hpp" #include "classfile/stringTable.hpp" #include "classfile/systemDictionary.hpp" +#if INCLUDE_CDS +#include "classfile/sharedClassUtil.hpp" +#include "classfile/systemDictionaryShared.hpp" +#endif #include "classfile/vmSymbols.hpp" #include "compiler/compileBroker.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/interpreter.hpp" +#include "memory/filemap.hpp" #include "memory/gcLocker.hpp" #include "memory/oopFactory.hpp" #include "oops/instanceKlass.hpp" @@ -110,6 +115,8 @@ void SystemDictionary::compute_java_system_loader(TRAPS) { CHECK); _java_system_loader = (oop)result.get_jobject(); + + CDS_ONLY(SystemDictionaryShared::initialize(CHECK);) } @@ -974,6 +981,7 @@ Klass* SystemDictionary::parse_stream(Symbol* class_name, // Create a new CLD for anonymous class, that uses the same class loader // as the host_klass guarantee(host_klass->class_loader() == class_loader(), "should be the same"); + guarantee(!DumpSharedSpaces, "must not create anonymous classes when dumping"); loader_data = ClassLoaderData::anonymous_class_loader_data(class_loader(), CHECK_NULL); loader_data->record_dependency(host_klass(), CHECK_NULL); } else { @@ -1134,7 +1142,7 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name, return k(); } - +#if INCLUDE_CDS void SystemDictionary::set_shared_dictionary(HashtableBucket* t, int length, int number_of_entries) { assert(length == _nof_buckets * sizeof(HashtableBucket), @@ -1167,15 +1175,21 @@ Klass* SystemDictionary::find_shared_class(Symbol* class_name) { instanceKlassHandle SystemDictionary::load_shared_class( Symbol* class_name, Handle class_loader, TRAPS) { instanceKlassHandle ik (THREAD, find_shared_class(class_name)); - return load_shared_class(ik, class_loader, THREAD); + // Make sure we only return the boot class for the NULL classloader. + if (ik.not_null() && + SharedClassUtil::is_shared_boot_class(ik()) && class_loader.is_null()) { + Handle protection_domain; + return load_shared_class(ik, class_loader, protection_domain, THREAD); + } + return instanceKlassHandle(); } -instanceKlassHandle SystemDictionary::load_shared_class( - instanceKlassHandle ik, Handle class_loader, TRAPS) { - assert(class_loader.is_null(), "non-null classloader for shared class?"); +instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik, + Handle class_loader, + Handle protection_domain, TRAPS) { if (ik.not_null()) { instanceKlassHandle nh = instanceKlassHandle(); // null Handle - Symbol* class_name = ik->name(); + Symbol* class_name = ik->name(); // Found the class, now load the superclass and interfaces. If they // are shared, add them to the main system dictionary and reset @@ -1184,7 +1198,7 @@ instanceKlassHandle SystemDictionary::load_shared_class( if (ik->super() != NULL) { Symbol* cn = ik->super()->name(); resolve_super_or_fail(class_name, cn, - class_loader, Handle(), true, CHECK_(nh)); + class_loader, protection_domain, true, CHECK_(nh)); } Array* interfaces = ik->local_interfaces(); @@ -1197,7 +1211,7 @@ instanceKlassHandle SystemDictionary::load_shared_class( // reinitialized yet (they will be once the interface classes // are loaded) Symbol* name = k->name(); - resolve_super_or_fail(class_name, name, class_loader, Handle(), false, CHECK_(nh)); + resolve_super_or_fail(class_name, name, class_loader, protection_domain, false, CHECK_(nh)); } // Adjust methods to recover missing data. They need addresses for @@ -1206,30 +1220,47 @@ instanceKlassHandle SystemDictionary::load_shared_class( // Updating methods must be done under a lock so multiple // threads don't update these in parallel - // Shared classes are all currently loaded by the bootstrap - // classloader, so this will never cause a deadlock on - // a custom class loader lock. + // + // Shared classes are all currently loaded by either the bootstrap or + // internal parallel class loaders, so this will never cause a deadlock + // on a custom class loader lock. + ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader()); { Handle lockObject = compute_loader_lock_object(class_loader, THREAD); check_loader_lock_contention(lockObject, THREAD); ObjectLocker ol(lockObject, THREAD, true); - ik->restore_unshareable_info(CHECK_(nh)); + ik->restore_unshareable_info(loader_data, protection_domain, CHECK_(nh)); } if (TraceClassLoading) { ResourceMark rm; tty->print("[Loaded %s", ik->external_name()); tty->print(" from shared objects file"); + if (class_loader.not_null()) { + tty->print(" by %s", loader_data->loader_name()); + } tty->print_cr("]"); } + +#if INCLUDE_CDS + if (DumpLoadedClassList != NULL && classlist_file->is_open()) { + // Only dump the classes that can be stored into CDS archive + if (SystemDictionaryShared::is_sharing_possible(loader_data)) { + ResourceMark rm(THREAD); + classlist_file->print_cr("%s", ik->name()->as_C_string()); + classlist_file->flush(); + } + } +#endif + // notify a class loaded from shared object ClassLoadingService::notify_class_loaded(InstanceKlass::cast(ik()), true /* shared class */); } return ik; } - +#endif instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) { instanceKlassHandle nh = instanceKlassHandle(); // null Handle @@ -1239,8 +1270,10 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha // shared spaces. instanceKlassHandle k; { +#if INCLUDE_CDS PerfTraceTime vmtimer(ClassLoader::perf_shared_classload_time()); k = load_shared_class(class_name, class_loader, THREAD); +#endif } if (k.is_null()) { @@ -1599,7 +1632,6 @@ void SystemDictionary::add_to_hierarchy(instanceKlassHandle k, TRAPS) { Universe::flush_dependents_on(k); } - // ---------------------------------------------------------------------------- // GC support @@ -1661,10 +1693,9 @@ public: // Note: anonymous classes are not in the SD. bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive) { // First, mark for unload all ClassLoaderData referencing a dead class loader. - bool has_dead_loaders = ClassLoaderDataGraph::do_unloading(is_alive); - bool unloading_occurred = false; - if (has_dead_loaders) { - unloading_occurred = dictionary()->do_unloading(); + bool unloading_occurred = ClassLoaderDataGraph::do_unloading(is_alive); + if (unloading_occurred) { + dictionary()->do_unloading(); constraints()->purge_loader_constraints(); resolution_errors()->purge_resolution_errors(); } @@ -1682,6 +1713,7 @@ bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive) { void SystemDictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) { strong->do_oop(&_java_system_loader); strong->do_oop(&_system_loader_lock_obj); + CDS_ONLY(SystemDictionaryShared::roots_oops_do(strong);) // Adjust dictionary dictionary()->roots_oops_do(strong, weak); @@ -1693,6 +1725,7 @@ void SystemDictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) { void SystemDictionary::oops_do(OopClosure* f) { f->do_oop(&_java_system_loader); f->do_oop(&_system_loader_lock_obj); + CDS_ONLY(SystemDictionaryShared::oops_do(f);) // Adjust dictionary dictionary()->oops_do(f); @@ -1754,6 +1787,10 @@ void SystemDictionary::methods_do(void f(Method*)) { invoke_method_table()->methods_do(f); } +void SystemDictionary::remove_classes_in_error_state() { + dictionary()->remove_classes_in_error_state(); +} + // ---------------------------------------------------------------------------- // Lazily load klasses @@ -2563,10 +2600,12 @@ int SystemDictionary::number_of_classes() { // ---------------------------------------------------------------------------- -#ifndef PRODUCT +void SystemDictionary::print_shared(bool details) { + shared_dictionary()->print(details); +} -void SystemDictionary::print() { - dictionary()->print(); +void SystemDictionary::print(bool details) { + dictionary()->print(details); // Placeholders GCMutexLocker mu(SystemDictionary_lock); @@ -2576,7 +2615,6 @@ void SystemDictionary::print() { constraints()->print(); } -#endif void SystemDictionary::verify() { guarantee(dictionary() != NULL, "Verify of system dictionary failed"); diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index f46f67bd9b5..33ecc83480b 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -111,6 +111,7 @@ class Ticks; do_klass(SecurityManager_klass, java_lang_SecurityManager, Pre ) \ do_klass(ProtectionDomain_klass, java_security_ProtectionDomain, Pre ) \ do_klass(AccessControlContext_klass, java_security_AccessControlContext, Pre ) \ + do_klass(SecureClassLoader_klass, java_security_SecureClassLoader, Pre ) \ do_klass(ClassNotFoundException_klass, java_lang_ClassNotFoundException, Pre ) \ do_klass(NoClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre ) \ do_klass(LinkageError_klass, java_lang_LinkageError, Pre ) \ @@ -166,6 +167,15 @@ class Ticks; do_klass(StringBuilder_klass, java_lang_StringBuilder, Pre ) \ do_klass(misc_Unsafe_klass, sun_misc_Unsafe, Pre ) \ \ + /* support for CDS */ \ + do_klass(ByteArrayInputStream_klass, java_io_ByteArrayInputStream, Pre ) \ + do_klass(File_klass, java_io_File, Pre ) \ + do_klass(URLClassLoader_klass, java_net_URLClassLoader, Pre ) \ + do_klass(URL_klass, java_net_URL, Pre ) \ + do_klass(Jar_Manifest_klass, java_util_jar_Manifest, Pre ) \ + do_klass(sun_misc_Launcher_klass, sun_misc_Launcher, Pre ) \ + do_klass(CodeSource_klass, java_security_CodeSource, Pre ) \ + \ /* It's NULL in non-1.4 JDKs. */ \ do_klass(StackTraceElement_klass, java_lang_StackTraceElement, Opt ) \ /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ @@ -221,7 +231,7 @@ class SystemDictionary : AllStatic { static Klass* resolve_or_fail(Symbol* class_name, Handle class_loader, Handle protection_domain, bool throw_error, TRAPS); // Convenient call for null loader and protection domain. static Klass* resolve_or_fail(Symbol* class_name, bool throw_error, TRAPS); -private: +protected: // handle error translation for resolve_or_null results static Klass* handle_resolution_exception(Symbol* class_name, bool throw_error, KlassHandle klass_h, TRAPS); @@ -326,6 +336,9 @@ public: // loaders. Returns "true" iff something was unloaded. static bool do_unloading(BoolObjectClosure* is_alive); + // Used by DumpSharedSpaces only to remove classes that failed verification + static void remove_classes_in_error_state(); + static int calculate_systemdictionary_size(int loadedclasses); // Applies "f->do_oop" to all root oops in the system dictionary. @@ -335,7 +348,7 @@ public: // System loader lock static oop system_loader_lock() { return _system_loader_lock_obj; } -private: +protected: // Extended Redefine classes support (tbi) static void preloaded_classes_do(KlassClosure* f); static void lazily_loaded_classes_do(KlassClosure* f); @@ -348,7 +361,8 @@ public: static void set_shared_dictionary(HashtableBucket* t, int length, int number_of_entries); // Printing - static void print() PRODUCT_RETURN; + static void print(bool details = true); + static void print_shared(bool details = true); static void print_class_statistics() PRODUCT_RETURN; static void print_method_statistics() PRODUCT_RETURN; @@ -424,7 +438,7 @@ public: static void load_abstract_ownable_synchronizer_klass(TRAPS); -private: +protected: // Tells whether ClassLoader.loadClassInternal is present static bool has_loadClassInternal() { return _has_loadClassInternal; } @@ -452,7 +466,7 @@ public: // Register a new class loader static ClassLoaderData* register_loader(Handle class_loader, TRAPS); -private: +protected: // Mirrors for primitive classes (created eagerly) static oop check_mirror(oop m) { assert(m != NULL, "mirror not initialized"); @@ -523,7 +537,7 @@ public: static Symbol* find_resolution_error(constantPoolHandle pool, int which, Symbol** message); - private: + protected: enum Constants { _loader_constraint_size = 107, // number of entries in constraint table @@ -574,7 +588,7 @@ public: friend class CounterDecay; static Klass* try_get_next_class(); -private: +protected: static void validate_protection_domain(instanceKlassHandle klass, Handle class_loader, Handle protection_domain, TRAPS); @@ -601,10 +615,10 @@ private: static instanceKlassHandle find_or_define_instance_class(Symbol* class_name, Handle class_loader, instanceKlassHandle k, TRAPS); - static instanceKlassHandle load_shared_class(Symbol* class_name, - Handle class_loader, TRAPS); static instanceKlassHandle load_shared_class(instanceKlassHandle ik, - Handle class_loader, TRAPS); + Handle class_loader, + Handle protection_domain, + TRAPS); static instanceKlassHandle load_instance_class(Symbol* class_name, Handle class_loader, TRAPS); static Handle compute_loader_lock_object(Handle class_loader, TRAPS); static void check_loader_lock_contention(Handle loader_lock, TRAPS); @@ -612,9 +626,12 @@ private: static bool is_parallelDefine(Handle class_loader); public: + static instanceKlassHandle load_shared_class(Symbol* class_name, + Handle class_loader, + TRAPS); static bool is_ext_class_loader(Handle class_loader); -private: +protected: static Klass* find_shared_class(Symbol* class_name); // Setup link to hierarchy diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/LineNotFoundException.java b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp similarity index 50% rename from jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/LineNotFoundException.java rename to hotspot/src/share/vm/classfile/systemDictionaryShared.hpp index 56b4ba3fa39..bc688798ce8 100644 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/LineNotFoundException.java +++ b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp @@ -1,12 +1,10 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. + * 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 @@ -21,31 +19,29 @@ * 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. + * */ -package com.sun.tools.example.debug.bdi; +#ifndef SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP +#define SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP -public class LineNotFoundException extends Exception -{ +#include "classfile/systemDictionary.hpp" - private static final long serialVersionUID = -5630418117861587582L; +class SystemDictionaryShared: public SystemDictionary { +public: + static void initialize(TRAPS) {} + static instanceKlassHandle find_or_load_shared_class(Symbol* class_name, + Handle class_loader, + TRAPS) { + return instanceKlassHandle(); + } + static void roots_oops_do(OopClosure* blk) {} + static void oops_do(OopClosure* f) {} + static bool is_sharing_possible(ClassLoaderData* loader_data) { + oop class_loader = loader_data->class_loader(); + return (class_loader == NULL); + } +}; - public LineNotFoundException() - { - super(); - } - - public LineNotFoundException(String s) - { - super(s); - } -} +#endif // SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index db09171dbe6..50fe81e8d24 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -91,11 +91,17 @@ template(java_lang_CharSequence, "java/lang/CharSequence") \ template(java_lang_SecurityManager, "java/lang/SecurityManager") \ template(java_security_AccessControlContext, "java/security/AccessControlContext") \ + template(java_security_CodeSource, "java/security/CodeSource") \ template(java_security_ProtectionDomain, "java/security/ProtectionDomain") \ + template(java_security_SecureClassLoader, "java/security/SecureClassLoader") \ + template(java_net_URLClassLoader, "java/net/URLClassLoader") \ + template(java_net_URL, "java/net/URL") \ + template(java_util_jar_Manifest, "java/util/jar/Manifest") \ template(impliesCreateAccessControlContext_name, "impliesCreateAccessControlContext") \ template(java_io_OutputStream, "java/io/OutputStream") \ template(java_io_Reader, "java/io/Reader") \ template(java_io_BufferedReader, "java/io/BufferedReader") \ + template(java_io_File, "java/io/File") \ template(java_io_FileInputStream, "java/io/FileInputStream") \ template(java_io_ByteArrayInputStream, "java/io/ByteArrayInputStream") \ template(java_io_Serializable, "java/io/Serializable") \ @@ -106,6 +112,7 @@ template(java_util_Hashtable, "java/util/Hashtable") \ template(java_lang_Compiler, "java/lang/Compiler") \ template(sun_misc_Signal, "sun/misc/Signal") \ + template(sun_misc_Launcher, "sun/misc/Launcher") \ template(java_lang_AssertionStatusDirectives, "java/lang/AssertionStatusDirectives") \ template(getBootClassPathEntryForClass_name, "getBootClassPathEntryForClass") \ template(sun_misc_PostVMInitHook, "sun/misc/PostVMInitHook") \ @@ -396,6 +403,14 @@ template(signers_name, "signers_name") \ template(loader_data_name, "loader_data") \ template(dependencies_name, "dependencies") \ + template(input_stream_void_signature, "(Ljava/io/InputStream;)V") \ + template(getFileURL_name, "getFileURL") \ + template(getFileURL_signature, "(Ljava/io/File;)Ljava/net/URL;") \ + template(definePackageInternal_name, "definePackageInternal") \ + template(definePackageInternal_signature, "(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)V") \ + template(getProtectionDomain_name, "getProtectionDomain") \ + template(getProtectionDomain_signature, "(Ljava/security/CodeSource;)Ljava/security/ProtectionDomain;") \ + template(url_code_signer_array_void_signature, "(Ljava/net/URL;[Ljava/security/CodeSigner;)V") \ \ /* non-intrinsic name/signature pairs: */ \ template(register_method_name, "register") \ diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp index 2164628a77f..460692b5cea 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp @@ -2734,10 +2734,12 @@ void CFLS_LAB::retire(int tid) { } } -void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, AdaptiveFreeList* fl) { - assert(fl->count() == 0, "Precondition."); - assert(word_sz < CompactibleFreeListSpace::IndexSetSize, - "Precondition"); +// Used by par_get_chunk_of_blocks() for the chunks from the +// indexed_free_lists. Looks for a chunk with size that is a multiple +// of "word_sz" and if found, splits it into "word_sz" chunks and add +// to the free list "fl". "n" is the maximum number of chunks to +// be added to "fl". +bool CompactibleFreeListSpace:: par_get_chunk_of_blocks_IFL(size_t word_sz, size_t n, AdaptiveFreeList* fl) { // We'll try all multiples of word_sz in the indexed set, starting with // word_sz itself and, if CMSSplitIndexedFreeListBlocks, try larger multiples, @@ -2818,11 +2820,15 @@ void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n Mutex::_no_safepoint_check_flag); ssize_t births = _indexedFreeList[word_sz].split_births() + num; _indexedFreeList[word_sz].set_split_births(births); - return; + return true; } } + return found; } - // Otherwise, we'll split a block from the dictionary. +} + +FreeChunk* CompactibleFreeListSpace::get_n_way_chunk_to_split(size_t word_sz, size_t n) { + FreeChunk* fc = NULL; FreeChunk* rem_fc = NULL; size_t rem; @@ -2833,16 +2839,12 @@ void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n fc = dictionary()->get_chunk(MAX2(n * word_sz, _dictionary->min_size()), FreeBlockDictionary::atLeast); if (fc != NULL) { - _bt.allocated((HeapWord*)fc, fc->size(), true /* reducing */); // update _unallocated_blk - dictionary()->dict_census_update(fc->size(), - true /*split*/, - false /*birth*/); break; } else { n--; } } - if (fc == NULL) return; + if (fc == NULL) return NULL; // Otherwise, split up that block. assert((ssize_t)n >= 1, "Control point invariant"); assert(fc->is_free(), "Error: should be a free block"); @@ -2864,10 +2866,14 @@ void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n // dictionary and return, leaving "fl" empty. if (n == 0) { returnChunkToDictionary(fc); - assert(fl->count() == 0, "We never allocated any blocks"); - return; + return NULL; } + _bt.allocated((HeapWord*)fc, fc->size(), true /* reducing */); // update _unallocated_blk + dictionary()->dict_census_update(fc->size(), + true /*split*/, + false /*birth*/); + // First return the remainder, if any. // Note that we hold the lock until we decide if we're going to give // back the remainder to the dictionary, since a concurrent allocation @@ -2900,7 +2906,24 @@ void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n _indexedFreeList[rem].return_chunk_at_head(rem_fc); smallSplitBirth(rem); } - assert((ssize_t)n > 0 && fc != NULL, "Consistency"); + assert(n * word_sz == fc->size(), + err_msg("Chunk size " SIZE_FORMAT " is not exactly splittable by " + SIZE_FORMAT " sized chunks of size " SIZE_FORMAT, + fc->size(), n, word_sz)); + return fc; +} + +void CompactibleFreeListSpace:: par_get_chunk_of_blocks_dictionary(size_t word_sz, size_t targetted_number_of_chunks, AdaptiveFreeList* fl) { + + FreeChunk* fc = get_n_way_chunk_to_split(word_sz, targetted_number_of_chunks); + + if (fc == NULL) { + return; + } + + size_t n = fc->size() / word_sz; + + assert((ssize_t)n > 0, "Consistency"); // Now do the splitting up. // Must do this in reverse order, so that anybody attempting to // access the main chunk sees it as a single free block until we @@ -2948,6 +2971,20 @@ void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n assert(fl->tail()->next() == NULL, "List invariant."); } +void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, AdaptiveFreeList* fl) { + assert(fl->count() == 0, "Precondition."); + assert(word_sz < CompactibleFreeListSpace::IndexSetSize, + "Precondition"); + + if (par_get_chunk_of_blocks_IFL(word_sz, n, fl)) { + // Got it + return; + } + + // Otherwise, we'll split a block from the dictionary. + par_get_chunk_of_blocks_dictionary(word_sz, n, fl); +} + // Set up the space's par_seq_tasks structure for work claiming // for parallel rescan. See CMSParRemarkTask where this is currently used. // XXX Need to suitably abstract and generalize this and the next diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp index ba2ff9c55ff..4b10e6fb2bc 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp @@ -172,6 +172,20 @@ class CompactibleFreeListSpace: public CompactibleSpace { // list of size "word_sz", and must now be decremented. void par_get_chunk_of_blocks(size_t word_sz, size_t n, AdaptiveFreeList* fl); + // Used by par_get_chunk_of_blocks() for the chunks from the + // indexed_free_lists. + bool par_get_chunk_of_blocks_IFL(size_t word_sz, size_t n, AdaptiveFreeList* fl); + + // Used by par_get_chunk_of_blocks_dictionary() to get a chunk + // evenly splittable into "n" "word_sz" chunks. Returns that + // evenly splittable chunk. May split a larger chunk to get the + // evenly splittable chunk. + FreeChunk* get_n_way_chunk_to_split(size_t word_sz, size_t n); + + // Used by par_get_chunk_of_blocks() for the chunks from the + // dictionary. + void par_get_chunk_of_blocks_dictionary(size_t word_sz, size_t n, AdaptiveFreeList* fl); + // Allocation helper functions // Allocate using a strategy that takes from the indexed free lists // first. This allocation strategy assumes a companion sweeping diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp index 90e0aedd084..f01f77ce1fa 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp @@ -81,8 +81,8 @@ void ConcurrentG1Refine::reset_threshold_step() { } } -void ConcurrentG1Refine::init() { - _hot_card_cache.initialize(); +void ConcurrentG1Refine::init(G1RegionToSpaceMapper* card_counts_storage) { + _hot_card_cache.initialize(card_counts_storage); } void ConcurrentG1Refine::stop() { diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp index f466e0de339..7f77163818c 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp @@ -34,6 +34,7 @@ class ConcurrentG1RefineThread; class G1CollectedHeap; class G1HotCardCache; +class G1RegionToSpaceMapper; class G1RemSet; class DirtyCardQueue; @@ -74,7 +75,7 @@ class ConcurrentG1Refine: public CHeapObj { ConcurrentG1Refine(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure); ~ConcurrentG1Refine(); - void init(); // Accomplish some initialization that has to wait. + void init(G1RegionToSpaceMapper* card_counts_storage); void stop(); void reinitialize_threads(); diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 737692135d1..b8755eb0dc5 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -36,6 +36,7 @@ #include "gc_implementation/g1/heapRegion.inline.hpp" #include "gc_implementation/g1/heapRegionRemSet.hpp" #include "gc_implementation/g1/heapRegionSeq.inline.hpp" +#include "gc_implementation/g1/heapRegionSet.inline.hpp" #include "gc_implementation/shared/vmGCOperations.hpp" #include "gc_implementation/shared/gcTimer.hpp" #include "gc_implementation/shared/gcTrace.hpp" @@ -99,12 +100,12 @@ int CMBitMapRO::heapWordDiffToOffsetDiff(size_t diff) const { } #ifndef PRODUCT -bool CMBitMapRO::covers(ReservedSpace heap_rs) const { +bool CMBitMapRO::covers(MemRegion heap_rs) const { // assert(_bm.map() == _virtual_space.low(), "map inconsistency"); assert(((size_t)_bm.size() * ((size_t)1 << _shifter)) == _bmWordSize, "size inconsistency"); - return _bmStartWord == (HeapWord*)(heap_rs.base()) && - _bmWordSize == heap_rs.size()>>LogHeapWordSize; + return _bmStartWord == (HeapWord*)(heap_rs.start()) && + _bmWordSize == heap_rs.word_size(); } #endif @@ -112,33 +113,73 @@ void CMBitMapRO::print_on_error(outputStream* st, const char* prefix) const { _bm.print_on_error(st, prefix); } -bool CMBitMap::allocate(ReservedSpace heap_rs) { - _bmStartWord = (HeapWord*)(heap_rs.base()); - _bmWordSize = heap_rs.size()/HeapWordSize; // heap_rs.size() is in bytes - ReservedSpace brs(ReservedSpace::allocation_align_size_up( - (_bmWordSize >> (_shifter + LogBitsPerByte)) + 1)); - if (!brs.is_reserved()) { - warning("ConcurrentMark marking bit map allocation failure"); - return false; - } - MemTracker::record_virtual_memory_type((address)brs.base(), mtGC); - // For now we'll just commit all of the bit map up front. - // Later on we'll try to be more parsimonious with swap. - if (!_virtual_space.initialize(brs, brs.size())) { - warning("ConcurrentMark marking bit map backing store failure"); - return false; - } - assert(_virtual_space.committed_size() == brs.size(), - "didn't reserve backing store for all of concurrent marking bit map?"); - _bm.set_map((BitMap::bm_word_t*)_virtual_space.low()); - assert(_virtual_space.committed_size() << (_shifter + LogBitsPerByte) >= - _bmWordSize, "inconsistency in bit map sizing"); - _bm.set_size(_bmWordSize >> _shifter); - return true; +size_t CMBitMap::compute_size(size_t heap_size) { + return heap_size / mark_distance(); } +size_t CMBitMap::mark_distance() { + return MinObjAlignmentInBytes * BitsPerByte; +} + +void CMBitMap::initialize(MemRegion heap, G1RegionToSpaceMapper* storage) { + _bmStartWord = heap.start(); + _bmWordSize = heap.word_size(); + + _bm.set_map((BitMap::bm_word_t*) storage->reserved().start()); + _bm.set_size(_bmWordSize >> _shifter); + + storage->set_mapping_changed_listener(&_listener); +} + +void CMBitMapMappingChangedListener::on_commit(uint start_region, size_t num_regions) { + // We need to clear the bitmap on commit, removing any existing information. + MemRegion mr(G1CollectedHeap::heap()->bottom_addr_for_region(start_region), num_regions * HeapRegion::GrainWords); + _bm->clearRange(mr); +} + +// Closure used for clearing the given mark bitmap. +class ClearBitmapHRClosure : public HeapRegionClosure { + private: + ConcurrentMark* _cm; + CMBitMap* _bitmap; + bool _may_yield; // The closure may yield during iteration. If yielded, abort the iteration. + public: + ClearBitmapHRClosure(ConcurrentMark* cm, CMBitMap* bitmap, bool may_yield) : HeapRegionClosure(), _cm(cm), _bitmap(bitmap), _may_yield(may_yield) { + assert(!may_yield || cm != NULL, "CM must be non-NULL if this closure is expected to yield."); + } + + virtual bool doHeapRegion(HeapRegion* r) { + size_t const chunk_size_in_words = M / HeapWordSize; + + HeapWord* cur = r->bottom(); + HeapWord* const end = r->end(); + + while (cur < end) { + MemRegion mr(cur, MIN2(cur + chunk_size_in_words, end)); + _bitmap->clearRange(mr); + + cur += chunk_size_in_words; + + // Abort iteration if after yielding the marking has been aborted. + if (_may_yield && _cm->do_yield_check() && _cm->has_aborted()) { + return true; + } + // Repeat the asserts from before the start of the closure. We will do them + // as asserts here to minimize their overhead on the product. However, we + // will have them as guarantees at the beginning / end of the bitmap + // clearing to get some checking in the product. + assert(!_may_yield || _cm->cmThread()->during_cycle(), "invariant"); + assert(!_may_yield || !G1CollectedHeap::heap()->mark_in_progress(), "invariant"); + } + + return false; + } +}; + void CMBitMap::clearAll() { - _bm.clear(); + ClearBitmapHRClosure cl(NULL, this, false /* may_yield */); + G1CollectedHeap::heap()->heap_region_iterate(&cl); + guarantee(cl.complete(), "Must have completed iteration."); return; } @@ -483,10 +524,10 @@ uint ConcurrentMark::scale_parallel_threads(uint n_par_threads) { return MAX2((n_par_threads + 2) / 4, 1U); } -ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, ReservedSpace heap_rs) : +ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev_bitmap_storage, G1RegionToSpaceMapper* next_bitmap_storage) : _g1h(g1h), - _markBitMap1(log2_intptr(MinObjAlignment)), - _markBitMap2(log2_intptr(MinObjAlignment)), + _markBitMap1(), + _markBitMap2(), _parallel_marking_threads(0), _max_parallel_marking_threads(0), _sleep_factor(0.0), @@ -495,7 +536,7 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, ReservedSpace heap_rs) : _cleanup_task_overhead(1.0), _cleanup_list("Cleanup List"), _region_bm((BitMap::idx_t)(g1h->max_regions()), false /* in_resource_area*/), - _card_bm((heap_rs.size() + CardTableModRefBS::card_size - 1) >> + _card_bm((g1h->reserved_region().byte_size() + CardTableModRefBS::card_size - 1) >> CardTableModRefBS::card_shift, false /* in_resource_area*/), @@ -545,14 +586,8 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, ReservedSpace heap_rs) : "heap end = " PTR_FORMAT, p2i(_heap_start), p2i(_heap_end)); } - if (!_markBitMap1.allocate(heap_rs)) { - warning("Failed to allocate first CM bit map"); - return; - } - if (!_markBitMap2.allocate(heap_rs)) { - warning("Failed to allocate second CM bit map"); - return; - } + _markBitMap1.initialize(g1h->reserved_region(), prev_bitmap_storage); + _markBitMap2.initialize(g1h->reserved_region(), next_bitmap_storage); // Create & start a ConcurrentMark thread. _cmThread = new ConcurrentMarkThread(this); @@ -563,8 +598,8 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, ReservedSpace heap_rs) : } assert(CGC_lock != NULL, "Where's the CGC_lock?"); - assert(_markBitMap1.covers(heap_rs), "_markBitMap1 inconsistency"); - assert(_markBitMap2.covers(heap_rs), "_markBitMap2 inconsistency"); + assert(_markBitMap1.covers(g1h->reserved_region()), "_markBitMap1 inconsistency"); + assert(_markBitMap2.covers(g1h->reserved_region()), "_markBitMap2 inconsistency"); SATBMarkQueueSet& satb_qs = JavaThread::satb_mark_queue_set(); satb_qs.set_buffer_size(G1SATBBufferSize); @@ -724,38 +759,17 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, ReservedSpace heap_rs) : clear_all_count_data(); // so that the call below can read a sensible value - _heap_start = (HeapWord*) heap_rs.base(); + _heap_start = g1h->reserved_region().start(); set_non_marking_state(); _completed_initialization = true; } -void ConcurrentMark::update_g1_committed(bool force) { - // If concurrent marking is not in progress, then we do not need to - // update _heap_end. - if (!concurrent_marking_in_progress() && !force) return; - - MemRegion committed = _g1h->g1_committed(); - assert(committed.start() == _heap_start, "start shouldn't change"); - HeapWord* new_end = committed.end(); - if (new_end > _heap_end) { - // The heap has been expanded. - - _heap_end = new_end; - } - // Notice that the heap can also shrink. However, this only happens - // during a Full GC (at least currently) and the entire marking - // phase will bail out and the task will not be restarted. So, let's - // do nothing. -} - void ConcurrentMark::reset() { // Starting values for these two. This should be called in a STW - // phase. CM will be notified of any future g1_committed expansions - // will be at the end of evacuation pauses, when tasks are - // inactive. - MemRegion committed = _g1h->g1_committed(); - _heap_start = committed.start(); - _heap_end = committed.end(); + // phase. + MemRegion reserved = _g1h->g1_reserved(); + _heap_start = reserved.start(); + _heap_end = reserved.end(); // Separated the asserts so that we know which one fires. assert(_heap_start != NULL, "heap bounds should look ok"); @@ -827,7 +841,6 @@ void ConcurrentMark::set_concurrency_and_phase(uint active_tasks, bool concurren assert(out_of_regions(), err_msg("only way to get here: _finger: "PTR_FORMAT", _heap_end: "PTR_FORMAT, p2i(_finger), p2i(_heap_end))); - update_g1_committed(true); } } @@ -846,7 +859,6 @@ ConcurrentMark::~ConcurrentMark() { void ConcurrentMark::clearNextBitmap() { G1CollectedHeap* g1h = G1CollectedHeap::heap(); - G1CollectorPolicy* g1p = g1h->g1_policy(); // Make sure that the concurrent mark thread looks to still be in // the current cycle. @@ -858,41 +870,36 @@ void ConcurrentMark::clearNextBitmap() { // is the case. guarantee(!g1h->mark_in_progress(), "invariant"); - // clear the mark bitmap (no grey objects to start with). - // We need to do this in chunks and offer to yield in between - // each chunk. - HeapWord* start = _nextMarkBitMap->startWord(); - HeapWord* end = _nextMarkBitMap->endWord(); - HeapWord* cur = start; - size_t chunkSize = M; - while (cur < end) { - HeapWord* next = cur + chunkSize; - if (next > end) { - next = end; - } - MemRegion mr(cur,next); - _nextMarkBitMap->clearRange(mr); - cur = next; - do_yield_check(); + ClearBitmapHRClosure cl(this, _nextMarkBitMap, true /* may_yield */); + g1h->heap_region_iterate(&cl); - // Repeat the asserts from above. We'll do them as asserts here to - // minimize their overhead on the product. However, we'll have - // them as guarantees at the beginning / end of the bitmap - // clearing to get some checking in the product. - assert(cmThread()->during_cycle(), "invariant"); - assert(!g1h->mark_in_progress(), "invariant"); + // Clear the liveness counting data. If the marking has been aborted, the abort() + // call already did that. + if (cl.complete()) { + clear_all_count_data(); } - // Clear the liveness counting data - clear_all_count_data(); - // Repeat the asserts from above. guarantee(cmThread()->during_cycle(), "invariant"); guarantee(!g1h->mark_in_progress(), "invariant"); } +class CheckBitmapClearHRClosure : public HeapRegionClosure { + CMBitMap* _bitmap; + bool _error; + public: + CheckBitmapClearHRClosure(CMBitMap* bitmap) : _bitmap(bitmap) { + } + + virtual bool doHeapRegion(HeapRegion* r) { + return _bitmap->getNextMarkedWordAddress(r->bottom(), r->end()) != r->end(); + } +}; + bool ConcurrentMark::nextMarkBitmapIsClear() { - return _nextMarkBitMap->getNextMarkedWordAddress(_heap_start, _heap_end) == _heap_end; + CheckBitmapClearHRClosure cl(_nextMarkBitMap); + _g1h->heap_region_iterate(&cl); + return cl.complete(); } class NoteStartOfMarkHRClosure: public HeapRegionClosure { @@ -2193,10 +2200,10 @@ void ConcurrentMark::completeCleanup() { _cleanup_list.length()); } - // Noone else should be accessing the _cleanup_list at this point, - // so it's not necessary to take any locks + // No one else should be accessing the _cleanup_list at this point, + // so it is not necessary to take any locks while (!_cleanup_list.is_empty()) { - HeapRegion* hr = _cleanup_list.remove_head(); + HeapRegion* hr = _cleanup_list.remove_region(true /* from_head */); assert(hr != NULL, "Got NULL from a non-empty list"); hr->par_clear(); tmp_free_list.add_ordered(hr); @@ -2980,22 +2987,25 @@ ConcurrentMark::claim_region(uint worker_id) { // claim_region() and a humongous object allocation might force us // to do a bit of unnecessary work (due to some unnecessary bitmap // iterations) but it should not introduce and correctness issues. - HeapRegion* curr_region = _g1h->heap_region_containing_raw(finger); - HeapWord* bottom = curr_region->bottom(); - HeapWord* end = curr_region->end(); - HeapWord* limit = curr_region->next_top_at_mark_start(); + HeapRegion* curr_region = _g1h->heap_region_containing_raw(finger); - if (verbose_low()) { - gclog_or_tty->print_cr("[%u] curr_region = "PTR_FORMAT" " - "["PTR_FORMAT", "PTR_FORMAT"), " - "limit = "PTR_FORMAT, - worker_id, p2i(curr_region), p2i(bottom), p2i(end), p2i(limit)); - } + // Above heap_region_containing_raw may return NULL as we always scan claim + // until the end of the heap. In this case, just jump to the next region. + HeapWord* end = curr_region != NULL ? curr_region->end() : finger + HeapRegion::GrainWords; // Is the gap between reading the finger and doing the CAS too long? HeapWord* res = (HeapWord*) Atomic::cmpxchg_ptr(end, &_finger, finger); - if (res == finger) { + if (res == finger && curr_region != NULL) { // we succeeded + HeapWord* bottom = curr_region->bottom(); + HeapWord* limit = curr_region->next_top_at_mark_start(); + + if (verbose_low()) { + gclog_or_tty->print_cr("[%u] curr_region = "PTR_FORMAT" " + "["PTR_FORMAT", "PTR_FORMAT"), " + "limit = "PTR_FORMAT, + worker_id, p2i(curr_region), p2i(bottom), p2i(end), p2i(limit)); + } // notice that _finger == end cannot be guaranteed here since, // someone else might have moved the finger even further @@ -3026,10 +3036,17 @@ ConcurrentMark::claim_region(uint worker_id) { } else { assert(_finger > finger, "the finger should have moved forward"); if (verbose_low()) { - gclog_or_tty->print_cr("[%u] somebody else moved the finger, " - "global finger = "PTR_FORMAT", " - "our finger = "PTR_FORMAT, - worker_id, p2i(_finger), p2i(finger)); + if (curr_region == NULL) { + gclog_or_tty->print_cr("[%u] found uncommitted region, moving finger, " + "global finger = "PTR_FORMAT", " + "our finger = "PTR_FORMAT, + worker_id, p2i(_finger), p2i(finger)); + } else { + gclog_or_tty->print_cr("[%u] somebody else moved the finger, " + "global finger = "PTR_FORMAT", " + "our finger = "PTR_FORMAT, + worker_id, p2i(_finger), p2i(finger)); + } } // read it again @@ -3144,8 +3161,10 @@ void ConcurrentMark::verify_no_cset_oops(bool verify_stacks, // happens, heap_region_containing() will return the bottom of the // corresponding starts humongous region and the check below will // not hold any more. + // Since we always iterate over all regions, we might get a NULL HeapRegion + // here. HeapRegion* global_hr = _g1h->heap_region_containing_raw(global_finger); - guarantee(global_finger == global_hr->bottom(), + guarantee(global_hr == NULL || global_finger == global_hr->bottom(), err_msg("global finger: "PTR_FORMAT" region: "HR_FORMAT, p2i(global_finger), HR_FORMAT_PARAMS(global_hr))); } @@ -3158,7 +3177,7 @@ void ConcurrentMark::verify_no_cset_oops(bool verify_stacks, if (task_finger != NULL && task_finger < _heap_end) { // See above note on the global finger verification. HeapRegion* task_hr = _g1h->heap_region_containing_raw(task_finger); - guarantee(task_finger == task_hr->bottom() || + guarantee(task_hr == NULL || task_finger == task_hr->bottom() || !task_hr->in_collection_set(), err_msg("task finger: "PTR_FORMAT" region: "HR_FORMAT, p2i(task_finger), HR_FORMAT_PARAMS(task_hr))); @@ -4674,7 +4693,6 @@ G1PrintRegionLivenessInfoClosure(outputStream* out, const char* phase_name) _hum_prev_live_bytes(0), _hum_next_live_bytes(0), _total_remset_bytes(0), _total_strong_code_roots_bytes(0) { G1CollectedHeap* g1h = G1CollectedHeap::heap(); - MemRegion g1_committed = g1h->g1_committed(); MemRegion g1_reserved = g1h->g1_reserved(); double now = os::elapsedTime(); @@ -4682,10 +4700,8 @@ G1PrintRegionLivenessInfoClosure(outputStream* out, const char* phase_name) _out->cr(); _out->print_cr(G1PPRL_LINE_PREFIX" PHASE %s @ %1.3f", phase_name, now); _out->print_cr(G1PPRL_LINE_PREFIX" HEAP" - G1PPRL_SUM_ADDR_FORMAT("committed") G1PPRL_SUM_ADDR_FORMAT("reserved") G1PPRL_SUM_BYTE_FORMAT("region-size"), - p2i(g1_committed.start()), p2i(g1_committed.end()), p2i(g1_reserved.start()), p2i(g1_reserved.end()), HeapRegion::GrainBytes); _out->print_cr(G1PPRL_LINE_PREFIX); diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp index a564855277b..e44ddb5b0ab 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp @@ -27,10 +27,12 @@ #include "classfile/javaClasses.hpp" #include "gc_implementation/g1/heapRegionSet.hpp" +#include "gc_implementation/g1/g1RegionToSpaceMapper.hpp" #include "gc_implementation/shared/gcId.hpp" #include "utilities/taskqueue.hpp" class G1CollectedHeap; +class CMBitMap; class CMTask; typedef GenericTaskQueue CMTaskQueue; typedef GenericTaskQueueSet CMTaskQueueSet; @@ -57,7 +59,6 @@ class CMBitMapRO VALUE_OBJ_CLASS_SPEC { HeapWord* _bmStartWord; // base address of range covered by map size_t _bmWordSize; // map size (in #HeapWords covered) const int _shifter; // map to char or bit - VirtualSpace _virtual_space; // underlying the bit map BitMap _bm; // the bit map itself public: @@ -115,42 +116,41 @@ class CMBitMapRO VALUE_OBJ_CLASS_SPEC { void print_on_error(outputStream* st, const char* prefix) const; // debugging - NOT_PRODUCT(bool covers(ReservedSpace rs) const;) + NOT_PRODUCT(bool covers(MemRegion rs) const;) +}; + +class CMBitMapMappingChangedListener : public G1MappingChangedListener { + private: + CMBitMap* _bm; + public: + CMBitMapMappingChangedListener() : _bm(NULL) {} + + void set_bitmap(CMBitMap* bm) { _bm = bm; } + + virtual void on_commit(uint start_idx, size_t num_regions); }; class CMBitMap : public CMBitMapRO { + private: + CMBitMapMappingChangedListener _listener; public: - // constructor - CMBitMap(int shifter) : - CMBitMapRO(shifter) {} + static size_t compute_size(size_t heap_size); + // Returns the amount of bytes on the heap between two marks in the bitmap. + static size_t mark_distance(); - // Allocates the back store for the marking bitmap - bool allocate(ReservedSpace heap_rs); + CMBitMap() : CMBitMapRO(LogMinObjAlignment), _listener() { _listener.set_bitmap(this); } + + // Initializes the underlying BitMap to cover the given area. + void initialize(MemRegion heap, G1RegionToSpaceMapper* storage); + + // Write marks. + inline void mark(HeapWord* addr); + inline void clear(HeapWord* addr); + inline bool parMark(HeapWord* addr); + inline bool parClear(HeapWord* addr); - // write marks - void mark(HeapWord* addr) { - assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize), - "outside underlying space?"); - _bm.set_bit(heapWordToOffset(addr)); - } - void clear(HeapWord* addr) { - assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize), - "outside underlying space?"); - _bm.clear_bit(heapWordToOffset(addr)); - } - bool parMark(HeapWord* addr) { - assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize), - "outside underlying space?"); - return _bm.par_set_bit(heapWordToOffset(addr)); - } - bool parClear(HeapWord* addr) { - assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize), - "outside underlying space?"); - return _bm.par_clear_bit(heapWordToOffset(addr)); - } void markRange(MemRegion mr); - void clearAll(); void clearRange(MemRegion mr); // Starting at the bit corresponding to "addr" (inclusive), find the next @@ -161,6 +161,9 @@ class CMBitMap : public CMBitMapRO { // the run. If there is no "1" bit at or after "addr", return an empty // MemRegion. MemRegion getAndClearMarkedRegion(HeapWord* addr, HeapWord* end_addr); + + // Clear the whole mark bitmap. + void clearAll(); }; // Represents a marking stack used by ConcurrentMarking in the G1 collector. @@ -680,7 +683,7 @@ public: return _task_queues->steal(worker_id, hash_seed, obj); } - ConcurrentMark(G1CollectedHeap* g1h, ReservedSpace heap_rs); + ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev_bitmap_storage, G1RegionToSpaceMapper* next_bitmap_storage); ~ConcurrentMark(); ConcurrentMarkThread* cmThread() { return _cmThread; } @@ -736,7 +739,8 @@ public: // Clear the next marking bitmap (will be called concurrently). void clearNextBitmap(); - // Return whether the next mark bitmap has no marks set. + // Return whether the next mark bitmap has no marks set. To be used for assertions + // only. Will not yield to pause requests. bool nextMarkBitmapIsClear(); // These two do the work that needs to be done before and after the @@ -794,12 +798,6 @@ public: bool verify_thread_buffers, bool verify_fingers) PRODUCT_RETURN; - // It is called at the end of an evacuation pause during marking so - // that CM is notified of where the new end of the heap is. It - // doesn't do anything if concurrent_marking_in_progress() is false, - // unless the force parameter is true. - void update_g1_committed(bool force = false); - bool isMarked(oop p) const { assert(p != NULL && p->is_oop(), "expected an oop"); HeapWord* addr = (HeapWord*)p; diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp index 12ba5683ed8..27ddac5a622 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp @@ -268,6 +268,36 @@ inline bool CMBitMapRO::iterate(BitMapClosure* cl) { return iterate(cl, mr); } +#define check_mark(addr) \ + assert(_bmStartWord <= (addr) && (addr) < (_bmStartWord + _bmWordSize), \ + "outside underlying space?"); \ + assert(G1CollectedHeap::heap()->is_in_exact(addr), \ + err_msg("Trying to access not available bitmap "PTR_FORMAT \ + " corresponding to "PTR_FORMAT" (%u)", \ + p2i(this), p2i(addr), G1CollectedHeap::heap()->addr_to_region(addr))); + +inline void CMBitMap::mark(HeapWord* addr) { + check_mark(addr); + _bm.set_bit(heapWordToOffset(addr)); +} + +inline void CMBitMap::clear(HeapWord* addr) { + check_mark(addr); + _bm.clear_bit(heapWordToOffset(addr)); +} + +inline bool CMBitMap::parMark(HeapWord* addr) { + check_mark(addr); + return _bm.par_set_bit(heapWordToOffset(addr)); +} + +inline bool CMBitMap::parClear(HeapWord* addr) { + check_mark(addr); + return _bm.par_clear_bit(heapWordToOffset(addr)); +} + +#undef check_mark + inline void CMTask::push(oop obj) { HeapWord* objAddr = (HeapWord*) obj; assert(_g1h->is_in_g1_reserved(objAddr), "invariant"); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.hpp index 050490dbbef..50cc9be07ea 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.hpp @@ -173,7 +173,7 @@ public: // Should be called when we want to release the active region which // is returned after it's been retired. - HeapRegion* release(); + virtual HeapRegion* release(); #if G1_ALLOC_REGION_TRACING void trace(const char* str, size_t word_size = 0, HeapWord* result = NULL); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp index c7d4ff3431a..1eae8b9d3f8 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp @@ -32,64 +32,37 @@ PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC +void G1BlockOffsetSharedArrayMappingChangedListener::on_commit(uint start_idx, size_t num_regions) { + // Nothing to do. The BOT is hard-wired to be part of the HeapRegion, and we cannot + // retrieve it here since this would cause firing of several asserts. The code + // executed after commit of a region already needs to do some re-initialization of + // the HeapRegion, so we combine that. +} + ////////////////////////////////////////////////////////////////////// // G1BlockOffsetSharedArray ////////////////////////////////////////////////////////////////////// -G1BlockOffsetSharedArray::G1BlockOffsetSharedArray(MemRegion reserved, - size_t init_word_size) : - _reserved(reserved), _end(NULL) -{ - size_t size = compute_size(reserved.word_size()); - ReservedSpace rs(ReservedSpace::allocation_align_size_up(size)); - if (!rs.is_reserved()) { - vm_exit_during_initialization("Could not reserve enough space for heap offset array"); - } - if (!_vs.initialize(rs, 0)) { - vm_exit_during_initialization("Could not reserve enough space for heap offset array"); - } +G1BlockOffsetSharedArray::G1BlockOffsetSharedArray(MemRegion heap, G1RegionToSpaceMapper* storage) : + _reserved(), _end(NULL), _listener(), _offset_array(NULL) { - MemTracker::record_virtual_memory_type((address)rs.base(), mtGC); + _reserved = heap; + _end = NULL; + + MemRegion bot_reserved = storage->reserved(); + + _offset_array = (u_char*)bot_reserved.start(); + _end = _reserved.end(); + + storage->set_mapping_changed_listener(&_listener); - _offset_array = (u_char*)_vs.low_boundary(); - resize(init_word_size); if (TraceBlockOffsetTable) { gclog_or_tty->print_cr("G1BlockOffsetSharedArray::G1BlockOffsetSharedArray: "); gclog_or_tty->print_cr(" " " rs.base(): " INTPTR_FORMAT " rs.size(): " INTPTR_FORMAT " rs end(): " INTPTR_FORMAT, - rs.base(), rs.size(), rs.base() + rs.size()); - gclog_or_tty->print_cr(" " - " _vs.low_boundary(): " INTPTR_FORMAT - " _vs.high_boundary(): " INTPTR_FORMAT, - _vs.low_boundary(), - _vs.high_boundary()); - } -} - -void G1BlockOffsetSharedArray::resize(size_t new_word_size) { - assert(new_word_size <= _reserved.word_size(), "Resize larger than reserved"); - size_t new_size = compute_size(new_word_size); - size_t old_size = _vs.committed_size(); - size_t delta; - char* high = _vs.high(); - _end = _reserved.start() + new_word_size; - if (new_size > old_size) { - delta = ReservedSpace::page_align_size_up(new_size - old_size); - assert(delta > 0, "just checking"); - if (!_vs.expand_by(delta)) { - // Do better than this for Merlin - vm_exit_out_of_memory(delta, OOM_MMAP_ERROR, "offset table expansion"); - } - assert(_vs.high() == high + delta, "invalid expansion"); - // Initialization of the contents is left to the - // G1BlockOffsetArray that uses it. - } else { - delta = ReservedSpace::page_align_size_down(old_size - new_size); - if (delta == 0) return; - _vs.shrink_by(delta); - assert(_vs.high() == high - delta, "invalid expansion"); + bot_reserved.start(), bot_reserved.byte_size(), bot_reserved.end()); } } @@ -100,18 +73,7 @@ bool G1BlockOffsetSharedArray::is_card_boundary(HeapWord* p) const { } void G1BlockOffsetSharedArray::set_offset_array(HeapWord* left, HeapWord* right, u_char offset) { - check_index(index_for(right - 1), "right address out of range"); - assert(left < right, "Heap addresses out of order"); - size_t num_cards = pointer_delta(right, left) >> LogN_words; - if (UseMemSetInBOT) { - memset(&_offset_array[index_for(left)], offset, num_cards); - } else { - size_t i = index_for(left); - const size_t end = i + num_cards; - for (; i < end; i++) { - _offset_array[i] = offset; - } - } + set_offset_array(index_for(left), index_for(right -1), offset); } ////////////////////////////////////////////////////////////////////// @@ -650,6 +612,25 @@ G1BlockOffsetArrayContigSpace(G1BlockOffsetSharedArray* array, _next_offset_index = 0; } +HeapWord* G1BlockOffsetArrayContigSpace::initialize_threshold_raw() { + assert(!Universe::heap()->is_in_reserved(_array->_offset_array), + "just checking"); + _next_offset_index = _array->index_for_raw(_bottom); + _next_offset_index++; + _next_offset_threshold = + _array->address_for_index_raw(_next_offset_index); + return _next_offset_threshold; +} + +void G1BlockOffsetArrayContigSpace::zero_bottom_entry_raw() { + assert(!Universe::heap()->is_in_reserved(_array->_offset_array), + "just checking"); + size_t bottom_index = _array->index_for_raw(_bottom); + assert(_array->address_for_index_raw(bottom_index) == _bottom, + "Precondition of call"); + _array->set_offset_array_raw(bottom_index, 0); +} + HeapWord* G1BlockOffsetArrayContigSpace::initialize_threshold() { assert(!Universe::heap()->is_in_reserved(_array->_offset_array), "just checking"); @@ -674,8 +655,7 @@ G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_top) { assert(new_top <= _end, "_end should have already been updated"); // The first BOT entry should have offset 0. - zero_bottom_entry(); - initialize_threshold(); + reset_bot(); alloc_block(_bottom, new_top); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp index 5395899f143..70bc41390a3 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_HPP #define SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_HPP +#include "gc_implementation/g1/g1RegionToSpaceMapper.hpp" #include "memory/memRegion.hpp" #include "runtime/virtualspace.hpp" #include "utilities/globalDefinitions.hpp" @@ -106,6 +107,11 @@ public: inline HeapWord* block_start_const(const void* addr) const; }; +class G1BlockOffsetSharedArrayMappingChangedListener : public G1MappingChangedListener { + public: + virtual void on_commit(uint start_idx, size_t num_regions); +}; + // This implementation of "G1BlockOffsetTable" divides the covered region // into "N"-word subregions (where "N" = 2^"LogN". An array with an entry // for each such subregion indicates how far back one must go to find the @@ -125,6 +131,7 @@ class G1BlockOffsetSharedArray: public CHeapObj { friend class VMStructs; private: + G1BlockOffsetSharedArrayMappingChangedListener _listener; // The reserved region covered by the shared array. MemRegion _reserved; @@ -133,16 +140,8 @@ private: // Array for keeping offsets for retrieving object start fast given an // address. - VirtualSpace _vs; u_char* _offset_array; // byte array keeping backwards offsets - void check_index(size_t index, const char* msg) const { - assert(index < _vs.committed_size(), - err_msg("%s - " - "index: " SIZE_FORMAT ", _vs.committed_size: " SIZE_FORMAT, - msg, index, _vs.committed_size())); - } - void check_offset(size_t offset, const char* msg) const { assert(offset <= N_words, err_msg("%s - " @@ -152,63 +151,33 @@ private: // Bounds checking accessors: // For performance these have to devolve to array accesses in product builds. - u_char offset_array(size_t index) const { - check_index(index, "index out of range"); - return _offset_array[index]; - } + inline u_char offset_array(size_t index) const; void set_offset_array(HeapWord* left, HeapWord* right, u_char offset); - void set_offset_array(size_t index, u_char offset) { - check_index(index, "index out of range"); - check_offset(offset, "offset too large"); + void set_offset_array_raw(size_t index, u_char offset) { _offset_array[index] = offset; } - void set_offset_array(size_t index, HeapWord* high, HeapWord* low) { - check_index(index, "index out of range"); - assert(high >= low, "addresses out of order"); - check_offset(pointer_delta(high, low), "offset too large"); - _offset_array[index] = (u_char) pointer_delta(high, low); - } + inline void set_offset_array(size_t index, u_char offset); - void set_offset_array(size_t left, size_t right, u_char offset) { - check_index(right, "right index out of range"); - assert(left <= right, "indexes out of order"); - size_t num_cards = right - left + 1; - if (UseMemSetInBOT) { - memset(&_offset_array[left], offset, num_cards); - } else { - size_t i = left; - const size_t end = i + num_cards; - for (; i < end; i++) { - _offset_array[i] = offset; - } - } - } + inline void set_offset_array(size_t index, HeapWord* high, HeapWord* low); - void check_offset_array(size_t index, HeapWord* high, HeapWord* low) const { - check_index(index, "index out of range"); - assert(high >= low, "addresses out of order"); - check_offset(pointer_delta(high, low), "offset too large"); - assert(_offset_array[index] == pointer_delta(high, low), "Wrong offset"); - } + inline void set_offset_array(size_t left, size_t right, u_char offset); + + inline void check_offset_array(size_t index, HeapWord* high, HeapWord* low) const; bool is_card_boundary(HeapWord* p) const; +public: + // Return the number of slots needed for an offset array // that covers mem_region_words words. - // We always add an extra slot because if an object - // ends on a card boundary we put a 0 in the next - // offset array slot, so we want that slot always - // to be reserved. - - size_t compute_size(size_t mem_region_words) { - size_t number_of_slots = (mem_region_words / N_words) + 1; - return ReservedSpace::page_align_size_up(number_of_slots); + static size_t compute_size(size_t mem_region_words) { + size_t number_of_slots = (mem_region_words / N_words); + return ReservedSpace::allocation_align_size_up(number_of_slots); } -public: enum SomePublicConstants { LogN = 9, LogN_words = LogN - LogHeapWordSize, @@ -222,25 +191,21 @@ public: // least "init_word_size".) The contents of the initial table are // undefined; it is the responsibility of the constituent // G1BlockOffsetTable(s) to initialize cards. - G1BlockOffsetSharedArray(MemRegion reserved, size_t init_word_size); - - // Notes a change in the committed size of the region covered by the - // table. The "new_word_size" may not be larger than the size of the - // reserved region this table covers. - void resize(size_t new_word_size); + G1BlockOffsetSharedArray(MemRegion heap, G1RegionToSpaceMapper* storage); void set_bottom(HeapWord* new_bottom); - // Updates all the BlockOffsetArray's sharing this shared array to - // reflect the current "top"'s of their spaces. - void update_offset_arrays(); - // Return the appropriate index into "_offset_array" for "p". inline size_t index_for(const void* p) const; + inline size_t index_for_raw(const void* p) const; // Return the address indicating the start of the region corresponding to // "index" in "_offset_array". inline HeapWord* address_for_index(size_t index) const; + // Variant of address_for_index that does not check the index for validity. + inline HeapWord* address_for_index_raw(size_t index) const { + return _reserved.start() + (index << LogN_words); + } }; // And here is the G1BlockOffsetTable subtype that uses the array. @@ -480,6 +445,14 @@ class G1BlockOffsetArrayContigSpace: public G1BlockOffsetArray { blk_start, blk_end); } + // Variant of zero_bottom_entry that does not check for availability of the + // memory first. + void zero_bottom_entry_raw(); + // Variant of initialize_threshold that does not check for availability of the + // memory first. + HeapWord* initialize_threshold_raw(); + // Zero out the entry for _bottom (offset will be zero). + void zero_bottom_entry(); public: G1BlockOffsetArrayContigSpace(G1BlockOffsetSharedArray* array, MemRegion mr); @@ -487,8 +460,10 @@ class G1BlockOffsetArrayContigSpace: public G1BlockOffsetArray { // bottom of the covered region. HeapWord* initialize_threshold(); - // Zero out the entry for _bottom (offset will be zero). - void zero_bottom_entry(); + void reset_bot() { + zero_bottom_entry_raw(); + initialize_threshold_raw(); + } // Return the next threshold, the point at which the table should be // updated. diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp index 4cf0a06cd74..cd4ebd2d05f 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp @@ -47,14 +47,69 @@ G1BlockOffsetTable::block_start_const(const void* addr) const { } } +#define check_index(index, msg) \ + assert((index) < (_reserved.word_size() >> LogN_words), \ + err_msg("%s - index: "SIZE_FORMAT", _vs.committed_size: "SIZE_FORMAT, \ + msg, (index), (_reserved.word_size() >> LogN_words))); \ + assert(G1CollectedHeap::heap()->is_in_exact(address_for_index_raw(index)), \ + err_msg("Index "SIZE_FORMAT" corresponding to "PTR_FORMAT \ + " (%u) is not in committed area.", \ + (index), \ + p2i(address_for_index_raw(index)), \ + G1CollectedHeap::heap()->addr_to_region(address_for_index_raw(index)))); + +u_char G1BlockOffsetSharedArray::offset_array(size_t index) const { + check_index(index, "index out of range"); + return _offset_array[index]; +} + +void G1BlockOffsetSharedArray::set_offset_array(size_t index, u_char offset) { + check_index(index, "index out of range"); + set_offset_array_raw(index, offset); +} + +void G1BlockOffsetSharedArray::set_offset_array(size_t index, HeapWord* high, HeapWord* low) { + check_index(index, "index out of range"); + assert(high >= low, "addresses out of order"); + size_t offset = pointer_delta(high, low); + check_offset(offset, "offset too large"); + set_offset_array(index, (u_char)offset); +} + +void G1BlockOffsetSharedArray::set_offset_array(size_t left, size_t right, u_char offset) { + check_index(right, "right index out of range"); + assert(left <= right, "indexes out of order"); + size_t num_cards = right - left + 1; + if (UseMemSetInBOT) { + memset(&_offset_array[left], offset, num_cards); + } else { + size_t i = left; + const size_t end = i + num_cards; + for (; i < end; i++) { + _offset_array[i] = offset; + } + } +} + +void G1BlockOffsetSharedArray::check_offset_array(size_t index, HeapWord* high, HeapWord* low) const { + check_index(index, "index out of range"); + assert(high >= low, "addresses out of order"); + check_offset(pointer_delta(high, low), "offset too large"); + assert(_offset_array[index] == pointer_delta(high, low), "Wrong offset"); +} + +// Variant of index_for that does not check the index for validity. +inline size_t G1BlockOffsetSharedArray::index_for_raw(const void* p) const { + return pointer_delta((char*)p, _reserved.start(), sizeof(char)) >> LogN; +} + inline size_t G1BlockOffsetSharedArray::index_for(const void* p) const { char* pc = (char*)p; assert(pc >= (char*)_reserved.start() && pc < (char*)_reserved.end(), err_msg("p (" PTR_FORMAT ") not in reserved [" PTR_FORMAT ", " PTR_FORMAT ")", p2i(p), p2i(_reserved.start()), p2i(_reserved.end()))); - size_t delta = pointer_delta(pc, _reserved.start(), sizeof(char)); - size_t result = delta >> LogN; + size_t result = index_for_raw(p); check_index(result, "bad index from address"); return result; } @@ -62,7 +117,7 @@ inline size_t G1BlockOffsetSharedArray::index_for(const void* p) const { inline HeapWord* G1BlockOffsetSharedArray::address_for_index(size_t index) const { check_index(index, "index out of range"); - HeapWord* result = _reserved.start() + (index << LogN_words); + HeapWord* result = address_for_index_raw(index); assert(result >= _reserved.start() && result < _reserved.end(), err_msg("bad address from index result " PTR_FORMAT " _reserved.start() " PTR_FORMAT " _reserved.end() " @@ -71,6 +126,8 @@ G1BlockOffsetSharedArray::address_for_index(size_t index) const { return result; } +#undef check_index + inline size_t G1BlockOffsetArray::block_size(const HeapWord* p) const { return gsp()->block_size(p); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp index 9fff9604ff2..f9fd47cfb64 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp @@ -33,31 +33,26 @@ PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC +void G1CardCountsMappingChangedListener::on_commit(uint start_idx, size_t num_regions) { + MemRegion mr(G1CollectedHeap::heap()->bottom_addr_for_region(start_idx), num_regions * HeapRegion::GrainWords); + _counts->clear_range(mr); +} + void G1CardCounts::clear_range(size_t from_card_num, size_t to_card_num) { if (has_count_table()) { - assert(from_card_num >= 0 && from_card_num < _committed_max_card_num, - err_msg("from card num out of range: "SIZE_FORMAT, from_card_num)); assert(from_card_num < to_card_num, err_msg("Wrong order? from: " SIZE_FORMAT ", to: "SIZE_FORMAT, from_card_num, to_card_num)); - assert(to_card_num <= _committed_max_card_num, - err_msg("to card num out of range: " - "to: "SIZE_FORMAT ", " - "max: "SIZE_FORMAT, - to_card_num, _committed_max_card_num)); - - to_card_num = MIN2(_committed_max_card_num, to_card_num); - Copy::fill_to_bytes(&_card_counts[from_card_num], (to_card_num - from_card_num)); } } G1CardCounts::G1CardCounts(G1CollectedHeap *g1h): - _g1h(g1h), _card_counts(NULL), - _reserved_max_card_num(0), _committed_max_card_num(0), - _committed_size(0) {} + _listener(), _g1h(g1h), _card_counts(NULL), _reserved_max_card_num(0) { + _listener.set_cardcounts(this); +} -void G1CardCounts::initialize() { +void G1CardCounts::initialize(G1RegionToSpaceMapper* mapper) { assert(_g1h->max_capacity() > 0, "initialization order"); assert(_g1h->capacity() == 0, "initialization order"); @@ -70,70 +65,9 @@ void G1CardCounts::initialize() { _ct_bs = _g1h->g1_barrier_set(); _ct_bot = _ct_bs->byte_for_const(_g1h->reserved_region().start()); - // Allocate/Reserve the counts table - size_t reserved_bytes = _g1h->max_capacity(); - _reserved_max_card_num = reserved_bytes >> CardTableModRefBS::card_shift; - - size_t reserved_size = _reserved_max_card_num * sizeof(jbyte); - ReservedSpace rs(ReservedSpace::allocation_align_size_up(reserved_size)); - if (!rs.is_reserved()) { - warning("Could not reserve enough space for the card counts table"); - guarantee(!has_reserved_count_table(), "should be NULL"); - return; - } - - MemTracker::record_virtual_memory_type((address)rs.base(), mtGC); - - _card_counts_storage.initialize(rs, 0); - _card_counts = (jubyte*) _card_counts_storage.low(); - } -} - -void G1CardCounts::resize(size_t heap_capacity) { - // Expand the card counts table to handle a heap with the given capacity. - - if (!has_reserved_count_table()) { - // Don't expand if we failed to reserve the card counts table. - return; - } - - assert(_committed_size == - ReservedSpace::allocation_align_size_up(_committed_size), - err_msg("Unaligned? committed_size: " SIZE_FORMAT, _committed_size)); - - // Verify that the committed space for the card counts matches our - // committed max card num. Note for some allocation alignments, the - // amount of space actually committed for the counts table will be able - // to span more cards than the number spanned by the maximum heap. - size_t prev_committed_size = _committed_size; - size_t prev_committed_card_num = committed_to_card_num(prev_committed_size); - - assert(prev_committed_card_num == _committed_max_card_num, - err_msg("Card mismatch: " - "prev: " SIZE_FORMAT ", " - "committed: "SIZE_FORMAT", " - "reserved: "SIZE_FORMAT, - prev_committed_card_num, _committed_max_card_num, _reserved_max_card_num)); - - size_t new_size = (heap_capacity >> CardTableModRefBS::card_shift) * sizeof(jbyte); - size_t new_committed_size = ReservedSpace::allocation_align_size_up(new_size); - size_t new_committed_card_num = committed_to_card_num(new_committed_size); - - if (_committed_max_card_num < new_committed_card_num) { - // we need to expand the backing store for the card counts - size_t expand_size = new_committed_size - prev_committed_size; - - if (!_card_counts_storage.expand_by(expand_size)) { - warning("Card counts table backing store commit failure"); - return; - } - assert(_card_counts_storage.committed_size() == new_committed_size, - "expansion commit failure"); - - _committed_size = new_committed_size; - _committed_max_card_num = new_committed_card_num; - - clear_range(prev_committed_card_num, _committed_max_card_num); + _card_counts = (jubyte*) mapper->reserved().start(); + _reserved_max_card_num = mapper->reserved().byte_size(); + mapper->set_mapping_changed_listener(&_listener); } } @@ -149,12 +83,13 @@ uint G1CardCounts::add_card_count(jbyte* card_ptr) { uint count = 0; if (has_count_table()) { size_t card_num = ptr_2_card_num(card_ptr); - if (card_num < _committed_max_card_num) { - count = (uint) _card_counts[card_num]; - if (count < G1ConcRSHotCardLimit) { - _card_counts[card_num] = - (jubyte)(MIN2((uintx)(_card_counts[card_num] + 1), G1ConcRSHotCardLimit)); - } + assert(card_num < _reserved_max_card_num, + err_msg("Card "SIZE_FORMAT" outside of card counts table (max size "SIZE_FORMAT")", + card_num, _reserved_max_card_num)); + count = (uint) _card_counts[card_num]; + if (count < G1ConcRSHotCardLimit) { + _card_counts[card_num] = + (jubyte)(MIN2((uintx)(_card_counts[card_num] + 1), G1ConcRSHotCardLimit)); } } return count; @@ -165,31 +100,23 @@ bool G1CardCounts::is_hot(uint count) { } void G1CardCounts::clear_region(HeapRegion* hr) { - assert(!hr->isHumongous(), "Should have been cleared"); + MemRegion mr(hr->bottom(), hr->end()); + clear_range(mr); +} + +void G1CardCounts::clear_range(MemRegion mr) { if (has_count_table()) { - HeapWord* bottom = hr->bottom(); - - // We use the last address in hr as hr could be the - // last region in the heap. In which case trying to find - // the card for hr->end() will be an OOB access to the - // card table. - HeapWord* last = hr->end() - 1; - assert(_g1h->g1_committed().contains(last), - err_msg("last not in committed: " - "last: " PTR_FORMAT ", " - "committed: [" PTR_FORMAT ", " PTR_FORMAT ")", - last, - _g1h->g1_committed().start(), - _g1h->g1_committed().end())); - - const jbyte* from_card_ptr = _ct_bs->byte_for_const(bottom); - const jbyte* last_card_ptr = _ct_bs->byte_for_const(last); + const jbyte* from_card_ptr = _ct_bs->byte_for_const(mr.start()); + // We use the last address in the range as the range could represent the + // last region in the heap. In which case trying to find the card will be an + // OOB access to the card table. + const jbyte* last_card_ptr = _ct_bs->byte_for_const(mr.last()); #ifdef ASSERT HeapWord* start_addr = _ct_bs->addr_for(from_card_ptr); - assert(start_addr == hr->bottom(), "alignment"); + assert(start_addr == mr.start(), "MemRegion start must be aligned to a card."); HeapWord* last_addr = _ct_bs->addr_for(last_card_ptr); - assert((last_addr + CardTableModRefBS::card_size_in_words) == hr->end(), "alignment"); + assert((last_addr + CardTableModRefBS::card_size_in_words) == mr.end(), "MemRegion end must be aligned to a card."); #endif // ASSERT // Clear the counts for the (exclusive) card range. @@ -199,14 +126,22 @@ void G1CardCounts::clear_region(HeapRegion* hr) { } } +class G1CardCountsClearClosure : public HeapRegionClosure { + private: + G1CardCounts* _card_counts; + public: + G1CardCountsClearClosure(G1CardCounts* card_counts) : + HeapRegionClosure(), _card_counts(card_counts) { } + + + virtual bool doHeapRegion(HeapRegion* r) { + _card_counts->clear_region(r); + return false; + } +}; + void G1CardCounts::clear_all() { assert(SafepointSynchronize::is_at_safepoint(), "don't call this otherwise"); - clear_range((size_t)0, _committed_max_card_num); + G1CardCountsClearClosure cl(this); + _g1h->heap_region_iterate(&cl); } - -G1CardCounts::~G1CardCounts() { - if (has_reserved_count_table()) { - _card_counts_storage.release(); - } -} - diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp index ef08479f60a..4252cba0937 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp @@ -25,14 +25,26 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1CARDCOUNTS_HPP #define SHARE_VM_GC_IMPLEMENTATION_G1_G1CARDCOUNTS_HPP +#include "gc_implementation/g1/g1RegionToSpaceMapper.hpp" #include "memory/allocation.hpp" #include "runtime/virtualspace.hpp" #include "utilities/globalDefinitions.hpp" class CardTableModRefBS; +class G1CardCounts; class G1CollectedHeap; +class G1RegionToSpaceMapper; class HeapRegion; +class G1CardCountsMappingChangedListener : public G1MappingChangedListener { + private: + G1CardCounts* _counts; + public: + void set_cardcounts(G1CardCounts* counts) { _counts = counts; } + + virtual void on_commit(uint start_idx, size_t num_regions); +}; + // Table to track the number of times a card has been refined. Once // a card has been refined a certain number of times, it is // considered 'hot' and its refinement is delayed by inserting the @@ -41,6 +53,8 @@ class HeapRegion; // is 'drained' during the next evacuation pause. class G1CardCounts: public CHeapObj { + G1CardCountsMappingChangedListener _listener; + G1CollectedHeap* _g1h; // The table of counts @@ -49,27 +63,18 @@ class G1CardCounts: public CHeapObj { // Max capacity of the reserved space for the counts table size_t _reserved_max_card_num; - // Max capacity of the committed space for the counts table - size_t _committed_max_card_num; - - // Size of committed space for the counts table - size_t _committed_size; - // CardTable bottom. const jbyte* _ct_bot; // Barrier set CardTableModRefBS* _ct_bs; - // The virtual memory backing the counts table - VirtualSpace _card_counts_storage; - // Returns true if the card counts table has been reserved. bool has_reserved_count_table() { return _card_counts != NULL; } // Returns true if the card counts table has been reserved and committed. bool has_count_table() { - return has_reserved_count_table() && _committed_max_card_num > 0; + return has_reserved_count_table(); } size_t ptr_2_card_num(const jbyte* card_ptr) { @@ -79,37 +84,24 @@ class G1CardCounts: public CHeapObj { "_ct_bot: " PTR_FORMAT, p2i(card_ptr), p2i(_ct_bot))); size_t card_num = pointer_delta(card_ptr, _ct_bot, sizeof(jbyte)); - assert(card_num >= 0 && card_num < _committed_max_card_num, + assert(card_num >= 0 && card_num < _reserved_max_card_num, err_msg("card pointer out of range: " PTR_FORMAT, p2i(card_ptr))); return card_num; } jbyte* card_num_2_ptr(size_t card_num) { - assert(card_num >= 0 && card_num < _committed_max_card_num, + assert(card_num >= 0 && card_num < _reserved_max_card_num, err_msg("card num out of range: "SIZE_FORMAT, card_num)); return (jbyte*) (_ct_bot + card_num); } - // Helper routine. - // Returns the number of cards that can be counted by the given committed - // table size, with a maximum of the number of cards spanned by the max - // capacity of the heap. - size_t committed_to_card_num(size_t committed_size) { - return MIN2(_reserved_max_card_num, committed_size / sizeof(jbyte)); - } - // Clear the counts table for the given (exclusive) index range. void clear_range(size_t from_card_num, size_t to_card_num); public: G1CardCounts(G1CollectedHeap* g1h); - ~G1CardCounts(); - void initialize(); - - // Resize the committed space for the card counts table in - // response to a resize of the committed space for the heap. - void resize(size_t heap_capacity); + void initialize(G1RegionToSpaceMapper* mapper); // Increments the refinement count for the given card. // Returns the pre-increment count value. @@ -122,8 +114,10 @@ class G1CardCounts: public CHeapObj { // Clears the card counts for the cards spanned by the region void clear_region(HeapRegion* hr); + // Clears the card counts for the cards spanned by the MemRegion + void clear_range(MemRegion mr); + // Clear the entire card counts table during GC. - // Updates the policy stats with the duration. void clear_all(); }; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 326cf049fe4..da2f34fdd62 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -45,12 +45,13 @@ #include "gc_implementation/g1/g1MarkSweep.hpp" #include "gc_implementation/g1/g1OopClosures.inline.hpp" #include "gc_implementation/g1/g1ParScanThreadState.inline.hpp" +#include "gc_implementation/g1/g1RegionToSpaceMapper.hpp" #include "gc_implementation/g1/g1RemSet.inline.hpp" #include "gc_implementation/g1/g1StringDedup.hpp" #include "gc_implementation/g1/g1YCTypes.hpp" #include "gc_implementation/g1/heapRegion.inline.hpp" #include "gc_implementation/g1/heapRegionRemSet.hpp" -#include "gc_implementation/g1/heapRegionSeq.inline.hpp" +#include "gc_implementation/g1/heapRegionSet.inline.hpp" #include "gc_implementation/g1/vm_operations_g1.hpp" #include "gc_implementation/shared/gcHeapSummary.hpp" #include "gc_implementation/shared/gcTimer.hpp" @@ -381,6 +382,14 @@ void YoungList::print() { gclog_or_tty->cr(); } +void G1RegionMappingChangedListener::reset_from_card_cache(uint start_idx, size_t num_regions) { + OtherRegionsTable::invalidate(start_idx, num_regions); +} + +void G1RegionMappingChangedListener::on_commit(uint start_idx, size_t num_regions) { + reset_from_card_cache(start_idx, num_regions); +} + void G1CollectedHeap::push_dirty_cards_region(HeapRegion* hr) { // Claim the right to put the region on the dirty cards region list @@ -523,9 +532,9 @@ G1CollectedHeap::new_region_try_secondary_free_list(bool is_old) { // again to allocate from it. append_secondary_free_list(); - assert(!_free_list.is_empty(), "if the secondary_free_list was not " + assert(_hrs.num_free_regions() > 0, "if the secondary_free_list was not " "empty we should have moved at least one entry to the free_list"); - HeapRegion* res = _free_list.remove_region(is_old); + HeapRegion* res = _hrs.allocate_free_region(is_old); if (G1ConcRegionFreeingVerbose) { gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : " "allocated "HR_FORMAT" from secondary_free_list", @@ -566,7 +575,7 @@ HeapRegion* G1CollectedHeap::new_region(size_t word_size, bool is_old, bool do_e } } - res = _free_list.remove_region(is_old); + res = _hrs.allocate_free_region(is_old); if (res == NULL) { if (G1ConcRegionFreeingVerbose) { @@ -591,8 +600,8 @@ HeapRegion* G1CollectedHeap::new_region(size_t word_size, bool is_old, bool do_e // Given that expand() succeeded in expanding the heap, and we // always expand the heap by an amount aligned to the heap // region size, the free list should in theory not be empty. - // In either case remove_region() will check for NULL. - res = _free_list.remove_region(is_old); + // In either case allocate_free_region() will check for NULL. + res = _hrs.allocate_free_region(is_old); } else { _expand_heap_after_alloc_failure = false; } @@ -600,55 +609,11 @@ HeapRegion* G1CollectedHeap::new_region(size_t word_size, bool is_old, bool do_e return res; } -uint G1CollectedHeap::humongous_obj_allocate_find_first(uint num_regions, - size_t word_size) { - assert(isHumongous(word_size), "word_size should be humongous"); - assert(num_regions * HeapRegion::GrainWords >= word_size, "pre-condition"); - - uint first = G1_NULL_HRS_INDEX; - if (num_regions == 1) { - // Only one region to allocate, no need to go through the slower - // path. The caller will attempt the expansion if this fails, so - // let's not try to expand here too. - HeapRegion* hr = new_region(word_size, true /* is_old */, false /* do_expand */); - if (hr != NULL) { - first = hr->hrs_index(); - } else { - first = G1_NULL_HRS_INDEX; - } - } else { - // We can't allocate humongous regions while cleanupComplete() is - // running, since some of the regions we find to be empty might not - // yet be added to the free list and it is not straightforward to - // know which list they are on so that we can remove them. Note - // that we only need to do this if we need to allocate more than - // one region to satisfy the current humongous allocation - // request. If we are only allocating one region we use the common - // region allocation code (see above). - wait_while_free_regions_coming(); - append_secondary_free_list_if_not_empty_with_lock(); - - if (free_regions() >= num_regions) { - first = _hrs.find_contiguous(num_regions); - if (first != G1_NULL_HRS_INDEX) { - for (uint i = first; i < first + num_regions; ++i) { - HeapRegion* hr = region_at(i); - assert(hr->is_empty(), "sanity"); - assert(is_on_master_free_list(hr), "sanity"); - hr->set_pending_removal(true); - } - _free_list.remove_all_pending(num_regions); - } - } - } - return first; -} - HeapWord* G1CollectedHeap::humongous_obj_allocate_initialize_regions(uint first, uint num_regions, size_t word_size) { - assert(first != G1_NULL_HRS_INDEX, "pre-condition"); + assert(first != G1_NO_HRS_INDEX, "pre-condition"); assert(isHumongous(word_size), "word_size should be humongous"); assert(num_regions * HeapRegion::GrainWords >= word_size, "pre-condition"); @@ -786,42 +751,70 @@ HeapWord* G1CollectedHeap::humongous_obj_allocate(size_t word_size) { verify_region_sets_optional(); - size_t word_size_rounded = round_to(word_size, HeapRegion::GrainWords); - uint num_regions = (uint) (word_size_rounded / HeapRegion::GrainWords); - uint x_num = expansion_regions(); - uint fs = _hrs.free_suffix(); - uint first = humongous_obj_allocate_find_first(num_regions, word_size); - if (first == G1_NULL_HRS_INDEX) { - // The only thing we can do now is attempt expansion. - if (fs + x_num >= num_regions) { - // If the number of regions we're trying to allocate for this - // object is at most the number of regions in the free suffix, - // then the call to humongous_obj_allocate_find_first() above - // should have succeeded and we wouldn't be here. - // - // We should only be trying to expand when the free suffix is - // not sufficient for the object _and_ we have some expansion - // room available. - assert(num_regions > fs, "earlier allocation should have succeeded"); + uint first = G1_NO_HRS_INDEX; + uint obj_regions = (uint)(align_size_up_(word_size, HeapRegion::GrainWords) / HeapRegion::GrainWords); + if (obj_regions == 1) { + // Only one region to allocate, try to use a fast path by directly allocating + // from the free lists. Do not try to expand here, we will potentially do that + // later. + HeapRegion* hr = new_region(word_size, true /* is_old */, false /* do_expand */); + if (hr != NULL) { + first = hr->hrs_index(); + } + } else { + // We can't allocate humongous regions spanning more than one region while + // cleanupComplete() is running, since some of the regions we find to be + // empty might not yet be added to the free list. It is not straightforward + // to know in which list they are on so that we can remove them. We only + // need to do this if we need to allocate more than one region to satisfy the + // current humongous allocation request. If we are only allocating one region + // we use the one-region region allocation code (see above), that already + // potentially waits for regions from the secondary free list. + wait_while_free_regions_coming(); + append_secondary_free_list_if_not_empty_with_lock(); + + // Policy: Try only empty regions (i.e. already committed first). Maybe we + // are lucky enough to find some. + first = _hrs.find_contiguous_only_empty(obj_regions); + if (first != G1_NO_HRS_INDEX) { + _hrs.allocate_free_regions_starting_at(first, obj_regions); + } + } + + if (first == G1_NO_HRS_INDEX) { + // Policy: We could not find enough regions for the humongous object in the + // free list. Look through the heap to find a mix of free and uncommitted regions. + // If so, try expansion. + first = _hrs.find_contiguous_empty_or_unavailable(obj_regions); + if (first != G1_NO_HRS_INDEX) { + // We found something. Make sure these regions are committed, i.e. expand + // the heap. Alternatively we could do a defragmentation GC. ergo_verbose1(ErgoHeapSizing, "attempt heap expansion", ergo_format_reason("humongous allocation request failed") ergo_format_byte("allocation request"), word_size * HeapWordSize); - if (expand((num_regions - fs) * HeapRegion::GrainBytes)) { - // Even though the heap was expanded, it might not have - // reached the desired size. So, we cannot assume that the - // allocation will succeed. - first = humongous_obj_allocate_find_first(num_regions, word_size); + + _hrs.expand_at(first, obj_regions); + g1_policy()->record_new_heap_size(num_regions()); + +#ifdef ASSERT + for (uint i = first; i < first + obj_regions; ++i) { + HeapRegion* hr = region_at(i); + assert(hr->is_empty(), "sanity"); + assert(is_on_master_free_list(hr), "sanity"); } +#endif + _hrs.allocate_free_regions_starting_at(first, obj_regions); + } else { + // Policy: Potentially trigger a defragmentation GC. } } HeapWord* result = NULL; - if (first != G1_NULL_HRS_INDEX) { - result = - humongous_obj_allocate_initialize_regions(first, num_regions, word_size); + if (first != G1_NO_HRS_INDEX) { + result = humongous_obj_allocate_initialize_regions(first, obj_regions, word_size); assert(result != NULL, "it should always return a valid result"); // A successful humongous object allocation changes the used space @@ -1384,7 +1377,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, G1MarkSweep::invoke_at_safepoint(ref_processor_stw(), do_clear_all_soft_refs); } - assert(free_regions() == 0, "we should not have added any free regions"); + assert(num_free_regions() == 0, "we should not have added any free regions"); rebuild_region_sets(false /* free_list_only */); // Enqueue any discovered reference objects that have @@ -1749,21 +1742,6 @@ HeapWord* G1CollectedHeap::expand_and_allocate(size_t word_size) { return NULL; } -void G1CollectedHeap::update_committed_space(HeapWord* old_end, - HeapWord* new_end) { - assert(old_end != new_end, "don't call this otherwise"); - assert((HeapWord*) _g1_storage.high() == new_end, "invariant"); - - // Update the committed mem region. - _g1_committed.set_end(new_end); - // Tell the card table about the update. - Universe::heap()->barrier_set()->resize_covered_region(_g1_committed); - // Tell the BOT about the update. - _bot_shared->resize(_g1_committed.word_size()); - // Tell the hot card cache about the update - _cg1r->hot_card_cache()->resize_card_counts(capacity()); -} - bool G1CollectedHeap::expand(size_t expand_bytes) { size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes); aligned_expand_bytes = align_size_up(aligned_expand_bytes, @@ -1774,55 +1752,22 @@ bool G1CollectedHeap::expand(size_t expand_bytes) { ergo_format_byte("attempted expansion amount"), expand_bytes, aligned_expand_bytes); - if (_g1_storage.uncommitted_size() == 0) { + if (is_maximal_no_gc()) { ergo_verbose0(ErgoHeapSizing, "did not expand the heap", ergo_format_reason("heap already fully expanded")); return false; } - // First commit the memory. - HeapWord* old_end = (HeapWord*) _g1_storage.high(); - bool successful = _g1_storage.expand_by(aligned_expand_bytes); - if (successful) { - // Then propagate this update to the necessary data structures. - HeapWord* new_end = (HeapWord*) _g1_storage.high(); - update_committed_space(old_end, new_end); + uint regions_to_expand = (uint)(aligned_expand_bytes / HeapRegion::GrainBytes); + assert(regions_to_expand > 0, "Must expand by at least one region"); - FreeRegionList expansion_list("Local Expansion List"); - MemRegion mr = _hrs.expand_by(old_end, new_end, &expansion_list); - assert(mr.start() == old_end, "post-condition"); - // mr might be a smaller region than what was requested if - // expand_by() was unable to allocate the HeapRegion instances - assert(mr.end() <= new_end, "post-condition"); + uint expanded_by = _hrs.expand_by(regions_to_expand); - size_t actual_expand_bytes = mr.byte_size(); + if (expanded_by > 0) { + size_t actual_expand_bytes = expanded_by * HeapRegion::GrainBytes; assert(actual_expand_bytes <= aligned_expand_bytes, "post-condition"); - assert(actual_expand_bytes == expansion_list.total_capacity_bytes(), - "post-condition"); - if (actual_expand_bytes < aligned_expand_bytes) { - // We could not expand _hrs to the desired size. In this case we - // need to shrink the committed space accordingly. - assert(mr.end() < new_end, "invariant"); - - size_t diff_bytes = aligned_expand_bytes - actual_expand_bytes; - // First uncommit the memory. - _g1_storage.shrink_by(diff_bytes); - // Then propagate this update to the necessary data structures. - update_committed_space(new_end, mr.end()); - } - _free_list.add_as_tail(&expansion_list); - - if (_hr_printer.is_active()) { - HeapWord* curr = mr.start(); - while (curr < mr.end()) { - HeapWord* curr_end = curr + HeapRegion::GrainWords; - _hr_printer.commit(curr, curr_end); - curr = curr_end; - } - assert(curr == mr.end(), "post-condition"); - } - g1_policy()->record_new_heap_size(n_regions()); + g1_policy()->record_new_heap_size(num_regions()); } else { ergo_verbose0(ErgoHeapSizing, "did not expand the heap", @@ -1830,12 +1775,12 @@ bool G1CollectedHeap::expand(size_t expand_bytes) { // The expansion of the virtual storage space was unsuccessful. // Let's see if it was because we ran out of swap. if (G1ExitOnExpansionFailure && - _g1_storage.uncommitted_size() >= aligned_expand_bytes) { + _hrs.available() >= regions_to_expand) { // We had head room... vm_exit_out_of_memory(aligned_expand_bytes, OOM_MMAP_ERROR, "G1 heap expansion"); } } - return successful; + return regions_to_expand > 0; } void G1CollectedHeap::shrink_helper(size_t shrink_bytes) { @@ -1846,7 +1791,6 @@ void G1CollectedHeap::shrink_helper(size_t shrink_bytes) { uint num_regions_to_remove = (uint)(shrink_bytes / HeapRegion::GrainBytes); uint num_regions_removed = _hrs.shrink_by(num_regions_to_remove); - HeapWord* old_end = (HeapWord*) _g1_storage.high(); size_t shrunk_bytes = num_regions_removed * HeapRegion::GrainBytes; ergo_verbose3(ErgoHeapSizing, @@ -1856,22 +1800,7 @@ void G1CollectedHeap::shrink_helper(size_t shrink_bytes) { ergo_format_byte("attempted shrinking amount"), shrink_bytes, aligned_shrink_bytes, shrunk_bytes); if (num_regions_removed > 0) { - _g1_storage.shrink_by(shrunk_bytes); - HeapWord* new_end = (HeapWord*) _g1_storage.high(); - - if (_hr_printer.is_active()) { - HeapWord* curr = old_end; - while (curr > new_end) { - HeapWord* curr_end = curr; - curr -= HeapRegion::GrainWords; - _hr_printer.uncommit(curr, curr_end); - } - } - - _expansion_regions += num_regions_removed; - update_committed_space(old_end, new_end); - HeapRegionRemSet::shrink_heap(n_regions()); - g1_policy()->record_new_heap_size(n_regions()); + g1_policy()->record_new_heap_size(num_regions()); } else { ergo_verbose0(ErgoHeapSizing, "did not shrink the heap", @@ -1922,7 +1851,6 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) : _g1mm(NULL), _refine_cte_cl(NULL), _full_collection(false), - _free_list("Master Free List", new MasterFreeRegionListMtSafeChecker()), _secondary_free_list("Secondary Free List", new SecondaryFreeRegionListMtSafeChecker()), _old_set("Old Set", false /* humongous */, new OldRegionSetMtSafeChecker()), _humongous_set("Master Humongous Set", true /* humongous */, new HumongousRegionSetMtSafeChecker()), @@ -2036,8 +1964,6 @@ jint G1CollectedHeap::initialize() { _reserved.set_start((HeapWord*)heap_rs.base()); _reserved.set_end((HeapWord*)(heap_rs.base() + heap_rs.size())); - _expansion_regions = (uint) (max_byte_size / HeapRegion::GrainBytes); - // Create the gen rem set (and barrier set) for the entire reserved region. _rem_set = collector_policy()->create_rem_set(_reserved, 2); set_barrier_set(rem_set()->bs()); @@ -2051,20 +1977,65 @@ jint G1CollectedHeap::initialize() { // Carve out the G1 part of the heap. - ReservedSpace g1_rs = heap_rs.first_part(max_byte_size); - _g1_reserved = MemRegion((HeapWord*)g1_rs.base(), - g1_rs.size()/HeapWordSize); + ReservedSpace g1_rs = heap_rs.first_part(max_byte_size); + G1RegionToSpaceMapper* heap_storage = + G1RegionToSpaceMapper::create_mapper(g1_rs, + UseLargePages ? os::large_page_size() : os::vm_page_size(), + HeapRegion::GrainBytes, + 1, + mtJavaHeap); + heap_storage->set_mapping_changed_listener(&_listener); - _g1_storage.initialize(g1_rs, 0); - _g1_committed = MemRegion((HeapWord*)_g1_storage.low(), (size_t) 0); - _hrs.initialize((HeapWord*) _g1_reserved.start(), - (HeapWord*) _g1_reserved.end()); - assert(_hrs.max_length() == _expansion_regions, - err_msg("max length: %u expansion regions: %u", - _hrs.max_length(), _expansion_regions)); + // Reserve space for the block offset table. We do not support automatic uncommit + // for the card table at this time. BOT only. + ReservedSpace bot_rs(G1BlockOffsetSharedArray::compute_size(g1_rs.size() / HeapWordSize)); + G1RegionToSpaceMapper* bot_storage = + G1RegionToSpaceMapper::create_mapper(bot_rs, + os::vm_page_size(), + HeapRegion::GrainBytes, + G1BlockOffsetSharedArray::N_bytes, + mtGC); - // Do later initialization work for concurrent refinement. - _cg1r->init(); + ReservedSpace cardtable_rs(G1SATBCardTableLoggingModRefBS::compute_size(g1_rs.size() / HeapWordSize)); + G1RegionToSpaceMapper* cardtable_storage = + G1RegionToSpaceMapper::create_mapper(cardtable_rs, + os::vm_page_size(), + HeapRegion::GrainBytes, + G1BlockOffsetSharedArray::N_bytes, + mtGC); + + // Reserve space for the card counts table. + ReservedSpace card_counts_rs(G1BlockOffsetSharedArray::compute_size(g1_rs.size() / HeapWordSize)); + G1RegionToSpaceMapper* card_counts_storage = + G1RegionToSpaceMapper::create_mapper(card_counts_rs, + os::vm_page_size(), + HeapRegion::GrainBytes, + G1BlockOffsetSharedArray::N_bytes, + mtGC); + + // Reserve space for prev and next bitmap. + size_t bitmap_size = CMBitMap::compute_size(g1_rs.size()); + + ReservedSpace prev_bitmap_rs(ReservedSpace::allocation_align_size_up(bitmap_size)); + G1RegionToSpaceMapper* prev_bitmap_storage = + G1RegionToSpaceMapper::create_mapper(prev_bitmap_rs, + os::vm_page_size(), + HeapRegion::GrainBytes, + CMBitMap::mark_distance(), + mtGC); + + ReservedSpace next_bitmap_rs(ReservedSpace::allocation_align_size_up(bitmap_size)); + G1RegionToSpaceMapper* next_bitmap_storage = + G1RegionToSpaceMapper::create_mapper(next_bitmap_rs, + os::vm_page_size(), + HeapRegion::GrainBytes, + CMBitMap::mark_distance(), + mtGC); + + _hrs.initialize(heap_storage, prev_bitmap_storage, next_bitmap_storage, bot_storage, cardtable_storage, card_counts_storage); + g1_barrier_set()->initialize(cardtable_storage); + // Do later initialization work for concurrent refinement. + _cg1r->init(card_counts_storage); // 6843694 - ensure that the maximum region index can fit // in the remembered set structures. @@ -2078,17 +2049,16 @@ jint G1CollectedHeap::initialize() { FreeRegionList::set_unrealistically_long_length(max_regions() + 1); - _bot_shared = new G1BlockOffsetSharedArray(_reserved, - heap_word_size(init_byte_size)); + _bot_shared = new G1BlockOffsetSharedArray(_reserved, bot_storage); _g1h = this; - _in_cset_fast_test.initialize(_g1_reserved.start(), _g1_reserved.end(), HeapRegion::GrainBytes); - _humongous_is_live.initialize(_g1_reserved.start(), _g1_reserved.end(), HeapRegion::GrainBytes); + _in_cset_fast_test.initialize(_hrs.reserved().start(), _hrs.reserved().end(), HeapRegion::GrainBytes); + _humongous_is_live.initialize(_hrs.reserved().start(), _hrs.reserved().end(), HeapRegion::GrainBytes); // Create the ConcurrentMark data structure and thread. // (Must do this late, so that "max_regions" is defined.) - _cm = new ConcurrentMark(this, heap_rs); + _cm = new ConcurrentMark(this, prev_bitmap_storage, next_bitmap_storage); if (_cm == NULL || !_cm->completed_initialization()) { vm_shutdown_during_initialization("Could not create/initialize ConcurrentMark"); return JNI_ENOMEM; @@ -2143,12 +2113,10 @@ jint G1CollectedHeap::initialize() { // counts and that mechanism. SpecializationStats::clear(); - // Here we allocate the dummy full region that is required by the - // G1AllocRegion class. If we don't pass an address in the reserved - // space here, lots of asserts fire. + // Here we allocate the dummy HeapRegion that is required by the + // G1AllocRegion class. + HeapRegion* dummy_region = _hrs.get_dummy_region(); - HeapRegion* dummy_region = new_heap_region(0 /* index of bottom region */, - _g1_reserved.start()); // We'll re-use the same region whether the alloc region will // require BOT updates or not and, if it doesn't, then a non-young // region will complain that it cannot support allocations without @@ -2264,7 +2232,7 @@ void G1CollectedHeap::ref_processing_init() { } size_t G1CollectedHeap::capacity() const { - return _g1_committed.byte_size(); + return _hrs.length() * HeapRegion::GrainBytes; } void G1CollectedHeap::reset_gc_time_stamps(HeapRegion* hr) { @@ -2548,7 +2516,7 @@ void G1CollectedHeap::collect(GCCause::Cause cause) { } } } else { - if (cause == GCCause::_gc_locker + if (cause == GCCause::_gc_locker || cause == GCCause::_wb_young_gc DEBUG_ONLY(|| cause == GCCause::_scavenge_alot)) { // Schedule a standard evacuation pause. We're setting word_size @@ -2569,8 +2537,8 @@ void G1CollectedHeap::collect(GCCause::Cause cause) { } bool G1CollectedHeap::is_in(const void* p) const { - if (_g1_committed.contains(p)) { - // Given that we know that p is in the committed space, + if (_hrs.reserved().contains(p)) { + // Given that we know that p is in the reserved space, // heap_region_containing_raw() should successfully // return the containing region. HeapRegion* hr = heap_region_containing_raw(p); @@ -2580,6 +2548,18 @@ bool G1CollectedHeap::is_in(const void* p) const { } } +#ifdef ASSERT +bool G1CollectedHeap::is_in_exact(const void* p) const { + bool contains = reserved_region().contains(p); + bool available = _hrs.is_available(addr_to_region((HeapWord*)p)); + if (contains && available) { + return true; + } else { + return false; + } +} +#endif + // Iteration functions. // Applies an ExtendedOopClosure onto all references of objects within a HeapRegion. @@ -2644,83 +2624,9 @@ void G1CollectedHeap::heap_region_iterate(HeapRegionClosure* cl) const { void G1CollectedHeap::heap_region_par_iterate_chunked(HeapRegionClosure* cl, uint worker_id, - uint no_of_par_workers, - jint claim_value) { - const uint regions = n_regions(); - const uint max_workers = (G1CollectedHeap::use_parallel_gc_threads() ? - no_of_par_workers : - 1); - assert(UseDynamicNumberOfGCThreads || - no_of_par_workers == workers()->total_workers(), - "Non dynamic should use fixed number of workers"); - // try to spread out the starting points of the workers - const HeapRegion* start_hr = - start_region_for_worker(worker_id, no_of_par_workers); - const uint start_index = start_hr->hrs_index(); - - // each worker will actually look at all regions - for (uint count = 0; count < regions; ++count) { - const uint index = (start_index + count) % regions; - assert(0 <= index && index < regions, "sanity"); - HeapRegion* r = region_at(index); - // we'll ignore "continues humongous" regions (we'll process them - // when we come across their corresponding "start humongous" - // region) and regions already claimed - if (r->claim_value() == claim_value || r->continuesHumongous()) { - continue; - } - // OK, try to claim it - if (r->claimHeapRegion(claim_value)) { - // success! - assert(!r->continuesHumongous(), "sanity"); - if (r->startsHumongous()) { - // If the region is "starts humongous" we'll iterate over its - // "continues humongous" first; in fact we'll do them - // first. The order is important. In on case, calling the - // closure on the "starts humongous" region might de-allocate - // and clear all its "continues humongous" regions and, as a - // result, we might end up processing them twice. So, we'll do - // them first (notice: most closures will ignore them anyway) and - // then we'll do the "starts humongous" region. - for (uint ch_index = index + 1; ch_index < regions; ++ch_index) { - HeapRegion* chr = region_at(ch_index); - - // if the region has already been claimed or it's not - // "continues humongous" we're done - if (chr->claim_value() == claim_value || - !chr->continuesHumongous()) { - break; - } - - // No one should have claimed it directly. We can given - // that we claimed its "starts humongous" region. - assert(chr->claim_value() != claim_value, "sanity"); - assert(chr->humongous_start_region() == r, "sanity"); - - if (chr->claimHeapRegion(claim_value)) { - // we should always be able to claim it; no one else should - // be trying to claim this region - - bool res2 = cl->doHeapRegion(chr); - assert(!res2, "Should not abort"); - - // Right now, this holds (i.e., no closure that actually - // does something with "continues humongous" regions - // clears them). We might have to weaken it in the future, - // but let's leave these two asserts here for extra safety. - assert(chr->continuesHumongous(), "should still be the case"); - assert(chr->humongous_start_region() == r, "sanity"); - } else { - guarantee(false, "we should not reach here"); - } - } - } - - assert(!r->continuesHumongous(), "sanity"); - bool res = cl->doHeapRegion(r); - assert(!res, "Should not abort"); - } - } + uint num_workers, + jint claim_value) const { + _hrs.par_iterate(cl, worker_id, num_workers, claim_value); } class ResetClaimValuesClosure: public HeapRegionClosure { @@ -2898,17 +2804,6 @@ HeapRegion* G1CollectedHeap::start_cset_region_for_worker(uint worker_i) { return result; } -HeapRegion* G1CollectedHeap::start_region_for_worker(uint worker_i, - uint no_of_par_workers) { - uint worker_num = - G1CollectedHeap::use_parallel_gc_threads() ? no_of_par_workers : 1U; - assert(UseDynamicNumberOfGCThreads || - no_of_par_workers == workers()->total_workers(), - "Non dynamic should use fixed number of workers"); - const uint start_index = n_regions() * worker_i / worker_num; - return region_at(start_index); -} - void G1CollectedHeap::collection_set_iterate(HeapRegionClosure* cl) { HeapRegion* r = g1_policy()->collection_set(); while (r != NULL) { @@ -2951,15 +2846,11 @@ void G1CollectedHeap::collection_set_iterate_from(HeapRegion* r, } HeapRegion* G1CollectedHeap::next_compaction_region(const HeapRegion* from) const { - // We're not using an iterator given that it will wrap around when - // it reaches the last region and this is not what we want here. - for (uint index = from->hrs_index() + 1; index < n_regions(); index++) { - HeapRegion* hr = region_at(index); - if (!hr->isHumongous()) { - return hr; - } + HeapRegion* result = _hrs.next_region_in_heap(from); + while (result != NULL && result->isHumongous()) { + result = _hrs.next_region_in_heap(result); } - return NULL; + return result; } Space* G1CollectedHeap::space_containing(const void* addr) const { @@ -3017,7 +2908,7 @@ size_t G1CollectedHeap::unsafe_max_tlab_alloc(Thread* ignored) const { } size_t G1CollectedHeap::max_capacity() const { - return _g1_reserved.byte_size(); + return _hrs.reserved().byte_size(); } jlong G1CollectedHeap::millis_since_last_gc() { @@ -3546,9 +3437,9 @@ void G1CollectedHeap::print_on(outputStream* st) const { st->print(" total " SIZE_FORMAT "K, used " SIZE_FORMAT "K", capacity()/K, used_unlocked()/K); st->print(" [" INTPTR_FORMAT ", " INTPTR_FORMAT ", " INTPTR_FORMAT ")", - _g1_storage.low_boundary(), - _g1_storage.high(), - _g1_storage.high_boundary()); + _hrs.reserved().start(), + _hrs.reserved().start() + _hrs.length() + HeapRegion::GrainWords, + _hrs.reserved().end()); st->cr(); st->print(" region size " SIZE_FORMAT "K, ", HeapRegion::GrainBytes / K); uint young_regions = _young_list->length(); @@ -4239,10 +4130,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { // No need for an ergo verbose message here, // expansion_amount() does this when it returns a value > 0. if (!expand(expand_bytes)) { - // We failed to expand the heap so let's verify that - // committed/uncommitted amount match the backing store - assert(capacity() == _g1_storage.committed_size(), "committed size mismatch"); - assert(max_capacity() == _g1_storage.reserved_size(), "reserved size mismatch"); + // We failed to expand the heap. Cannot do anything about it. } } } @@ -4302,10 +4190,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { // RETIRE events are generated before the end GC event. _hr_printer.end_gc(false /* full */, (size_t) total_collections()); - if (mark_in_progress()) { - concurrent_mark()->update_g1_committed(); - } - #ifdef TRACESPINNING ParallelTaskTerminator::print_termination_counts(); #endif @@ -6140,6 +6024,7 @@ void G1CollectedHeap::free_region(HeapRegion* hr, bool locked) { assert(!hr->isHumongous(), "this is only for non-humongous regions"); assert(!hr->is_empty(), "the region should not be empty"); + assert(_hrs.is_available(hr->hrs_index()), "region should be committed"); assert(free_list != NULL, "pre-condition"); if (G1VerifyBitmaps) { @@ -6194,7 +6079,7 @@ void G1CollectedHeap::prepend_to_freelist(FreeRegionList* list) { assert(list != NULL, "list can't be null"); if (!list->is_empty()) { MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag); - _free_list.add_ordered(list); + _hrs.insert_list_into_free_list(list); } } @@ -6802,22 +6687,22 @@ void G1CollectedHeap::tear_down_region_sets(bool free_list_only) { // this is that during a full GC string deduplication needs to know if // a collected region was young or old when the full GC was initiated. } - _free_list.remove_all(); + _hrs.remove_all_free_regions(); } class RebuildRegionSetsClosure : public HeapRegionClosure { private: bool _free_list_only; HeapRegionSet* _old_set; - FreeRegionList* _free_list; + HeapRegionSeq* _hrs; size_t _total_used; public: RebuildRegionSetsClosure(bool free_list_only, - HeapRegionSet* old_set, FreeRegionList* free_list) : + HeapRegionSet* old_set, HeapRegionSeq* hrs) : _free_list_only(free_list_only), - _old_set(old_set), _free_list(free_list), _total_used(0) { - assert(_free_list->is_empty(), "pre-condition"); + _old_set(old_set), _hrs(hrs), _total_used(0) { + assert(_hrs->num_free_regions() == 0, "pre-condition"); if (!free_list_only) { assert(_old_set->is_empty(), "pre-condition"); } @@ -6830,7 +6715,7 @@ public: if (r->is_empty()) { // Add free regions to the free list - _free_list->add_as_tail(r); + _hrs->insert_into_free_list(r); } else if (!_free_list_only) { assert(!r->is_young(), "we should not come across young regions"); @@ -6858,7 +6743,7 @@ void G1CollectedHeap::rebuild_region_sets(bool free_list_only) { _young_list->empty_list(); } - RebuildRegionSetsClosure cl(free_list_only, &_old_set, &_free_list); + RebuildRegionSetsClosure cl(free_list_only, &_old_set, &_hrs); heap_region_iterate(&cl); if (!free_list_only) { @@ -7013,13 +6898,42 @@ void OldGCAllocRegion::retire_region(HeapRegion* alloc_region, _g1h->retire_gc_alloc_region(alloc_region, allocated_bytes, GCAllocForTenured); } + +HeapRegion* OldGCAllocRegion::release() { + HeapRegion* cur = get(); + if (cur != NULL) { + // Determine how far we are from the next card boundary. If it is smaller than + // the minimum object size we can allocate into, expand into the next card. + HeapWord* top = cur->top(); + HeapWord* aligned_top = (HeapWord*)align_ptr_up(top, G1BlockOffsetSharedArray::N_bytes); + + size_t to_allocate_words = pointer_delta(aligned_top, top, HeapWordSize); + + if (to_allocate_words != 0) { + // We are not at a card boundary. Fill up, possibly into the next, taking the + // end of the region and the minimum object size into account. + to_allocate_words = MIN2(pointer_delta(cur->end(), cur->top(), HeapWordSize), + MAX2(to_allocate_words, G1CollectedHeap::min_fill_size())); + + // Skip allocation if there is not enough space to allocate even the smallest + // possible object. In this case this region will not be retained, so the + // original problem cannot occur. + if (to_allocate_words >= G1CollectedHeap::min_fill_size()) { + HeapWord* dummy = attempt_allocation(to_allocate_words, true /* bot_updates */); + CollectedHeap::fill_with_object(dummy, to_allocate_words); + } + } + } + return G1AllocRegion::release(); +} + // Heap region set verification class VerifyRegionListsClosure : public HeapRegionClosure { private: HeapRegionSet* _old_set; HeapRegionSet* _humongous_set; - FreeRegionList* _free_list; + HeapRegionSeq* _hrs; public: HeapRegionSetCount _old_count; @@ -7028,8 +6942,8 @@ public: VerifyRegionListsClosure(HeapRegionSet* old_set, HeapRegionSet* humongous_set, - FreeRegionList* free_list) : - _old_set(old_set), _humongous_set(humongous_set), _free_list(free_list), + HeapRegionSeq* hrs) : + _old_set(old_set), _humongous_set(humongous_set), _hrs(hrs), _old_count(), _humongous_count(), _free_count(){ } bool doHeapRegion(HeapRegion* hr) { @@ -7043,7 +6957,7 @@ public: assert(hr->containing_set() == _humongous_set, err_msg("Heap region %u is starts humongous but not in humongous set.", hr->hrs_index())); _humongous_count.increment(1u, hr->capacity()); } else if (hr->is_empty()) { - assert(hr->containing_set() == _free_list, err_msg("Heap region %u is empty but not on the free list.", hr->hrs_index())); + assert(_hrs->is_free(hr), err_msg("Heap region %u is empty but not on the free list.", hr->hrs_index())); _free_count.increment(1u, hr->capacity()); } else { assert(hr->containing_set() == _old_set, err_msg("Heap region %u is old but not in the old set.", hr->hrs_index())); @@ -7052,7 +6966,7 @@ public: return false; } - void verify_counts(HeapRegionSet* old_set, HeapRegionSet* humongous_set, FreeRegionList* free_list) { + void verify_counts(HeapRegionSet* old_set, HeapRegionSet* humongous_set, HeapRegionSeq* free_list) { guarantee(old_set->length() == _old_count.length(), err_msg("Old set count mismatch. Expected %u, actual %u.", old_set->length(), _old_count.length())); guarantee(old_set->total_capacity_bytes() == _old_count.capacity(), err_msg("Old set capacity mismatch. Expected " SIZE_FORMAT ", actual " SIZE_FORMAT, old_set->total_capacity_bytes(), _old_count.capacity())); @@ -7061,26 +6975,17 @@ public: guarantee(humongous_set->total_capacity_bytes() == _humongous_count.capacity(), err_msg("Hum set capacity mismatch. Expected " SIZE_FORMAT ", actual " SIZE_FORMAT, humongous_set->total_capacity_bytes(), _humongous_count.capacity())); - guarantee(free_list->length() == _free_count.length(), err_msg("Free list count mismatch. Expected %u, actual %u.", free_list->length(), _free_count.length())); + guarantee(free_list->num_free_regions() == _free_count.length(), err_msg("Free list count mismatch. Expected %u, actual %u.", free_list->num_free_regions(), _free_count.length())); guarantee(free_list->total_capacity_bytes() == _free_count.capacity(), err_msg("Free list capacity mismatch. Expected " SIZE_FORMAT ", actual " SIZE_FORMAT, free_list->total_capacity_bytes(), _free_count.capacity())); } }; -HeapRegion* G1CollectedHeap::new_heap_region(uint hrs_index, - HeapWord* bottom) { - HeapWord* end = bottom + HeapRegion::GrainWords; - MemRegion mr(bottom, end); - assert(_g1_reserved.contains(mr), "invariant"); - // This might return NULL if the allocation fails - return new HeapRegion(hrs_index, _bot_shared, mr); -} - void G1CollectedHeap::verify_region_sets() { assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */); // First, check the explicit lists. - _free_list.verify_list(); + _hrs.verify(); { // Given that a concurrent operation might be adding regions to // the secondary free list we have to take the lock before @@ -7111,9 +7016,9 @@ void G1CollectedHeap::verify_region_sets() { // Finally, make sure that the region accounting in the lists is // consistent with what we see in the heap. - VerifyRegionListsClosure cl(&_old_set, &_humongous_set, &_free_list); + VerifyRegionListsClosure cl(&_old_set, &_humongous_set, &_hrs); heap_region_iterate(&cl); - cl.verify_counts(&_old_set, &_humongous_set, &_free_list); + cl.verify_counts(&_old_set, &_humongous_set, &_hrs); } // Optimized nmethod scanning diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index ae00d56ae42..34667c1162c 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -183,6 +183,13 @@ protected: public: OldGCAllocRegion() : G1AllocRegion("Old GC Alloc Region", true /* bot_updates */) { } + + // This specialization of release() makes sure that the last card that has been + // allocated into has been completely filled by a dummy object. + // This avoids races when remembered set scanning wants to update the BOT of the + // last card in the retained old gc alloc region, and allocation threads + // allocating into that card at the same time. + virtual HeapRegion* release(); }; // The G1 STW is alive closure. @@ -199,6 +206,13 @@ public: class RefineCardTableEntryClosure; +class G1RegionMappingChangedListener : public G1MappingChangedListener { + private: + void reset_from_card_cache(uint start_idx, size_t num_regions); + public: + virtual void on_commit(uint start_idx, size_t num_regions); +}; + class G1CollectedHeap : public SharedHeap { friend class VM_CollectForMetadataAllocation; friend class VM_G1CollectForAllocation; @@ -237,19 +251,9 @@ private: static size_t _humongous_object_threshold_in_words; - // Storage for the G1 heap. - VirtualSpace _g1_storage; - MemRegion _g1_reserved; - - // The part of _g1_storage that is currently committed. - MemRegion _g1_committed; - - // The master free list. It will satisfy all new region allocations. - FreeRegionList _free_list; - // The secondary free list which contains regions that have been - // freed up during the cleanup process. This will be appended to the - // master free list when appropriate. + // freed up during the cleanup process. This will be appended to + // the master free list when appropriate. FreeRegionList _secondary_free_list; // It keeps track of the old regions. @@ -283,6 +287,9 @@ private: // after heap shrinking (free_list_only == true). void rebuild_region_sets(bool free_list_only); + // Callback for region mapping changed events. + G1RegionMappingChangedListener _listener; + // The sequence of all heap regions in the heap. HeapRegionSeq _hrs; @@ -513,14 +520,6 @@ protected: // humongous object, set is_old to true. If not, to false. HeapRegion* new_region(size_t word_size, bool is_old, bool do_expand); - // Attempt to satisfy a humongous allocation request of the given - // size by finding a contiguous set of free regions of num_regions - // length and remove them from the master free list. Return the - // index of the first region or G1_NULL_HRS_INDEX if the search - // was unsuccessful. - uint humongous_obj_allocate_find_first(uint num_regions, - size_t word_size); - // Initialize a contiguous set of free regions of length num_regions // and starting at index first so that they appear as a single // humongous region. @@ -862,11 +861,6 @@ protected: CodeBlobClosure* scan_strong_code, uint worker_i); - // Notifies all the necessary spaces that the committed space has - // been updated (either expanded or shrunk). It should be called - // after _g1_storage is updated. - void update_committed_space(HeapWord* old_end, HeapWord* new_end); - // The concurrent marker (and the thread it runs in.) ConcurrentMark* _cm; ConcurrentMarkThread* _cmThread; @@ -1177,27 +1171,20 @@ public: // But G1CollectedHeap doesn't yet support this. virtual bool is_maximal_no_gc() const { - return _g1_storage.uncommitted_size() == 0; + return _hrs.available() == 0; } - // The total number of regions in the heap. - uint n_regions() const { return _hrs.length(); } + // The current number of regions in the heap. + uint num_regions() const { return _hrs.length(); } // The max number of regions in the heap. uint max_regions() const { return _hrs.max_length(); } // The number of regions that are completely free. - uint free_regions() const { return _free_list.length(); } + uint num_free_regions() const { return _hrs.num_free_regions(); } // The number of regions that are not completely free. - uint used_regions() const { return n_regions() - free_regions(); } - - // The number of regions available for "regular" expansion. - uint expansion_regions() const { return _expansion_regions; } - - // Factory method for HeapRegion instances. It will return NULL if - // the allocation fails. - HeapRegion* new_heap_region(uint hrs_index, HeapWord* bottom); + uint num_used_regions() const { return num_regions() - num_free_regions(); } void verify_not_dirty_region(HeapRegion* hr) PRODUCT_RETURN; void verify_dirty_region(HeapRegion* hr) PRODUCT_RETURN; @@ -1246,7 +1233,7 @@ public: #ifdef ASSERT bool is_on_master_free_list(HeapRegion* hr) { - return hr->containing_set() == &_free_list; + return _hrs.is_free(hr); } #endif // ASSERT @@ -1258,7 +1245,7 @@ public: } void append_secondary_free_list() { - _free_list.add_ordered(&_secondary_free_list); + _hrs.insert_list_into_free_list(&_secondary_free_list); } void append_secondary_free_list_if_not_empty_with_lock() { @@ -1304,6 +1291,11 @@ public: // Returns "TRUE" iff "p" points into the committed areas of the heap. virtual bool is_in(const void* p) const; +#ifdef ASSERT + // Returns whether p is in one of the available areas of the heap. Slow but + // extensive version. + bool is_in_exact(const void* p) const; +#endif // Return "TRUE" iff the given object address is within the collection // set. Slow implementation. @@ -1364,25 +1356,19 @@ public: // Return "TRUE" iff the given object address is in the reserved // region of g1. bool is_in_g1_reserved(const void* p) const { - return _g1_reserved.contains(p); + return _hrs.reserved().contains(p); } // Returns a MemRegion that corresponds to the space that has been // reserved for the heap - MemRegion g1_reserved() { - return _g1_reserved; - } - - // Returns a MemRegion that corresponds to the space that has been - // committed in the heap - MemRegion g1_committed() { - return _g1_committed; + MemRegion g1_reserved() const { + return _hrs.reserved(); } virtual bool is_in_closed_subset(const void* p) const; - G1SATBCardTableModRefBS* g1_barrier_set() { - return (G1SATBCardTableModRefBS*) barrier_set(); + G1SATBCardTableLoggingModRefBS* g1_barrier_set() { + return (G1SATBCardTableLoggingModRefBS*) barrier_set(); } // This resets the card table to all zeros. It is used after @@ -1416,6 +1402,8 @@ public: // within the heap. inline uint addr_to_region(HeapWord* addr) const; + inline HeapWord* bottom_addr_for_region(uint index) const; + // Divide the heap region sequence into "chunks" of some size (the number // of regions divided by the number of parallel threads times some // overpartition factor, currently 4). Assumes that this will be called @@ -1429,10 +1417,10 @@ public: // setting the claim value of the second and subsequent regions of the // chunk.) For now requires that "doHeapRegion" always returns "false", // i.e., that a closure never attempt to abort a traversal. - void heap_region_par_iterate_chunked(HeapRegionClosure* blk, - uint worker, - uint no_of_par_workers, - jint claim_value); + void heap_region_par_iterate_chunked(HeapRegionClosure* cl, + uint worker_id, + uint num_workers, + jint claim_value) const; // It resets all the region claim values to the default. void reset_heap_region_claim_values(); @@ -1457,11 +1445,6 @@ public: // starting region for iterating over the current collection set. HeapRegion* start_cset_region_for_worker(uint worker_i); - // This is a convenience method that is used by the - // HeapRegionIterator classes to calculate the starting region for - // each worker so that they do not all start from the same region. - HeapRegion* start_region_for_worker(uint worker_i, uint no_of_par_workers); - // Iterate over the regions (if any) in the current collection set. void collection_set_iterate(HeapRegionClosure* blk); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp index 2ea0cba679a..f0efb2eb191 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp @@ -47,19 +47,21 @@ inline uint G1CollectedHeap::addr_to_region(HeapWord* addr) const { return (uint)(pointer_delta(addr, _reserved.start(), sizeof(uint8_t)) >> HeapRegion::LogOfHRGrainBytes); } +inline HeapWord* G1CollectedHeap::bottom_addr_for_region(uint index) const { + return _hrs.reserved().start() + index * HeapRegion::GrainWords; +} + template -inline HeapRegion* -G1CollectedHeap::heap_region_containing_raw(const T addr) const { +inline HeapRegion* G1CollectedHeap::heap_region_containing_raw(const T addr) const { assert(addr != NULL, "invariant"); - assert(_g1_reserved.contains((const void*) addr), + assert(is_in_g1_reserved((const void*) addr), err_msg("Address "PTR_FORMAT" is outside of the heap ranging from ["PTR_FORMAT" to "PTR_FORMAT")", - p2i((void*)addr), p2i(_g1_reserved.start()), p2i(_g1_reserved.end()))); + p2i((void*)addr), p2i(g1_reserved().start()), p2i(g1_reserved().end()))); return _hrs.addr_to_region((HeapWord*) addr); } template -inline HeapRegion* -G1CollectedHeap::heap_region_containing(const T addr) const { +inline HeapRegion* G1CollectedHeap::heap_region_containing(const T addr) const { HeapRegion* hr = heap_region_containing_raw(addr); if (hr->continuesHumongous()) { return hr->humongous_start_region(); @@ -89,10 +91,9 @@ inline bool G1CollectedHeap::obj_in_cs(oop obj) { return r != NULL && r->in_collection_set(); } -inline HeapWord* -G1CollectedHeap::attempt_allocation(size_t word_size, - unsigned int* gc_count_before_ret, - int* gclocker_retry_count_ret) { +inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size, + unsigned int* gc_count_before_ret, + int* gclocker_retry_count_ret) { assert_heap_not_locked_and_not_at_safepoint(); assert(!isHumongous(word_size), "attempt_allocation() should not " "be called for humongous allocation requests"); @@ -252,8 +253,7 @@ G1CollectedHeap::set_evacuation_failure_alot_for_current_gc() { } } -inline bool -G1CollectedHeap::evacuation_should_fail() { +inline bool G1CollectedHeap::evacuation_should_fail() { if (!G1EvacuationFailureALot || !_evacuation_failure_alot_for_current_gc) { return false; } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index eba482046fd..931c4e3d25e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -456,7 +456,7 @@ void G1CollectorPolicy::init() { } else { _young_list_fixed_length = _young_gen_sizer->min_desired_young_length(); } - _free_regions_at_end_of_collection = _g1->free_regions(); + _free_regions_at_end_of_collection = _g1->num_free_regions(); update_young_list_target_length(); // We may immediately start allocating regions and placing them on the @@ -829,7 +829,7 @@ void G1CollectorPolicy::record_full_collection_end() { record_survivor_regions(0, NULL, NULL); - _free_regions_at_end_of_collection = _g1->free_regions(); + _free_regions_at_end_of_collection = _g1->num_free_regions(); // Reset survivors SurvRateGroup. _survivor_surv_rate_group->reset(); update_young_list_target_length(); @@ -1181,7 +1181,7 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, Evacua _in_marking_window = new_in_marking_window; _in_marking_window_im = new_in_marking_window_im; - _free_regions_at_end_of_collection = _g1->free_regions(); + _free_regions_at_end_of_collection = _g1->num_free_regions(); update_young_list_target_length(); // Note that _mmu_tracker->max_gc_time() returns the time in seconds. @@ -1203,7 +1203,7 @@ void G1CollectorPolicy::record_heap_size_info_at_start(bool full) { _survivor_used_bytes_before_gc = young_list->survivor_used_bytes(); _heap_capacity_bytes_before_gc = _g1->capacity(); _heap_used_bytes_before_gc = _g1->used(); - _cur_collection_pause_used_regions_at_start = _g1->used_regions(); + _cur_collection_pause_used_regions_at_start = _g1->num_used_regions(); _eden_capacity_bytes_before_gc = (_young_list_target_length * HeapRegion::GrainBytes) - _survivor_used_bytes_before_gc; @@ -1618,7 +1618,7 @@ void G1CollectorPolicy::record_concurrent_mark_cleanup_end(int no_of_gc_threads) { _collectionSetChooser->clear(); - uint region_num = _g1->n_regions(); + uint region_num = _g1->num_regions(); if (G1CollectedHeap::use_parallel_gc_threads()) { const uint OverpartitionFactor = 4; uint WorkUnit; @@ -1639,7 +1639,7 @@ G1CollectorPolicy::record_concurrent_mark_cleanup_end(int no_of_gc_threads) { MAX2(region_num / (uint) (ParallelGCThreads * OverpartitionFactor), MinWorkUnit); } - _collectionSetChooser->prepare_for_par_region_addition(_g1->n_regions(), + _collectionSetChooser->prepare_for_par_region_addition(_g1->num_regions(), WorkUnit); ParKnownGarbageTask parKnownGarbageTask(_collectionSetChooser, (int) WorkUnit); @@ -1936,7 +1936,7 @@ uint G1CollectorPolicy::calc_max_old_cset_length() { // of them are available. G1CollectedHeap* g1h = G1CollectedHeap::heap(); - const size_t region_num = g1h->n_regions(); + const size_t region_num = g1h->num_regions(); const size_t perc = (size_t) G1OldCSetRegionThresholdPercent; size_t result = region_num * perc / 100; // emulate ceiling diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp index a75ba66e06f..79655933da7 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp @@ -33,7 +33,7 @@ G1HotCardCache::G1HotCardCache(G1CollectedHeap *g1h): _g1h(g1h), _hot_cache(NULL), _use_cache(false), _card_counts(g1h) {} -void G1HotCardCache::initialize() { +void G1HotCardCache::initialize(G1RegionToSpaceMapper* card_counts_storage) { if (default_use_cache()) { _use_cache = true; @@ -49,7 +49,7 @@ void G1HotCardCache::initialize() { _hot_cache_par_chunk_size = MAX2(1, _hot_cache_size / (int)n_workers); _hot_cache_par_claimed_idx = 0; - _card_counts.initialize(); + _card_counts.initialize(card_counts_storage); } } @@ -135,11 +135,8 @@ void G1HotCardCache::drain(uint worker_i, // above, are discarded prior to re-enabling the cache near the end of the GC. } -void G1HotCardCache::resize_card_counts(size_t heap_capacity) { - _card_counts.resize(heap_capacity); -} - void G1HotCardCache::reset_card_counts(HeapRegion* hr) { + assert(!hr->isHumongous(), "Should have been cleared"); _card_counts.clear_region(hr); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.hpp index 5dc929c25e2..becd6832769 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.hpp @@ -78,7 +78,7 @@ class G1HotCardCache: public CHeapObj { G1HotCardCache(G1CollectedHeap* g1h); ~G1HotCardCache(); - void initialize(); + void initialize(G1RegionToSpaceMapper* card_counts_storage); bool use_cache() { return _use_cache; } @@ -115,9 +115,6 @@ class G1HotCardCache: public CHeapObj { bool hot_cache_is_empty() { return _n_hot == 0; } - // Resizes the card counts table to match the given capacity - void resize_card_counts(size_t heap_capacity); - // Zeros the values in the card counts table for entire committed heap void reset_card_counts(); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp new file mode 100644 index 00000000000..1b294edffed --- /dev/null +++ b/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2014, 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. + * + */ + +#include "precompiled.hpp" +#include "gc_implementation/g1/g1PageBasedVirtualSpace.hpp" +#include "oops/markOop.hpp" +#include "oops/oop.inline.hpp" +#include "services/memTracker.hpp" +#ifdef TARGET_OS_FAMILY_linux +# include "os_linux.inline.hpp" +#endif +#ifdef TARGET_OS_FAMILY_solaris +# include "os_solaris.inline.hpp" +#endif +#ifdef TARGET_OS_FAMILY_windows +# include "os_windows.inline.hpp" +#endif +#ifdef TARGET_OS_FAMILY_aix +# include "os_aix.inline.hpp" +#endif +#ifdef TARGET_OS_FAMILY_bsd +# include "os_bsd.inline.hpp" +#endif +#include "utilities/bitMap.inline.hpp" + +G1PageBasedVirtualSpace::G1PageBasedVirtualSpace() : _low_boundary(NULL), + _high_boundary(NULL), _committed(), _page_size(0), _special(false), _executable(false) { +} + +bool G1PageBasedVirtualSpace::initialize_with_granularity(ReservedSpace rs, size_t page_size) { + if (!rs.is_reserved()) { + return false; // Allocation failed. + } + assert(_low_boundary == NULL, "VirtualSpace already initialized"); + assert(page_size > 0, "Granularity must be non-zero."); + + _low_boundary = rs.base(); + _high_boundary = _low_boundary + rs.size(); + + _special = rs.special(); + _executable = rs.executable(); + + _page_size = page_size; + + assert(_committed.size() == 0, "virtual space initialized more than once"); + uintx size_in_bits = rs.size() / page_size; + _committed.resize(size_in_bits, /* in_resource_area */ false); + + return true; +} + + +G1PageBasedVirtualSpace::~G1PageBasedVirtualSpace() { + release(); +} + +void G1PageBasedVirtualSpace::release() { + // This does not release memory it never reserved. + // Caller must release via rs.release(); + _low_boundary = NULL; + _high_boundary = NULL; + _special = false; + _executable = false; + _page_size = 0; + _committed.resize(0, false); +} + +size_t G1PageBasedVirtualSpace::committed_size() const { + return _committed.count_one_bits() * _page_size; +} + +size_t G1PageBasedVirtualSpace::reserved_size() const { + return pointer_delta(_high_boundary, _low_boundary, sizeof(char)); +} + +size_t G1PageBasedVirtualSpace::uncommitted_size() const { + return reserved_size() - committed_size(); +} + +uintptr_t G1PageBasedVirtualSpace::addr_to_page_index(char* addr) const { + return (addr - _low_boundary) / _page_size; +} + +bool G1PageBasedVirtualSpace::is_area_committed(uintptr_t start, size_t size_in_pages) const { + uintptr_t end = start + size_in_pages; + return _committed.get_next_zero_offset(start, end) >= end; +} + +bool G1PageBasedVirtualSpace::is_area_uncommitted(uintptr_t start, size_t size_in_pages) const { + uintptr_t end = start + size_in_pages; + return _committed.get_next_one_offset(start, end) >= end; +} + +char* G1PageBasedVirtualSpace::page_start(uintptr_t index) { + return _low_boundary + index * _page_size; +} + +size_t G1PageBasedVirtualSpace::byte_size_for_pages(size_t num) { + return num * _page_size; +} + +MemRegion G1PageBasedVirtualSpace::commit(uintptr_t start, size_t size_in_pages) { + // We need to make sure to commit all pages covered by the given area. + guarantee(is_area_uncommitted(start, size_in_pages), "Specified area is not uncommitted"); + + if (!_special) { + os::commit_memory_or_exit(page_start(start), byte_size_for_pages(size_in_pages), _executable, + err_msg("Failed to commit pages from "SIZE_FORMAT" of length "SIZE_FORMAT, start, size_in_pages)); + } + _committed.set_range(start, start + size_in_pages); + + MemRegion result((HeapWord*)page_start(start), byte_size_for_pages(size_in_pages) / HeapWordSize); + return result; +} + +MemRegion G1PageBasedVirtualSpace::uncommit(uintptr_t start, size_t size_in_pages) { + guarantee(is_area_committed(start, size_in_pages), "checking"); + + if (!_special) { + os::uncommit_memory(page_start(start), byte_size_for_pages(size_in_pages)); + } + + _committed.clear_range(start, start + size_in_pages); + + MemRegion result((HeapWord*)page_start(start), byte_size_for_pages(size_in_pages) / HeapWordSize); + return result; +} + +bool G1PageBasedVirtualSpace::contains(const void* p) const { + return _low_boundary <= (const char*) p && (const char*) p < _high_boundary; +} + +#ifndef PRODUCT +void G1PageBasedVirtualSpace::print_on(outputStream* out) { + out->print ("Virtual space:"); + if (special()) out->print(" (pinned in memory)"); + out->cr(); + out->print_cr(" - committed: " SIZE_FORMAT, committed_size()); + out->print_cr(" - reserved: " SIZE_FORMAT, reserved_size()); + out->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", p2i(_low_boundary), p2i(_high_boundary)); +} + +void G1PageBasedVirtualSpace::print() { + print_on(tty); +} +#endif diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp new file mode 100644 index 00000000000..972a69b2e8f --- /dev/null +++ b/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2014, 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. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1PAGEBASEDVIRTUALSPACE_HPP +#define SHARE_VM_GC_IMPLEMENTATION_G1_G1PAGEBASEDVIRTUALSPACE_HPP + +#include "memory/allocation.hpp" +#include "memory/memRegion.hpp" +#include "runtime/virtualspace.hpp" +#include "utilities/bitMap.hpp" + +// Virtual space management helper for a virtual space with an OS page allocation +// granularity. +// (De-)Allocation requests are always OS page aligned by passing a page index +// and multiples of pages. +// The implementation gives an error when trying to commit or uncommit pages that +// have already been committed or uncommitted. +class G1PageBasedVirtualSpace VALUE_OBJ_CLASS_SPEC { + friend class VMStructs; + private: + // Reserved area addresses. + char* _low_boundary; + char* _high_boundary; + + // The commit/uncommit granularity in bytes. + size_t _page_size; + + // Bitmap used for verification of commit/uncommit operations. + BitMap _committed; + + // Indicates that the entire space has been committed and pinned in memory, + // os::commit_memory() or os::uncommit_memory() have no function. + bool _special; + + // Indicates whether the committed space should be executable. + bool _executable; + + // Returns the index of the page which contains the given address. + uintptr_t addr_to_page_index(char* addr) const; + // Returns the address of the given page index. + char* page_start(uintptr_t index); + // Returns the byte size of the given number of pages. + size_t byte_size_for_pages(size_t num); + + // Returns true if the entire area is backed by committed memory. + bool is_area_committed(uintptr_t start, size_t size_in_pages) const; + // Returns true if the entire area is not backed by committed memory. + bool is_area_uncommitted(uintptr_t start, size_t size_in_pages) const; + + public: + + // Commit the given area of pages starting at start being size_in_pages large. + MemRegion commit(uintptr_t start, size_t size_in_pages); + + // Uncommit the given area of pages starting at start being size_in_pages large. + MemRegion uncommit(uintptr_t start, size_t size_in_pages); + + bool special() const { return _special; } + + // Initialization + G1PageBasedVirtualSpace(); + bool initialize_with_granularity(ReservedSpace rs, size_t page_size); + + // Destruction + ~G1PageBasedVirtualSpace(); + + // Amount of reserved memory. + size_t reserved_size() const; + // Memory used in this virtual space. + size_t committed_size() const; + // Memory left to use/expand in this virtual space. + size_t uncommitted_size() const; + + bool contains(const void* p) const; + + MemRegion reserved() { + MemRegion x((HeapWord*)_low_boundary, reserved_size() / HeapWordSize); + return x; + } + + void release(); + + void check_for_contiguity() PRODUCT_RETURN; + + // Debugging + void print_on(outputStream* out) PRODUCT_RETURN; + void print(); +}; + +#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1PAGEBASEDVIRTUALSPACE_HPP diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp new file mode 100644 index 00000000000..da0976ca99b --- /dev/null +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2001, 2013, 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. + * + */ + +#include "precompiled.hpp" +#include "gc_implementation/g1/g1BiasedArray.hpp" +#include "gc_implementation/g1/g1RegionToSpaceMapper.hpp" +#include "memory/allocation.inline.hpp" +#include "runtime/virtualspace.hpp" +#include "services/memTracker.hpp" +#include "utilities/bitMap.inline.hpp" + +G1RegionToSpaceMapper::G1RegionToSpaceMapper(ReservedSpace rs, + size_t commit_granularity, + size_t region_granularity, + MemoryType type) : + _storage(), + _commit_granularity(commit_granularity), + _region_granularity(region_granularity), + _listener(NULL), + _commit_map() { + guarantee(is_power_of_2(commit_granularity), "must be"); + guarantee(is_power_of_2(region_granularity), "must be"); + _storage.initialize_with_granularity(rs, commit_granularity); + + MemTracker::record_virtual_memory_type((address)rs.base(), type); +} + +// G1RegionToSpaceMapper implementation where the region granularity is larger than +// or the same as the commit granularity. +// Basically, the space corresponding to one region region spans several OS pages. +class G1RegionsLargerThanCommitSizeMapper : public G1RegionToSpaceMapper { + private: + size_t _pages_per_region; + + public: + G1RegionsLargerThanCommitSizeMapper(ReservedSpace rs, + size_t os_commit_granularity, + size_t alloc_granularity, + size_t commit_factor, + MemoryType type) : + G1RegionToSpaceMapper(rs, os_commit_granularity, alloc_granularity, type), + _pages_per_region(alloc_granularity / (os_commit_granularity * commit_factor)) { + + guarantee(alloc_granularity >= os_commit_granularity, "allocation granularity smaller than commit granularity"); + _commit_map.resize(rs.size() * commit_factor / alloc_granularity, /* in_resource_area */ false); + } + + virtual void commit_regions(uintptr_t start_idx, size_t num_regions) { + _storage.commit(start_idx * _pages_per_region, num_regions * _pages_per_region); + _commit_map.set_range(start_idx, start_idx + num_regions); + fire_on_commit(start_idx, num_regions); + } + + virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions) { + _storage.uncommit(start_idx * _pages_per_region, num_regions * _pages_per_region); + _commit_map.clear_range(start_idx, start_idx + num_regions); + } +}; + +// G1RegionToSpaceMapper implementation where the region granularity is smaller +// than the commit granularity. +// Basically, the contents of one OS page span several regions. +class G1RegionsSmallerThanCommitSizeMapper : public G1RegionToSpaceMapper { + private: + class CommitRefcountArray : public G1BiasedMappedArray { + protected: + virtual uint default_value() const { return 0; } + }; + + size_t _regions_per_page; + + CommitRefcountArray _refcounts; + + uintptr_t region_idx_to_page_idx(uint region) const { + return region / _regions_per_page; + } + + public: + G1RegionsSmallerThanCommitSizeMapper(ReservedSpace rs, + size_t os_commit_granularity, + size_t alloc_granularity, + size_t commit_factor, + MemoryType type) : + G1RegionToSpaceMapper(rs, os_commit_granularity, alloc_granularity, type), + _regions_per_page((os_commit_granularity * commit_factor) / alloc_granularity), _refcounts() { + + guarantee((os_commit_granularity * commit_factor) >= alloc_granularity, "allocation granularity smaller than commit granularity"); + _refcounts.initialize((HeapWord*)rs.base(), (HeapWord*)(rs.base() + rs.size()), os_commit_granularity); + _commit_map.resize(rs.size() * commit_factor / alloc_granularity, /* in_resource_area */ false); + } + + virtual void commit_regions(uintptr_t start_idx, size_t num_regions) { + for (uintptr_t i = start_idx; i < start_idx + num_regions; i++) { + assert(!_commit_map.at(i), err_msg("Trying to commit storage at region "INTPTR_FORMAT" that is already committed", i)); + uintptr_t idx = region_idx_to_page_idx(i); + uint old_refcount = _refcounts.get_by_index(idx); + if (old_refcount == 0) { + _storage.commit(idx, 1); + } + _refcounts.set_by_index(idx, old_refcount + 1); + _commit_map.set_bit(i); + fire_on_commit(i, 1); + } + } + + virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions) { + for (uintptr_t i = start_idx; i < start_idx + num_regions; i++) { + assert(_commit_map.at(i), err_msg("Trying to uncommit storage at region "INTPTR_FORMAT" that is not committed", i)); + uintptr_t idx = region_idx_to_page_idx(i); + uint old_refcount = _refcounts.get_by_index(idx); + assert(old_refcount > 0, "must be"); + if (old_refcount == 1) { + _storage.uncommit(idx, 1); + } + _refcounts.set_by_index(idx, old_refcount - 1); + _commit_map.clear_bit(i); + } + } +}; + +void G1RegionToSpaceMapper::fire_on_commit(uint start_idx, size_t num_regions) { + if (_listener != NULL) { + _listener->on_commit(start_idx, num_regions); + } +} + +G1RegionToSpaceMapper* G1RegionToSpaceMapper::create_mapper(ReservedSpace rs, + size_t os_commit_granularity, + size_t region_granularity, + size_t commit_factor, + MemoryType type) { + + if (region_granularity >= (os_commit_granularity * commit_factor)) { + return new G1RegionsLargerThanCommitSizeMapper(rs, os_commit_granularity, region_granularity, commit_factor, type); + } else { + return new G1RegionsSmallerThanCommitSizeMapper(rs, os_commit_granularity, region_granularity, commit_factor, type); + } +} diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.hpp new file mode 100644 index 00000000000..5f614b7a866 --- /dev/null +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.hpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014, 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. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1REGIONTOSPACEMAPPER_HPP +#define SHARE_VM_GC_IMPLEMENTATION_G1_G1REGIONTOSPACEMAPPER_HPP + +#include "gc_implementation/g1/g1PageBasedVirtualSpace.hpp" +#include "memory/allocation.hpp" +#include "utilities/debug.hpp" + +class G1MappingChangedListener VALUE_OBJ_CLASS_SPEC { + public: + // Fired after commit of the memory, i.e. the memory this listener is registered + // for can be accessed. + virtual void on_commit(uint start_idx, size_t num_regions) = 0; +}; + +// Maps region based commit/uncommit requests to the underlying page sized virtual +// space. +class G1RegionToSpaceMapper : public CHeapObj { + private: + G1MappingChangedListener* _listener; + protected: + // Backing storage. + G1PageBasedVirtualSpace _storage; + size_t _commit_granularity; + size_t _region_granularity; + // Mapping management + BitMap _commit_map; + + G1RegionToSpaceMapper(ReservedSpace rs, size_t commit_granularity, size_t region_granularity, MemoryType type); + + void fire_on_commit(uint start_idx, size_t num_regions); + public: + MemRegion reserved() { return _storage.reserved(); } + + void set_mapping_changed_listener(G1MappingChangedListener* listener) { _listener = listener; } + + virtual ~G1RegionToSpaceMapper() { + _commit_map.resize(0, /* in_resource_area */ false); + } + + bool is_committed(uintptr_t idx) const { + return _commit_map.at(idx); + } + + virtual void commit_regions(uintptr_t start_idx, size_t num_regions = 1) = 0; + virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions = 1) = 0; + + // Creates an appropriate G1RegionToSpaceMapper for the given parameters. + // The byte_translation_factor defines how many bytes in a region correspond to + // a single byte in the data structure this mapper is for. + // Eg. in the card table, this value corresponds to the size a single card + // table entry corresponds to. + static G1RegionToSpaceMapper* create_mapper(ReservedSpace rs, + size_t os_commit_granularity, + size_t region_granularity, + size_t byte_translation_factor, + MemoryType type); +}; + +#endif /* SHARE_VM_GC_IMPLEMENTATION_G1_G1REGIONTOSPACEMAPPER_HPP */ diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp index 96f885a730c..c8e30f1d3b8 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp @@ -540,6 +540,12 @@ G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h, bool G1RemSet::refine_card(jbyte* card_ptr, uint worker_i, bool check_for_refs_into_cset) { + assert(_g1->is_in_exact(_ct_bs->addr_for(card_ptr)), + err_msg("Card at "PTR_FORMAT" index "SIZE_FORMAT" representing heap at "PTR_FORMAT" (%u) must be in committed heap", + p2i(card_ptr), + _ct_bs->index_for(_ct_bs->addr_for(card_ptr)), + _ct_bs->addr_for(card_ptr), + _g1->addr_to_region(_ct_bs->addr_for(card_ptr)))); // If the card is no longer dirty, nothing to do. if (*card_ptr != CardTableModRefBS::dirty_card_val()) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp index bcabcdd9bfa..2156577ea92 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" #include "gc_implementation/g1/heapRegion.hpp" #include "gc_implementation/g1/satbQueue.hpp" @@ -38,7 +39,6 @@ G1SATBCardTableModRefBS::G1SATBCardTableModRefBS(MemRegion whole_heap, _kind = G1SATBCT; } - void G1SATBCardTableModRefBS::enqueue(oop pre_val) { // Nulls should have been already filtered. assert(pre_val->is_oop(true), "Error"); @@ -125,13 +125,52 @@ void G1SATBCardTableModRefBS::verify_g1_young_region(MemRegion mr) { } #endif +void G1SATBCardTableLoggingModRefBSChangedListener::on_commit(uint start_idx, size_t num_regions) { + MemRegion mr(G1CollectedHeap::heap()->bottom_addr_for_region(start_idx), num_regions * HeapRegion::GrainWords); + _card_table->clear(mr); +} + G1SATBCardTableLoggingModRefBS:: G1SATBCardTableLoggingModRefBS(MemRegion whole_heap, int max_covered_regions) : G1SATBCardTableModRefBS(whole_heap, max_covered_regions), - _dcqs(JavaThread::dirty_card_queue_set()) + _dcqs(JavaThread::dirty_card_queue_set()), + _listener() { _kind = G1SATBCTLogging; + _listener.set_card_table(this); +} + +void G1SATBCardTableLoggingModRefBS::initialize(G1RegionToSpaceMapper* mapper) { + mapper->set_mapping_changed_listener(&_listener); + + _byte_map_size = mapper->reserved().byte_size(); + + _guard_index = cards_required(_whole_heap.word_size()) - 1; + _last_valid_index = _guard_index - 1; + + HeapWord* low_bound = _whole_heap.start(); + HeapWord* high_bound = _whole_heap.end(); + + _cur_covered_regions = 1; + _covered[0] = _whole_heap; + + _byte_map = (jbyte*) mapper->reserved().start(); + byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift); + assert(byte_for(low_bound) == &_byte_map[0], "Checking start of map"); + assert(byte_for(high_bound-1) <= &_byte_map[_last_valid_index], "Checking end of map"); + + if (TraceCardTableModRefBS) { + gclog_or_tty->print_cr("G1SATBCardTableModRefBS::G1SATBCardTableModRefBS: "); + gclog_or_tty->print_cr(" " + " &_byte_map[0]: " INTPTR_FORMAT + " &_byte_map[_last_valid_index]: " INTPTR_FORMAT, + p2i(&_byte_map[0]), + p2i(&_byte_map[_last_valid_index])); + gclog_or_tty->print_cr(" " + " byte_map_base: " INTPTR_FORMAT, + p2i(byte_map_base)); + } } void diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp index 3e612605c02..f02c28c227b 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1SATBCARDTABLEMODREFBS_HPP #define SHARE_VM_GC_IMPLEMENTATION_G1_G1SATBCARDTABLEMODREFBS_HPP +#include "gc_implementation/g1/g1RegionToSpaceMapper.hpp" #include "memory/cardTableModRefBS.hpp" #include "memory/memRegion.hpp" #include "oops/oop.inline.hpp" @@ -33,6 +34,7 @@ #if INCLUDE_ALL_GCS class DirtyCardQueueSet; +class G1SATBCardTableLoggingModRefBS; // This barrier is specialized to use a logging barrier to support // snapshot-at-the-beginning marking. @@ -126,18 +128,40 @@ public: jbyte val = _byte_map[card_index]; return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val(); } +}; +class G1SATBCardTableLoggingModRefBSChangedListener : public G1MappingChangedListener { + private: + G1SATBCardTableLoggingModRefBS* _card_table; + public: + G1SATBCardTableLoggingModRefBSChangedListener() : _card_table(NULL) { } + + void set_card_table(G1SATBCardTableLoggingModRefBS* card_table) { _card_table = card_table; } + + virtual void on_commit(uint start_idx, size_t num_regions); }; // Adds card-table logging to the post-barrier. // Usual invariant: all dirty cards are logged in the DirtyCardQueueSet. class G1SATBCardTableLoggingModRefBS: public G1SATBCardTableModRefBS { + friend class G1SATBCardTableLoggingModRefBSChangedListener; private: + G1SATBCardTableLoggingModRefBSChangedListener _listener; DirtyCardQueueSet& _dcqs; public: + static size_t compute_size(size_t mem_region_size_in_words) { + size_t number_of_slots = (mem_region_size_in_words / card_size_in_words); + return ReservedSpace::allocation_align_size_up(number_of_slots); + } + G1SATBCardTableLoggingModRefBS(MemRegion whole_heap, int max_covered_regions); + virtual void initialize() { } + virtual void initialize(G1RegionToSpaceMapper* mapper); + + virtual void resize_covered_region(MemRegion new_region) { ShouldNotReachHere(); } + bool is_a(BarrierSet::Name bsn) { return bsn == BarrierSet::G1SATBCTLogging || G1SATBCardTableModRefBS::is_a(bsn); @@ -154,8 +178,6 @@ class G1SATBCardTableLoggingModRefBS: public G1SATBCardTableModRefBS { void write_region_work(MemRegion mr) { invalidate(mr); } void write_ref_array_work(MemRegion mr) { invalidate(mr); } - - }; diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp index 524f2f315fb..ea10843e3ed 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp @@ -345,11 +345,6 @@ HeapWord* HeapRegion::next_block_start_careful(HeapWord* addr) { return low; } -#ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away -#pragma warning( disable:4355 ) // 'this' : used in base member initializer list -#endif // _MSC_VER - - HeapRegion::HeapRegion(uint hrs_index, G1BlockOffsetSharedArray* sharedOffsetArray, MemRegion mr) : @@ -361,7 +356,7 @@ HeapRegion::HeapRegion(uint hrs_index, _claimed(InitialClaimValue), _evacuation_failed(false), _prev_marked_bytes(0), _next_marked_bytes(0), _gc_efficiency(0.0), _young_type(NotYoung), _next_young_region(NULL), - _next_dirty_cards_region(NULL), _next(NULL), _prev(NULL), _pending_removal(false), + _next_dirty_cards_region(NULL), _next(NULL), _prev(NULL), #ifdef ASSERT _containing_set(NULL), #endif // ASSERT @@ -370,14 +365,20 @@ HeapRegion::HeapRegion(uint hrs_index, _predicted_bytes_to_copy(0) { _rem_set = new HeapRegionRemSet(sharedOffsetArray, this); + assert(HeapRegionRemSet::num_par_rem_sets() > 0, "Invariant."); + + initialize(mr); +} + +void HeapRegion::initialize(MemRegion mr, bool clear_space, bool mangle_space) { + assert(_rem_set->is_empty(), "Remembered set must be empty"); + + G1OffsetTableContigSpace::initialize(mr, clear_space, mangle_space); + _orig_end = mr.end(); - // Note that initialize() will set the start of the unmarked area of the - // region. hr_clear(false /*par*/, false /*clear_space*/); set_top(bottom()); record_top_and_timestamp(); - - assert(HeapRegionRemSet::num_par_rem_sets() > 0, "Invariant."); } CompactibleSpace* HeapRegion::next_compaction_space() const { @@ -905,7 +906,7 @@ void HeapRegion::verify(VerifyOption vo, } // If it returns false, verify_for_object() will output the - // appropriate messasge. + // appropriate message. if (do_bot_verify && !g1->is_obj_dead(obj, this) && !_offsets.verify_for_object(p, obj_size)) { @@ -1036,8 +1037,7 @@ void G1OffsetTableContigSpace::clear(bool mangle_space) { set_top(bottom()); set_saved_mark_word(bottom()); CompactibleSpace::clear(mangle_space); - _offsets.zero_bottom_entry(); - _offsets.initialize_threshold(); + reset_bot(); } void G1OffsetTableContigSpace::set_bottom(HeapWord* new_bottom) { @@ -1127,9 +1127,11 @@ G1OffsetTableContigSpace(G1BlockOffsetSharedArray* sharedOffsetArray, _gc_time_stamp(0) { _offsets.set_space(this); - // false ==> we'll do the clearing if there's clearing to be done. - CompactibleSpace::initialize(mr, false, SpaceDecorator::Mangle); - _top = bottom(); - _offsets.zero_bottom_entry(); - _offsets.initialize_threshold(); } + +void G1OffsetTableContigSpace::initialize(MemRegion mr, bool clear_space, bool mangle_space) { + CompactibleSpace::initialize(mr, clear_space, mangle_space); + _top = bottom(); + reset_bot(); +} + diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp index 42c9eac5431..7f6485b316c 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp @@ -62,7 +62,7 @@ class nmethod; p2i((_hr_)->bottom()), p2i((_hr_)->top()), p2i((_hr_)->end()) // sentinel value for hrs_index -#define G1_NULL_HRS_INDEX ((uint) -1) +#define G1_NO_HRS_INDEX ((uint) -1) // A dirty card to oop closure for heap regions. It // knows how to get the G1 heap and how to use the bitmap @@ -146,6 +146,9 @@ class G1OffsetTableContigSpace: public CompactibleSpace { HeapWord* top() const { return _top; } protected: + // Reset the G1OffsetTableContigSpace. + virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space); + HeapWord** top_addr() { return &_top; } // Allocation helpers (return NULL if full). inline HeapWord* allocate_impl(size_t word_size, HeapWord* end_value); @@ -200,8 +203,7 @@ class G1OffsetTableContigSpace: public CompactibleSpace { virtual void print() const; void reset_bot() { - _offsets.zero_bottom_entry(); - _offsets.initialize_threshold(); + _offsets.reset_bot(); } void update_bot_for_object(HeapWord* start, size_t word_size) { @@ -264,7 +266,6 @@ class HeapRegion: public G1OffsetTableContigSpace { #ifdef ASSERT HeapRegionSetBase* _containing_set; #endif // ASSERT - bool _pending_removal; // For parallel heapRegion traversal. jint _claimed; @@ -333,6 +334,12 @@ class HeapRegion: public G1OffsetTableContigSpace { G1BlockOffsetSharedArray* sharedOffsetArray, MemRegion mr); + // Initializing the HeapRegion not only resets the data structure, but also + // resets the BOT for that heap region. + // The default values for clear_space means that we will do the clearing if + // there's clearing to be done ourselves. We also always mangle the space. + virtual void initialize(MemRegion mr, bool clear_space = false, bool mangle_space = SpaceDecorator::Mangle); + static int LogOfHRGrainBytes; static int LogOfHRGrainWords; @@ -553,26 +560,6 @@ class HeapRegion: public G1OffsetTableContigSpace { // to provide a dummy version of it. #endif // ASSERT - // If we want to remove regions from a list in bulk we can simply tag - // them with the pending_removal tag and call the - // remove_all_pending() method on the list. - - bool pending_removal() { return _pending_removal; } - - void set_pending_removal(bool pending_removal) { - if (pending_removal) { - assert(!_pending_removal && containing_set() != NULL, - "can only set pending removal to true if it's false and " - "the region belongs to a region set"); - } else { - assert( _pending_removal && containing_set() == NULL, - "can only set pending removal to false if it's true and " - "the region does not belong to a region set"); - } - - _pending_removal = pending_removal; - } - HeapRegion* get_next_young_region() { return _next_young_region; } void set_next_young_region(HeapRegion* hr) { _next_young_region = hr; diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp index 5093327e997..21d70c33572 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp @@ -373,17 +373,17 @@ void FromCardCache::initialize(uint n_par_rs, uint max_num_regions) { _max_regions, &_static_mem_size); - for (uint i = 0; i < n_par_rs; i++) { - for (uint j = 0; j < _max_regions; j++) { - set(i, j, InvalidCard); - } - } + invalidate(0, _max_regions); } -void FromCardCache::shrink(uint new_num_regions) { +void FromCardCache::invalidate(uint start_idx, size_t new_num_regions) { + guarantee((size_t)start_idx + new_num_regions <= max_uintx, + err_msg("Trying to invalidate beyond maximum region, from %u size "SIZE_FORMAT, + start_idx, new_num_regions)); for (uint i = 0; i < HeapRegionRemSet::num_par_rem_sets(); i++) { - assert(new_num_regions <= _max_regions, "Must be within max."); - for (uint j = new_num_regions; j < _max_regions; j++) { + uint end_idx = (start_idx + (uint)new_num_regions); + assert(end_idx <= _max_regions, "Must be within max."); + for (uint j = start_idx; j < end_idx; j++) { set(i, j, InvalidCard); } } @@ -407,12 +407,12 @@ void FromCardCache::clear(uint region_idx) { } } -void OtherRegionsTable::init_from_card_cache(uint max_regions) { +void OtherRegionsTable::initialize(uint max_regions) { FromCardCache::initialize(HeapRegionRemSet::num_par_rem_sets(), max_regions); } -void OtherRegionsTable::shrink_from_card_cache(uint new_num_regions) { - FromCardCache::shrink(new_num_regions); +void OtherRegionsTable::invalidate(uint start_idx, size_t num_regions) { + FromCardCache::invalidate(start_idx, num_regions); } void OtherRegionsTable::print_from_card_cache() { @@ -841,7 +841,7 @@ HeapRegionRemSet::HeapRegionRemSet(G1BlockOffsetSharedArray* bosa, HeapRegion* hr) : _bosa(bosa), _m(Mutex::leaf, FormatBuffer<128>("HeapRegionRemSet lock #%u", hr->hrs_index()), true), - _code_roots(), _other_regions(hr, &_m) { + _code_roots(), _other_regions(hr, &_m), _iter_state(Unclaimed), _iter_claimed(0) { reset_for_par_iteration(); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp index 1ac1bb45f23..70eae9bdf2b 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp @@ -84,7 +84,7 @@ class FromCardCache : public AllStatic { static void initialize(uint n_par_rs, uint max_num_regions); - static void shrink(uint new_num_regions); + static void invalidate(uint start_idx, size_t num_regions); static void print(outputStream* out = gclog_or_tty) PRODUCT_RETURN; @@ -213,11 +213,11 @@ public: // Declare the heap size (in # of regions) to the OtherRegionsTable. // (Uses it to initialize from_card_cache). - static void init_from_card_cache(uint max_regions); + static void initialize(uint max_regions); - // Declares that only regions i s.t. 0 <= i < new_n_regs are in use. - // Make sure any entries for higher regions are invalid. - static void shrink_from_card_cache(uint new_num_regions); + // Declares that regions between start_idx <= i < start_idx + num_regions are + // not in use. Make sure that any entries for these regions are invalid. + static void invalidate(uint start_idx, size_t num_regions); static void print_from_card_cache(); }; @@ -400,12 +400,11 @@ public: // Declare the heap size (in # of regions) to the HeapRegionRemSet(s). // (Uses it to initialize from_card_cache). static void init_heap(uint max_regions) { - OtherRegionsTable::init_from_card_cache(max_regions); + OtherRegionsTable::initialize(max_regions); } - // Declares that only regions i s.t. 0 <= i < new_n_regs are in use. - static void shrink_heap(uint new_n_regs) { - OtherRegionsTable::shrink_from_card_cache(new_n_regs); + static void invalidate(uint start_idx, uint num_regions) { + OtherRegionsTable::invalidate(start_idx, num_regions); } #ifndef PRODUCT diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp index 04f48e60550..418d01a228b 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp @@ -25,236 +25,426 @@ #include "precompiled.hpp" #include "gc_implementation/g1/heapRegion.hpp" #include "gc_implementation/g1/heapRegionSeq.inline.hpp" -#include "gc_implementation/g1/heapRegionSet.hpp" +#include "gc_implementation/g1/heapRegionSet.inline.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" +#include "gc_implementation/g1/concurrentG1Refine.hpp" #include "memory/allocation.hpp" -// Private +void HeapRegionSeq::initialize(G1RegionToSpaceMapper* heap_storage, + G1RegionToSpaceMapper* prev_bitmap, + G1RegionToSpaceMapper* next_bitmap, + G1RegionToSpaceMapper* bot, + G1RegionToSpaceMapper* cardtable, + G1RegionToSpaceMapper* card_counts) { + _allocated_heapregions_length = 0; -uint HeapRegionSeq::find_contiguous_from(uint from, uint num) { - uint len = length(); - assert(num > 1, "use this only for sequences of length 2 or greater"); - assert(from <= len, - err_msg("from: %u should be valid and <= than %u", from, len)); + _heap_mapper = heap_storage; - uint curr = from; - uint first = G1_NULL_HRS_INDEX; - uint num_so_far = 0; - while (curr < len && num_so_far < num) { - if (at(curr)->is_empty()) { - if (first == G1_NULL_HRS_INDEX) { - first = curr; - num_so_far = 1; - } else { - num_so_far += 1; - } - } else { - first = G1_NULL_HRS_INDEX; - num_so_far = 0; + _prev_bitmap_mapper = prev_bitmap; + _next_bitmap_mapper = next_bitmap; + + _bot_mapper = bot; + _cardtable_mapper = cardtable; + + _card_counts_mapper = card_counts; + + MemRegion reserved = heap_storage->reserved(); + _regions.initialize(reserved.start(), reserved.end(), HeapRegion::GrainBytes); + + _available_map.resize(_regions.length(), false); + _available_map.clear(); +} + +bool HeapRegionSeq::is_available(uint region) const { + return _available_map.at(region); +} + +#ifdef ASSERT +bool HeapRegionSeq::is_free(HeapRegion* hr) const { + return _free_list.contains(hr); +} +#endif + +HeapRegion* HeapRegionSeq::new_heap_region(uint hrs_index) { + HeapWord* bottom = G1CollectedHeap::heap()->bottom_addr_for_region(hrs_index); + MemRegion mr(bottom, bottom + HeapRegion::GrainWords); + assert(reserved().contains(mr), "invariant"); + return new HeapRegion(hrs_index, G1CollectedHeap::heap()->bot_shared(), mr); +} + +void HeapRegionSeq::commit_regions(uint index, size_t num_regions) { + guarantee(num_regions > 0, "Must commit more than zero regions"); + guarantee(_num_committed + num_regions <= max_length(), "Cannot commit more than the maximum amount of regions"); + + _num_committed += (uint)num_regions; + + _heap_mapper->commit_regions(index, num_regions); + + // Also commit auxiliary data + _prev_bitmap_mapper->commit_regions(index, num_regions); + _next_bitmap_mapper->commit_regions(index, num_regions); + + _bot_mapper->commit_regions(index, num_regions); + _cardtable_mapper->commit_regions(index, num_regions); + + _card_counts_mapper->commit_regions(index, num_regions); +} + +void HeapRegionSeq::uncommit_regions(uint start, size_t num_regions) { + guarantee(num_regions >= 1, err_msg("Need to specify at least one region to uncommit, tried to uncommit zero regions at %u", start)); + guarantee(_num_committed >= num_regions, "pre-condition"); + + // Print before uncommitting. + if (G1CollectedHeap::heap()->hr_printer()->is_active()) { + for (uint i = start; i < start + num_regions; i++) { + HeapRegion* hr = at(i); + G1CollectedHeap::heap()->hr_printer()->uncommit(hr->bottom(), hr->end()); } - curr += 1; } - assert(num_so_far <= num, "post-condition"); - if (num_so_far == num) { - // we found enough space for the humongous object - assert(from <= first && first < len, "post-condition"); - assert(first < curr && (curr - first) == num, "post-condition"); - for (uint i = first; i < first + num; ++i) { - assert(at(i)->is_empty(), "post-condition"); + + _num_committed -= (uint)num_regions; + + _available_map.par_clear_range(start, start + num_regions, BitMap::unknown_range); + _heap_mapper->uncommit_regions(start, num_regions); + + // Also uncommit auxiliary data + _prev_bitmap_mapper->uncommit_regions(start, num_regions); + _next_bitmap_mapper->uncommit_regions(start, num_regions); + + _bot_mapper->uncommit_regions(start, num_regions); + _cardtable_mapper->uncommit_regions(start, num_regions); + + _card_counts_mapper->uncommit_regions(start, num_regions); +} + +void HeapRegionSeq::make_regions_available(uint start, uint num_regions) { + guarantee(num_regions > 0, "No point in calling this for zero regions"); + commit_regions(start, num_regions); + for (uint i = start; i < start + num_regions; i++) { + if (_regions.get_by_index(i) == NULL) { + HeapRegion* new_hr = new_heap_region(i); + _regions.set_by_index(i, new_hr); + _allocated_heapregions_length = MAX2(_allocated_heapregions_length, i + 1); } - return first; + } + + _available_map.par_set_range(start, start + num_regions, BitMap::unknown_range); + + for (uint i = start; i < start + num_regions; i++) { + assert(is_available(i), err_msg("Just made region %u available but is apparently not.", i)); + HeapRegion* hr = at(i); + if (G1CollectedHeap::heap()->hr_printer()->is_active()) { + G1CollectedHeap::heap()->hr_printer()->commit(hr->bottom(), hr->end()); + } + HeapWord* bottom = G1CollectedHeap::heap()->bottom_addr_for_region(i); + MemRegion mr(bottom, bottom + HeapRegion::GrainWords); + + hr->initialize(mr); + insert_into_free_list(at(i)); + } +} + +uint HeapRegionSeq::expand_by(uint num_regions) { + return expand_at(0, num_regions); +} + +uint HeapRegionSeq::expand_at(uint start, uint num_regions) { + if (num_regions == 0) { + return 0; + } + + uint cur = start; + uint idx_last_found = 0; + uint num_last_found = 0; + + uint expanded = 0; + + while (expanded < num_regions && + (num_last_found = find_unavailable_from_idx(cur, &idx_last_found)) > 0) { + uint to_expand = MIN2(num_regions - expanded, num_last_found); + make_regions_available(idx_last_found, to_expand); + expanded += to_expand; + cur = idx_last_found + num_last_found + 1; + } + + verify_optional(); + return expanded; +} + +uint HeapRegionSeq::find_contiguous(size_t num, bool empty_only) { + uint found = 0; + size_t length_found = 0; + uint cur = 0; + + while (length_found < num && cur < max_length()) { + HeapRegion* hr = _regions.get_by_index(cur); + if ((!empty_only && !is_available(cur)) || (is_available(cur) && hr != NULL && hr->is_empty())) { + // This region is a potential candidate for allocation into. + length_found++; + } else { + // This region is not a candidate. The next region is the next possible one. + found = cur + 1; + length_found = 0; + } + cur++; + } + + if (length_found == num) { + for (uint i = found; i < (found + num); i++) { + HeapRegion* hr = _regions.get_by_index(i); + // sanity check + guarantee((!empty_only && !is_available(i)) || (is_available(i) && hr != NULL && hr->is_empty()), + err_msg("Found region sequence starting at " UINT32_FORMAT ", length " SIZE_FORMAT + " that is not empty at " UINT32_FORMAT ". Hr is " PTR_FORMAT, found, num, i, p2i(hr))); + } + return found; } else { - // we failed to find enough space for the humongous object - return G1_NULL_HRS_INDEX; + return G1_NO_HRS_INDEX; } } -// Public - -void HeapRegionSeq::initialize(HeapWord* bottom, HeapWord* end) { - assert((uintptr_t) bottom % HeapRegion::GrainBytes == 0, - "bottom should be heap region aligned"); - assert((uintptr_t) end % HeapRegion::GrainBytes == 0, - "end should be heap region aligned"); - - _next_search_index = 0; - _allocated_length = 0; - - _regions.initialize(bottom, end, HeapRegion::GrainBytes); -} - -MemRegion HeapRegionSeq::expand_by(HeapWord* old_end, - HeapWord* new_end, - FreeRegionList* list) { - assert(old_end < new_end, "don't call it otherwise"); - G1CollectedHeap* g1h = G1CollectedHeap::heap(); - - HeapWord* next_bottom = old_end; - assert(heap_bottom() <= next_bottom, "invariant"); - while (next_bottom < new_end) { - assert(next_bottom < heap_end(), "invariant"); - uint index = length(); - - assert(index < max_length(), "otherwise we cannot expand further"); - if (index == 0) { - // We have not allocated any regions so far - assert(next_bottom == heap_bottom(), "invariant"); - } else { - // next_bottom should match the end of the last/previous region - assert(next_bottom == at(index - 1)->end(), "invariant"); +HeapRegion* HeapRegionSeq::next_region_in_heap(const HeapRegion* r) const { + guarantee(r != NULL, "Start region must be a valid region"); + guarantee(is_available(r->hrs_index()), err_msg("Trying to iterate starting from region %u which is not in the heap", r->hrs_index())); + for (uint i = r->hrs_index() + 1; i < _allocated_heapregions_length; i++) { + HeapRegion* hr = _regions.get_by_index(i); + if (is_available(i)) { + return hr; } - - if (index == _allocated_length) { - // We have to allocate a new HeapRegion. - HeapRegion* new_hr = g1h->new_heap_region(index, next_bottom); - if (new_hr == NULL) { - // allocation failed, we bail out and return what we have done so far - return MemRegion(old_end, next_bottom); - } - assert(_regions.get_by_index(index) == NULL, "invariant"); - _regions.set_by_index(index, new_hr); - increment_allocated_length(); - } - // Have to increment the length first, otherwise we will get an - // assert failure at(index) below. - increment_length(); - HeapRegion* hr = at(index); - list->add_as_tail(hr); - - next_bottom = hr->end(); } - assert(next_bottom == new_end, "post-condition"); - return MemRegion(old_end, next_bottom); -} - -uint HeapRegionSeq::free_suffix() { - uint res = 0; - uint index = length(); - while (index > 0) { - index -= 1; - if (!at(index)->is_empty()) { - break; - } - res += 1; - } - return res; -} - -uint HeapRegionSeq::find_contiguous(uint num) { - assert(num > 1, "use this only for sequences of length 2 or greater"); - assert(_next_search_index <= length(), - err_msg("_next_search_index: %u should be valid and <= than %u", - _next_search_index, length())); - - uint start = _next_search_index; - uint res = find_contiguous_from(start, num); - if (res == G1_NULL_HRS_INDEX && start > 0) { - // Try starting from the beginning. If _next_search_index was 0, - // no point in doing this again. - res = find_contiguous_from(0, num); - } - if (res != G1_NULL_HRS_INDEX) { - assert(res < length(), err_msg("res: %u should be valid", res)); - _next_search_index = res + num; - assert(_next_search_index <= length(), - err_msg("_next_search_index: %u should be valid and <= than %u", - _next_search_index, length())); - } - return res; + return NULL; } void HeapRegionSeq::iterate(HeapRegionClosure* blk) const { - iterate_from((HeapRegion*) NULL, blk); -} + uint len = max_length(); -void HeapRegionSeq::iterate_from(HeapRegion* hr, HeapRegionClosure* blk) const { - uint hr_index = 0; - if (hr != NULL) { - hr_index = hr->hrs_index(); - } - - uint len = length(); - for (uint i = hr_index; i < len; i += 1) { + for (uint i = 0; i < len; i++) { + if (!is_available(i)) { + continue; + } + guarantee(at(i) != NULL, err_msg("Tried to access region %u that has a NULL HeapRegion*", i)); bool res = blk->doHeapRegion(at(i)); if (res) { blk->incomplete(); return; } } - for (uint i = 0; i < hr_index; i += 1) { - bool res = blk->doHeapRegion(at(i)); +} + +uint HeapRegionSeq::find_unavailable_from_idx(uint start_idx, uint* res_idx) const { + guarantee(res_idx != NULL, "checking"); + guarantee(start_idx <= (max_length() + 1), "checking"); + + uint num_regions = 0; + + uint cur = start_idx; + while (cur < max_length() && is_available(cur)) { + cur++; + } + if (cur == max_length()) { + return num_regions; + } + *res_idx = cur; + while (cur < max_length() && !is_available(cur)) { + cur++; + } + num_regions = cur - *res_idx; +#ifdef ASSERT + for (uint i = *res_idx; i < (*res_idx + num_regions); i++) { + assert(!is_available(i), "just checking"); + } + assert(cur == max_length() || num_regions == 0 || is_available(cur), + err_msg("The region at the current position %u must be available or at the end of the heap.", cur)); +#endif + return num_regions; +} + +uint HeapRegionSeq::start_region_for_worker(uint worker_i, uint num_workers, uint num_regions) const { + return num_regions * worker_i / num_workers; +} + +void HeapRegionSeq::par_iterate(HeapRegionClosure* blk, uint worker_id, uint num_workers, jint claim_value) const { + const uint start_index = start_region_for_worker(worker_id, num_workers, _allocated_heapregions_length); + + // Every worker will actually look at all regions, skipping over regions that + // are currently not committed. + // This also (potentially) iterates over regions newly allocated during GC. This + // is no problem except for some extra work. + for (uint count = 0; count < _allocated_heapregions_length; count++) { + const uint index = (start_index + count) % _allocated_heapregions_length; + assert(0 <= index && index < _allocated_heapregions_length, "sanity"); + // Skip over unavailable regions + if (!is_available(index)) { + continue; + } + HeapRegion* r = _regions.get_by_index(index); + // We'll ignore "continues humongous" regions (we'll process them + // when we come across their corresponding "start humongous" + // region) and regions already claimed. + if (r->claim_value() == claim_value || r->continuesHumongous()) { + continue; + } + // OK, try to claim it + if (!r->claimHeapRegion(claim_value)) { + continue; + } + // Success! + if (r->startsHumongous()) { + // If the region is "starts humongous" we'll iterate over its + // "continues humongous" first; in fact we'll do them + // first. The order is important. In one case, calling the + // closure on the "starts humongous" region might de-allocate + // and clear all its "continues humongous" regions and, as a + // result, we might end up processing them twice. So, we'll do + // them first (note: most closures will ignore them anyway) and + // then we'll do the "starts humongous" region. + for (uint ch_index = index + 1; ch_index < index + r->region_num(); ch_index++) { + HeapRegion* chr = _regions.get_by_index(ch_index); + + assert(chr->continuesHumongous(), "Must be humongous region"); + assert(chr->humongous_start_region() == r, + err_msg("Must work on humongous continuation of the original start region " + PTR_FORMAT ", but is " PTR_FORMAT, p2i(r), p2i(chr))); + assert(chr->claim_value() != claim_value, + "Must not have been claimed yet because claiming of humongous continuation first claims the start region"); + + bool claim_result = chr->claimHeapRegion(claim_value); + // We should always be able to claim it; no one else should + // be trying to claim this region. + guarantee(claim_result, "We should always be able to claim the continuesHumongous part of the humongous object"); + + bool res2 = blk->doHeapRegion(chr); + if (res2) { + return; + } + + // Right now, this holds (i.e., no closure that actually + // does something with "continues humongous" regions + // clears them). We might have to weaken it in the future, + // but let's leave these two asserts here for extra safety. + assert(chr->continuesHumongous(), "should still be the case"); + assert(chr->humongous_start_region() == r, "sanity"); + } + } + + bool res = blk->doHeapRegion(r); if (res) { - blk->incomplete(); return; } } } uint HeapRegionSeq::shrink_by(uint num_regions_to_remove) { - // Reset this in case it's currently pointing into the regions that - // we just removed. - _next_search_index = 0; - assert(length() > 0, "the region sequence should not be empty"); - assert(length() <= _allocated_length, "invariant"); - assert(_allocated_length > 0, "we should have at least one region committed"); + assert(length() <= _allocated_heapregions_length, "invariant"); + assert(_allocated_heapregions_length > 0, "we should have at least one region committed"); assert(num_regions_to_remove < length(), "We should never remove all regions"); - uint i = 0; - for (; i < num_regions_to_remove; i++) { - HeapRegion* cur = at(length() - 1); - - if (!cur->is_empty()) { - // We have to give up if the region can not be moved - break; + if (num_regions_to_remove == 0) { + return 0; } - assert(!cur->isHumongous(), "Humongous regions should not be empty"); - decrement_length(); + uint removed = 0; + uint cur = _allocated_heapregions_length - 1; + uint idx_last_found = 0; + uint num_last_found = 0; + + while ((removed < num_regions_to_remove) && + (num_last_found = find_empty_from_idx_reverse(cur, &idx_last_found)) > 0) { + // Only allow uncommit from the end of the heap. + if ((idx_last_found + num_last_found) != _allocated_heapregions_length) { + return 0; + } + uint to_remove = MIN2(num_regions_to_remove - removed, num_last_found); + + uncommit_regions(idx_last_found + num_last_found - to_remove, to_remove); + + cur -= num_last_found; + removed += to_remove; } - return i; + + verify_optional(); + + return removed; } -#ifndef PRODUCT -void HeapRegionSeq::verify_optional() { - guarantee(length() <= _allocated_length, - err_msg("invariant: _length: %u _allocated_length: %u", - length(), _allocated_length)); - guarantee(_allocated_length <= max_length(), - err_msg("invariant: _allocated_length: %u _max_length: %u", - _allocated_length, max_length())); - guarantee(_next_search_index <= length(), - err_msg("invariant: _next_search_index: %u _length: %u", - _next_search_index, length())); +uint HeapRegionSeq::find_empty_from_idx_reverse(uint start_idx, uint* res_idx) const { + guarantee(start_idx < _allocated_heapregions_length, "checking"); + guarantee(res_idx != NULL, "checking"); + uint num_regions_found = 0; + + jlong cur = start_idx; + while (cur != -1 && !(is_available(cur) && at(cur)->is_empty())) { + cur--; + } + if (cur == -1) { + return num_regions_found; + } + jlong old_cur = cur; + // cur indexes the first empty region + while (cur != -1 && is_available(cur) && at(cur)->is_empty()) { + cur--; + } + *res_idx = cur + 1; + num_regions_found = old_cur - cur; + +#ifdef ASSERT + for (uint i = *res_idx; i < (*res_idx + num_regions_found); i++) { + assert(at(i)->is_empty(), "just checking"); + } +#endif + return num_regions_found; +} + +void HeapRegionSeq::verify() { + guarantee(length() <= _allocated_heapregions_length, + err_msg("invariant: _length: %u _allocated_length: %u", + length(), _allocated_heapregions_length)); + guarantee(_allocated_heapregions_length <= max_length(), + err_msg("invariant: _allocated_length: %u _max_length: %u", + _allocated_heapregions_length, max_length())); + + bool prev_committed = true; + uint num_committed = 0; HeapWord* prev_end = heap_bottom(); - for (uint i = 0; i < _allocated_length; i += 1) { + for (uint i = 0; i < _allocated_heapregions_length; i++) { + if (!is_available(i)) { + prev_committed = false; + continue; + } + num_committed++; HeapRegion* hr = _regions.get_by_index(i); guarantee(hr != NULL, err_msg("invariant: i: %u", i)); - guarantee(hr->bottom() == prev_end, + guarantee(!prev_committed || hr->bottom() == prev_end, err_msg("invariant i: %u "HR_FORMAT" prev_end: "PTR_FORMAT, i, HR_FORMAT_PARAMS(hr), p2i(prev_end))); guarantee(hr->hrs_index() == i, err_msg("invariant: i: %u hrs_index(): %u", i, hr->hrs_index())); - if (i < length()) { - // Asserts will fire if i is >= _length - HeapWord* addr = hr->bottom(); - guarantee(addr_to_region(addr) == hr, "sanity"); - } else { - guarantee(hr->is_empty(), "sanity"); - guarantee(!hr->isHumongous(), "sanity"); - // using assert instead of guarantee here since containing_set() - // is only available in non-product builds. - assert(hr->containing_set() == NULL, "sanity"); - } + // Asserts will fire if i is >= _length + HeapWord* addr = hr->bottom(); + guarantee(addr_to_region(addr) == hr, "sanity"); + // We cannot check whether the region is part of a particular set: at the time + // this method may be called, we have only completed allocation of the regions, + // but not put into a region set. + prev_committed = true; if (hr->startsHumongous()) { prev_end = hr->orig_end(); } else { prev_end = hr->end(); } } - for (uint i = _allocated_length; i < max_length(); i += 1) { + for (uint i = _allocated_heapregions_length; i < max_length(); i++) { guarantee(_regions.get_by_index(i) == NULL, err_msg("invariant i: %u", i)); } + + guarantee(num_committed == _num_committed, err_msg("Found %u committed regions, but should be %u", num_committed, _num_committed)); + _free_list.verify(); +} + +#ifndef PRODUCT +void HeapRegionSeq::verify_optional() { + verify(); } #endif // PRODUCT + diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp index 888b2ce5289..18b28fb93db 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp @@ -26,6 +26,8 @@ #define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_HPP #include "gc_implementation/g1/g1BiasedArray.hpp" +#include "gc_implementation/g1/g1RegionToSpaceMapper.hpp" +#include "gc_implementation/g1/heapRegionSet.hpp" class HeapRegion; class HeapRegionClosure; @@ -33,16 +35,20 @@ class FreeRegionList; class G1HeapRegionTable : public G1BiasedMappedArray { protected: - virtual HeapRegion* default_value() const { return NULL; } + virtual HeapRegion* default_value() const { return NULL; } }; -// This class keeps track of the region metadata (i.e., HeapRegion -// instances). They are kept in the _regions array in address -// order. A region's index in the array corresponds to its index in -// the heap (i.e., 0 is the region at the bottom of the heap, 1 is -// the one after it, etc.). Two regions that are consecutive in the -// array should also be adjacent in the address space (i.e., -// region(i).end() == region(i+1).bottom(). +// This class keeps track of the actual heap memory, auxiliary data +// and its metadata (i.e., HeapRegion instances) and the list of free regions. +// +// This allows maximum flexibility for deciding what to commit or uncommit given +// a request from outside. +// +// HeapRegions are kept in the _regions array in address order. A region's +// index in the array corresponds to its index in the heap (i.e., 0 is the +// region at the bottom of the heap, 1 is the one after it, etc.). Two +// regions that are consecutive in the array should also be adjacent in the +// address space (i.e., region(i).end() == region(i+1).bottom(). // // We create a HeapRegion when we commit the region's address space // for the first time. When we uncommit the address space of a @@ -51,56 +57,94 @@ class G1HeapRegionTable : public G1BiasedMappedArray { // // We keep track of three lengths: // -// * _committed_length (returned by length()) is the number of currently -// committed regions. -// * _allocated_length (not exposed outside this class) is the -// number of regions for which we have HeapRegions. +// * _num_committed (returned by length()) is the number of currently +// committed regions. These may not be contiguous. +// * _allocated_heapregions_length (not exposed outside this class) is the +// number of regions+1 for which we have HeapRegions. // * max_length() returns the maximum number of regions the heap can have. // -// and maintain that: _committed_length <= _allocated_length <= max_length() class HeapRegionSeq: public CHeapObj { friend class VMStructs; G1HeapRegionTable _regions; - // The number of regions committed in the heap. - uint _committed_length; + G1RegionToSpaceMapper* _heap_mapper; + G1RegionToSpaceMapper* _prev_bitmap_mapper; + G1RegionToSpaceMapper* _next_bitmap_mapper; + G1RegionToSpaceMapper* _bot_mapper; + G1RegionToSpaceMapper* _cardtable_mapper; + G1RegionToSpaceMapper* _card_counts_mapper; - // A hint for which index to start searching from for humongous - // allocations. - uint _next_search_index; + FreeRegionList _free_list; - // The number of regions for which we have allocated HeapRegions for. - uint _allocated_length; + // Each bit in this bitmap indicates that the corresponding region is available + // for allocation. + BitMap _available_map; - // Find a contiguous set of empty regions of length num, starting - // from the given index. - uint find_contiguous_from(uint from, uint num); + // The number of regions committed in the heap. + uint _num_committed; - void increment_allocated_length() { - assert(_allocated_length < max_length(), "pre-condition"); - _allocated_length++; - } - - void increment_length() { - assert(length() < max_length(), "pre-condition"); - _committed_length++; - } - - void decrement_length() { - assert(length() > 0, "pre-condition"); - _committed_length--; - } + // Internal only. The highest heap region +1 we allocated a HeapRegion instance for. + uint _allocated_heapregions_length; HeapWord* heap_bottom() const { return _regions.bottom_address_mapped(); } HeapWord* heap_end() const {return _regions.end_address_mapped(); } + void make_regions_available(uint index, uint num_regions = 1); + + // Pass down commit calls to the VirtualSpace. + void commit_regions(uint index, size_t num_regions = 1); + void uncommit_regions(uint index, size_t num_regions = 1); + + // Notify other data structures about change in the heap layout. + void update_committed_space(HeapWord* old_end, HeapWord* new_end); + // Calculate the starting region for each worker during parallel iteration so + // that they do not all start from the same region. + uint start_region_for_worker(uint worker_i, uint num_workers, uint num_regions) const; + + // Find a contiguous set of empty or uncommitted regions of length num and return + // the index of the first region or G1_NO_HRS_INDEX if the search was unsuccessful. + // If only_empty is true, only empty regions are considered. + // Searches from bottom to top of the heap, doing a first-fit. + uint find_contiguous(size_t num, bool only_empty); + // Finds the next sequence of unavailable regions starting from start_idx. Returns the + // length of the sequence found. If this result is zero, no such sequence could be found, + // otherwise res_idx indicates the start index of these regions. + uint find_unavailable_from_idx(uint start_idx, uint* res_idx) const; + // Finds the next sequence of empty regions starting from start_idx, going backwards in + // the heap. Returns the length of the sequence found. If this value is zero, no + // sequence could be found, otherwise res_idx contains the start index of this range. + uint find_empty_from_idx_reverse(uint start_idx, uint* res_idx) const; + // Allocate a new HeapRegion for the given index. + HeapRegion* new_heap_region(uint hrs_index); +#ifdef ASSERT +public: + bool is_free(HeapRegion* hr) const; +#endif + // Returns whether the given region is available for allocation. + bool is_available(uint region) const; + public: // Empty constructor, we'll initialize it with the initialize() method. - HeapRegionSeq() : _regions(), _committed_length(0), _next_search_index(0), _allocated_length(0) { } + HeapRegionSeq() : _regions(), _heap_mapper(NULL), _num_committed(0), + _next_bitmap_mapper(NULL), _prev_bitmap_mapper(NULL), _bot_mapper(NULL), + _allocated_heapregions_length(0), _available_map(), + _free_list("Free list", new MasterFreeRegionListMtSafeChecker()) + { } - void initialize(HeapWord* bottom, HeapWord* end); + void initialize(G1RegionToSpaceMapper* heap_storage, + G1RegionToSpaceMapper* prev_bitmap, + G1RegionToSpaceMapper* next_bitmap, + G1RegionToSpaceMapper* bot, + G1RegionToSpaceMapper* cardtable, + G1RegionToSpaceMapper* card_counts); + + // Return the "dummy" region used for G1AllocRegion. This is currently a hardwired + // new HeapRegion that owns HeapRegion at index 0. Since at the moment we commit + // the heap from the lowest address, this region (and its associated data + // structures) are available and we do not need to check further. + HeapRegion* get_dummy_region() { return new_heap_region(0); } // Return the HeapRegion at the given index. Assume that the index // is valid. @@ -110,45 +154,86 @@ class HeapRegionSeq: public CHeapObj { // HeapRegion, otherwise return NULL. inline HeapRegion* addr_to_region(HeapWord* addr) const; + // Insert the given region into the free region list. + inline void insert_into_free_list(HeapRegion* hr); + + // Insert the given region list into the global free region list. + void insert_list_into_free_list(FreeRegionList* list) { + _free_list.add_ordered(list); + } + + HeapRegion* allocate_free_region(bool is_old) { + HeapRegion* hr = _free_list.remove_region(is_old); + + if (hr != NULL) { + assert(hr->next() == NULL, "Single region should not have next"); + assert(is_available(hr->hrs_index()), "Must be committed"); + } + return hr; + } + + inline void allocate_free_regions_starting_at(uint first, uint num_regions); + + // Remove all regions from the free list. + void remove_all_free_regions() { + _free_list.remove_all(); + } + + // Return the number of committed free regions in the heap. + uint num_free_regions() const { + return _free_list.length(); + } + + size_t total_capacity_bytes() const { + return num_free_regions() * HeapRegion::GrainBytes; + } + + // Return the number of available (uncommitted) regions. + uint available() const { return max_length() - length(); } + // Return the number of regions that have been committed in the heap. - uint length() const { return _committed_length; } + uint length() const { return _num_committed; } // Return the maximum number of regions in the heap. uint max_length() const { return (uint)_regions.length(); } - // Expand the sequence to reflect that the heap has grown from - // old_end to new_end. Either create new HeapRegions, or re-use - // existing ones, and return them in the given list. Returns the - // memory region that covers the newly-created regions. If a - // HeapRegion allocation fails, the result memory region might be - // smaller than the desired one. - MemRegion expand_by(HeapWord* old_end, HeapWord* new_end, - FreeRegionList* list); + MemRegion reserved() const { return MemRegion(heap_bottom(), heap_end()); } - // Return the number of contiguous regions at the end of the sequence - // that are available for allocation. - uint free_suffix(); + // Expand the sequence to reflect that the heap has grown. Either create new + // HeapRegions, or re-use existing ones. Returns the number of regions the + // sequence was expanded by. If a HeapRegion allocation fails, the resulting + // number of regions might be smaller than what's desired. + uint expand_by(uint num_regions); - // Find a contiguous set of empty regions of length num and return - // the index of the first region or G1_NULL_HRS_INDEX if the - // search was unsuccessful. - uint find_contiguous(uint num); + // Makes sure that the regions from start to start+num_regions-1 are available + // for allocation. Returns the number of regions that were committed to achieve + // this. + uint expand_at(uint start, uint num_regions); + + // Find a contiguous set of empty regions of length num. Returns the start index of + // that set, or G1_NO_HRS_INDEX. + uint find_contiguous_only_empty(size_t num) { return find_contiguous(num, true); } + // Find a contiguous set of empty or unavailable regions of length num. Returns the + // start index of that set, or G1_NO_HRS_INDEX. + uint find_contiguous_empty_or_unavailable(size_t num) { return find_contiguous(num, false); } + + HeapRegion* next_region_in_heap(const HeapRegion* r) const; // Apply blk->doHeapRegion() on all committed regions in address order, // terminating the iteration early if doHeapRegion() returns true. void iterate(HeapRegionClosure* blk) const; - // As above, but start the iteration from hr and loop around. If hr - // is NULL, we start from the first region in the heap. - void iterate_from(HeapRegion* hr, HeapRegionClosure* blk) const; + void par_iterate(HeapRegionClosure* blk, uint worker_id, uint no_of_par_workers, jint claim_value) const; - // Tag as uncommitted as many regions that are completely free as - // possible, up to num_regions_to_remove, from the suffix of the committed - // sequence. Return the actual number of removed regions. + // Uncommit up to num_regions_to_remove regions that are completely free. + // Return the actual number of uncommitted regions. uint shrink_by(uint num_regions_to_remove); + void verify(); + // Do some sanity checking. void verify_optional() PRODUCT_RETURN; }; #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_HPP + diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.inline.hpp index 4028b7a4a5d..f5c1ffff9c3 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.inline.hpp @@ -27,6 +27,7 @@ #include "gc_implementation/g1/heapRegion.hpp" #include "gc_implementation/g1/heapRegionSeq.hpp" +#include "gc_implementation/g1/heapRegionSet.inline.hpp" inline HeapRegion* HeapRegionSeq::addr_to_region(HeapWord* addr) const { assert(addr < heap_end(), @@ -35,16 +36,23 @@ inline HeapRegion* HeapRegionSeq::addr_to_region(HeapWord* addr) const { err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT, p2i(addr), p2i(heap_bottom()))); HeapRegion* hr = _regions.get_by_address(addr); - assert(hr != NULL, "invariant"); return hr; } inline HeapRegion* HeapRegionSeq::at(uint index) const { - assert(index < length(), "pre-condition"); + assert(is_available(index), "pre-condition"); HeapRegion* hr = _regions.get_by_index(index); assert(hr != NULL, "sanity"); assert(hr->hrs_index() == index, "sanity"); return hr; } +inline void HeapRegionSeq::insert_into_free_list(HeapRegion* hr) { + _free_list.add_ordered(hr); +} + +inline void HeapRegionSeq::allocate_free_regions_starting_at(uint first, uint num_regions) { + _free_list.remove_starting_at(at(first), num_regions); +} + #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_INLINE_HPP diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.cpp index fa5ab14287e..691ade1dcd4 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/heapRegionRemSet.hpp" #include "gc_implementation/g1/heapRegionSet.inline.hpp" @@ -67,7 +68,7 @@ void HeapRegionSetBase::verify_start() { // Do the basic verification first before we do the checks over the regions. HeapRegionSetBase::verify(); - _verify_in_progress = true; + _verify_in_progress = true; } void HeapRegionSetBase::verify_end() { @@ -103,62 +104,7 @@ void FreeRegionList::set_unrealistically_long_length(uint len) { } void FreeRegionList::fill_in_ext_msg_extra(hrs_ext_msg* msg) { - msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, head(), tail()); -} - -void FreeRegionList::add_as_head_or_tail(FreeRegionList* from_list, bool as_head) { - check_mt_safety(); - from_list->check_mt_safety(); - - verify_optional(); - from_list->verify_optional(); - - if (from_list->is_empty()) { - return; - } - -#ifdef ASSERT - FreeRegionListIterator iter(from_list); - while (iter.more_available()) { - HeapRegion* hr = iter.get_next(); - // In set_containing_set() we check that we either set the value - // from NULL to non-NULL or vice versa to catch bugs. So, we have - // to NULL it first before setting it to the value. - hr->set_containing_set(NULL); - hr->set_containing_set(this); - } -#endif // ASSERT - - if (_head == NULL) { - assert(length() == 0 && _tail == NULL, hrs_ext_msg(this, "invariant")); - _head = from_list->_head; - _tail = from_list->_tail; - } else { - assert(length() > 0 && _tail != NULL, hrs_ext_msg(this, "invariant")); - if (as_head) { - from_list->_tail->set_next(_head); - _head->set_prev(from_list->_tail); - _head = from_list->_head; - } else { - _tail->set_next(from_list->_head); - from_list->_head->set_prev(_tail); - _tail = from_list->_tail; - } - } - - _count.increment(from_list->length(), from_list->total_capacity_bytes()); - from_list->clear(); - - verify_optional(); - from_list->verify_optional(); -} - -void FreeRegionList::add_as_head(FreeRegionList* from_list) { - add_as_head_or_tail(from_list, true /* as_head */); -} - -void FreeRegionList::add_as_tail(FreeRegionList* from_list) { - add_as_head_or_tail(from_list, false /* as_head */); + msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, _head, _tail); } void FreeRegionList::remove_all() { @@ -191,11 +137,6 @@ void FreeRegionList::add_ordered(FreeRegionList* from_list) { return; } - if (is_empty()) { - add_as_head(from_list); - return; - } - #ifdef ASSERT FreeRegionListIterator iter(from_list); while (iter.more_available()) { @@ -208,37 +149,43 @@ void FreeRegionList::add_ordered(FreeRegionList* from_list) { } #endif // ASSERT - HeapRegion* curr_to = _head; - HeapRegion* curr_from = from_list->_head; - - while (curr_from != NULL) { - while (curr_to != NULL && curr_to->hrs_index() < curr_from->hrs_index()) { - curr_to = curr_to->next(); - } - - if (curr_to == NULL) { - // The rest of the from list should be added as tail - _tail->set_next(curr_from); - curr_from->set_prev(_tail); - curr_from = NULL; - } else { - HeapRegion* next_from = curr_from->next(); - - curr_from->set_next(curr_to); - curr_from->set_prev(curr_to->prev()); - if (curr_to->prev() == NULL) { - _head = curr_from; - } else { - curr_to->prev()->set_next(curr_from); - } - curr_to->set_prev(curr_from); - - curr_from = next_from; - } - } - - if (_tail->hrs_index() < from_list->_tail->hrs_index()) { + if (is_empty()) { + assert(length() == 0 && _tail == NULL, hrs_ext_msg(this, "invariant")); + _head = from_list->_head; _tail = from_list->_tail; + } else { + HeapRegion* curr_to = _head; + HeapRegion* curr_from = from_list->_head; + + while (curr_from != NULL) { + while (curr_to != NULL && curr_to->hrs_index() < curr_from->hrs_index()) { + curr_to = curr_to->next(); + } + + if (curr_to == NULL) { + // The rest of the from list should be added as tail + _tail->set_next(curr_from); + curr_from->set_prev(_tail); + curr_from = NULL; + } else { + HeapRegion* next_from = curr_from->next(); + + curr_from->set_next(curr_to); + curr_from->set_prev(curr_to->prev()); + if (curr_to->prev() == NULL) { + _head = curr_from; + } else { + curr_to->prev()->set_next(curr_from); + } + curr_to->set_prev(curr_from); + + curr_from = next_from; + } + } + + if (_tail->hrs_index() < from_list->_tail->hrs_index()) { + _tail = from_list->_tail; + } } _count.increment(from_list->length(), from_list->total_capacity_bytes()); @@ -248,68 +195,59 @@ void FreeRegionList::add_ordered(FreeRegionList* from_list) { from_list->verify_optional(); } -void FreeRegionList::remove_all_pending(uint target_count) { +void FreeRegionList::remove_starting_at(HeapRegion* first, uint num_regions) { check_mt_safety(); - assert(target_count > 1, hrs_ext_msg(this, "pre-condition")); + assert(num_regions >= 1, hrs_ext_msg(this, "pre-condition")); assert(!is_empty(), hrs_ext_msg(this, "pre-condition")); verify_optional(); DEBUG_ONLY(uint old_length = length();) - HeapRegion* curr = _head; + HeapRegion* curr = first; uint count = 0; - while (curr != NULL) { + while (count < num_regions) { verify_region(curr); HeapRegion* next = curr->next(); HeapRegion* prev = curr->prev(); - if (curr->pending_removal()) { - assert(count < target_count, - hrs_err_msg("[%s] should not come across more regions " - "pending for removal than target_count: %u", - name(), target_count)); + assert(count < num_regions, + hrs_err_msg("[%s] should not come across more regions " + "pending for removal than num_regions: %u", + name(), num_regions)); - if (prev == NULL) { - assert(_head == curr, hrs_ext_msg(this, "invariant")); - _head = next; - } else { - assert(_head != curr, hrs_ext_msg(this, "invariant")); - prev->set_next(next); - } - if (next == NULL) { - assert(_tail == curr, hrs_ext_msg(this, "invariant")); - _tail = prev; - } else { - assert(_tail != curr, hrs_ext_msg(this, "invariant")); - next->set_prev(prev); - } - if (_last = curr) { - _last = NULL; - } - - curr->set_next(NULL); - curr->set_prev(NULL); - remove(curr); - curr->set_pending_removal(false); - - count += 1; - - // If we have come across the target number of regions we can - // just bail out. However, for debugging purposes, we can just - // carry on iterating to make sure there are not more regions - // tagged with pending removal. - DEBUG_ONLY(if (count == target_count) break;) + if (prev == NULL) { + assert(_head == curr, hrs_ext_msg(this, "invariant")); + _head = next; + } else { + assert(_head != curr, hrs_ext_msg(this, "invariant")); + prev->set_next(next); } + if (next == NULL) { + assert(_tail == curr, hrs_ext_msg(this, "invariant")); + _tail = prev; + } else { + assert(_tail != curr, hrs_ext_msg(this, "invariant")); + next->set_prev(prev); + } + if (_last = curr) { + _last = NULL; + } + + curr->set_next(NULL); + curr->set_prev(NULL); + remove(curr); + + count++; curr = next; } - assert(count == target_count, - hrs_err_msg("[%s] count: %u should be == target_count: %u", - name(), count, target_count)); - assert(length() + target_count == old_length, + assert(count == num_regions, + hrs_err_msg("[%s] count: %u should be == num_regions: %u", + name(), count, num_regions)); + assert(length() + num_regions == old_length, hrs_err_msg("[%s] new length should be consistent " - "new length: %u old length: %u target_count: %u", - name(), length(), old_length, target_count)); + "new length: %u old length: %u num_regions: %u", + name(), length(), old_length, num_regions)); verify_optional(); } @@ -348,10 +286,12 @@ void FreeRegionList::print_on(outputStream* out, bool print_contents) { hr->print_on(out); } } + + out->cr(); } void FreeRegionList::verify_list() { - HeapRegion* curr = head(); + HeapRegion* curr = _head; HeapRegion* prev1 = NULL; HeapRegion* prev0 = NULL; uint count = 0; @@ -379,7 +319,7 @@ void FreeRegionList::verify_list() { curr = curr->next(); } - guarantee(tail() == prev0, err_msg("Expected %s to end with %u but it ended with %u.", name(), tail()->hrs_index(), prev0->hrs_index())); + guarantee(_tail == prev0, err_msg("Expected %s to end with %u but it ended with %u.", name(), _tail->hrs_index(), prev0->hrs_index())); guarantee(_tail == NULL || _tail->next() == NULL, "_tail should not have a next"); guarantee(length() == count, err_msg("%s count mismatch. Expected %u, actual %u.", name(), length(), count)); guarantee(total_capacity_bytes() == capacity, err_msg("%s capacity mismatch. Expected " SIZE_FORMAT ", actual " SIZE_FORMAT, @@ -463,3 +403,41 @@ void HumongousRegionSetMtSafeChecker::check() { "master humongous set MT safety protocol outside a safepoint"); } } + +void FreeRegionList_test() { + FreeRegionList l("test"); + + const uint num_regions_in_test = 5; + // Create a fake heap. It does not need to be valid, as the HeapRegion constructor + // does not access it. + MemRegion heap(NULL, num_regions_in_test * HeapRegion::GrainWords); + // Allocate a fake BOT because the HeapRegion constructor initializes + // the BOT. + size_t bot_size = G1BlockOffsetSharedArray::compute_size(heap.word_size()); + HeapWord* bot_data = NEW_C_HEAP_ARRAY(HeapWord, bot_size, mtGC); + ReservedSpace bot_rs(G1BlockOffsetSharedArray::compute_size(heap.word_size())); + G1RegionToSpaceMapper* bot_storage = + G1RegionToSpaceMapper::create_mapper(bot_rs, + os::vm_page_size(), + HeapRegion::GrainBytes, + G1BlockOffsetSharedArray::N_bytes, + mtGC); + G1BlockOffsetSharedArray oa(heap, bot_storage); + bot_storage->commit_regions(0, num_regions_in_test); + HeapRegion hr0(0, &oa, heap); + HeapRegion hr1(1, &oa, heap); + HeapRegion hr2(2, &oa, heap); + HeapRegion hr3(3, &oa, heap); + HeapRegion hr4(4, &oa, heap); + l.add_ordered(&hr1); + l.add_ordered(&hr0); + l.add_ordered(&hr3); + l.add_ordered(&hr4); + l.add_ordered(&hr2); + assert(l.length() == num_regions_in_test, "wrong length"); + l.verify_list(); + + bot_storage->uncommit_regions(0, num_regions_in_test); + delete bot_storage; + FREE_C_HEAP_ARRAY(HeapWord, bot_data, mtGC); +} diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.hpp index 8502763ccf1..5bbae915fda 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.hpp @@ -162,7 +162,7 @@ public: // diagnosing failures. class hrs_ext_msg : public hrs_err_msg { public: - hrs_ext_msg(HeapRegionSetBase* set, const char* message) : hrs_err_msg("%s","") { + hrs_ext_msg(HeapRegionSetBase* set, const char* message) : hrs_err_msg("%s", "") { set->fill_in_ext_msg(this, message); } }; @@ -192,13 +192,9 @@ public: }; // A set that links all the regions added to it in a doubly-linked -// list. We should try to avoid doing operations that iterate over +// sorted list. We should try to avoid doing operations that iterate over // such lists in performance critical paths. Typically we should -// add / remove one region at a time or concatenate two lists. There are -// two ways to treat your lists, ordered and un-ordered. All un-ordered -// operations are done in constant time. To keep a list ordered only use -// add_ordered() to add elements to the list. If a list is not ordered -// from start, there is no way to sort it later. +// add / remove one region at a time or concatenate two lists. class FreeRegionListIterator; @@ -210,13 +206,13 @@ private: HeapRegion* _tail; // _last is used to keep track of where we added an element the last - // time in ordered lists. It helps to improve performance when adding - // several ordered items in a row. + // time. It helps to improve performance when adding several ordered items in a row. HeapRegion* _last; static uint _unrealistically_long_length; - void add_as_head_or_tail(FreeRegionList* from_list, bool as_head); + inline HeapRegion* remove_from_head_impl(); + inline HeapRegion* remove_from_tail_impl(); protected: virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg); @@ -232,8 +228,11 @@ public: void verify_list(); - HeapRegion* head() { return _head; } - HeapRegion* tail() { return _tail; } +#ifdef ASSERT + bool contains(HeapRegion* hr) const { + return hr->containing_set() == this; + } +#endif static void set_unrealistically_long_length(uint len); @@ -242,55 +241,20 @@ public: // is determined by hrs_index. inline void add_ordered(HeapRegion* hr); - // It adds hr to the list as the new head. The region should not be - // a member of another set. - inline void add_as_head(HeapRegion* hr); - - // It adds hr to the list as the new tail. The region should not be - // a member of another set. - inline void add_as_tail(HeapRegion* hr); - - // It removes and returns the head of the list. It assumes that the - // list is not empty so it will return a non-NULL value. - inline HeapRegion* remove_head(); - - // Convenience method. - inline HeapRegion* remove_head_or_null(); - - // Removes and returns the last element (_tail) of the list. It assumes - // that the list isn't empty so that it can return a non-NULL value. - inline HeapRegion* remove_tail(); - - // Convenience method - inline HeapRegion* remove_tail_or_null(); - // Removes from head or tail based on the given argument. - inline HeapRegion* remove_region(bool from_head); + HeapRegion* remove_region(bool from_head); // Merge two ordered lists. The result is also ordered. The order is // determined by hrs_index. void add_ordered(FreeRegionList* from_list); - // It moves the regions from from_list to this list and empties - // from_list. The new regions will appear in the same order as they - // were in from_list and be linked in the beginning of this list. - void add_as_head(FreeRegionList* from_list); - - // It moves the regions from from_list to this list and empties - // from_list. The new regions will appear in the same order as they - // were in from_list and be linked in the end of this list. - void add_as_tail(FreeRegionList* from_list); - // It empties the list by removing all regions from it. void remove_all(); - // It removes all regions in the list that are pending for removal - // (i.e., they have been tagged with "pending_removal"). The list - // must not be empty, target_count should reflect the exact number - // of regions that are pending for removal in the list, and - // target_count should be > 1 (currently, we never need to remove a - // single region using this). - void remove_all_pending(uint target_count); + // Remove all (contiguous) regions from first to first + num_regions -1 from + // this list. + // Num_regions must be > 1. + void remove_starting_at(HeapRegion* first, uint num_regions); virtual void verify(); @@ -298,7 +262,7 @@ public: }; // Iterator class that provides a convenient way to iterate over the -// regions of a HeapRegionLinkedList instance. +// regions of a FreeRegionList. class FreeRegionListIterator : public StackObj { private: @@ -324,7 +288,7 @@ public: } FreeRegionListIterator(FreeRegionList* list) : _curr(NULL), _list(list) { - _curr = list->head(); + _curr = list->_head; } }; diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp index 08f74a776ac..683c4c9202e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp @@ -30,7 +30,8 @@ inline void HeapRegionSetBase::add(HeapRegion* hr) { check_mt_safety(); assert(hr->containing_set() == NULL, hrs_ext_msg(this, "should not already have a containing set %u")); - assert(hr->next() == NULL && hr->prev() == NULL, hrs_ext_msg(this, "should not already be linked")); + assert(hr->next() == NULL, hrs_ext_msg(this, "should not already be linked")); + assert(hr->prev() == NULL, hrs_ext_msg(this, "should not already be linked")); _count.increment(1u, hr->capacity()); hr->set_containing_set(this); @@ -40,7 +41,8 @@ inline void HeapRegionSetBase::add(HeapRegion* hr) { inline void HeapRegionSetBase::remove(HeapRegion* hr) { check_mt_safety(); verify_region(hr); - assert(hr->next() == NULL && hr->prev() == NULL, hrs_ext_msg(this, "should already be unlinked")); + assert(hr->next() == NULL, hrs_ext_msg(this, "should already be unlinked")); + assert(hr->prev() == NULL, hrs_ext_msg(this, "should already be unlinked")); hr->set_containing_set(NULL); assert(_count.length() > 0, hrs_ext_msg(this, "pre-condition")); @@ -48,8 +50,7 @@ inline void HeapRegionSetBase::remove(HeapRegion* hr) { } inline void FreeRegionList::add_ordered(HeapRegion* hr) { - check_mt_safety(); - assert((length() == 0 && _head == NULL && _tail == NULL) || + assert((length() == 0 && _head == NULL && _tail == NULL && _last == NULL) || (length() > 0 && _head != NULL && _tail != NULL), hrs_ext_msg(this, "invariant")); // add() will verify the region and check mt safety. @@ -95,89 +96,48 @@ inline void FreeRegionList::add_ordered(HeapRegion* hr) { _last = hr; } -inline void FreeRegionList::add_as_head(HeapRegion* hr) { - assert((length() == 0 && _head == NULL && _tail == NULL) || - (length() > 0 && _head != NULL && _tail != NULL), - hrs_ext_msg(this, "invariant")); - // add() will verify the region and check mt safety. - add(hr); - - // Now link the region. - if (_head != NULL) { - hr->set_next(_head); - _head->set_prev(hr); - } else { - _tail = hr; - } - _head = hr; -} - -inline void FreeRegionList::add_as_tail(HeapRegion* hr) { - check_mt_safety(); - assert((length() == 0 && _head == NULL && _tail == NULL) || - (length() > 0 && _head != NULL && _tail != NULL), - hrs_ext_msg(this, "invariant")); - // add() will verify the region and check mt safety. - add(hr); - - // Now link the region. - if (_tail != NULL) { - _tail->set_next(hr); - hr->set_prev(_tail); - } else { - _head = hr; - } - _tail = hr; -} - -inline HeapRegion* FreeRegionList::remove_head() { - assert(!is_empty(), hrs_ext_msg(this, "the list should not be empty")); - assert(length() > 0 && _head != NULL && _tail != NULL, - hrs_ext_msg(this, "invariant")); - - // We need to unlink it first. - HeapRegion* hr = _head; - _head = hr->next(); +inline HeapRegion* FreeRegionList::remove_from_head_impl() { + HeapRegion* result = _head; + _head = result->next(); if (_head == NULL) { _tail = NULL; } else { _head->set_prev(NULL); } - hr->set_next(NULL); - - if (_last == hr) { - _last = NULL; - } - - // remove() will verify the region and check mt safety. - remove(hr); - return hr; + result->set_next(NULL); + return result; } -inline HeapRegion* FreeRegionList::remove_head_or_null() { - check_mt_safety(); - if (!is_empty()) { - return remove_head(); - } else { - return NULL; - } -} +inline HeapRegion* FreeRegionList::remove_from_tail_impl() { + HeapRegion* result = _tail; -inline HeapRegion* FreeRegionList::remove_tail() { - assert(!is_empty(), hrs_ext_msg(this, "The list should not be empty")); - assert(length() > 0 && _head != NULL && _tail != NULL, - hrs_ext_msg(this, "invariant")); - - // We need to unlink it first - HeapRegion* hr = _tail; - - _tail = hr->prev(); + _tail = result->prev(); if (_tail == NULL) { _head = NULL; } else { _tail->set_next(NULL); } - hr->set_prev(NULL); + result->set_prev(NULL); + return result; +} + +inline HeapRegion* FreeRegionList::remove_region(bool from_head) { + check_mt_safety(); + verify_optional(); + + if (is_empty()) { + return NULL; + } + assert(length() > 0 && _head != NULL && _tail != NULL, + hrs_ext_msg(this, "invariant")); + + HeapRegion* hr; + + if (from_head) { + hr = remove_from_head_impl(); + } else { + hr = remove_from_tail_impl(); + } if (_last == hr) { _last = NULL; @@ -188,22 +148,5 @@ inline HeapRegion* FreeRegionList::remove_tail() { return hr; } -inline HeapRegion* FreeRegionList::remove_tail_or_null() { - check_mt_safety(); - - if (!is_empty()) { - return remove_tail(); - } else { - return NULL; - } -} - -inline HeapRegion* FreeRegionList::remove_region(bool from_head) { - if (from_head) { - return remove_head_or_null(); - } else { - return remove_tail_or_null(); - } -} - #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSET_INLINE_HPP + diff --git a/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp b/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp index f32bfb0e3a3..4277ab55abe 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp @@ -43,10 +43,9 @@ nonstatic_field(G1HeapRegionTable, _shift_by, uint) \ \ nonstatic_field(HeapRegionSeq, _regions, G1HeapRegionTable) \ - nonstatic_field(HeapRegionSeq, _committed_length, uint) \ + nonstatic_field(HeapRegionSeq, _num_committed, uint) \ \ nonstatic_field(G1CollectedHeap, _hrs, HeapRegionSeq) \ - nonstatic_field(G1CollectedHeap, _g1_committed, MemRegion) \ nonstatic_field(G1CollectedHeap, _summary_bytes_used, size_t) \ nonstatic_field(G1CollectedHeap, _g1mm, G1MonitoringSupport*) \ nonstatic_field(G1CollectedHeap, _old_set, HeapRegionSetBase) \ diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp index b7d521a4884..5262c6bc55e 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp @@ -78,6 +78,7 @@ jint ParallelScavengeHeap::initialize() { (HeapWord*)(heap_rs.base() + heap_rs.size())); CardTableExtension* const barrier_set = new CardTableExtension(_reserved, 3); + barrier_set->initialize(); _barrier_set = barrier_set; oopDesc::set_bs(_barrier_set); if (_barrier_set == NULL) { diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp index aede4e5b641..3a8f347bc8d 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp @@ -70,7 +70,7 @@ void VM_ParallelGCSystemGC::doit() { "must be a ParallelScavengeHeap"); GCCauseSetter gccs(heap, _gc_cause); - if (_gc_cause == GCCause::_gc_locker + if (_gc_cause == GCCause::_gc_locker || _gc_cause == GCCause::_wb_young_gc DEBUG_ONLY(|| _gc_cause == GCCause::_scavenge_alot)) { // If (and only if) the scavenge fails, this will invoke a full gc. heap->invoke_scavenge(); diff --git a/hotspot/src/share/vm/gc_interface/gcCause.cpp b/hotspot/src/share/vm/gc_interface/gcCause.cpp index 2588621aa6b..879bce11304 100644 --- a/hotspot/src/share/vm/gc_interface/gcCause.cpp +++ b/hotspot/src/share/vm/gc_interface/gcCause.cpp @@ -51,6 +51,9 @@ const char* GCCause::to_string(GCCause::Cause cause) { case _heap_dump: return "Heap Dump Initiated GC"; + case _wb_young_gc: + return "WhiteBox Initiated Young GC"; + case _no_gc: return "No GC"; diff --git a/hotspot/src/share/vm/gc_interface/gcCause.hpp b/hotspot/src/share/vm/gc_interface/gcCause.hpp index 1df82dba700..31a7a9d3827 100644 --- a/hotspot/src/share/vm/gc_interface/gcCause.hpp +++ b/hotspot/src/share/vm/gc_interface/gcCause.hpp @@ -46,6 +46,7 @@ class GCCause : public AllStatic { _gc_locker, _heap_inspection, _heap_dump, + _wb_young_gc, /* implementation independent, but reserved for GC use */ _no_gc, diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index 323f67fc1f6..dc2a782ea05 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -3402,7 +3402,7 @@ BytecodeInterpreter::print() { tty->print_cr("osr._osr_buf: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_buf); tty->print_cr("osr._osr_entry: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_entry); tty->print_cr("prev_link: " INTPTR_FORMAT, (uintptr_t) this->_prev_link); - tty->print_cr("native_mirror: " INTPTR_FORMAT, (uintptr_t) this->_oop_temp); + tty->print_cr("native_mirror: " INTPTR_FORMAT, (uintptr_t) p2i(this->_oop_temp)); tty->print_cr("stack_base: " INTPTR_FORMAT, (uintptr_t) this->_stack_base); tty->print_cr("stack_limit: " INTPTR_FORMAT, (uintptr_t) this->_stack_limit); tty->print_cr("monitor_base: " INTPTR_FORMAT, (uintptr_t) this->_monitor_base); diff --git a/hotspot/src/share/vm/memory/allocation.hpp b/hotspot/src/share/vm/memory/allocation.hpp index adb72e86aab..a1faa70871a 100644 --- a/hotspot/src/share/vm/memory/allocation.hpp +++ b/hotspot/src/share/vm/memory/allocation.hpp @@ -265,7 +265,8 @@ class MetaspaceObj { f(ConstantPool) \ f(ConstantPoolCache) \ f(Annotation) \ - f(MethodCounters) + f(MethodCounters) \ + f(Deallocated) #define METASPACE_OBJ_TYPE_DECLARE(name) name ## Type, #define METASPACE_OBJ_TYPE_NAME_CASE(name) case name ## Type: return #name; diff --git a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp index 1f56344c95d..30e8618d597 100644 --- a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp +++ b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp @@ -44,13 +44,6 @@ // enumerate ref fields that have been modified (since the last // enumeration.) -size_t CardTableModRefBS::cards_required(size_t covered_words) -{ - // Add one for a guard card, used to detect errors. - const size_t words = align_size_up(covered_words, card_size_in_words); - return words / card_size_in_words + 1; -} - size_t CardTableModRefBS::compute_byte_map_size() { assert(_guard_index == cards_required(_whole_heap.word_size()) - 1, @@ -64,27 +57,50 @@ CardTableModRefBS::CardTableModRefBS(MemRegion whole_heap, int max_covered_regions): ModRefBarrierSet(max_covered_regions), _whole_heap(whole_heap), - _guard_index(cards_required(whole_heap.word_size()) - 1), - _last_valid_index(_guard_index - 1), + _guard_index(0), + _guard_region(), + _last_valid_index(0), _page_size(os::vm_page_size()), - _byte_map_size(compute_byte_map_size()) + _byte_map_size(0), + _covered(NULL), + _committed(NULL), + _cur_covered_regions(0), + _byte_map(NULL), + byte_map_base(NULL), + // LNC functionality + _lowest_non_clean(NULL), + _lowest_non_clean_chunk_size(NULL), + _lowest_non_clean_base_chunk_index(NULL), + _last_LNC_resizing_collection(NULL) { _kind = BarrierSet::CardTableModRef; - HeapWord* low_bound = _whole_heap.start(); - HeapWord* high_bound = _whole_heap.end(); - assert((uintptr_t(low_bound) & (card_size - 1)) == 0, "heap must start at card boundary"); - assert((uintptr_t(high_bound) & (card_size - 1)) == 0, "heap must end at card boundary"); + assert((uintptr_t(_whole_heap.start()) & (card_size - 1)) == 0, "heap must start at card boundary"); + assert((uintptr_t(_whole_heap.end()) & (card_size - 1)) == 0, "heap must end at card boundary"); assert(card_size <= 512, "card_size must be less than 512"); // why? - _covered = new MemRegion[max_covered_regions]; - _committed = new MemRegion[max_covered_regions]; - if (_covered == NULL || _committed == NULL) { - vm_exit_during_initialization("couldn't alloc card table covered region set."); + _covered = new MemRegion[_max_covered_regions]; + if (_covered == NULL) { + vm_exit_during_initialization("Could not allocate card table covered region set."); } +} + +void CardTableModRefBS::initialize() { + _guard_index = cards_required(_whole_heap.word_size()) - 1; + _last_valid_index = _guard_index - 1; + + _byte_map_size = compute_byte_map_size(); + + HeapWord* low_bound = _whole_heap.start(); + HeapWord* high_bound = _whole_heap.end(); _cur_covered_regions = 0; + _committed = new MemRegion[_max_covered_regions]; + if (_committed == NULL) { + vm_exit_during_initialization("Could not allocate card table committed region set."); + } + const size_t rs_align = _page_size == (size_t) os::vm_page_size() ? 0 : MAX2(_page_size, (size_t) os::vm_allocation_granularity()); ReservedSpace heap_rs(_byte_map_size, rs_align, false); @@ -114,20 +130,20 @@ CardTableModRefBS::CardTableModRefBS(MemRegion whole_heap, !ExecMem, "card table last card"); *guard_card = last_card; - _lowest_non_clean = - NEW_C_HEAP_ARRAY(CardArr, max_covered_regions, mtGC); + _lowest_non_clean = + NEW_C_HEAP_ARRAY(CardArr, _max_covered_regions, mtGC); _lowest_non_clean_chunk_size = - NEW_C_HEAP_ARRAY(size_t, max_covered_regions, mtGC); + NEW_C_HEAP_ARRAY(size_t, _max_covered_regions, mtGC); _lowest_non_clean_base_chunk_index = - NEW_C_HEAP_ARRAY(uintptr_t, max_covered_regions, mtGC); + NEW_C_HEAP_ARRAY(uintptr_t, _max_covered_regions, mtGC); _last_LNC_resizing_collection = - NEW_C_HEAP_ARRAY(int, max_covered_regions, mtGC); + NEW_C_HEAP_ARRAY(int, _max_covered_regions, mtGC); if (_lowest_non_clean == NULL || _lowest_non_clean_chunk_size == NULL || _lowest_non_clean_base_chunk_index == NULL || _last_LNC_resizing_collection == NULL) vm_exit_during_initialization("couldn't allocate an LNC array."); - for (int i = 0; i < max_covered_regions; i++) { + for (int i = 0; i < _max_covered_regions; i++) { _lowest_non_clean[i] = NULL; _lowest_non_clean_chunk_size[i] = 0; _last_LNC_resizing_collection[i] = -1; @@ -650,7 +666,7 @@ void CardTableModRefBS::verify_region(MemRegion mr, jbyte val, bool val_equals) { jbyte* start = byte_for(mr.start()); jbyte* end = byte_for(mr.last()); - bool failures = false; + bool failures = false; for (jbyte* curr = start; curr <= end; ++curr) { jbyte curr_val = *curr; bool failed = (val_equals) ? (curr_val != val) : (curr_val == val); diff --git a/hotspot/src/share/vm/memory/cardTableModRefBS.hpp b/hotspot/src/share/vm/memory/cardTableModRefBS.hpp index 5e72b4640f9..c824e6185a0 100644 --- a/hotspot/src/share/vm/memory/cardTableModRefBS.hpp +++ b/hotspot/src/share/vm/memory/cardTableModRefBS.hpp @@ -96,12 +96,12 @@ class CardTableModRefBS: public ModRefBarrierSet { // The declaration order of these const fields is important; see the // constructor before changing. const MemRegion _whole_heap; // the region covered by the card table - const size_t _guard_index; // index of very last element in the card + size_t _guard_index; // index of very last element in the card // table; it is set to a guard value // (last_card) and should never be modified - const size_t _last_valid_index; // index of the last valid element + size_t _last_valid_index; // index of the last valid element const size_t _page_size; // page size used when mapping _byte_map - const size_t _byte_map_size; // in bytes + size_t _byte_map_size; // in bytes jbyte* _byte_map; // the card marking array int _cur_covered_regions; @@ -123,7 +123,12 @@ class CardTableModRefBS: public ModRefBarrierSet { protected: // Initialization utilities; covered_words is the size of the covered region // in, um, words. - inline size_t cards_required(size_t covered_words); + inline size_t cards_required(size_t covered_words) { + // Add one for a guard card, used to detect errors. + const size_t words = align_size_up(covered_words, card_size_in_words); + return words / card_size_in_words + 1; + } + inline size_t compute_byte_map_size(); // Finds and return the index of the region, if any, to which the given @@ -137,7 +142,7 @@ class CardTableModRefBS: public ModRefBarrierSet { int find_covering_region_containing(HeapWord* addr); // Resize one of the regions covered by the remembered set. - void resize_covered_region(MemRegion new_region); + virtual void resize_covered_region(MemRegion new_region); // Returns the leftmost end of a committed region corresponding to a // covered region before covered region "ind", or else "NULL" if "ind" is @@ -282,6 +287,8 @@ public: CardTableModRefBS(MemRegion whole_heap, int max_covered_regions); ~CardTableModRefBS(); + virtual void initialize(); + // *** Barrier set functions. bool has_write_ref_pre_barrier() { return false; } diff --git a/hotspot/src/share/vm/memory/cardTableRS.cpp b/hotspot/src/share/vm/memory/cardTableRS.cpp index 078c22b7c47..90f72d19efd 100644 --- a/hotspot/src/share/vm/memory/cardTableRS.cpp +++ b/hotspot/src/share/vm/memory/cardTableRS.cpp @@ -54,6 +54,7 @@ CardTableRS::CardTableRS(MemRegion whole_heap, #else _ct_bs = new CardTableModRefBSForCTRS(whole_heap, max_covered_regions); #endif + _ct_bs->initialize(); set_bs(_ct_bs); _last_cur_val_in_gen = NEW_C_HEAP_ARRAY3(jbyte, GenCollectedHeap::max_gens + 1, mtGC, CURRENT_PC, AllocFailStrategy::RETURN_NULL); diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp index 2f5c0165893..4d6c57b816f 100644 --- a/hotspot/src/share/vm/memory/filemap.cpp +++ b/hotspot/src/share/vm/memory/filemap.cpp @@ -24,9 +24,14 @@ #include "precompiled.hpp" #include "classfile/classLoader.hpp" +#include "classfile/sharedClassUtil.hpp" #include "classfile/symbolTable.hpp" +#include "classfile/systemDictionaryShared.hpp" #include "classfile/altHashing.hpp" #include "memory/filemap.hpp" +#include "memory/metadataFactory.hpp" +#include "memory/oopFactory.hpp" +#include "oops/objArrayOop.hpp" #include "runtime/arguments.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" @@ -42,7 +47,6 @@ #endif PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC - extern address JVM_FunctionAtStart(); extern address JVM_FunctionAtEnd(); @@ -78,16 +82,27 @@ void FileMapInfo::fail_stop(const char *msg, ...) { void FileMapInfo::fail_continue(const char *msg, ...) { va_list ap; va_start(ap, msg); - if (RequireSharedSpaces) { - fail(msg, ap); + MetaspaceShared::set_archive_loading_failed(); + if (PrintSharedArchiveAndExit && _validating_classpath_entry_table) { + // If we are doing PrintSharedArchiveAndExit and some of the classpath entries + // do not validate, we can still continue "limping" to validate the remaining + // entries. No need to quit. + tty->print("["); + tty->vprint(msg, ap); + tty->print_cr("]"); } else { - if (PrintSharedSpaces) { - tty->print_cr("UseSharedSpaces: %s", msg); + if (RequireSharedSpaces) { + fail(msg, ap); + } else { + if (PrintSharedSpaces) { + tty->print_cr("UseSharedSpaces: %s", msg); + } } } va_end(ap); UseSharedSpaces = false; - close(); + assert(current_info() != NULL, "singleton must be registered"); + current_info()->close(); } // Fill in the fileMapInfo structure with data about this VM instance. @@ -122,67 +137,201 @@ template static void get_header_version(char (&header_version) [N]) { } } +FileMapInfo::FileMapInfo() { + assert(_current_info == NULL, "must be singleton"); // not thread safe + _current_info = this; + memset(this, 0, sizeof(FileMapInfo)); + _file_offset = 0; + _file_open = false; + _header = SharedClassUtil::allocate_file_map_header(); + _header->_version = _invalid_version; +} + +FileMapInfo::~FileMapInfo() { + assert(_current_info == this, "must be singleton"); // not thread safe + _current_info = NULL; +} + void FileMapInfo::populate_header(size_t alignment) { - _header._magic = 0xf00baba2; - _header._version = _current_version; - _header._alignment = alignment; - _header._obj_alignment = ObjectAlignmentInBytes; + _header->populate(this, alignment); +} + +size_t FileMapInfo::FileMapHeader::data_size() { + return SharedClassUtil::file_map_header_size() - sizeof(FileMapInfo::FileMapHeaderBase); +} + +void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) { + _magic = 0xf00baba2; + _version = _current_version; + _alignment = alignment; + _obj_alignment = ObjectAlignmentInBytes; + _classpath_entry_table_size = mapinfo->_classpath_entry_table_size; + _classpath_entry_table = mapinfo->_classpath_entry_table; + _classpath_entry_size = mapinfo->_classpath_entry_size; // The following fields are for sanity checks for whether this archive // will function correctly with this JVM and the bootclasspath it's // invoked with. // JVM version string ... changes on each build. - get_header_version(_header._jvm_ident); + get_header_version(_jvm_ident); +} - // Build checks on classpath and jar files - _header._num_jars = 0; - ClassPathEntry *cpe = ClassLoader::classpath_entry(0); - for ( ; cpe != NULL; cpe = cpe->next()) { +void FileMapInfo::allocate_classpath_entry_table() { + int bytes = 0; + int count = 0; + char* strptr = NULL; + char* strptr_max = NULL; + Thread* THREAD = Thread::current(); - if (cpe->is_jar_file()) { - if (_header._num_jars >= JVM_SHARED_JARS_MAX) { - fail_stop("Too many jar files to share.", NULL); - } + ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); + size_t entry_size = SharedClassUtil::shared_class_path_entry_size(); - // Jar file - record timestamp and file size. - struct stat st; - const char *path = cpe->name(); - if (os::stat(path, &st) != 0) { - // If we can't access a jar file in the boot path, then we can't - // make assumptions about where classes get loaded from. - fail_stop("Unable to open jar file %s.", path); - } - _header._jar[_header._num_jars]._timestamp = st.st_mtime; - _header._jar[_header._num_jars]._filesize = st.st_size; - _header._num_jars++; - } else { + for (int pass=0; pass<2; pass++) { + ClassPathEntry *cpe = ClassLoader::classpath_entry(0); - // If directories appear in boot classpath, they must be empty to - // avoid having to verify each individual class file. - const char* name = ((ClassPathDirEntry*)cpe)->name(); - if (!os::dir_is_empty(name)) { - fail_stop("Boot classpath directory %s is not empty.", name); + for (int cur_entry = 0 ; cpe != NULL; cpe = cpe->next(), cur_entry++) { + const char *name = cpe->name(); + int name_bytes = (int)(strlen(name) + 1); + + if (pass == 0) { + count ++; + bytes += (int)entry_size; + bytes += name_bytes; + if (TraceClassPaths || (TraceClassLoading && Verbose)) { + tty->print_cr("[Add main shared path (%s) %s]", (cpe->is_jar_file() ? "jar" : "dir"), name); + } + } else { + SharedClassPathEntry* ent = shared_classpath(cur_entry); + if (cpe->is_jar_file()) { + struct stat st; + if (os::stat(name, &st) != 0) { + // The file/dir must exist, or it would not have been added + // into ClassLoader::classpath_entry(). + // + // If we can't access a jar file in the boot path, then we can't + // make assumptions about where classes get loaded from. + FileMapInfo::fail_stop("Unable to open jar file %s.", name); + } + + EXCEPTION_MARK; // The following call should never throw, but would exit VM on error. + SharedClassUtil::update_shared_classpath(cpe, ent, st.st_mtime, st.st_size, THREAD); + } else { + ent->_filesize = -1; + if (!os::dir_is_empty(name)) { + ClassLoader::exit_with_path_failure("Cannot have non-empty directory in archived classpaths", name); + } + } + ent->_name = strptr; + if (strptr + name_bytes <= strptr_max) { + strncpy(strptr, name, (size_t)name_bytes); // name_bytes includes trailing 0. + strptr += name_bytes; + } else { + assert(0, "miscalculated buffer size"); + } } } + + if (pass == 0) { + EXCEPTION_MARK; // The following call should never throw, but would exit VM on error. + Array* arr = MetadataFactory::new_array(loader_data, (bytes + 7)/8, THREAD); + strptr = (char*)(arr->data()); + strptr_max = strptr + bytes; + SharedClassPathEntry* table = (SharedClassPathEntry*)strptr; + strptr += entry_size * count; + + _classpath_entry_table_size = count; + _classpath_entry_table = table; + _classpath_entry_size = entry_size; + } } } +bool FileMapInfo::validate_classpath_entry_table() { + _validating_classpath_entry_table = true; + + int count = _header->_classpath_entry_table_size; + + _classpath_entry_table = _header->_classpath_entry_table; + _classpath_entry_size = _header->_classpath_entry_size; + + for (int i=0; i_name; + bool ok = true; + if (TraceClassPaths || (TraceClassLoading && Verbose)) { + tty->print_cr("[Checking shared classpath entry: %s]", name); + } + if (os::stat(name, &st) != 0) { + fail_continue("Required classpath entry does not exist: %s", name); + ok = false; + } else if (ent->is_dir()) { + if (!os::dir_is_empty(name)) { + fail_continue("directory is not empty: %s", name); + ok = false; + } + } else { + if (ent->_timestamp != st.st_mtime || + ent->_filesize != st.st_size) { + ok = false; + if (PrintSharedArchiveAndExit) { + fail_continue(ent->_timestamp != st.st_mtime ? + "Timestamp mismatch" : + "File size mismatch"); + } else { + fail_continue("A jar file is not the one used while building" + " the shared archive file: %s", name); + } + } + } + if (ok) { + if (TraceClassPaths || (TraceClassLoading && Verbose)) { + tty->print_cr("[ok]"); + } + } else if (!PrintSharedArchiveAndExit) { + _validating_classpath_entry_table = false; + return false; + } + } + + _classpath_entry_table_size = _header->_classpath_entry_table_size; + _validating_classpath_entry_table = false; + return true; +} + // Read the FileMapInfo information from the file. bool FileMapInfo::init_from_file(int fd) { - - size_t n = read(fd, &_header, sizeof(struct FileMapHeader)); - if (n != sizeof(struct FileMapHeader)) { + size_t sz = _header->data_size(); + char* addr = _header->data(); + size_t n = os::read(fd, addr, (unsigned int)sz); + if (n != sz) { fail_continue("Unable to read the file header."); return false; } - if (_header._version != current_version()) { + if (_header->_version != current_version()) { fail_continue("The shared archive file has the wrong version."); return false; } _file_offset = (long)n; + + size_t info_size = _header->_paths_misc_info_size; + _paths_misc_info = NEW_C_HEAP_ARRAY_RETURN_NULL(char, info_size, mtClass); + if (_paths_misc_info == NULL) { + fail_continue("Unable to read the file header."); + return false; + } + n = os::read(fd, _paths_misc_info, (unsigned int)info_size); + if (n != info_size) { + fail_continue("Unable to read the shared path info header."); + FREE_C_HEAP_ARRAY(char, _paths_misc_info, mtClass); + _paths_misc_info = NULL; + return false; + } + + _file_offset += (long)n; return true; } @@ -237,7 +386,16 @@ void FileMapInfo::open_for_write() { // Write the header to the file, seek to the next allocation boundary. void FileMapInfo::write_header() { - write_bytes_aligned(&_header, sizeof(FileMapHeader)); + int info_size = ClassLoader::get_shared_paths_misc_info_size(); + + _header->_paths_misc_info_size = info_size; + + align_file_position(); + size_t sz = _header->data_size(); + char* addr = _header->data(); + write_bytes(addr, (int)sz); // skip the C++ vtable + write_bytes(ClassLoader::get_shared_paths_misc_info(), info_size); + align_file_position(); } @@ -247,7 +405,7 @@ void FileMapInfo::write_space(int i, Metaspace* space, bool read_only) { align_file_position(); size_t used = space->used_bytes_slow(Metaspace::NonClassType); size_t capacity = space->capacity_bytes_slow(Metaspace::NonClassType); - struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[i]; + struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i]; write_region(i, (char*)space->bottom(), used, capacity, read_only, false); } @@ -257,7 +415,7 @@ void FileMapInfo::write_space(int i, Metaspace* space, bool read_only) { void FileMapInfo::write_region(int region, char* base, size_t size, size_t capacity, bool read_only, bool allow_exec) { - struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[region]; + struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[region]; if (_file_open) { guarantee(si->_file_offset == _file_offset, "file offset mismatch."); @@ -339,7 +497,7 @@ void FileMapInfo::close() { // JVM/TI RedefineClasses() support: // Remap the shared readonly space to shared readwrite, private. bool FileMapInfo::remap_shared_readonly_as_readwrite() { - struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[0]; + struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[0]; if (!si->_read_only) { // the space is already readwrite so we are done return true; @@ -367,7 +525,7 @@ bool FileMapInfo::remap_shared_readonly_as_readwrite() { // Map the whole region at once, assumed to be allocated contiguously. ReservedSpace FileMapInfo::reserve_shared_memory() { - struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[0]; + struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[0]; char* requested_addr = si->_base; size_t size = FileMapInfo::shared_spaces_size(); @@ -389,7 +547,7 @@ ReservedSpace FileMapInfo::reserve_shared_memory() { static const char* shared_region_name[] = { "ReadOnly", "ReadWrite", "MiscData", "MiscCode"}; char* FileMapInfo::map_region(int i) { - struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[i]; + struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i]; size_t used = si->_used; size_t alignment = os::vm_allocation_granularity(); size_t size = align_size_up(used, alignment); @@ -415,7 +573,7 @@ char* FileMapInfo::map_region(int i) { // Unmap a memory region in the address space. void FileMapInfo::unmap_region(int i) { - struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[i]; + struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i]; size_t used = si->_used; size_t size = align_size_up(used, os::vm_allocation_granularity()); if (!os::unmap_memory(si->_base, size)) { @@ -432,12 +590,21 @@ void FileMapInfo::assert_mark(bool check) { FileMapInfo* FileMapInfo::_current_info = NULL; - +SharedClassPathEntry* FileMapInfo::_classpath_entry_table = NULL; +int FileMapInfo::_classpath_entry_table_size = 0; +size_t FileMapInfo::_classpath_entry_size = 0x1234baad; +bool FileMapInfo::_validating_classpath_entry_table = false; // Open the shared archive file, read and validate the header // information (version, boot classpath, etc.). If initialization // fails, shared spaces are disabled and the file is closed. [See // fail_continue.] +// +// Validation of the archive is done in two steps: +// +// [1] validate_header() - done here. This checks the header, including _paths_misc_info. +// [2] validate_classpath_entry_table - this is done later, because the table is in the RW +// region of the archive, which is not mapped yet. bool FileMapInfo::initialize() { assert(UseSharedSpaces, "UseSharedSpaces expected."); @@ -451,92 +618,66 @@ bool FileMapInfo::initialize() { } init_from_file(_fd); - if (!validate()) { + if (!validate_header()) { return false; } - SharedReadOnlySize = _header._space[0]._capacity; - SharedReadWriteSize = _header._space[1]._capacity; - SharedMiscDataSize = _header._space[2]._capacity; - SharedMiscCodeSize = _header._space[3]._capacity; + SharedReadOnlySize = _header->_space[0]._capacity; + SharedReadWriteSize = _header->_space[1]._capacity; + SharedMiscDataSize = _header->_space[2]._capacity; + SharedMiscCodeSize = _header->_space[3]._capacity; return true; } - -bool FileMapInfo::validate() { - if (_header._version != current_version()) { - fail_continue("The shared archive file is the wrong version."); +bool FileMapInfo::FileMapHeader::validate() { + if (_version != current_version()) { + FileMapInfo::fail_continue("The shared archive file is the wrong version."); return false; } - if (_header._magic != (int)0xf00baba2) { - fail_continue("The shared archive file has a bad magic number."); + if (_magic != (int)0xf00baba2) { + FileMapInfo::fail_continue("The shared archive file has a bad magic number."); return false; } char header_version[JVM_IDENT_MAX]; get_header_version(header_version); - if (strncmp(_header._jvm_ident, header_version, JVM_IDENT_MAX-1) != 0) { - fail_continue("The shared archive file was created by a different" - " version or build of HotSpot."); - return false; - } - if (_header._obj_alignment != ObjectAlignmentInBytes) { - fail_continue("The shared archive file's ObjectAlignmentInBytes of %d" - " does not equal the current ObjectAlignmentInBytes of %d.", - _header._obj_alignment, ObjectAlignmentInBytes); - return false; - } - - // Cannot verify interpreter yet, as it can only be created after the GC - // heap has been initialized. - - if (_header._num_jars >= JVM_SHARED_JARS_MAX) { - fail_continue("Too many jar files to share."); - return false; - } - - // Build checks on classpath and jar files - int num_jars_now = 0; - ClassPathEntry *cpe = ClassLoader::classpath_entry(0); - for ( ; cpe != NULL; cpe = cpe->next()) { - - if (cpe->is_jar_file()) { - if (num_jars_now < _header._num_jars) { - - // Jar file - verify timestamp and file size. - struct stat st; - const char *path = cpe->name(); - if (os::stat(path, &st) != 0) { - fail_continue("Unable to open jar file %s.", path); - return false; - } - if (_header._jar[num_jars_now]._timestamp != st.st_mtime || - _header._jar[num_jars_now]._filesize != st.st_size) { - fail_continue("A jar file is not the one used while building" - " the shared archive file."); - return false; - } - } - ++num_jars_now; - } else { - - // If directories appear in boot classpath, they must be empty to - // avoid having to verify each individual class file. - const char* name = ((ClassPathDirEntry*)cpe)->name(); - if (!os::dir_is_empty(name)) { - fail_continue("Boot classpath directory %s is not empty.", name); - return false; - } + if (strncmp(_jvm_ident, header_version, JVM_IDENT_MAX-1) != 0) { + if (TraceClassPaths) { + tty->print_cr("Expected: %s", header_version); + tty->print_cr("Actual: %s", _jvm_ident); } + FileMapInfo::fail_continue("The shared archive file was created by a different" + " version or build of HotSpot"); + return false; } - if (num_jars_now < _header._num_jars) { - fail_continue("The number of jar files in the boot classpath is" - " less than the number the shared archive was created with."); + if (_obj_alignment != ObjectAlignmentInBytes) { + FileMapInfo::fail_continue("The shared archive file's ObjectAlignmentInBytes of %d" + " does not equal the current ObjectAlignmentInBytes of %d.", + _obj_alignment, ObjectAlignmentInBytes); return false; } return true; } +bool FileMapInfo::validate_header() { + bool status = _header->validate(); + + if (status) { + if (!ClassLoader::check_shared_paths_misc_info(_paths_misc_info, _header->_paths_misc_info_size)) { + if (!PrintSharedArchiveAndExit) { + fail_continue("shared class paths mismatch (hint: enable -XX:+TraceClassPaths to diagnose the failure)"); + status = false; + } + } + } + + if (_paths_misc_info != NULL) { + FREE_C_HEAP_ARRAY(char, _paths_misc_info, mtClass); + _paths_misc_info = NULL; + } + return status; +} + // The following method is provided to see whether a given pointer // falls in the mapped shared space. // Param: @@ -545,8 +686,8 @@ bool FileMapInfo::validate() { // True if the p is within the mapped shared space, otherwise, false. bool FileMapInfo::is_in_shared_space(const void* p) { for (int i = 0; i < MetaspaceShared::n_regions; i++) { - if (p >= _header._space[i]._base && - p < _header._space[i]._base + _header._space[i]._used) { + if (p >= _header->_space[i]._base && + p < _header->_space[i]._base + _header->_space[i]._used) { return true; } } @@ -557,7 +698,7 @@ bool FileMapInfo::is_in_shared_space(const void* p) { void FileMapInfo::print_shared_spaces() { gclog_or_tty->print_cr("Shared Spaces:"); for (int i = 0; i < MetaspaceShared::n_regions; i++) { - struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[i]; + struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i]; gclog_or_tty->print(" %s " INTPTR_FORMAT "-" INTPTR_FORMAT, shared_region_name[i], si->_base, si->_base + si->_used); @@ -570,9 +711,9 @@ void FileMapInfo::stop_sharing_and_unmap(const char* msg) { if (map_info) { map_info->fail_continue(msg); for (int i = 0; i < MetaspaceShared::n_regions; i++) { - if (map_info->_header._space[i]._base != NULL) { + if (map_info->_header->_space[i]._base != NULL) { map_info->unmap_region(i); - map_info->_header._space[i]._base = NULL; + map_info->_header->_space[i]._base = NULL; } } } else if (DumpSharedSpaces) { diff --git a/hotspot/src/share/vm/memory/filemap.hpp b/hotspot/src/share/vm/memory/filemap.hpp index 166486fa3f0..b2b722a91aa 100644 --- a/hotspot/src/share/vm/memory/filemap.hpp +++ b/hotspot/src/share/vm/memory/filemap.hpp @@ -37,30 +37,55 @@ // misc data (block offset table, string table, symbols, dictionary, etc.) // tag(666) -static const int JVM_SHARED_JARS_MAX = 128; -static const int JVM_SPACENAME_MAX = 128; static const int JVM_IDENT_MAX = 256; -static const int JVM_ARCH_MAX = 12; - class Metaspace; +class SharedClassPathEntry VALUE_OBJ_CLASS_SPEC { +public: + const char *_name; + time_t _timestamp; // jar timestamp, 0 if is directory + long _filesize; // jar file size, -1 if is directory + bool is_dir() { + return _filesize == -1; + } +}; + class FileMapInfo : public CHeapObj { private: + friend class ManifestStream; enum { _invalid_version = -1, - _current_version = 1 + _current_version = 2 }; bool _file_open; int _fd; long _file_offset; +private: + static SharedClassPathEntry* _classpath_entry_table; + static int _classpath_entry_table_size; + static size_t _classpath_entry_size; + static bool _validating_classpath_entry_table; + // FileMapHeader describes the shared space data in the file to be // mapped. This structure gets written to a file. It is not a class, so // that the compilers don't add any compiler-private data to it. - struct FileMapHeader { +public: + struct FileMapHeaderBase : public CHeapObj { + virtual bool validate() = 0; + virtual void populate(FileMapInfo* info, size_t alignment) = 0; + }; + struct FileMapHeader : FileMapHeaderBase { + // Use data() and data_size() to memcopy to/from the FileMapHeader. We need to + // avoid read/writing the C++ vtable pointer. + static size_t data_size(); + char* data() { + return ((char*)this) + sizeof(FileMapHeaderBase); + } + int _magic; // identify file type. int _version; // (from enum, above.) size_t _alignment; // how shared archive should be aligned @@ -78,44 +103,64 @@ private: // The following fields are all sanity checks for whether this archive // will function correctly with this JVM and the bootclasspath it's // invoked with. - char _arch[JVM_ARCH_MAX]; // architecture char _jvm_ident[JVM_IDENT_MAX]; // identifier for jvm - int _num_jars; // Number of jars in bootclasspath - // Per jar file data: timestamp, size. + // The _paths_misc_info is a variable-size structure that records "miscellaneous" + // information during dumping. It is generated and validated by the + // SharedPathsMiscInfo class. See SharedPathsMiscInfo.hpp and sharedClassUtil.hpp for + // detailed description. + // + // The _paths_misc_info data is stored as a byte array in the archive file header, + // immediately after the _header field. This information is used only when + // checking the validity of the archive and is deallocated after the archive is loaded. + // + // Note that the _paths_misc_info does NOT include information for JAR files + // that existed during dump time. Their information is stored in _classpath_entry_table. + int _paths_misc_info_size; + + // The following is a table of all the class path entries that were used + // during dumping. At run time, we require these files to exist and have the same + // size/modification time, or else the archive will refuse to load. + // + // All of these entries must be JAR files. The dumping process would fail if a non-empty + // directory was specified in the classpaths. If an empty directory was specified + // it is checked by the _paths_misc_info as described above. + // + // FIXME -- if JAR files in the tail of the list were specified but not used during dumping, + // they should be removed from this table, to save space and to avoid spurious + // loading failures during runtime. + int _classpath_entry_table_size; + size_t _classpath_entry_size; + SharedClassPathEntry* _classpath_entry_table; + + virtual bool validate(); + virtual void populate(FileMapInfo* info, size_t alignment); + }; + + FileMapHeader * _header; - struct { - time_t _timestamp; // jar timestamp. - long _filesize; // jar file size. - } _jar[JVM_SHARED_JARS_MAX]; - } _header; const char* _full_path; + char* _paths_misc_info; static FileMapInfo* _current_info; bool init_from_file(int fd); void align_file_position(); + bool validate_header_impl(); public: - FileMapInfo() { - _file_offset = 0; - _file_open = false; - _header._version = _invalid_version; - } + FileMapInfo(); + ~FileMapInfo(); static int current_version() { return _current_version; } void populate_header(size_t alignment); - bool validate(); + bool validate_header(); void invalidate(); - int version() { return _header._version; } - size_t alignment() { return _header._alignment; } - size_t space_capacity(int i) { return _header._space[i]._capacity; } - char* region_base(int i) { return _header._space[i]._base; } - struct FileMapHeader* header() { return &_header; } - - static void set_current_info(FileMapInfo* info) { - CDS_ONLY(_current_info = info;) - } + int version() { return _header->_version; } + size_t alignment() { return _header->_alignment; } + size_t space_capacity(int i) { return _header->_space[i]._capacity; } + char* region_base(int i) { return _header->_space[i]._base; } + struct FileMapHeader* header() { return _header; } static FileMapInfo* current_info() { CDS_ONLY(return _current_info;) @@ -146,7 +191,7 @@ public: // Errors. static void fail_stop(const char *msg, ...); - void fail_continue(const char *msg, ...); + static void fail_continue(const char *msg, ...); // Return true if given address is in the mapped shared space. bool is_in_shared_space(const void* p) NOT_CDS_RETURN_(false); @@ -160,6 +205,22 @@ public: // Stop CDS sharing and unmap CDS regions. static void stop_sharing_and_unmap(const char* msg); + + static void allocate_classpath_entry_table(); + bool validate_classpath_entry_table(); + + static SharedClassPathEntry* shared_classpath(int index) { + char* p = (char*)_classpath_entry_table; + p += _classpath_entry_size * index; + return (SharedClassPathEntry*)p; + } + static const char* shared_classpath_name(int index) { + return shared_classpath(index)->_name; + } + + static int get_number_of_share_classpaths() { + return _classpath_entry_table_size; + } }; #endif // SHARE_VM_MEMORY_FILEMAP_HPP diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.cpp b/hotspot/src/share/vm/memory/genCollectedHeap.cpp index 4b5deb03c05..9cd841f038a 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp @@ -708,15 +708,18 @@ void GenCollectedHeap::collect(GCCause::Cause cause) { #else // INCLUDE_ALL_GCS ShouldNotReachHere(); #endif // INCLUDE_ALL_GCS + } else if (cause == GCCause::_wb_young_gc) { + // minor collection for WhiteBox API + collect(cause, 0); } else { #ifdef ASSERT - if (cause == GCCause::_scavenge_alot) { - // minor collection only - collect(cause, 0); - } else { - // Stop-the-world full collection - collect(cause, n_gens() - 1); - } + if (cause == GCCause::_scavenge_alot) { + // minor collection only + collect(cause, 0); + } else { + // Stop-the-world full collection + collect(cause, n_gens() - 1); + } #else // Stop-the-world full collection collect(cause, n_gens() - 1); diff --git a/hotspot/src/share/vm/memory/metadataFactory.hpp b/hotspot/src/share/vm/memory/metadataFactory.hpp index dbb936fdf57..0f9936802cd 100644 --- a/hotspot/src/share/vm/memory/metadataFactory.hpp +++ b/hotspot/src/share/vm/memory/metadataFactory.hpp @@ -79,6 +79,12 @@ class MetadataFactory : AllStatic { // Deallocation method for metadata template static void free_metadata(ClassLoaderData* loader_data, T md) { + if (DumpSharedSpaces) { + // FIXME: the freeing code is buggy, especially when PrintSharedSpaces is enabled. + // Disable for now -- this means if you specify bad classes in your classlist you + // may have wasted space inside the archive. + return; + } if (md != NULL) { assert(loader_data != NULL, "shouldn't pass null"); int size = md->size(); diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp index 2f52e388d52..678af113ff9 100644 --- a/hotspot/src/share/vm/memory/metaspace.cpp +++ b/hotspot/src/share/vm/memory/metaspace.cpp @@ -413,6 +413,7 @@ static bool should_commit_large_pages_when_reserving(size_t bytes) { VirtualSpaceNode::VirtualSpaceNode(size_t bytes) : _top(NULL), _next(NULL), _rs(), _container_count(0) { assert_is_size_aligned(bytes, Metaspace::reserve_alignment()); +#if INCLUDE_CDS // This allocates memory with mmap. For DumpSharedspaces, try to reserve // configurable address, generally at the top of the Java heap so other // memory addresses don't conflict. @@ -428,7 +429,9 @@ VirtualSpaceNode::VirtualSpaceNode(size_t bytes) : _top(NULL), _next(NULL), _rs( _rs = ReservedSpace(bytes, Metaspace::reserve_alignment(), large_pages); } MetaspaceShared::set_shared_rs(&_rs); - } else { + } else +#endif + { bool large_pages = should_commit_large_pages_when_reserving(bytes); _rs = ReservedSpace(bytes, Metaspace::reserve_alignment(), large_pages); @@ -2939,11 +2942,14 @@ void Metaspace::set_narrow_klass_base_and_shift(address metaspace_base, address // between the lower base and higher address. address lower_base; address higher_address; +#if INCLUDE_CDS if (UseSharedSpaces) { higher_address = MAX2((address)(cds_base + FileMapInfo::shared_spaces_size()), (address)(metaspace_base + compressed_class_space_size())); lower_base = MIN2(metaspace_base, cds_base); - } else { + } else +#endif + { higher_address = metaspace_base + compressed_class_space_size(); lower_base = metaspace_base; @@ -2964,6 +2970,7 @@ void Metaspace::set_narrow_klass_base_and_shift(address metaspace_base, address } } +#if INCLUDE_CDS // Return TRUE if the specified metaspace_base and cds_base are close enough // to work with compressed klass pointers. bool Metaspace::can_use_cds_with_metaspace_addr(char* metaspace_base, address cds_base) { @@ -2974,6 +2981,7 @@ bool Metaspace::can_use_cds_with_metaspace_addr(char* metaspace_base, address cd (address)(metaspace_base + compressed_class_space_size())); return ((uint64_t)(higher_address - lower_base) <= UnscaledClassSpaceMax); } +#endif // Try to allocate the metaspace at the requested addr. void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, address cds_base) { @@ -2993,6 +3001,7 @@ void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, a large_pages, requested_addr, 0); if (!metaspace_rs.is_reserved()) { +#if INCLUDE_CDS if (UseSharedSpaces) { size_t increment = align_size_up(1*G, _reserve_alignment); @@ -3007,7 +3016,7 @@ void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, a _reserve_alignment, large_pages, addr, 0); } } - +#endif // If no successful allocation then try to allocate the space anywhere. If // that fails then OOM doom. At this point we cannot try allocating the // metaspace as if UseCompressedClassPointers is off because too much @@ -3026,12 +3035,13 @@ void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, a // If we got here then the metaspace got allocated. MemTracker::record_virtual_memory_type((address)metaspace_rs.base(), mtClass); +#if INCLUDE_CDS // Verify that we can use shared spaces. Otherwise, turn off CDS. if (UseSharedSpaces && !can_use_cds_with_metaspace_addr(metaspace_rs.base(), cds_base)) { FileMapInfo::stop_sharing_and_unmap( "Could not allocate metaspace at a compatible address"); } - +#endif set_narrow_klass_base_and_shift((address)metaspace_rs.base(), UseSharedSpaces ? (address)cds_base : 0); @@ -3115,6 +3125,7 @@ void Metaspace::global_initialize() { MetaspaceShared::set_max_alignment(max_alignment); if (DumpSharedSpaces) { +#if INCLUDE_CDS SharedReadOnlySize = align_size_up(SharedReadOnlySize, max_alignment); SharedReadWriteSize = align_size_up(SharedReadWriteSize, max_alignment); SharedMiscDataSize = align_size_up(SharedMiscDataSize, max_alignment); @@ -3152,23 +3163,22 @@ void Metaspace::global_initialize() { } Universe::set_narrow_klass_shift(0); -#endif - +#endif // _LP64 +#endif // INCLUDE_CDS } else { +#if INCLUDE_CDS // If using shared space, open the file that contains the shared space // and map in the memory before initializing the rest of metaspace (so // the addresses don't conflict) address cds_address = NULL; if (UseSharedSpaces) { FileMapInfo* mapinfo = new FileMapInfo(); - memset(mapinfo, 0, sizeof(FileMapInfo)); // Open the shared archive file, read and validate the header. If // initialization fails, shared spaces [UseSharedSpaces] are // disabled and the file is closed. // Map in spaces now also if (mapinfo->initialize() && MetaspaceShared::map_shared_spaces(mapinfo)) { - FileMapInfo::set_current_info(mapinfo); cds_total = FileMapInfo::shared_spaces_size(); cds_address = (address)mapinfo->region_base(0); } else { @@ -3176,21 +3186,23 @@ void Metaspace::global_initialize() { "archive file not closed or shared spaces not disabled."); } } - +#endif // INCLUDE_CDS #ifdef _LP64 // If UseCompressedClassPointers is set then allocate the metaspace area // above the heap and above the CDS area (if it exists). if (using_class_space()) { if (UseSharedSpaces) { +#if INCLUDE_CDS char* cds_end = (char*)(cds_address + cds_total); cds_end = (char *)align_ptr_up(cds_end, _reserve_alignment); allocate_metaspace_compressed_klass_ptrs(cds_end, cds_address); +#endif } else { char* base = (char*)align_ptr_up(Universe::heap()->reserved_region().end(), _reserve_alignment); allocate_metaspace_compressed_klass_ptrs(base, 0); } } -#endif +#endif // _LP64 // Initialize these before initializing the VirtualSpaceList _first_chunk_word_size = InitialBootClassLoaderMetaspaceSize / BytesPerWord; @@ -3380,6 +3392,10 @@ void Metaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) { assert(!SafepointSynchronize::is_at_safepoint() || Thread::current()->is_VM_thread(), "should be the VM thread"); + if (DumpSharedSpaces && PrintSharedSpaces) { + record_deallocation(ptr, vsm()->get_raw_word_size(word_size)); + } + MutexLockerEx ml(vsm()->lock(), Mutex::_no_safepoint_check_flag); if (word_size < TreeChunk >::min_size()) { @@ -3417,8 +3433,9 @@ MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, if (result == NULL) { report_out_of_shared_space(read_only ? SharedReadOnly : SharedReadWrite); } - - space->record_allocation(result, type, space->vsm()->get_raw_word_size(word_size)); + if (PrintSharedSpaces) { + space->record_allocation(result, type, space->vsm()->get_raw_word_size(word_size)); + } // Zero initialize. Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0); @@ -3517,15 +3534,55 @@ const char* Metaspace::metadata_type_name(Metaspace::MetadataType mdtype) { void Metaspace::record_allocation(void* ptr, MetaspaceObj::Type type, size_t word_size) { assert(DumpSharedSpaces, "sanity"); - AllocRecord *rec = new AllocRecord((address)ptr, type, (int)word_size * HeapWordSize); + int byte_size = (int)word_size * HeapWordSize; + AllocRecord *rec = new AllocRecord((address)ptr, type, byte_size); + if (_alloc_record_head == NULL) { _alloc_record_head = _alloc_record_tail = rec; - } else { + } else if (_alloc_record_tail->_ptr + _alloc_record_tail->_byte_size == (address)ptr) { _alloc_record_tail->_next = rec; _alloc_record_tail = rec; + } else { + // slow linear search, but this doesn't happen that often, and only when dumping + for (AllocRecord *old = _alloc_record_head; old; old = old->_next) { + if (old->_ptr == ptr) { + assert(old->_type == MetaspaceObj::DeallocatedType, "sanity"); + int remain_bytes = old->_byte_size - byte_size; + assert(remain_bytes >= 0, "sanity"); + old->_type = type; + + if (remain_bytes == 0) { + delete(rec); + } else { + address remain_ptr = address(ptr) + byte_size; + rec->_ptr = remain_ptr; + rec->_byte_size = remain_bytes; + rec->_type = MetaspaceObj::DeallocatedType; + rec->_next = old->_next; + old->_byte_size = byte_size; + old->_next = rec; + } + return; + } + } + assert(0, "reallocating a freed pointer that was not recorded"); } } +void Metaspace::record_deallocation(void* ptr, size_t word_size) { + assert(DumpSharedSpaces, "sanity"); + + for (AllocRecord *rec = _alloc_record_head; rec; rec = rec->_next) { + if (rec->_ptr == ptr) { + assert(rec->_byte_size == (int)word_size * HeapWordSize, "sanity"); + rec->_type = MetaspaceObj::DeallocatedType; + return; + } + } + + assert(0, "deallocating a pointer that was not recorded"); +} + void Metaspace::iterate(Metaspace::AllocRecordClosure *closure) { assert(DumpSharedSpaces, "unimplemented for !DumpSharedSpaces"); diff --git a/hotspot/src/share/vm/memory/metaspace.hpp b/hotspot/src/share/vm/memory/metaspace.hpp index 545bf0e7fbd..ef9ad65b088 100644 --- a/hotspot/src/share/vm/memory/metaspace.hpp +++ b/hotspot/src/share/vm/memory/metaspace.hpp @@ -171,9 +171,10 @@ class Metaspace : public CHeapObj { static const MetaspaceTracer* tracer() { return _tracer; } private: - // This is used by DumpSharedSpaces only, where only _vsm is used. So we will + // These 2 methods are used by DumpSharedSpaces only, where only _vsm is used. So we will // maintain a single list for now. void record_allocation(void* ptr, MetaspaceObj::Type type, size_t word_size); + void record_deallocation(void* ptr, size_t word_size); #ifdef _LP64 static void set_narrow_klass_base_and_shift(address metaspace_base, address cds_base); diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp index 8aff392b5a1..f9e3b17ec9d 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.cpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp @@ -26,6 +26,7 @@ #include "classfile/dictionary.hpp" #include "classfile/loaderConstraints.hpp" #include "classfile/placeholders.hpp" +#include "classfile/sharedClassUtil.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "code/codeCache.hpp" @@ -47,6 +48,10 @@ int MetaspaceShared::_max_alignment = 0; ReservedSpace* MetaspaceShared::_shared_rs = NULL; +bool MetaspaceShared::_link_classes_made_progress; +bool MetaspaceShared::_check_classes_made_progress; +bool MetaspaceShared::_has_error_classes; +bool MetaspaceShared::_archive_loading_failed = false; // Read/write a data stream for restoring/preserving metadata pointers and // miscellaneous data from/to the shared archive file. @@ -446,6 +451,23 @@ void VM_PopulateDumpSharedSpace::doit() { SystemDictionary::classes_do(collect_classes); tty->print_cr("Number of classes %d", _global_klass_objects->length()); + { + int num_type_array = 0, num_obj_array = 0, num_inst = 0; + for (int i = 0; i < _global_klass_objects->length(); i++) { + Klass* k = _global_klass_objects->at(i); + if (k->oop_is_instance()) { + num_inst ++; + } else if (k->oop_is_objArray()) { + num_obj_array ++; + } else { + assert(k->oop_is_typeArray(), "sanity"); + num_type_array ++; + } + } + tty->print_cr(" instance classes = %5d", num_inst); + tty->print_cr(" obj array classes = %5d", num_obj_array); + tty->print_cr(" type array classes = %5d", num_type_array); + } // Update all the fingerprints in the shared methods. tty->print("Calculating fingerprints ... "); @@ -611,38 +633,58 @@ void VM_PopulateDumpSharedSpace::doit() { #undef fmt_space } -static void link_shared_classes(Klass* obj, TRAPS) { + +void MetaspaceShared::link_one_shared_class(Klass* obj, TRAPS) { Klass* k = obj; if (k->oop_is_instance()) { InstanceKlass* ik = (InstanceKlass*) k; // Link the class to cause the bytecodes to be rewritten and the - // cpcache to be created. - if (ik->init_state() < InstanceKlass::linked) { - ik->link_class(THREAD); - guarantee(!HAS_PENDING_EXCEPTION, "exception in class rewriting"); + // cpcache to be created. Class verification is done according + // to -Xverify setting. + _link_classes_made_progress |= try_link_class(ik, THREAD); + guarantee(!HAS_PENDING_EXCEPTION, "exception in link_class"); + } +} + +void MetaspaceShared::check_one_shared_class(Klass* k) { + if (k->oop_is_instance() && InstanceKlass::cast(k)->check_sharing_error_state()) { + _check_classes_made_progress = true; + } +} + +void MetaspaceShared::link_and_cleanup_shared_classes(TRAPS) { + // We need to iterate because verification may cause additional classes + // to be loaded. + do { + _link_classes_made_progress = false; + SystemDictionary::classes_do(link_one_shared_class, THREAD); + guarantee(!HAS_PENDING_EXCEPTION, "exception in link_class"); + } while (_link_classes_made_progress); + + if (_has_error_classes) { + // Mark all classes whose super class or interfaces failed verification. + do { + // Not completely sure if we need to do this iteratively. Anyway, + // we should come here only if there are unverifiable classes, which + // shouldn't happen in normal cases. So better safe than sorry. + _check_classes_made_progress = false; + SystemDictionary::classes_do(check_one_shared_class); + } while (_check_classes_made_progress); + + if (IgnoreUnverifiableClassesDuringDump) { + // This is useful when running JCK or SQE tests. You should not + // enable this when running real apps. + SystemDictionary::remove_classes_in_error_state(); + } else { + tty->print_cr("Please remove the unverifiable classes from your class list and try again"); + exit(1); } } } - -// Support for a simple checksum of the contents of the class list -// file to prevent trivial tampering. The algorithm matches that in -// the MakeClassList program used by the J2SE build process. -#define JSUM_SEED ((jlong)CONST64(0xcafebabebabecafe)) -static jlong -jsum(jlong start, const char *buf, const int len) -{ - jlong h = start; - char *p = (char *)buf, *e = p + len; - while (p < e) { - char c = *p++; - if (c <= ' ') { - /* Skip spaces and control characters */ - continue; - } - h = 31 * h + c; - } - return h; +void MetaspaceShared::prepare_for_dumping() { + ClassLoader::initialize_shared_path(); + FileMapInfo::allocate_classpath_entry_table(); } // Preload classes from a list, populate the shared spaces and dump to a @@ -651,72 +693,112 @@ void MetaspaceShared::preload_and_dump(TRAPS) { TraceTime timer("Dump Shared Spaces", TraceStartupTime); ResourceMark rm; + tty->print_cr("Allocated shared space: %d bytes at " PTR_FORMAT, + MetaspaceShared::shared_rs()->size(), + MetaspaceShared::shared_rs()->base()); + // Preload classes to be shared. // Should use some os:: method rather than fopen() here. aB. - // Construct the path to the class list (in jre/lib) - // Walk up two directories from the location of the VM and - // optionally tack on "lib" (depending on platform) - char class_list_path[JVM_MAXPATHLEN]; - os::jvm_path(class_list_path, sizeof(class_list_path)); - for (int i = 0; i < 3; i++) { - char *end = strrchr(class_list_path, *os::file_separator()); - if (end != NULL) *end = '\0'; - } - int class_list_path_len = (int)strlen(class_list_path); - if (class_list_path_len >= 3) { - if (strcmp(class_list_path + class_list_path_len - 3, "lib") != 0) { - strcat(class_list_path, os::file_separator()); - strcat(class_list_path, "lib"); + const char* class_list_path; + if (SharedClassListFile == NULL) { + // Construct the path to the class list (in jre/lib) + // Walk up two directories from the location of the VM and + // optionally tack on "lib" (depending on platform) + char class_list_path_str[JVM_MAXPATHLEN]; + os::jvm_path(class_list_path_str, sizeof(class_list_path_str)); + for (int i = 0; i < 3; i++) { + char *end = strrchr(class_list_path_str, *os::file_separator()); + if (end != NULL) *end = '\0'; } + int class_list_path_len = (int)strlen(class_list_path_str); + if (class_list_path_len >= 3) { + if (strcmp(class_list_path_str + class_list_path_len - 3, "lib") != 0) { + strcat(class_list_path_str, os::file_separator()); + strcat(class_list_path_str, "lib"); + } + } + strcat(class_list_path_str, os::file_separator()); + strcat(class_list_path_str, "classlist"); + class_list_path = class_list_path_str; + } else { + class_list_path = SharedClassListFile; } - strcat(class_list_path, os::file_separator()); - strcat(class_list_path, "classlist"); + int class_count = 0; + GrowableArray* class_promote_order = new GrowableArray(); + + // sun.io.Converters + static const char obj_array_sig[] = "[[Ljava/lang/Object;"; + SymbolTable::new_permanent_symbol(obj_array_sig, THREAD); + + // java.util.HashMap + static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;"; + SymbolTable::new_permanent_symbol(map_entry_array_sig, THREAD); + + tty->print_cr("Loading classes to share ..."); + _has_error_classes = false; + class_count += preload_and_dump(class_list_path, class_promote_order, + THREAD); + if (ExtraSharedClassListFile) { + class_count += preload_and_dump(ExtraSharedClassListFile, class_promote_order, + THREAD); + } + tty->print_cr("Loading classes to share: done."); + + if (PrintSharedSpaces) { + tty->print_cr("Shared spaces: preloaded %d classes", class_count); + } + + // Rewrite and link classes + tty->print_cr("Rewriting and linking classes ..."); + + // Link any classes which got missed. This would happen if we have loaded classes that + // were not explicitly specified in the classlist. E.g., if an interface implemented by class K + // fails verification, all other interfaces that were not specified in the classlist but + // are implemented by K are not verified. + link_and_cleanup_shared_classes(CATCH); + tty->print_cr("Rewriting and linking classes: done"); + + // Create and dump the shared spaces. Everything so far is loaded + // with the null class loader. + ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); + VM_PopulateDumpSharedSpace op(loader_data, class_promote_order); + VMThread::execute(&op); + + // Since various initialization steps have been undone by this process, + // it is not reasonable to continue running a java process. + exit(0); +} + +int MetaspaceShared::preload_and_dump(const char * class_list_path, + GrowableArray* class_promote_order, + TRAPS) { FILE* file = fopen(class_list_path, "r"); + char class_name[256]; + int class_count = 0; + if (file != NULL) { - jlong computed_jsum = JSUM_SEED; - jlong file_jsum = 0; - - char class_name[256]; - int class_count = 0; - GrowableArray* class_promote_order = new GrowableArray(); - - // sun.io.Converters - static const char obj_array_sig[] = "[[Ljava/lang/Object;"; - SymbolTable::new_permanent_symbol(obj_array_sig, THREAD); - - // java.util.HashMap - static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;"; - SymbolTable::new_permanent_symbol(map_entry_array_sig, THREAD); - - tty->print("Loading classes to share ... "); while ((fgets(class_name, sizeof class_name, file)) != NULL) { - if (*class_name == '#') { - jint fsh, fsl; - if (sscanf(class_name, "# %8x%8x\n", &fsh, &fsl) == 2) { - file_jsum = ((jlong)(fsh) << 32) | (fsl & 0xffffffff); - } - + if (*class_name == '#') { // comment continue; } // Remove trailing newline size_t name_len = strlen(class_name); - class_name[name_len-1] = '\0'; - - computed_jsum = jsum(computed_jsum, class_name, (const int)name_len - 1); + if (class_name[name_len-1] == '\n') { + class_name[name_len-1] = '\0'; + } // Got a class name - load it. TempNewSymbol class_name_symbol = SymbolTable::new_permanent_symbol(class_name, THREAD); guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol."); Klass* klass = SystemDictionary::resolve_or_null(class_name_symbol, THREAD); - guarantee(!HAS_PENDING_EXCEPTION, "Exception resolving a class."); + CLEAR_PENDING_EXCEPTION; if (klass != NULL) { if (PrintSharedSpaces && Verbose && WizardMode) { tty->print_cr("Shared spaces preloaded: %s", class_name); } - InstanceKlass* ik = InstanceKlass::cast(klass); // Should be class load order as per -XX:+TraceClassLoadingPreorder @@ -726,52 +808,14 @@ void MetaspaceShared::preload_and_dump(TRAPS) { // cpcache to be created. The linking is done as soon as classes // are loaded in order that the related data structures (klass and // cpCache) are located together. - - if (ik->init_state() < InstanceKlass::linked) { - ik->link_class(THREAD); - guarantee(!(HAS_PENDING_EXCEPTION), "exception in class rewriting"); - } - - // TODO: Resolve klasses in constant pool - ik->constants()->resolve_class_constants(THREAD); + try_link_class(ik, THREAD); + guarantee(!HAS_PENDING_EXCEPTION, "exception in link_class"); class_count++; } else { - if (PrintSharedSpaces && Verbose && WizardMode) { - tty->cr(); - tty->print_cr(" Preload failed: %s", class_name); - } + //tty->print_cr("Preload failed: %s", class_name); } - file_jsum = 0; // Checksum must be on last line of file } - if (computed_jsum != file_jsum) { - tty->cr(); - tty->print_cr("Preload failed: checksum of class list was incorrect."); - exit(1); - } - - tty->print_cr("done. "); - - if (PrintSharedSpaces) { - tty->print_cr("Shared spaces: preloaded %d classes", class_count); - } - - // Rewrite and unlink classes. - tty->print("Rewriting and linking classes ... "); - - // Link any classes which got missed. (It's not quite clear why - // they got missed.) This iteration would be unsafe if we weren't - // single-threaded at this point; however we can't do it on the VM - // thread because it requires object allocation. - SystemDictionary::classes_do(link_shared_classes, CATCH); - tty->print_cr("done. "); - - // Create and dump the shared spaces. Everything so far is loaded - // with the null class loader. - ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); - VM_PopulateDumpSharedSpace op(loader_data, class_promote_order); - VMThread::execute(&op); - } else { char errmsg[JVM_MAXPATHLEN]; os::lasterror(errmsg, JVM_MAXPATHLEN); @@ -779,11 +823,39 @@ void MetaspaceShared::preload_and_dump(TRAPS) { exit(1); } - // Since various initialization steps have been undone by this process, - // it is not reasonable to continue running a java process. - exit(0); + return class_count; } +// Returns true if the class's status has changed +bool MetaspaceShared::try_link_class(InstanceKlass* ik, TRAPS) { + assert(DumpSharedSpaces, "should only be called during dumping"); + if (ik->init_state() < InstanceKlass::linked) { + bool saved = BytecodeVerificationLocal; + if (!SharedClassUtil::is_shared_boot_class(ik)) { + // The verification decision is based on BytecodeVerificationRemote + // for non-system classes. Since we are using the NULL classloader + // to load non-system classes during dumping, we need to temporarily + // change BytecodeVerificationLocal to be the same as + // BytecodeVerificationRemote. Note this can cause the parent system + // classes also being verified. The extra overhead is acceptable during + // dumping. + BytecodeVerificationLocal = BytecodeVerificationRemote; + } + ik->link_class(THREAD); + if (HAS_PENDING_EXCEPTION) { + ResourceMark rm; + tty->print_cr("Preload Error: Verification failed for %s", + ik->external_name()); + CLEAR_PENDING_EXCEPTION; + ik->set_in_error_state(); + _has_error_classes = true; + } + BytecodeVerificationLocal = saved; + return true; + } else { + return false; + } +} // Closure for serializing initialization data in from a data area // (ptr_array) read from the shared file. @@ -867,7 +939,8 @@ bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) { (_rw_base = mapinfo->map_region(rw)) != NULL && (_md_base = mapinfo->map_region(md)) != NULL && (_mc_base = mapinfo->map_region(mc)) != NULL && - (image_alignment == (size_t)max_alignment())) { + (image_alignment == (size_t)max_alignment()) && + mapinfo->validate_classpath_entry_table()) { // Success (no need to do anything) return true; } else { @@ -884,7 +957,7 @@ bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) { // If -Xshare:on is specified, print out the error message and exit VM, // otherwise, set UseSharedSpaces to false and continue. if (RequireSharedSpaces) { - vm_exit_during_initialization("Unable to use shared archive.", NULL); + vm_exit_during_initialization("Unable to use shared archive.", "Failed map_region for using -Xshare:on."); } else { FLAG_SET_DEFAULT(UseSharedSpaces, false); } @@ -984,6 +1057,20 @@ void MetaspaceShared::initialize_shared_spaces() { // Close the mapinfo file mapinfo->close(); + + if (PrintSharedArchiveAndExit) { + if (PrintSharedDictionary) { + tty->print_cr("\nShared classes:\n"); + SystemDictionary::print_shared(false); + } + if (_archive_loading_failed) { + tty->print_cr("archive is invalid"); + vm_exit(1); + } else { + tty->print_cr("archive is valid"); + vm_exit(0); + } + } } // JVM/TI RedefineClasses() support: diff --git a/hotspot/src/share/vm/memory/metaspaceShared.hpp b/hotspot/src/share/vm/memory/metaspaceShared.hpp index 12c8af510f0..b724196c77f 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.hpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp @@ -38,7 +38,10 @@ class MetaspaceShared : AllStatic { // CDS support static ReservedSpace* _shared_rs; static int _max_alignment; - + static bool _link_classes_made_progress; + static bool _check_classes_made_progress; + static bool _has_error_classes; + static bool _archive_loading_failed; public: enum { vtbl_list_size = 17, // number of entries in the shared space vtable list. @@ -67,7 +70,11 @@ class MetaspaceShared : AllStatic { NOT_CDS(return 0); } + static void prepare_for_dumping() NOT_CDS_RETURN; static void preload_and_dump(TRAPS) NOT_CDS_RETURN; + static int preload_and_dump(const char * class_list_path, + GrowableArray* class_promote_order, + TRAPS) NOT_CDS_RETURN; static ReservedSpace* shared_rs() { CDS_ONLY(return _shared_rs); @@ -78,6 +85,9 @@ class MetaspaceShared : AllStatic { CDS_ONLY(_shared_rs = rs;) } + static void set_archive_loading_failed() { + _archive_loading_failed = true; + } static bool map_shared_spaces(FileMapInfo* mapinfo) NOT_CDS_RETURN_(false); static void initialize_shared_spaces() NOT_CDS_RETURN; @@ -97,5 +107,10 @@ class MetaspaceShared : AllStatic { static bool remap_shared_readonly_as_readwrite() NOT_CDS_RETURN_(true); static void print_shared_spaces(); + + static bool try_link_class(InstanceKlass* ik, TRAPS); + static void link_one_shared_class(Klass* obj, TRAPS); + static void check_one_shared_class(Klass* obj); + static void link_and_cleanup_shared_classes(TRAPS); }; #endif // SHARE_VM_MEMORY_METASPACE_SHARED_HPP diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index 8ea866f4dec..a85ec509dff 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -26,6 +26,9 @@ #include "classfile/classLoader.hpp" #include "classfile/classLoaderData.hpp" #include "classfile/javaClasses.hpp" +#if INCLUDE_CDS +#include "classfile/sharedClassUtil.hpp" +#endif #include "classfile/stringTable.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" @@ -34,6 +37,7 @@ #include "gc_interface/collectedHeap.inline.hpp" #include "interpreter/interpreter.hpp" #include "memory/cardTableModRefBS.hpp" +#include "memory/filemap.hpp" #include "memory/gcLocker.inline.hpp" #include "memory/genCollectedHeap.hpp" #include "memory/genRemSet.hpp" @@ -239,8 +243,9 @@ void Universe::check_alignment(uintx size, uintx alignment, const char* name) { void initialize_basic_type_klass(Klass* k, TRAPS) { Klass* ok = SystemDictionary::Object_klass(); if (UseSharedSpaces) { + ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); assert(k->super() == ok, "u3"); - k->restore_unshareable_info(CHECK); + k->restore_unshareable_info(loader_data, Handle(), CHECK); } else { k->initialize_supers(ok, CHECK); } @@ -666,6 +671,10 @@ jint universe_init() { SymbolTable::create_table(); StringTable::create_table(); ClassLoader::create_package_info_table(); + + if (DumpSharedSpaces) { + MetaspaceShared::prepare_for_dumping(); + } } return JNI_OK; @@ -1155,6 +1164,11 @@ bool universe_post_init() { MemoryService::add_metaspace_memory_pools(); MemoryService::set_universe_heap(Universe::_collectedHeap); +#if INCLUDE_CDS + if (UseSharedSpaces) { + SharedClassUtil::initialize(CHECK_false); + } +#endif return true; } diff --git a/hotspot/src/share/vm/oops/arrayKlass.cpp b/hotspot/src/share/vm/oops/arrayKlass.cpp index e8a367a3766..726c21db2da 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.cpp +++ b/hotspot/src/share/vm/oops/arrayKlass.cpp @@ -186,8 +186,9 @@ void ArrayKlass::remove_unshareable_info() { set_component_mirror(NULL); } -void ArrayKlass::restore_unshareable_info(TRAPS) { - Klass::restore_unshareable_info(CHECK); +void ArrayKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { + assert(loader_data == ClassLoaderData::the_null_class_loader_data(), "array classes belong to null loader"); + Klass::restore_unshareable_info(loader_data, protection_domain, CHECK); // Klass recreates the component mirror also } diff --git a/hotspot/src/share/vm/oops/arrayKlass.hpp b/hotspot/src/share/vm/oops/arrayKlass.hpp index f42d96e1679..3b55e031616 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.hpp +++ b/hotspot/src/share/vm/oops/arrayKlass.hpp @@ -137,7 +137,7 @@ class ArrayKlass: public Klass { // CDS support - remove and restore oops from metadata. Oops are not shared. virtual void remove_unshareable_info(); - virtual void restore_unshareable_info(TRAPS); + virtual void restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS); // Printing void print_on(outputStream* st) const; diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 2dba59265b1..9e6ef6ffad9 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -2303,12 +2303,14 @@ void InstanceKlass::remove_unshareable_info() { array_klasses_do(remove_unshareable_in_class); } -void restore_unshareable_in_class(Klass* k, TRAPS) { - k->restore_unshareable_info(CHECK); +static void restore_unshareable_in_class(Klass* k, TRAPS) { + // Array classes have null protection domain. + // --> see ArrayKlass::complete_create_array_klass() + k->restore_unshareable_info(ClassLoaderData::the_null_class_loader_data(), Handle(), CHECK); } -void InstanceKlass::restore_unshareable_info(TRAPS) { - Klass::restore_unshareable_info(CHECK); +void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { + Klass::restore_unshareable_info(loader_data, protection_domain, CHECK); instanceKlassHandle ik(THREAD, this); Array* methods = ik->methods(); @@ -2334,6 +2336,38 @@ void InstanceKlass::restore_unshareable_info(TRAPS) { ik->array_klasses_do(restore_unshareable_in_class, CHECK); } +// returns true IFF is_in_error_state() has been changed as a result of this call. +bool InstanceKlass::check_sharing_error_state() { + assert(DumpSharedSpaces, "should only be called during dumping"); + bool old_state = is_in_error_state(); + + if (!is_in_error_state()) { + bool bad = false; + for (InstanceKlass* sup = java_super(); sup; sup = sup->java_super()) { + if (sup->is_in_error_state()) { + bad = true; + break; + } + } + if (!bad) { + Array* interfaces = transitive_interfaces(); + for (int i = 0; i < interfaces->length(); i++) { + Klass* iface = interfaces->at(i); + if (InstanceKlass::cast(iface)->is_in_error_state()) { + bad = true; + break; + } + } + } + + if (bad) { + set_in_error_state(); + } + } + + return (old_state != is_in_error_state()); +} + static void clear_all_breakpoints(Method* m) { m->clear_all_breakpoints(); } diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index f2904057146..737bf70364b 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -980,6 +980,13 @@ class InstanceKlass: public Klass { u2 idnum_allocated_count() const { return _idnum_allocated_count; } +public: + void set_in_error_state() { + assert(DumpSharedSpaces, "only call this when dumping archive"); + _init_state = initialization_error; + } + bool check_sharing_error_state(); + private: // initialization state #ifdef ASSERT @@ -1038,7 +1045,7 @@ private: public: // CDS support - remove and restore oops from metadata. Oops are not shared. virtual void remove_unshareable_info(); - virtual void restore_unshareable_info(TRAPS); + virtual void restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS); // jvm support jint compute_modifier_flags(TRAPS) const; diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index 1df975312c7..810c8d729cd 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -184,6 +184,7 @@ Klass::Klass() { // The klass doesn't have any references at this point. clear_modified_oops(); clear_accumulated_modified_oops(); + _shared_class_path_index = -1; } jint Klass::array_layout_helper(BasicType etype) { @@ -500,13 +501,12 @@ void Klass::remove_unshareable_info() { set_class_loader_data(NULL); } -void Klass::restore_unshareable_info(TRAPS) { +void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { TRACE_INIT_ID(this); // If an exception happened during CDS restore, some of these fields may already be // set. We leave the class on the CLD list, even if incomplete so that we don't // modify the CLD list outside a safepoint. if (class_loader_data() == NULL) { - ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); // Restore class_loader_data to the null class loader data set_class_loader_data(loader_data); @@ -515,12 +515,12 @@ void Klass::restore_unshareable_info(TRAPS) { loader_data->add_class(this); } - // Recreate the class mirror. The protection_domain is always null for - // boot loader, for now. + // Recreate the class mirror. // Only recreate it if not present. A previous attempt to restore may have // gotten an OOM later but keep the mirror if it was created. if (java_mirror() == NULL) { - java_lang_Class::create_mirror(this, Handle(NULL), Handle(NULL), CHECK); + Handle loader = loader_data->class_loader(); + java_lang_Class::create_mirror(this, loader, protection_domain, CHECK); } } diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index e443dddeed8..620dffa0e1b 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -147,6 +147,16 @@ class Klass : public Metadata { jbyte _modified_oops; // Card Table Equivalent (YC/CMS support) jbyte _accumulated_modified_oops; // Mod Union Equivalent (CMS support) +private: + // This is an index into FileMapHeader::_classpath_entry_table[], to + // associate this class with the JAR file where it's loaded from during + // dump time. If a class is not loaded from the shared archive, this field is + // -1. + jshort _shared_class_path_index; + + friend class SharedClassUtil; +protected: + // Constructor Klass(); @@ -253,6 +263,15 @@ class Klass : public Metadata { void clear_accumulated_modified_oops() { _accumulated_modified_oops = 0; } bool has_accumulated_modified_oops() { return _accumulated_modified_oops == 1; } + int shared_classpath_index() const { + return _shared_class_path_index; + }; + + void set_shared_classpath_index(int index) { + _shared_class_path_index = index; + }; + + protected: // internal accessors void set_subklass(Klass* s); void set_next_sibling(Klass* s); @@ -422,7 +441,7 @@ class Klass : public Metadata { public: // CDS support - remove and restore oops from metadata. Oops are not shared. virtual void remove_unshareable_info(); - virtual void restore_unshareable_info(TRAPS); + virtual void restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS); protected: // computes the subtype relationship diff --git a/hotspot/src/share/vm/opto/callnode.cpp b/hotspot/src/share/vm/opto/callnode.cpp index 3ee81242e5b..04d91ff034a 100644 --- a/hotspot/src/share/vm/opto/callnode.cpp +++ b/hotspot/src/share/vm/opto/callnode.cpp @@ -1815,3 +1815,57 @@ Node *UnlockNode::Ideal(PhaseGVN *phase, bool can_reshape) { } return result; } + +ArrayCopyNode::ArrayCopyNode(Compile* C, bool alloc_tightly_coupled) + : CallNode(arraycopy_type(), NULL, TypeRawPtr::BOTTOM), _alloc_tightly_coupled(alloc_tightly_coupled), _kind(ArrayCopy) { + init_class_id(Class_ArrayCopy); + init_flags(Flag_is_macro); + C->add_macro_node(this); +} + +uint ArrayCopyNode::size_of() const { return sizeof(*this); } + +ArrayCopyNode* ArrayCopyNode::make(GraphKit* kit, bool may_throw, + Node* src, Node* src_offset, + Node* dest, Node* dest_offset, + Node* length, + bool alloc_tightly_coupled, + Node* src_length, Node* dest_length, + Node* src_klass, Node* dest_klass) { + + ArrayCopyNode* ac = new ArrayCopyNode(kit->C, alloc_tightly_coupled); + Node* prev_mem = kit->set_predefined_input_for_runtime_call(ac); + + ac->init_req(ArrayCopyNode::Src, src); + ac->init_req(ArrayCopyNode::SrcPos, src_offset); + ac->init_req(ArrayCopyNode::Dest, dest); + ac->init_req(ArrayCopyNode::DestPos, dest_offset); + ac->init_req(ArrayCopyNode::Length, length); + ac->init_req(ArrayCopyNode::SrcLen, src_length); + ac->init_req(ArrayCopyNode::DestLen, dest_length); + ac->init_req(ArrayCopyNode::SrcKlass, src_klass); + ac->init_req(ArrayCopyNode::DestKlass, dest_klass); + + if (may_throw) { + ac->set_req(TypeFunc::I_O , kit->i_o()); + kit->add_safepoint_edges(ac, false); + } + + return ac; +} + +void ArrayCopyNode::connect_outputs(GraphKit* kit) { + kit->set_all_memory_call(this, true); + kit->set_control(kit->gvn().transform(new ProjNode(this,TypeFunc::Control))); + kit->set_i_o(kit->gvn().transform(new ProjNode(this, TypeFunc::I_O))); + kit->make_slow_call_ex(this, kit->env()->Throwable_klass(), true); + kit->set_all_memory_call(this); +} + +#ifndef PRODUCT +const char* ArrayCopyNode::_kind_names[] = {"arraycopy", "arraycopy, validated arguments", "clone", "oop array clone", "CopyOf", "CopyOfRange"}; +void ArrayCopyNode::dump_spec(outputStream *st) const { + CallNode::dump_spec(st); + st->print(" (%s%s)", _kind_names[_kind], _alloc_tightly_coupled ? ", tightly coupled allocation" : ""); +} +#endif diff --git a/hotspot/src/share/vm/opto/callnode.hpp b/hotspot/src/share/vm/opto/callnode.hpp index 6eb78b0cb7b..2d6df8a5829 100644 --- a/hotspot/src/share/vm/opto/callnode.hpp +++ b/hotspot/src/share/vm/opto/callnode.hpp @@ -1063,4 +1063,108 @@ public: virtual bool guaranteed_safepoint() { return false; } }; +class GraphKit; + +class ArrayCopyNode : public CallNode { +private: + + // What kind of arraycopy variant is this? + enum { + ArrayCopy, // System.arraycopy() + ArrayCopyNoTest, // System.arraycopy(), all arguments validated + CloneBasic, // A clone that can be copied by 64 bit chunks + CloneOop, // An oop array clone + CopyOf, // Arrays.copyOf() + CopyOfRange // Arrays.copyOfRange() + } _kind; + +#ifndef PRODUCT + static const char* _kind_names[CopyOfRange+1]; +#endif + // Is the alloc obtained with + // AllocateArrayNode::Ideal_array_allocation() tighly coupled + // (arraycopy follows immediately the allocation)? + // We cache the result of LibraryCallKit::tightly_coupled_allocation + // here because it's much easier to find whether there's a tightly + // couple allocation at parse time than at macro expansion time. At + // macro expansion time, for every use of the allocation node we + // would need to figure out whether it happens after the arraycopy (and + // can be ignored) or between the allocation and the arraycopy. At + // parse time, it's straightforward because whatever happens after + // the arraycopy is not parsed yet so doesn't exist when + // LibraryCallKit::tightly_coupled_allocation() is called. + bool _alloc_tightly_coupled; + + static const TypeFunc* arraycopy_type() { + const Type** fields = TypeTuple::fields(ParmLimit - TypeFunc::Parms); + fields[Src] = TypeInstPtr::BOTTOM; + fields[SrcPos] = TypeInt::INT; + fields[Dest] = TypeInstPtr::BOTTOM; + fields[DestPos] = TypeInt::INT; + fields[Length] = TypeInt::INT; + fields[SrcLen] = TypeInt::INT; + fields[DestLen] = TypeInt::INT; + fields[SrcKlass] = TypeKlassPtr::BOTTOM; + fields[DestKlass] = TypeKlassPtr::BOTTOM; + const TypeTuple *domain = TypeTuple::make(ParmLimit, fields); + + // create result type (range) + fields = TypeTuple::fields(0); + + const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields); + + return TypeFunc::make(domain, range); + } + + ArrayCopyNode(Compile* C, bool alloc_tightly_coupled); + +public: + + enum { + Src = TypeFunc::Parms, + SrcPos, + Dest, + DestPos, + Length, + SrcLen, + DestLen, + SrcKlass, + DestKlass, + ParmLimit + }; + + static ArrayCopyNode* make(GraphKit* kit, bool may_throw, + Node* src, Node* src_offset, + Node* dest, Node* dest_offset, + Node* length, + bool alloc_tightly_coupled, + Node* src_length = NULL, Node* dest_length = NULL, + Node* src_klass = NULL, Node* dest_klass = NULL); + + void connect_outputs(GraphKit* kit); + + bool is_arraycopy() const { return _kind == ArrayCopy; } + bool is_arraycopy_notest() const { return _kind == ArrayCopyNoTest; } + bool is_clonebasic() const { return _kind == CloneBasic; } + bool is_cloneoop() const { return _kind == CloneOop; } + bool is_copyof() const { return _kind == CopyOf; } + bool is_copyofrange() const { return _kind == CopyOfRange; } + + void set_arraycopy() { _kind = ArrayCopy; } + void set_arraycopy_notest() { _kind = ArrayCopyNoTest; } + void set_clonebasic() { _kind = CloneBasic; } + void set_cloneoop() { _kind = CloneOop; } + void set_copyof() { _kind = CopyOf; } + void set_copyofrange() { _kind = CopyOfRange; } + + virtual int Opcode() const; + virtual uint size_of() const; // Size is bigger + virtual bool guaranteed_safepoint() { return false; } + + bool is_alloc_tightly_coupled() const { return _alloc_tightly_coupled; } + +#ifndef PRODUCT + virtual void dump_spec(outputStream *st) const; +#endif +}; #endif // SHARE_VM_OPTO_CALLNODE_HPP diff --git a/hotspot/src/share/vm/opto/classes.hpp b/hotspot/src/share/vm/opto/classes.hpp index 54a63db1a98..238e3491862 100644 --- a/hotspot/src/share/vm/opto/classes.hpp +++ b/hotspot/src/share/vm/opto/classes.hpp @@ -37,6 +37,7 @@ macro(Allocate) macro(AllocateArray) macro(AndI) macro(AndL) +macro(ArrayCopy) macro(AryEq) macro(AtanD) macro(Binary) diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index 9bf539deb71..a70e538d744 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -3795,6 +3795,56 @@ void Compile::ConstantTable::fill_jump_table(CodeBuffer& cb, MachConstantNode* n } } +//----------------------------static_subtype_check----------------------------- +// Shortcut important common cases when superklass is exact: +// (0) superklass is java.lang.Object (can occur in reflective code) +// (1) subklass is already limited to a subtype of superklass => always ok +// (2) subklass does not overlap with superklass => always fail +// (3) superklass has NO subtypes and we can check with a simple compare. +int Compile::static_subtype_check(ciKlass* superk, ciKlass* subk) { + if (StressReflectiveCode) { + return SSC_full_test; // Let caller generate the general case. + } + + if (superk == env()->Object_klass()) { + return SSC_always_true; // (0) this test cannot fail + } + + ciType* superelem = superk; + if (superelem->is_array_klass()) + superelem = superelem->as_array_klass()->base_element_type(); + + if (!subk->is_interface()) { // cannot trust static interface types yet + if (subk->is_subtype_of(superk)) { + return SSC_always_true; // (1) false path dead; no dynamic test needed + } + if (!(superelem->is_klass() && superelem->as_klass()->is_interface()) && + !superk->is_subtype_of(subk)) { + return SSC_always_false; + } + } + + // If casting to an instance klass, it must have no subtypes + if (superk->is_interface()) { + // Cannot trust interfaces yet. + // %%% S.B. superk->nof_implementors() == 1 + } else if (superelem->is_instance_klass()) { + ciInstanceKlass* ik = superelem->as_instance_klass(); + if (!ik->has_subklass() && !ik->is_interface()) { + if (!ik->is_final()) { + // Add a dependency if there is a chance of a later subclass. + dependencies()->assert_leaf_type(ik); + } + return SSC_easy_test; // (3) caller can do a simple ptr comparison + } + } else { + // A primitive array type has no subtypes. + return SSC_easy_test; // (3) caller can do a simple ptr comparison + } + + return SSC_full_test; +} + // The message about the current inlining is accumulated in // _print_inlining_stream and transfered into the _print_inlining_list // once we know whether inlining succeeds or not. For regular diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp index d9af09a3af1..5a98e8e254d 100644 --- a/hotspot/src/share/vm/opto/compile.hpp +++ b/hotspot/src/share/vm/opto/compile.hpp @@ -1200,6 +1200,10 @@ class Compile : public Phase { // Definitions of pd methods static void pd_compiler2_init(); + // Static parse-time type checking logic for gen_subtype_check: + enum { SSC_always_false, SSC_always_true, SSC_easy_test, SSC_full_test }; + int static_subtype_check(ciKlass* superk, ciKlass* subk); + // Auxiliary method for randomized fuzzing/stressing static bool randomized_select(int count); }; diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index 8228aad4fac..8b8969fc370 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -2520,6 +2520,21 @@ void GraphKit::make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool sep set_control(norm); } +static IfNode* gen_subtype_check_compare(Node* ctrl, Node* in1, Node* in2, BoolTest::mask test, float p, PhaseGVN* gvn, BasicType bt) { + Node* cmp = NULL; + switch(bt) { + case T_INT: cmp = new CmpINode(in1, in2); break; + case T_ADDRESS: cmp = new CmpPNode(in1, in2); break; + default: fatal(err_msg("unexpected comparison type %s", type2name(bt))); + } + gvn->transform(cmp); + Node* bol = gvn->transform(new BoolNode(cmp, test)); + IfNode* iff = new IfNode(ctrl, bol, p, COUNT_UNKNOWN); + gvn->transform(iff); + if (!bol->is_Con()) gvn->record_for_igvn(iff); + return iff; +} + //-------------------------------gen_subtype_check----------------------------- // Generate a subtyping check. Takes as input the subtype and supertype. @@ -2529,16 +2544,17 @@ void GraphKit::make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool sep // but that's not exposed to the optimizer. This call also doesn't take in an // Object; if you wish to check an Object you need to load the Object's class // prior to coming here. -Node* GraphKit::gen_subtype_check(Node* subklass, Node* superklass) { +Node* Phase::gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, MergeMemNode* mem, PhaseGVN* gvn) { + Compile* C = gvn->C; // Fast check for identical types, perhaps identical constants. // The types can even be identical non-constants, in cases // involving Array.newInstance, Object.clone, etc. if (subklass == superklass) - return top(); // false path is dead; no test needed. + return C->top(); // false path is dead; no test needed. - if (_gvn.type(superklass)->singleton()) { - ciKlass* superk = _gvn.type(superklass)->is_klassptr()->klass(); - ciKlass* subk = _gvn.type(subklass)->is_klassptr()->klass(); + if (gvn->type(superklass)->singleton()) { + ciKlass* superk = gvn->type(superklass)->is_klassptr()->klass(); + ciKlass* subk = gvn->type(subklass)->is_klassptr()->klass(); // In the common case of an exact superklass, try to fold up the // test before generating code. You may ask, why not just generate @@ -2549,25 +2565,23 @@ Node* GraphKit::gen_subtype_check(Node* subklass, Node* superklass) { // Foo[] fa = blah(); Foo x = fa[0]; fa[1] = x; // Here, the type of 'fa' is often exact, so the store check // of fa[1]=x will fold up, without testing the nullness of x. - switch (static_subtype_check(superk, subk)) { - case SSC_always_false: + switch (C->static_subtype_check(superk, subk)) { + case Compile::SSC_always_false: { - Node* always_fail = control(); - set_control(top()); + Node* always_fail = *ctrl; + *ctrl = gvn->C->top(); return always_fail; } - case SSC_always_true: - return top(); - case SSC_easy_test: + case Compile::SSC_always_true: + return C->top(); + case Compile::SSC_easy_test: { // Just do a direct pointer compare and be done. - Node* cmp = _gvn.transform( new CmpPNode(subklass, superklass) ); - Node* bol = _gvn.transform( new BoolNode(cmp, BoolTest::eq) ); - IfNode* iff = create_and_xform_if(control(), bol, PROB_STATIC_FREQUENT, COUNT_UNKNOWN); - set_control( _gvn.transform( new IfTrueNode (iff) ) ); - return _gvn.transform( new IfFalseNode(iff) ); + IfNode* iff = gen_subtype_check_compare(*ctrl, subklass, superklass, BoolTest::eq, PROB_STATIC_FREQUENT, gvn, T_ADDRESS); + *ctrl = gvn->transform(new IfTrueNode(iff)); + return gvn->transform(new IfFalseNode(iff)); } - case SSC_full_test: + case Compile::SSC_full_test: break; default: ShouldNotReachHere(); @@ -2579,11 +2593,11 @@ Node* GraphKit::gen_subtype_check(Node* subklass, Node* superklass) { // will always succeed. We could leave a dependency behind to ensure this. // First load the super-klass's check-offset - Node *p1 = basic_plus_adr( superklass, superklass, in_bytes(Klass::super_check_offset_offset()) ); - Node *chk_off = _gvn.transform(new LoadINode(NULL, memory(p1), p1, _gvn.type(p1)->is_ptr(), - TypeInt::INT, MemNode::unordered)); + Node *p1 = gvn->transform(new AddPNode(superklass, superklass, gvn->MakeConX(in_bytes(Klass::super_check_offset_offset())))); + Node* m = mem->memory_at(C->get_alias_index(gvn->type(p1)->is_ptr())); + Node *chk_off = gvn->transform(new LoadINode(NULL, m, p1, gvn->type(p1)->is_ptr(), TypeInt::INT, MemNode::unordered)); int cacheoff_con = in_bytes(Klass::secondary_super_cache_offset()); - bool might_be_cache = (find_int_con(chk_off, cacheoff_con) == cacheoff_con); + bool might_be_cache = (gvn->find_int_con(chk_off, cacheoff_con) == cacheoff_con); // Load from the sub-klass's super-class display list, or a 1-word cache of // the secondary superclass list, or a failing value with a sentinel offset @@ -2591,42 +2605,44 @@ Node* GraphKit::gen_subtype_check(Node* subklass, Node* superklass) { // hierarchy and we have to scan the secondary superclass list the hard way. // Worst-case type is a little odd: NULL is allowed as a result (usually // klass loads can never produce a NULL). - Node *chk_off_X = ConvI2X(chk_off); - Node *p2 = _gvn.transform( new AddPNode(subklass,subklass,chk_off_X) ); + Node *chk_off_X = chk_off; +#ifdef _LP64 + chk_off_X = gvn->transform(new ConvI2LNode(chk_off_X)); +#endif + Node *p2 = gvn->transform(new AddPNode(subklass,subklass,chk_off_X)); // For some types like interfaces the following loadKlass is from a 1-word // cache which is mutable so can't use immutable memory. Other // types load from the super-class display table which is immutable. - Node *kmem = might_be_cache ? memory(p2) : immutable_memory(); - Node *nkls = _gvn.transform( LoadKlassNode::make( _gvn, kmem, p2, _gvn.type(p2)->is_ptr(), TypeKlassPtr::OBJECT_OR_NULL ) ); + m = mem->memory_at(C->get_alias_index(gvn->type(p2)->is_ptr())); + Node *kmem = might_be_cache ? m : C->immutable_memory(); + Node *nkls = gvn->transform(LoadKlassNode::make(*gvn, kmem, p2, gvn->type(p2)->is_ptr(), TypeKlassPtr::OBJECT_OR_NULL)); // Compile speed common case: ARE a subtype and we canNOT fail if( superklass == nkls ) - return top(); // false path is dead; no test needed. + return C->top(); // false path is dead; no test needed. // See if we get an immediate positive hit. Happens roughly 83% of the // time. Test to see if the value loaded just previously from the subklass // is exactly the superklass. - Node *cmp1 = _gvn.transform( new CmpPNode( superklass, nkls ) ); - Node *bol1 = _gvn.transform( new BoolNode( cmp1, BoolTest::eq ) ); - IfNode *iff1 = create_and_xform_if( control(), bol1, PROB_LIKELY(0.83f), COUNT_UNKNOWN ); - Node *iftrue1 = _gvn.transform( new IfTrueNode ( iff1 ) ); - set_control( _gvn.transform( new IfFalseNode( iff1 ) ) ); + IfNode *iff1 = gen_subtype_check_compare(*ctrl, superklass, nkls, BoolTest::eq, PROB_LIKELY(0.83f), gvn, T_ADDRESS); + Node *iftrue1 = gvn->transform( new IfTrueNode (iff1)); + *ctrl = gvn->transform(new IfFalseNode(iff1)); // Compile speed common case: Check for being deterministic right now. If // chk_off is a constant and not equal to cacheoff then we are NOT a // subklass. In this case we need exactly the 1 test above and we can // return those results immediately. if (!might_be_cache) { - Node* not_subtype_ctrl = control(); - set_control(iftrue1); // We need exactly the 1 test above + Node* not_subtype_ctrl = *ctrl; + *ctrl = iftrue1; // We need exactly the 1 test above return not_subtype_ctrl; } // Gather the various success & failures here RegionNode *r_ok_subtype = new RegionNode(4); - record_for_igvn(r_ok_subtype); + gvn->record_for_igvn(r_ok_subtype); RegionNode *r_not_subtype = new RegionNode(3); - record_for_igvn(r_not_subtype); + gvn->record_for_igvn(r_not_subtype); r_ok_subtype->init_req(1, iftrue1); @@ -2635,21 +2651,17 @@ Node* GraphKit::gen_subtype_check(Node* subklass, Node* superklass) { // check-offset points into the subklass display list or the 1-element // cache. If it points to the display (and NOT the cache) and the display // missed then it's not a subtype. - Node *cacheoff = _gvn.intcon(cacheoff_con); - Node *cmp2 = _gvn.transform( new CmpINode( chk_off, cacheoff ) ); - Node *bol2 = _gvn.transform( new BoolNode( cmp2, BoolTest::ne ) ); - IfNode *iff2 = create_and_xform_if( control(), bol2, PROB_LIKELY(0.63f), COUNT_UNKNOWN ); - r_not_subtype->init_req(1, _gvn.transform( new IfTrueNode (iff2) ) ); - set_control( _gvn.transform( new IfFalseNode(iff2) ) ); + Node *cacheoff = gvn->intcon(cacheoff_con); + IfNode *iff2 = gen_subtype_check_compare(*ctrl, chk_off, cacheoff, BoolTest::ne, PROB_LIKELY(0.63f), gvn, T_INT); + r_not_subtype->init_req(1, gvn->transform(new IfTrueNode (iff2))); + *ctrl = gvn->transform(new IfFalseNode(iff2)); // Check for self. Very rare to get here, but it is taken 1/3 the time. // No performance impact (too rare) but allows sharing of secondary arrays // which has some footprint reduction. - Node *cmp3 = _gvn.transform( new CmpPNode( subklass, superklass ) ); - Node *bol3 = _gvn.transform( new BoolNode( cmp3, BoolTest::eq ) ); - IfNode *iff3 = create_and_xform_if( control(), bol3, PROB_LIKELY(0.36f), COUNT_UNKNOWN ); - r_ok_subtype->init_req(2, _gvn.transform( new IfTrueNode ( iff3 ) ) ); - set_control( _gvn.transform( new IfFalseNode( iff3 ) ) ); + IfNode *iff3 = gen_subtype_check_compare(*ctrl, subklass, superklass, BoolTest::eq, PROB_LIKELY(0.36f), gvn, T_ADDRESS); + r_ok_subtype->init_req(2, gvn->transform(new IfTrueNode(iff3))); + *ctrl = gvn->transform(new IfFalseNode(iff3)); // -- Roads not taken here: -- // We could also have chosen to perform the self-check at the beginning @@ -2672,68 +2684,16 @@ Node* GraphKit::gen_subtype_check(Node* subklass, Node* superklass) { // out of line, and it can only improve I-cache density. // The decision to inline or out-of-line this final check is platform // dependent, and is found in the AD file definition of PartialSubtypeCheck. - Node* psc = _gvn.transform( - new PartialSubtypeCheckNode(control(), subklass, superklass) ); + Node* psc = gvn->transform( + new PartialSubtypeCheckNode(*ctrl, subklass, superklass)); - Node *cmp4 = _gvn.transform( new CmpPNode( psc, null() ) ); - Node *bol4 = _gvn.transform( new BoolNode( cmp4, BoolTest::ne ) ); - IfNode *iff4 = create_and_xform_if( control(), bol4, PROB_FAIR, COUNT_UNKNOWN ); - r_not_subtype->init_req(2, _gvn.transform( new IfTrueNode (iff4) ) ); - r_ok_subtype ->init_req(3, _gvn.transform( new IfFalseNode(iff4) ) ); + IfNode *iff4 = gen_subtype_check_compare(*ctrl, psc, gvn->zerocon(T_OBJECT), BoolTest::ne, PROB_FAIR, gvn, T_ADDRESS); + r_not_subtype->init_req(2, gvn->transform(new IfTrueNode (iff4))); + r_ok_subtype ->init_req(3, gvn->transform(new IfFalseNode(iff4))); // Return false path; set default control to true path. - set_control( _gvn.transform(r_ok_subtype) ); - return _gvn.transform(r_not_subtype); -} - -//----------------------------static_subtype_check----------------------------- -// Shortcut important common cases when superklass is exact: -// (0) superklass is java.lang.Object (can occur in reflective code) -// (1) subklass is already limited to a subtype of superklass => always ok -// (2) subklass does not overlap with superklass => always fail -// (3) superklass has NO subtypes and we can check with a simple compare. -int GraphKit::static_subtype_check(ciKlass* superk, ciKlass* subk) { - if (StressReflectiveCode) { - return SSC_full_test; // Let caller generate the general case. - } - - if (superk == env()->Object_klass()) { - return SSC_always_true; // (0) this test cannot fail - } - - ciType* superelem = superk; - if (superelem->is_array_klass()) - superelem = superelem->as_array_klass()->base_element_type(); - - if (!subk->is_interface()) { // cannot trust static interface types yet - if (subk->is_subtype_of(superk)) { - return SSC_always_true; // (1) false path dead; no dynamic test needed - } - if (!(superelem->is_klass() && superelem->as_klass()->is_interface()) && - !superk->is_subtype_of(subk)) { - return SSC_always_false; - } - } - - // If casting to an instance klass, it must have no subtypes - if (superk->is_interface()) { - // Cannot trust interfaces yet. - // %%% S.B. superk->nof_implementors() == 1 - } else if (superelem->is_instance_klass()) { - ciInstanceKlass* ik = superelem->as_instance_klass(); - if (!ik->has_subklass() && !ik->is_interface()) { - if (!ik->is_final()) { - // Add a dependency if there is a chance of a later subclass. - C->dependencies()->assert_leaf_type(ik); - } - return SSC_easy_test; // (3) caller can do a simple ptr comparison - } - } else { - // A primitive array type has no subtypes. - return SSC_easy_test; // (3) caller can do a simple ptr comparison - } - - return SSC_full_test; + *ctrl = gvn->transform(r_ok_subtype); + return gvn->transform(r_not_subtype); } // Profile-driven exact type check: @@ -2813,7 +2773,7 @@ Node* GraphKit::maybe_cast_profiled_receiver(Node* not_null_obj, ciKlass* exact_kls = spec_klass == NULL ? profile_has_unique_klass() : spec_klass; if (exact_kls != NULL) {// no cast failures here if (require_klass == NULL || - static_subtype_check(require_klass, exact_kls) == SSC_always_true) { + C->static_subtype_check(require_klass, exact_kls) == Compile::SSC_always_true) { // If we narrow the type to match what the type profile sees or // the speculative type, we can then remove the rest of the // cast. @@ -2833,7 +2793,7 @@ Node* GraphKit::maybe_cast_profiled_receiver(Node* not_null_obj, } return exact_obj; } - // assert(ssc == SSC_always_true)... except maybe the profile lied to us. + // assert(ssc == Compile::SSC_always_true)... except maybe the profile lied to us. } return NULL; @@ -2938,8 +2898,8 @@ Node* GraphKit::gen_instanceof(Node* obj, Node* superklass, bool safe_for_replac ciKlass* superk = _gvn.type(superklass)->is_klassptr()->klass(); ciKlass* subk = _gvn.type(obj)->is_oopptr()->klass(); if (subk != NULL && subk->is_loaded()) { - int static_res = static_subtype_check(superk, subk); - known_statically = (static_res == SSC_always_true || static_res == SSC_always_false); + int static_res = C->static_subtype_check(superk, subk); + known_statically = (static_res == Compile::SSC_always_true || static_res == Compile::SSC_always_false); } } @@ -3007,13 +2967,13 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass, if (tk->singleton()) { const TypeOopPtr* objtp = _gvn.type(obj)->isa_oopptr(); if (objtp != NULL && objtp->klass() != NULL) { - switch (static_subtype_check(tk->klass(), objtp->klass())) { - case SSC_always_true: + switch (C->static_subtype_check(tk->klass(), objtp->klass())) { + case Compile::SSC_always_true: // If we know the type check always succeed then we don't use // the profiling data at this bytecode. Don't lose it, feed it // to the type system as a speculative type. return record_profiled_receiver_for_speculation(obj); - case SSC_always_false: + case Compile::SSC_always_false: // It needs a null check because a null will *pass* the cast check. // A non-null value will always produce an exception. return null_assert(obj); diff --git a/hotspot/src/share/vm/opto/graphKit.hpp b/hotspot/src/share/vm/opto/graphKit.hpp index 683be5c9060..26f5dfd21c1 100644 --- a/hotspot/src/share/vm/opto/graphKit.hpp +++ b/hotspot/src/share/vm/opto/graphKit.hpp @@ -829,17 +829,13 @@ class GraphKit : public Phase { Node* gen_checkcast( Node *subobj, Node* superkls, Node* *failure_control = NULL ); - // Generate a subtyping check. Takes as input the subtype and supertype. - // Returns 2 values: sets the default control() to the true path and - // returns the false path. Only reads from constant memory taken from the - // default memory; does not write anything. It also doesn't take in an - // Object; if you wish to check an Object you need to load the Object's - // class prior to coming here. - Node* gen_subtype_check(Node* subklass, Node* superklass); - - // Static parse-time type checking logic for gen_subtype_check: - enum { SSC_always_false, SSC_always_true, SSC_easy_test, SSC_full_test }; - int static_subtype_check(ciKlass* superk, ciKlass* subk); + Node* gen_subtype_check(Node* subklass, Node* superklass) { + MergeMemNode* mem = merged_memory(); + Node* ctrl = control(); + Node* n = Phase::gen_subtype_check(subklass, superklass, &ctrl, mem, &_gvn); + set_control(ctrl); + return n; + } // Exact type check used for predicted calls and casts. // Rewrites (*casted_receiver) to be casted to the stronger type. diff --git a/hotspot/src/share/vm/opto/ifnode.cpp b/hotspot/src/share/vm/opto/ifnode.cpp index 96551a804d2..c0080c81d57 100644 --- a/hotspot/src/share/vm/opto/ifnode.cpp +++ b/hotspot/src/share/vm/opto/ifnode.cpp @@ -503,7 +503,7 @@ int IfNode::is_range_check(Node* &range, Node* &index, jint &offset) { jint off = 0; if (l->is_top()) { return 0; - } else if (l->is_Add()) { + } else if (l->Opcode() == Op_AddI) { if ((off = l->in(1)->find_int_con(0)) != 0) { ind = l->in(2); } else if ((off = l->in(2)->find_int_con(0)) != 0) { diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 1cfa17b5852..8339cce6ea4 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -146,15 +146,10 @@ class LibraryCallKit : public GraphKit { Node* generate_negative_guard(Node* index, RegionNode* region, // resulting CastII of index: Node* *pos_index = NULL); - Node* generate_nonpositive_guard(Node* index, bool never_negative, - // resulting CastII of index: - Node* *pos_index = NULL); Node* generate_limit_guard(Node* offset, Node* subseq_length, Node* array_length, RegionNode* region); Node* generate_current_thread(Node* &tls_output); - address basictype2arraycopy(BasicType t, Node *src_offset, Node *dest_offset, - bool disjoint_bases, const char* &name, bool dest_uninitialized); Node* load_mirror_from_klass(Node* klass); Node* load_klass_from_mirror_common(Node* mirror, bool never_see_null, RegionNode* region, int null_path, @@ -264,47 +259,8 @@ class LibraryCallKit : public GraphKit { // Helper functions for inlining arraycopy bool inline_arraycopy(); - void generate_arraycopy(const TypePtr* adr_type, - BasicType basic_elem_type, - Node* src, Node* src_offset, - Node* dest, Node* dest_offset, - Node* copy_length, - bool disjoint_bases = false, - bool length_never_negative = false, - RegionNode* slow_region = NULL); AllocateArrayNode* tightly_coupled_allocation(Node* ptr, RegionNode* slow_region); - void generate_clear_array(const TypePtr* adr_type, - Node* dest, - BasicType basic_elem_type, - Node* slice_off, - Node* slice_len, - Node* slice_end); - bool generate_block_arraycopy(const TypePtr* adr_type, - BasicType basic_elem_type, - AllocateNode* alloc, - Node* src, Node* src_offset, - Node* dest, Node* dest_offset, - Node* dest_size, bool dest_uninitialized); - void generate_slow_arraycopy(const TypePtr* adr_type, - Node* src, Node* src_offset, - Node* dest, Node* dest_offset, - Node* copy_length, bool dest_uninitialized); - Node* generate_checkcast_arraycopy(const TypePtr* adr_type, - Node* dest_elem_klass, - Node* src, Node* src_offset, - Node* dest, Node* dest_offset, - Node* copy_length, bool dest_uninitialized); - Node* generate_generic_arraycopy(const TypePtr* adr_type, - Node* src, Node* src_offset, - Node* dest, Node* dest_offset, - Node* copy_length, bool dest_uninitialized); - void generate_unchecked_arraycopy(const TypePtr* adr_type, - BasicType basic_elem_type, - bool disjoint_bases, - Node* src, Node* src_offset, - Node* dest, Node* dest_offset, - Node* copy_length, bool dest_uninitialized); typedef enum { LS_xadd, LS_xchg, LS_cmpxchg } LoadStoreKind; bool inline_unsafe_load_store(BasicType type, LoadStoreKind kind); bool inline_unsafe_ordered_store(BasicType type); @@ -1049,25 +1005,6 @@ inline Node* LibraryCallKit::generate_negative_guard(Node* index, RegionNode* re return is_neg; } -inline Node* LibraryCallKit::generate_nonpositive_guard(Node* index, bool never_negative, - Node* *pos_index) { - if (stopped()) - return NULL; // already stopped - if (_gvn.type(index)->higher_equal(TypeInt::POS1)) // [1,maxint] - return NULL; // index is already adequately typed - Node* cmp_le = _gvn.transform(new CmpINode(index, intcon(0))); - BoolTest::mask le_or_eq = (never_negative ? BoolTest::eq : BoolTest::le); - Node* bol_le = _gvn.transform(new BoolNode(cmp_le, le_or_eq)); - Node* is_notp = generate_guard(bol_le, NULL, PROB_MIN); - if (is_notp != NULL && pos_index != NULL) { - // Emulate effect of Parse::adjust_map_after_if. - Node* ccast = new CastIINode(index, TypeInt::POS1); - ccast->set_req(0, control()); - (*pos_index) = _gvn.transform(ccast); - } - return is_notp; -} - // Make sure that 'position' is a valid limit index, in [0..length]. // There are two equivalent plans for checking this: // A. (offset + copyLength) unsigned<= arrayLength @@ -2658,7 +2595,8 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas if (need_mem_bar) insert_mem_bar(Op_MemBarCPUOrder); if (!is_store) { - Node* p = make_load(control(), adr, value_type, type, adr_type, MemNode::unordered, is_volatile); + MemNode::MemOrd mo = is_volatile ? MemNode::acquire : MemNode::unordered; + Node* p = make_load(control(), adr, value_type, type, adr_type, mo, is_volatile); // load value switch (type) { case T_BOOLEAN: @@ -3928,13 +3866,18 @@ bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) { // oop stores need checking. // Extreme case: Arrays.copyOf((Integer[])x, 10, String[].class). // This will fail a store-check if x contains any non-nulls. - bool disjoint_bases = true; - // if start > orig_length then the length of the copy may be - // negative. - bool length_never_negative = !is_copyOfRange; - generate_arraycopy(TypeAryPtr::OOPS, T_OBJECT, - original, start, newcopy, intcon(0), moved, - disjoint_bases, length_never_negative); + + Node* alloc = tightly_coupled_allocation(newcopy, NULL); + + ArrayCopyNode* ac = ArrayCopyNode::make(this, true, original, start, newcopy, intcon(0), moved, alloc != NULL); + if (!is_copyOfRange) { + ac->set_copyof(); + } else { + ac->set_copyofrange(); + } + Node* n = _gvn.transform(ac); + assert(n == ac, "cannot disappear"); + ac->connect_outputs(this); } } // original reexecute is set back here @@ -4445,10 +4388,12 @@ void LibraryCallKit::copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, b countx = _gvn.transform(new URShiftXNode(countx, intcon(LogBytesPerLong) )); const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM; - bool disjoint_bases = true; - generate_unchecked_arraycopy(raw_adr_type, T_LONG, disjoint_bases, - src, NULL, dest, NULL, countx, - /*dest_uninitialized*/true); + + ArrayCopyNode* ac = ArrayCopyNode::make(this, false, src, NULL, dest, NULL, countx, false); + ac->set_clonebasic(); + Node* n = _gvn.transform(ac); + assert(n == ac, "cannot disappear"); + set_predefined_output_for_runtime_call(ac, ac->in(TypeFunc::Memory), raw_adr_type); // If necessary, emit some card marks afterwards. (Non-arrays only.) if (card_mark) { @@ -4557,12 +4502,13 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) { PreserveJVMState pjvms2(this); set_control(is_obja); // Generate a direct call to the right arraycopy function(s). - bool disjoint_bases = true; - bool length_never_negative = true; - generate_arraycopy(TypeAryPtr::OOPS, T_OBJECT, - obj, intcon(0), alloc_obj, intcon(0), - obj_length, - disjoint_bases, length_never_negative); + Node* alloc = tightly_coupled_allocation(alloc_obj, NULL); + ArrayCopyNode* ac = ArrayCopyNode::make(this, true, obj, intcon(0), alloc_obj, intcon(0), obj_length, alloc != NULL); + ac->set_cloneoop(); + Node* n = _gvn.transform(ac); + assert(n == ac, "cannot disappear"); + ac->connect_outputs(this); + result_reg->init_req(_objArray_path, control()); result_val->init_req(_objArray_path, alloc_obj); result_i_o ->set_req(_objArray_path, i_o()); @@ -4656,42 +4602,6 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) { return true; } -//------------------------------basictype2arraycopy---------------------------- -address LibraryCallKit::basictype2arraycopy(BasicType t, - Node* src_offset, - Node* dest_offset, - bool disjoint_bases, - const char* &name, - bool dest_uninitialized) { - const TypeInt* src_offset_inttype = gvn().find_int_type(src_offset);; - const TypeInt* dest_offset_inttype = gvn().find_int_type(dest_offset);; - - bool aligned = false; - bool disjoint = disjoint_bases; - - // if the offsets are the same, we can treat the memory regions as - // disjoint, because either the memory regions are in different arrays, - // or they are identical (which we can treat as disjoint.) We can also - // treat a copy with a destination index less that the source index - // as disjoint since a low->high copy will work correctly in this case. - if (src_offset_inttype != NULL && src_offset_inttype->is_con() && - dest_offset_inttype != NULL && dest_offset_inttype->is_con()) { - // both indices are constants - int s_offs = src_offset_inttype->get_con(); - int d_offs = dest_offset_inttype->get_con(); - int element_size = type2aelembytes(t); - aligned = ((arrayOopDesc::base_offset_in_bytes(t) + s_offs * element_size) % HeapWordSize == 0) && - ((arrayOopDesc::base_offset_in_bytes(t) + d_offs * element_size) % HeapWordSize == 0); - if (s_offs >= d_offs) disjoint = true; - } else if (src_offset == dest_offset && src_offset != NULL) { - // This can occur if the offsets are identical non-constants. - disjoint = true; - } - - return StubRoutines::select_arraycopy_function(t, aligned, disjoint, name, dest_uninitialized); -} - - //------------------------------inline_arraycopy----------------------- // public static native void java.lang.System.arraycopy(Object src, int srcPos, // Object dest, int destPos, @@ -4704,13 +4614,26 @@ bool LibraryCallKit::inline_arraycopy() { Node* dest_offset = argument(3); // type: int Node* length = argument(4); // type: int - // Compile time checks. If any of these checks cannot be verified at compile time, - // we do not make a fast path for this call. Instead, we let the call remain as it - // is. The checks we choose to mandate at compile time are: - // + // The following tests must be performed // (1) src and dest are arrays. - const Type* src_type = src->Value(&_gvn); - const Type* dest_type = dest->Value(&_gvn); + // (2) src and dest arrays must have elements of the same BasicType + // (3) src and dest must not be null. + // (4) src_offset must not be negative. + // (5) dest_offset must not be negative. + // (6) length must not be negative. + // (7) src_offset + length must not exceed length of src. + // (8) dest_offset + length must not exceed length of dest. + // (9) each element of an oop array must be assignable + + // (3) src and dest must not be null. + // always do this here because we need the JVM state for uncommon traps + src = null_check(src, T_ARRAY); + dest = null_check(dest, T_ARRAY); + + bool notest = false; + + const Type* src_type = _gvn.type(src); + const Type* dest_type = _gvn.type(dest); const TypeAryPtr* top_src = src_type->isa_aryptr(); const TypeAryPtr* top_dest = dest_type->isa_aryptr(); @@ -4768,556 +4691,119 @@ bool LibraryCallKit::inline_arraycopy() { } } - if (!has_src || !has_dest) { - // Conservatively insert a memory barrier on all memory slices. - // Do not let writes into the source float below the arraycopy. - insert_mem_bar(Op_MemBarCPUOrder); + if (has_src && has_dest) { + BasicType src_elem = top_src->klass()->as_array_klass()->element_type()->basic_type(); + BasicType dest_elem = top_dest->klass()->as_array_klass()->element_type()->basic_type(); + if (src_elem == T_ARRAY) src_elem = T_OBJECT; + if (dest_elem == T_ARRAY) dest_elem = T_OBJECT; - // Call StubRoutines::generic_arraycopy stub. - generate_arraycopy(TypeRawPtr::BOTTOM, T_CONFLICT, - src, src_offset, dest, dest_offset, length); - - // Do not let reads from the destination float above the arraycopy. - // Since we cannot type the arrays, we don't know which slices - // might be affected. We could restrict this barrier only to those - // memory slices which pertain to array elements--but don't bother. - if (!InsertMemBarAfterArraycopy) - // (If InsertMemBarAfterArraycopy, there is already one in place.) - insert_mem_bar(Op_MemBarCPUOrder); - return true; - } - - // (2) src and dest arrays must have elements of the same BasicType - // Figure out the size and type of the elements we will be copying. - BasicType src_elem = top_src->klass()->as_array_klass()->element_type()->basic_type(); - BasicType dest_elem = top_dest->klass()->as_array_klass()->element_type()->basic_type(); - if (src_elem == T_ARRAY) src_elem = T_OBJECT; - if (dest_elem == T_ARRAY) dest_elem = T_OBJECT; - - if (src_elem != dest_elem || dest_elem == T_VOID) { - // The component types are not the same or are not recognized. Punt. - // (But, avoid the native method wrapper to JVM_ArrayCopy.) - generate_slow_arraycopy(TypePtr::BOTTOM, - src, src_offset, dest, dest_offset, length, - /*dest_uninitialized*/false); - return true; - } - - if (src_elem == T_OBJECT) { - // If both arrays are object arrays then having the exact types - // for both will remove the need for a subtype check at runtime - // before the call and may make it possible to pick a faster copy - // routine (without a subtype check on every element) - // Do we have the exact type of src? - bool could_have_src = src_spec; - // Do we have the exact type of dest? - bool could_have_dest = dest_spec; - ciKlass* src_k = top_src->klass(); - ciKlass* dest_k = top_dest->klass(); - if (!src_spec) { - src_k = src_type->speculative_type_not_null(); - if (src_k != NULL && src_k->is_array_klass()) { + if (src_elem == dest_elem && src_elem == T_OBJECT) { + // If both arrays are object arrays then having the exact types + // for both will remove the need for a subtype check at runtime + // before the call and may make it possible to pick a faster copy + // routine (without a subtype check on every element) + // Do we have the exact type of src? + bool could_have_src = src_spec; + // Do we have the exact type of dest? + bool could_have_dest = dest_spec; + ciKlass* src_k = top_src->klass(); + ciKlass* dest_k = top_dest->klass(); + if (!src_spec) { + src_k = src_type->speculative_type_not_null(); + if (src_k != NULL && src_k->is_array_klass()) { could_have_src = true; - } - } - if (!dest_spec) { - dest_k = dest_type->speculative_type_not_null(); - if (dest_k != NULL && dest_k->is_array_klass()) { - could_have_dest = true; - } - } - if (could_have_src && could_have_dest) { - // If we can have both exact types, emit the missing guards - if (could_have_src && !src_spec) { - src = maybe_cast_profiled_obj(src, src_k); - } - if (could_have_dest && !dest_spec) { - dest = maybe_cast_profiled_obj(dest, dest_k); - } - } - } - - //--------------------------------------------------------------------------- - // We will make a fast path for this call to arraycopy. - - // We have the following tests left to perform: - // - // (3) src and dest must not be null. - // (4) src_offset must not be negative. - // (5) dest_offset must not be negative. - // (6) length must not be negative. - // (7) src_offset + length must not exceed length of src. - // (8) dest_offset + length must not exceed length of dest. - // (9) each element of an oop array must be assignable - - RegionNode* slow_region = new RegionNode(1); - record_for_igvn(slow_region); - - // (3) operands must not be null - // We currently perform our null checks with the null_check routine. - // This means that the null exceptions will be reported in the caller - // rather than (correctly) reported inside of the native arraycopy call. - // This should be corrected, given time. We do our null check with the - // stack pointer restored. - src = null_check(src, T_ARRAY); - dest = null_check(dest, T_ARRAY); - - // (4) src_offset must not be negative. - generate_negative_guard(src_offset, slow_region); - - // (5) dest_offset must not be negative. - generate_negative_guard(dest_offset, slow_region); - - // (6) length must not be negative (moved to generate_arraycopy()). - // generate_negative_guard(length, slow_region); - - // (7) src_offset + length must not exceed length of src. - generate_limit_guard(src_offset, length, - load_array_length(src), - slow_region); - - // (8) dest_offset + length must not exceed length of dest. - generate_limit_guard(dest_offset, length, - load_array_length(dest), - slow_region); - - // (9) each element of an oop array must be assignable - // The generate_arraycopy subroutine checks this. - - // This is where the memory effects are placed: - const TypePtr* adr_type = TypeAryPtr::get_array_body_type(dest_elem); - generate_arraycopy(adr_type, dest_elem, - src, src_offset, dest, dest_offset, length, - false, false, slow_region); - - return true; -} - -//-----------------------------generate_arraycopy---------------------- -// Generate an optimized call to arraycopy. -// Caller must guard against non-arrays. -// Caller must determine a common array basic-type for both arrays. -// Caller must validate offsets against array bounds. -// The slow_region has already collected guard failure paths -// (such as out of bounds length or non-conformable array types). -// The generated code has this shape, in general: -// -// if (length == 0) return // via zero_path -// slowval = -1 -// if (types unknown) { -// slowval = call generic copy loop -// if (slowval == 0) return // via checked_path -// } else if (indexes in bounds) { -// if ((is object array) && !(array type check)) { -// slowval = call checked copy loop -// if (slowval == 0) return // via checked_path -// } else { -// call bulk copy loop -// return // via fast_path -// } -// } -// // adjust params for remaining work: -// if (slowval != -1) { -// n = -1^slowval; src_offset += n; dest_offset += n; length -= n -// } -// slow_region: -// call slow arraycopy(src, src_offset, dest, dest_offset, length) -// return // via slow_call_path -// -// This routine is used from several intrinsics: System.arraycopy, -// Object.clone (the array subcase), and Arrays.copyOf[Range]. -// -void -LibraryCallKit::generate_arraycopy(const TypePtr* adr_type, - BasicType basic_elem_type, - Node* src, Node* src_offset, - Node* dest, Node* dest_offset, - Node* copy_length, - bool disjoint_bases, - bool length_never_negative, - RegionNode* slow_region) { - - if (slow_region == NULL) { - slow_region = new RegionNode(1); - record_for_igvn(slow_region); - } - - Node* original_dest = dest; - AllocateArrayNode* alloc = NULL; // used for zeroing, if needed - bool dest_uninitialized = false; - - // See if this is the initialization of a newly-allocated array. - // If so, we will take responsibility here for initializing it to zero. - // (Note: Because tightly_coupled_allocation performs checks on the - // out-edges of the dest, we need to avoid making derived pointers - // from it until we have checked its uses.) - if (ReduceBulkZeroing - && !ZeroTLAB // pointless if already zeroed - && basic_elem_type != T_CONFLICT // avoid corner case - && !src->eqv_uncast(dest) - && ((alloc = tightly_coupled_allocation(dest, slow_region)) - != NULL) - && _gvn.find_int_con(alloc->in(AllocateNode::ALength), 1) > 0 - && alloc->maybe_set_complete(&_gvn)) { - // "You break it, you buy it." - InitializeNode* init = alloc->initialization(); - assert(init->is_complete(), "we just did this"); - init->set_complete_with_arraycopy(); - assert(dest->is_CheckCastPP(), "sanity"); - assert(dest->in(0)->in(0) == init, "dest pinned"); - adr_type = TypeRawPtr::BOTTOM; // all initializations are into raw memory - // From this point on, every exit path is responsible for - // initializing any non-copied parts of the object to zero. - // Also, if this flag is set we make sure that arraycopy interacts properly - // with G1, eliding pre-barriers. See CR 6627983. - dest_uninitialized = true; - } else { - // No zeroing elimination here. - alloc = NULL; - //original_dest = dest; - //dest_uninitialized = false; - } - - // Results are placed here: - enum { fast_path = 1, // normal void-returning assembly stub - checked_path = 2, // special assembly stub with cleanup - slow_call_path = 3, // something went wrong; call the VM - zero_path = 4, // bypass when length of copy is zero - bcopy_path = 5, // copy primitive array by 64-bit blocks - PATH_LIMIT = 6 - }; - RegionNode* result_region = new RegionNode(PATH_LIMIT); - PhiNode* result_i_o = new PhiNode(result_region, Type::ABIO); - PhiNode* result_memory = new PhiNode(result_region, Type::MEMORY, adr_type); - record_for_igvn(result_region); - _gvn.set_type_bottom(result_i_o); - _gvn.set_type_bottom(result_memory); - assert(adr_type != TypePtr::BOTTOM, "must be RawMem or a T[] slice"); - - // The slow_control path: - Node* slow_control; - Node* slow_i_o = i_o(); - Node* slow_mem = memory(adr_type); - debug_only(slow_control = (Node*) badAddress); - - // Checked control path: - Node* checked_control = top(); - Node* checked_mem = NULL; - Node* checked_i_o = NULL; - Node* checked_value = NULL; - - if (basic_elem_type == T_CONFLICT) { - assert(!dest_uninitialized, ""); - Node* cv = generate_generic_arraycopy(adr_type, - src, src_offset, dest, dest_offset, - copy_length, dest_uninitialized); - if (cv == NULL) cv = intcon(-1); // failure (no stub available) - checked_control = control(); - checked_i_o = i_o(); - checked_mem = memory(adr_type); - checked_value = cv; - set_control(top()); // no fast path - } - - Node* not_pos = generate_nonpositive_guard(copy_length, length_never_negative); - if (not_pos != NULL) { - PreserveJVMState pjvms(this); - set_control(not_pos); - - // (6) length must not be negative. - if (!length_never_negative) { - generate_negative_guard(copy_length, slow_region); - } - - // copy_length is 0. - if (!stopped() && dest_uninitialized) { - Node* dest_length = alloc->in(AllocateNode::ALength); - if (copy_length->eqv_uncast(dest_length) - || _gvn.find_int_con(dest_length, 1) <= 0) { - // There is no zeroing to do. No need for a secondary raw memory barrier. - } else { - // Clear the whole thing since there are no source elements to copy. - generate_clear_array(adr_type, dest, basic_elem_type, - intcon(0), NULL, - alloc->in(AllocateNode::AllocSize)); - // Use a secondary InitializeNode as raw memory barrier. - // Currently it is needed only on this path since other - // paths have stub or runtime calls as raw memory barriers. - InitializeNode* init = insert_mem_bar_volatile(Op_Initialize, - Compile::AliasIdxRaw, - top())->as_Initialize(); - init->set_complete(&_gvn); // (there is no corresponding AllocateNode) - } - } - - // Present the results of the fast call. - result_region->init_req(zero_path, control()); - result_i_o ->init_req(zero_path, i_o()); - result_memory->init_req(zero_path, memory(adr_type)); - } - - if (!stopped() && dest_uninitialized) { - // We have to initialize the *uncopied* part of the array to zero. - // The copy destination is the slice dest[off..off+len]. The other slices - // are dest_head = dest[0..off] and dest_tail = dest[off+len..dest.length]. - Node* dest_size = alloc->in(AllocateNode::AllocSize); - Node* dest_length = alloc->in(AllocateNode::ALength); - Node* dest_tail = _gvn.transform(new AddINode(dest_offset, copy_length)); - - // If there is a head section that needs zeroing, do it now. - if (find_int_con(dest_offset, -1) != 0) { - generate_clear_array(adr_type, dest, basic_elem_type, - intcon(0), dest_offset, - NULL); - } - - // Next, perform a dynamic check on the tail length. - // It is often zero, and we can win big if we prove this. - // There are two wins: Avoid generating the ClearArray - // with its attendant messy index arithmetic, and upgrade - // the copy to a more hardware-friendly word size of 64 bits. - Node* tail_ctl = NULL; - if (!stopped() && !dest_tail->eqv_uncast(dest_length)) { - Node* cmp_lt = _gvn.transform(new CmpINode(dest_tail, dest_length)); - Node* bol_lt = _gvn.transform(new BoolNode(cmp_lt, BoolTest::lt)); - tail_ctl = generate_slow_guard(bol_lt, NULL); - assert(tail_ctl != NULL || !stopped(), "must be an outcome"); - } - - // At this point, let's assume there is no tail. - if (!stopped() && alloc != NULL && basic_elem_type != T_OBJECT) { - // There is no tail. Try an upgrade to a 64-bit copy. - bool didit = false; - { PreserveJVMState pjvms(this); - didit = generate_block_arraycopy(adr_type, basic_elem_type, alloc, - src, src_offset, dest, dest_offset, - dest_size, dest_uninitialized); - if (didit) { - // Present the results of the block-copying fast call. - result_region->init_req(bcopy_path, control()); - result_i_o ->init_req(bcopy_path, i_o()); - result_memory->init_req(bcopy_path, memory(adr_type)); } } - if (didit) - set_control(top()); // no regular fast path - } - - // Clear the tail, if any. - if (tail_ctl != NULL) { - Node* notail_ctl = stopped() ? NULL : control(); - set_control(tail_ctl); - if (notail_ctl == NULL) { - generate_clear_array(adr_type, dest, basic_elem_type, - dest_tail, NULL, - dest_size); - } else { - // Make a local merge. - Node* done_ctl = new RegionNode(3); - Node* done_mem = new PhiNode(done_ctl, Type::MEMORY, adr_type); - done_ctl->init_req(1, notail_ctl); - done_mem->init_req(1, memory(adr_type)); - generate_clear_array(adr_type, dest, basic_elem_type, - dest_tail, NULL, - dest_size); - done_ctl->init_req(2, control()); - done_mem->init_req(2, memory(adr_type)); - set_control( _gvn.transform(done_ctl)); - set_memory( _gvn.transform(done_mem), adr_type ); + if (!dest_spec) { + dest_k = dest_type->speculative_type_not_null(); + if (dest_k != NULL && dest_k->is_array_klass()) { + could_have_dest = true; + } + } + if (could_have_src && could_have_dest) { + // If we can have both exact types, emit the missing guards + if (could_have_src && !src_spec) { + src = maybe_cast_profiled_obj(src, src_k); + } + if (could_have_dest && !dest_spec) { + dest = maybe_cast_profiled_obj(dest, dest_k); + } } } } - BasicType copy_type = basic_elem_type; - assert(basic_elem_type != T_ARRAY, "caller must fix this"); - if (!stopped() && copy_type == T_OBJECT) { - // If src and dest have compatible element types, we can copy bits. - // Types S[] and D[] are compatible if D is a supertype of S. - // - // If they are not, we will use checked_oop_disjoint_arraycopy, - // which performs a fast optimistic per-oop check, and backs off - // further to JVM_ArrayCopy on the first per-oop check that fails. - // (Actually, we don't move raw bits only; the GC requires card marks.) + if (!too_many_traps(Deoptimization::Reason_intrinsic) && !src->is_top() && !dest->is_top()) { + // validate arguments: enables transformation the ArrayCopyNode + notest = true; - // Get the Klass* for both src and dest + RegionNode* slow_region = new RegionNode(1); + record_for_igvn(slow_region); + + // (1) src and dest are arrays. + generate_non_array_guard(load_object_klass(src), slow_region); + generate_non_array_guard(load_object_klass(dest), slow_region); + + // (2) src and dest arrays must have elements of the same BasicType + // done at macro expansion or at Ideal transformation time + + // (4) src_offset must not be negative. + generate_negative_guard(src_offset, slow_region); + + // (5) dest_offset must not be negative. + generate_negative_guard(dest_offset, slow_region); + + // (7) src_offset + length must not exceed length of src. + generate_limit_guard(src_offset, length, + load_array_length(src), + slow_region); + + // (8) dest_offset + length must not exceed length of dest. + generate_limit_guard(dest_offset, length, + load_array_length(dest), + slow_region); + + // (9) each element of an oop array must be assignable Node* src_klass = load_object_klass(src); Node* dest_klass = load_object_klass(dest); - - // Generate the subtype check. - // This might fold up statically, or then again it might not. - // - // Non-static example: Copying List.elements to a new String[]. - // The backing store for a List is always an Object[], - // but its elements are always type String, if the generic types - // are correct at the source level. - // - // Test S[] against D[], not S against D, because (probably) - // the secondary supertype cache is less busy for S[] than S. - // This usually only matters when D is an interface. Node* not_subtype_ctrl = gen_subtype_check(src_klass, dest_klass); - // Plug failing path into checked_oop_disjoint_arraycopy + if (not_subtype_ctrl != top()) { PreserveJVMState pjvms(this); set_control(not_subtype_ctrl); - // (At this point we can assume disjoint_bases, since types differ.) - int ek_offset = in_bytes(ObjArrayKlass::element_klass_offset()); - Node* p1 = basic_plus_adr(dest_klass, ek_offset); - Node* n1 = LoadKlassNode::make(_gvn, immutable_memory(), p1, TypeRawPtr::BOTTOM); - Node* dest_elem_klass = _gvn.transform(n1); - Node* cv = generate_checkcast_arraycopy(adr_type, - dest_elem_klass, - src, src_offset, dest, dest_offset, - ConvI2X(copy_length), dest_uninitialized); - if (cv == NULL) cv = intcon(-1); // failure (no stub available) - checked_control = control(); - checked_i_o = i_o(); - checked_mem = memory(adr_type); - checked_value = cv; + uncommon_trap(Deoptimization::Reason_intrinsic, + Deoptimization::Action_make_not_entrant); + assert(stopped(), "Should be stopped"); } - // At this point we know we do not need type checks on oop stores. - - // Let's see if we need card marks: - if (alloc != NULL && use_ReduceInitialCardMarks()) { - // If we do not need card marks, copy using the jint or jlong stub. - copy_type = LP64_ONLY(UseCompressedOops ? T_INT : T_LONG) NOT_LP64(T_INT); - assert(type2aelembytes(basic_elem_type) == type2aelembytes(copy_type), - "sizes agree"); + { + PreserveJVMState pjvms(this); + set_control(_gvn.transform(slow_region)); + uncommon_trap(Deoptimization::Reason_intrinsic, + Deoptimization::Action_make_not_entrant); + assert(stopped(), "Should be stopped"); } } - if (!stopped()) { - // Generate the fast path, if possible. - PreserveJVMState pjvms(this); - generate_unchecked_arraycopy(adr_type, copy_type, disjoint_bases, - src, src_offset, dest, dest_offset, - ConvI2X(copy_length), dest_uninitialized); - - // Present the results of the fast call. - result_region->init_req(fast_path, control()); - result_i_o ->init_req(fast_path, i_o()); - result_memory->init_req(fast_path, memory(adr_type)); + if (stopped()) { + return true; } - // Here are all the slow paths up to this point, in one bundle: - slow_control = top(); - if (slow_region != NULL) - slow_control = _gvn.transform(slow_region); - DEBUG_ONLY(slow_region = (RegionNode*)badAddress); + AllocateArrayNode* alloc = tightly_coupled_allocation(dest, NULL); + ArrayCopyNode* ac = ArrayCopyNode::make(this, true, src, src_offset, dest, dest_offset, length, alloc != NULL, + // Create LoadRange and LoadKlass nodes for use during macro expansion here + // so the compiler has a chance to eliminate them: during macro expansion, + // we have to set their control (CastPP nodes are eliminated). + load_array_length(src), load_array_length(dest), + load_object_klass(src), load_object_klass(dest)); - set_control(checked_control); - if (!stopped()) { - // Clean up after the checked call. - // The returned value is either 0 or -1^K, - // where K = number of partially transferred array elements. - Node* cmp = _gvn.transform(new CmpINode(checked_value, intcon(0))); - Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq)); - IfNode* iff = create_and_map_if(control(), bol, PROB_MAX, COUNT_UNKNOWN); - - // If it is 0, we are done, so transfer to the end. - Node* checks_done = _gvn.transform(new IfTrueNode(iff)); - result_region->init_req(checked_path, checks_done); - result_i_o ->init_req(checked_path, checked_i_o); - result_memory->init_req(checked_path, checked_mem); - - // If it is not zero, merge into the slow call. - set_control( _gvn.transform(new IfFalseNode(iff) )); - RegionNode* slow_reg2 = new RegionNode(3); - PhiNode* slow_i_o2 = new PhiNode(slow_reg2, Type::ABIO); - PhiNode* slow_mem2 = new PhiNode(slow_reg2, Type::MEMORY, adr_type); - record_for_igvn(slow_reg2); - slow_reg2 ->init_req(1, slow_control); - slow_i_o2 ->init_req(1, slow_i_o); - slow_mem2 ->init_req(1, slow_mem); - slow_reg2 ->init_req(2, control()); - slow_i_o2 ->init_req(2, checked_i_o); - slow_mem2 ->init_req(2, checked_mem); - - slow_control = _gvn.transform(slow_reg2); - slow_i_o = _gvn.transform(slow_i_o2); - slow_mem = _gvn.transform(slow_mem2); - - if (alloc != NULL) { - // We'll restart from the very beginning, after zeroing the whole thing. - // This can cause double writes, but that's OK since dest is brand new. - // So we ignore the low 31 bits of the value returned from the stub. - } else { - // We must continue the copy exactly where it failed, or else - // another thread might see the wrong number of writes to dest. - Node* checked_offset = _gvn.transform(new XorINode(checked_value, intcon(-1))); - Node* slow_offset = new PhiNode(slow_reg2, TypeInt::INT); - slow_offset->init_req(1, intcon(0)); - slow_offset->init_req(2, checked_offset); - slow_offset = _gvn.transform(slow_offset); - - // Adjust the arguments by the conditionally incoming offset. - Node* src_off_plus = _gvn.transform(new AddINode(src_offset, slow_offset)); - Node* dest_off_plus = _gvn.transform(new AddINode(dest_offset, slow_offset)); - Node* length_minus = _gvn.transform(new SubINode(copy_length, slow_offset)); - - // Tweak the node variables to adjust the code produced below: - src_offset = src_off_plus; - dest_offset = dest_off_plus; - copy_length = length_minus; - } + if (notest) { + ac->set_arraycopy_notest(); } - set_control(slow_control); - if (!stopped()) { - // Generate the slow path, if needed. - PreserveJVMState pjvms(this); // replace_in_map may trash the map + Node* n = _gvn.transform(ac); + assert(n == ac, "cannot disappear"); + ac->connect_outputs(this); - set_memory(slow_mem, adr_type); - set_i_o(slow_i_o); - - if (dest_uninitialized) { - generate_clear_array(adr_type, dest, basic_elem_type, - intcon(0), NULL, - alloc->in(AllocateNode::AllocSize)); - } - - generate_slow_arraycopy(adr_type, - src, src_offset, dest, dest_offset, - copy_length, /*dest_uninitialized*/false); - - result_region->init_req(slow_call_path, control()); - result_i_o ->init_req(slow_call_path, i_o()); - result_memory->init_req(slow_call_path, memory(adr_type)); - } - - // Remove unused edges. - for (uint i = 1; i < result_region->req(); i++) { - if (result_region->in(i) == NULL) - result_region->init_req(i, top()); - } - - // Finished; return the combined state. - set_control( _gvn.transform(result_region)); - set_i_o( _gvn.transform(result_i_o) ); - set_memory( _gvn.transform(result_memory), adr_type ); - - // The memory edges above are precise in order to model effects around - // array copies accurately to allow value numbering of field loads around - // arraycopy. Such field loads, both before and after, are common in Java - // collections and similar classes involving header/array data structures. - // - // But with low number of register or when some registers are used or killed - // by arraycopy calls it causes registers spilling on stack. See 6544710. - // The next memory barrier is added to avoid it. If the arraycopy can be - // optimized away (which it can, sometimes) then we can manually remove - // the membar also. - // - // Do not let reads from the cloned object float above the arraycopy. - if (alloc != NULL) { - // Do not let stores that initialize this object be reordered with - // a subsequent store that would make this object accessible by - // other threads. - // Record what AllocateNode this StoreStore protects so that - // escape analysis can go from the MemBarStoreStoreNode to the - // AllocateNode and eliminate the MemBarStoreStoreNode if possible - // based on the escape status of the AllocateNode. - insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out(AllocateNode::RawAddress)); - } else if (InsertMemBarAfterArraycopy) - insert_mem_bar(Op_MemBarCPUOrder); + return true; } @@ -5397,305 +4883,6 @@ LibraryCallKit::tightly_coupled_allocation(Node* ptr, return alloc; } -// Helper for initialization of arrays, creating a ClearArray. -// It writes zero bits in [start..end), within the body of an array object. -// The memory effects are all chained onto the 'adr_type' alias category. -// -// Since the object is otherwise uninitialized, we are free -// to put a little "slop" around the edges of the cleared area, -// as long as it does not go back into the array's header, -// or beyond the array end within the heap. -// -// The lower edge can be rounded down to the nearest jint and the -// upper edge can be rounded up to the nearest MinObjAlignmentInBytes. -// -// Arguments: -// adr_type memory slice where writes are generated -// dest oop of the destination array -// basic_elem_type element type of the destination -// slice_idx array index of first element to store -// slice_len number of elements to store (or NULL) -// dest_size total size in bytes of the array object -// -// Exactly one of slice_len or dest_size must be non-NULL. -// If dest_size is non-NULL, zeroing extends to the end of the object. -// If slice_len is non-NULL, the slice_idx value must be a constant. -void -LibraryCallKit::generate_clear_array(const TypePtr* adr_type, - Node* dest, - BasicType basic_elem_type, - Node* slice_idx, - Node* slice_len, - Node* dest_size) { - // one or the other but not both of slice_len and dest_size: - assert((slice_len != NULL? 1: 0) + (dest_size != NULL? 1: 0) == 1, ""); - if (slice_len == NULL) slice_len = top(); - if (dest_size == NULL) dest_size = top(); - - // operate on this memory slice: - Node* mem = memory(adr_type); // memory slice to operate on - - // scaling and rounding of indexes: - int scale = exact_log2(type2aelembytes(basic_elem_type)); - int abase = arrayOopDesc::base_offset_in_bytes(basic_elem_type); - int clear_low = (-1 << scale) & (BytesPerInt - 1); - int bump_bit = (-1 << scale) & BytesPerInt; - - // determine constant starts and ends - const intptr_t BIG_NEG = -128; - assert(BIG_NEG + 2*abase < 0, "neg enough"); - intptr_t slice_idx_con = (intptr_t) find_int_con(slice_idx, BIG_NEG); - intptr_t slice_len_con = (intptr_t) find_int_con(slice_len, BIG_NEG); - if (slice_len_con == 0) { - return; // nothing to do here - } - intptr_t start_con = (abase + (slice_idx_con << scale)) & ~clear_low; - intptr_t end_con = find_intptr_t_con(dest_size, -1); - if (slice_idx_con >= 0 && slice_len_con >= 0) { - assert(end_con < 0, "not two cons"); - end_con = round_to(abase + ((slice_idx_con + slice_len_con) << scale), - BytesPerLong); - } - - if (start_con >= 0 && end_con >= 0) { - // Constant start and end. Simple. - mem = ClearArrayNode::clear_memory(control(), mem, dest, - start_con, end_con, &_gvn); - } else if (start_con >= 0 && dest_size != top()) { - // Constant start, pre-rounded end after the tail of the array. - Node* end = dest_size; - mem = ClearArrayNode::clear_memory(control(), mem, dest, - start_con, end, &_gvn); - } else if (start_con >= 0 && slice_len != top()) { - // Constant start, non-constant end. End needs rounding up. - // End offset = round_up(abase + ((slice_idx_con + slice_len) << scale), 8) - intptr_t end_base = abase + (slice_idx_con << scale); - int end_round = (-1 << scale) & (BytesPerLong - 1); - Node* end = ConvI2X(slice_len); - if (scale != 0) - end = _gvn.transform(new LShiftXNode(end, intcon(scale) )); - end_base += end_round; - end = _gvn.transform(new AddXNode(end, MakeConX(end_base))); - end = _gvn.transform(new AndXNode(end, MakeConX(~end_round))); - mem = ClearArrayNode::clear_memory(control(), mem, dest, - start_con, end, &_gvn); - } else if (start_con < 0 && dest_size != top()) { - // Non-constant start, pre-rounded end after the tail of the array. - // This is almost certainly a "round-to-end" operation. - Node* start = slice_idx; - start = ConvI2X(start); - if (scale != 0) - start = _gvn.transform(new LShiftXNode( start, intcon(scale) )); - start = _gvn.transform(new AddXNode(start, MakeConX(abase))); - if ((bump_bit | clear_low) != 0) { - int to_clear = (bump_bit | clear_low); - // Align up mod 8, then store a jint zero unconditionally - // just before the mod-8 boundary. - if (((abase + bump_bit) & ~to_clear) - bump_bit - < arrayOopDesc::length_offset_in_bytes() + BytesPerInt) { - bump_bit = 0; - assert((abase & to_clear) == 0, "array base must be long-aligned"); - } else { - // Bump 'start' up to (or past) the next jint boundary: - start = _gvn.transform(new AddXNode(start, MakeConX(bump_bit))); - assert((abase & clear_low) == 0, "array base must be int-aligned"); - } - // Round bumped 'start' down to jlong boundary in body of array. - start = _gvn.transform(new AndXNode(start, MakeConX(~to_clear))); - if (bump_bit != 0) { - // Store a zero to the immediately preceding jint: - Node* x1 = _gvn.transform(new AddXNode(start, MakeConX(-bump_bit))); - Node* p1 = basic_plus_adr(dest, x1); - mem = StoreNode::make(_gvn, control(), mem, p1, adr_type, intcon(0), T_INT, MemNode::unordered); - mem = _gvn.transform(mem); - } - } - Node* end = dest_size; // pre-rounded - mem = ClearArrayNode::clear_memory(control(), mem, dest, - start, end, &_gvn); - } else { - // Non-constant start, unrounded non-constant end. - // (Nobody zeroes a random midsection of an array using this routine.) - ShouldNotReachHere(); // fix caller - } - - // Done. - set_memory(mem, adr_type); -} - - -bool -LibraryCallKit::generate_block_arraycopy(const TypePtr* adr_type, - BasicType basic_elem_type, - AllocateNode* alloc, - Node* src, Node* src_offset, - Node* dest, Node* dest_offset, - Node* dest_size, bool dest_uninitialized) { - // See if there is an advantage from block transfer. - int scale = exact_log2(type2aelembytes(basic_elem_type)); - if (scale >= LogBytesPerLong) - return false; // it is already a block transfer - - // Look at the alignment of the starting offsets. - int abase = arrayOopDesc::base_offset_in_bytes(basic_elem_type); - - intptr_t src_off_con = (intptr_t) find_int_con(src_offset, -1); - intptr_t dest_off_con = (intptr_t) find_int_con(dest_offset, -1); - if (src_off_con < 0 || dest_off_con < 0) - // At present, we can only understand constants. - return false; - - intptr_t src_off = abase + (src_off_con << scale); - intptr_t dest_off = abase + (dest_off_con << scale); - - if (((src_off | dest_off) & (BytesPerLong-1)) != 0) { - // Non-aligned; too bad. - // One more chance: Pick off an initial 32-bit word. - // This is a common case, since abase can be odd mod 8. - if (((src_off | dest_off) & (BytesPerLong-1)) == BytesPerInt && - ((src_off ^ dest_off) & (BytesPerLong-1)) == 0) { - Node* sptr = basic_plus_adr(src, src_off); - Node* dptr = basic_plus_adr(dest, dest_off); - Node* sval = make_load(control(), sptr, TypeInt::INT, T_INT, adr_type, MemNode::unordered); - store_to_memory(control(), dptr, sval, T_INT, adr_type, MemNode::unordered); - src_off += BytesPerInt; - dest_off += BytesPerInt; - } else { - return false; - } - } - assert(src_off % BytesPerLong == 0, ""); - assert(dest_off % BytesPerLong == 0, ""); - - // Do this copy by giant steps. - Node* sptr = basic_plus_adr(src, src_off); - Node* dptr = basic_plus_adr(dest, dest_off); - Node* countx = dest_size; - countx = _gvn.transform(new SubXNode(countx, MakeConX(dest_off))); - countx = _gvn.transform(new URShiftXNode(countx, intcon(LogBytesPerLong))); - - bool disjoint_bases = true; // since alloc != NULL - generate_unchecked_arraycopy(adr_type, T_LONG, disjoint_bases, - sptr, NULL, dptr, NULL, countx, dest_uninitialized); - - return true; -} - - -// Helper function; generates code for the slow case. -// We make a call to a runtime method which emulates the native method, -// but without the native wrapper overhead. -void -LibraryCallKit::generate_slow_arraycopy(const TypePtr* adr_type, - Node* src, Node* src_offset, - Node* dest, Node* dest_offset, - Node* copy_length, bool dest_uninitialized) { - assert(!dest_uninitialized, "Invariant"); - Node* call = make_runtime_call(RC_NO_LEAF | RC_UNCOMMON, - OptoRuntime::slow_arraycopy_Type(), - OptoRuntime::slow_arraycopy_Java(), - "slow_arraycopy", adr_type, - src, src_offset, dest, dest_offset, - copy_length); - - // Handle exceptions thrown by this fellow: - make_slow_call_ex(call, env()->Throwable_klass(), false); -} - -// Helper function; generates code for cases requiring runtime checks. -Node* -LibraryCallKit::generate_checkcast_arraycopy(const TypePtr* adr_type, - Node* dest_elem_klass, - Node* src, Node* src_offset, - Node* dest, Node* dest_offset, - Node* copy_length, bool dest_uninitialized) { - if (stopped()) return NULL; - - address copyfunc_addr = StubRoutines::checkcast_arraycopy(dest_uninitialized); - if (copyfunc_addr == NULL) { // Stub was not generated, go slow path. - return NULL; - } - - // Pick out the parameters required to perform a store-check - // for the target array. This is an optimistic check. It will - // look in each non-null element's class, at the desired klass's - // super_check_offset, for the desired klass. - int sco_offset = in_bytes(Klass::super_check_offset_offset()); - Node* p3 = basic_plus_adr(dest_elem_klass, sco_offset); - Node* n3 = new LoadINode(NULL, memory(p3), p3, _gvn.type(p3)->is_ptr(), TypeInt::INT, MemNode::unordered); - Node* check_offset = ConvI2X(_gvn.transform(n3)); - Node* check_value = dest_elem_klass; - - Node* src_start = array_element_address(src, src_offset, T_OBJECT); - Node* dest_start = array_element_address(dest, dest_offset, T_OBJECT); - - // (We know the arrays are never conjoint, because their types differ.) - Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, - OptoRuntime::checkcast_arraycopy_Type(), - copyfunc_addr, "checkcast_arraycopy", adr_type, - // five arguments, of which two are - // intptr_t (jlong in LP64) - src_start, dest_start, - copy_length XTOP, - check_offset XTOP, - check_value); - - return _gvn.transform(new ProjNode(call, TypeFunc::Parms)); -} - - -// Helper function; generates code for cases requiring runtime checks. -Node* -LibraryCallKit::generate_generic_arraycopy(const TypePtr* adr_type, - Node* src, Node* src_offset, - Node* dest, Node* dest_offset, - Node* copy_length, bool dest_uninitialized) { - assert(!dest_uninitialized, "Invariant"); - if (stopped()) return NULL; - address copyfunc_addr = StubRoutines::generic_arraycopy(); - if (copyfunc_addr == NULL) { // Stub was not generated, go slow path. - return NULL; - } - - Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, - OptoRuntime::generic_arraycopy_Type(), - copyfunc_addr, "generic_arraycopy", adr_type, - src, src_offset, dest, dest_offset, copy_length); - - return _gvn.transform(new ProjNode(call, TypeFunc::Parms)); -} - -// Helper function; generates the fast out-of-line call to an arraycopy stub. -void -LibraryCallKit::generate_unchecked_arraycopy(const TypePtr* adr_type, - BasicType basic_elem_type, - bool disjoint_bases, - Node* src, Node* src_offset, - Node* dest, Node* dest_offset, - Node* copy_length, bool dest_uninitialized) { - if (stopped()) return; // nothing to do - - Node* src_start = src; - Node* dest_start = dest; - if (src_offset != NULL || dest_offset != NULL) { - assert(src_offset != NULL && dest_offset != NULL, ""); - src_start = array_element_address(src, src_offset, basic_elem_type); - dest_start = array_element_address(dest, dest_offset, basic_elem_type); - } - - // Figure out which arraycopy runtime method to call. - const char* copyfunc_name = "arraycopy"; - address copyfunc_addr = - basictype2arraycopy(basic_elem_type, src_offset, dest_offset, - disjoint_bases, copyfunc_name, dest_uninitialized); - - // Call it. Note that the count_ix value is not scaled to a byte-size. - make_runtime_call(RC_LEAF|RC_NO_FP, - OptoRuntime::fast_arraycopy_Type(), - copyfunc_addr, copyfunc_name, adr_type, - src_start, dest_start, copy_length XTOP); -} - //-------------inline_encodeISOArray----------------------------------- // encode char[] to byte[] in ISO_8859_1 bool LibraryCallKit::inline_encodeISOArray() { @@ -5915,8 +5102,19 @@ Node * LibraryCallKit::load_field_from_object(Node * fromObj, const char * field type = Type::get_const_basic_type(bt); } + if (support_IRIW_for_not_multiple_copy_atomic_cpu && is_vol) { + insert_mem_bar(Op_MemBarVolatile); // StoreLoad barrier + } // Build the load. - Node* loadedField = make_load(NULL, adr, type, bt, adr_type, MemNode::unordered, is_vol); + MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered; + Node* loadedField = make_load(NULL, adr, type, bt, adr_type, mo, is_vol); + // If reference is volatile, prevent following memory ops from + // floating up past the volatile read. Also prevents commoning + // another volatile read. + if (is_vol) { + // Memory barrier includes bogus read of value to force load BEFORE membar + insert_mem_bar(Op_MemBarAcquire, loadedField); + } return loadedField; } diff --git a/hotspot/src/share/vm/opto/loopPredicate.cpp b/hotspot/src/share/vm/opto/loopPredicate.cpp index a55f73db1ac..2539ae4d402 100644 --- a/hotspot/src/share/vm/opto/loopPredicate.cpp +++ b/hotspot/src/share/vm/opto/loopPredicate.cpp @@ -763,9 +763,7 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) { loop->dump_head(); } #endif - } else if ((cl != NULL) && (proj->_con == predicate_proj->_con) && - loop->is_range_check_if(iff, this, invar)) { - + } else if (cl != NULL && loop->is_range_check_if(iff, this, invar)) { // Range check for counted loops const Node* cmp = bol->in(1)->as_Cmp(); Node* idx = cmp->in(1); @@ -800,18 +798,31 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) { } // Test the lower bound - Node* lower_bound_bol = rc_predicate(loop, ctrl, scale, offset, init, limit, stride, rng, false); + BoolNode* lower_bound_bol = rc_predicate(loop, ctrl, scale, offset, init, limit, stride, rng, false); + // Negate test if necessary + bool negated = false; + if (proj->_con != predicate_proj->_con) { + lower_bound_bol = new BoolNode(lower_bound_bol->in(1), lower_bound_bol->_test.negate()); + register_new_node(lower_bound_bol, ctrl); + negated = true; + } IfNode* lower_bound_iff = lower_bound_proj->in(0)->as_If(); _igvn.hash_delete(lower_bound_iff); lower_bound_iff->set_req(1, lower_bound_bol); - if (TraceLoopPredicate) tty->print_cr("lower bound check if: %d", lower_bound_iff->_idx); + if (TraceLoopPredicate) tty->print_cr("lower bound check if: %s %d ", negated ? " negated" : "", lower_bound_iff->_idx); // Test the upper bound - Node* upper_bound_bol = rc_predicate(loop, lower_bound_proj, scale, offset, init, limit, stride, rng, true); + BoolNode* upper_bound_bol = rc_predicate(loop, lower_bound_proj, scale, offset, init, limit, stride, rng, true); + negated = false; + if (proj->_con != predicate_proj->_con) { + upper_bound_bol = new BoolNode(upper_bound_bol->in(1), upper_bound_bol->_test.negate()); + register_new_node(upper_bound_bol, ctrl); + negated = true; + } IfNode* upper_bound_iff = upper_bound_proj->in(0)->as_If(); _igvn.hash_delete(upper_bound_iff); upper_bound_iff->set_req(1, upper_bound_bol); - if (TraceLoopPredicate) tty->print_cr("upper bound check if: %d", lower_bound_iff->_idx); + if (TraceLoopPredicate) tty->print_cr("upper bound check if: %s %d ", negated ? " negated" : "", lower_bound_iff->_idx); // Fall through into rest of the clean up code which will move // any dependent nodes onto the upper bound test. diff --git a/hotspot/src/share/vm/opto/macro.cpp b/hotspot/src/share/vm/opto/macro.cpp index 33e808383c9..40cc26aa0d1 100644 --- a/hotspot/src/share/vm/opto/macro.cpp +++ b/hotspot/src/share/vm/opto/macro.cpp @@ -94,7 +94,8 @@ void PhaseMacroExpand::copy_call_debug_info(CallNode *oldcall, CallNode * newcal newcall->add_req(old_in); } - newcall->set_jvms(oldcall->jvms()); + // JVMS may be shared so clone it before we modify it + newcall->set_jvms(oldcall->jvms() != NULL ? oldcall->jvms()->clone_deep(C) : NULL); for (JVMState *jvms = newcall->jvms(); jvms != NULL; jvms = jvms->caller()) { jvms->set_map(newcall); jvms->set_locoff(jvms->locoff()+jvms_adj); @@ -2469,6 +2470,8 @@ void PhaseMacroExpand::eliminate_macro_nodes() { assert(!n->as_AbstractLock()->is_eliminated(), "sanity"); _has_locks = true; break; + case Node::Class_ArrayCopy: + break; default: assert(n->Opcode() == Op_LoopLimit || n->Opcode() == Op_Opaque1 || @@ -2544,6 +2547,25 @@ bool PhaseMacroExpand::expand_macro_nodes() { } } + // expand arraycopy "macro" nodes first + // For ReduceBulkZeroing, we must first process all arraycopy nodes + // before the allocate nodes are expanded. + int macro_idx = C->macro_count() - 1; + while (macro_idx >= 0) { + Node * n = C->macro_node(macro_idx); + assert(n->is_macro(), "only macro nodes expected here"); + if (_igvn.type(n) == Type::TOP || n->in(0)->is_top() ) { + // node is unreachable, so don't try to expand it + C->remove_macro_node(n); + } else if (n->is_ArrayCopy()){ + int macro_count = C->macro_count(); + expand_arraycopy_node(n->as_ArrayCopy()); + assert(C->macro_count() < macro_count, "must have deleted a node from macro list"); + } + if (C->failing()) return true; + macro_idx --; + } + // expand "macro" nodes // nodes are removed from the macro list as they are processed while (C->macro_count() > 0) { diff --git a/hotspot/src/share/vm/opto/macro.hpp b/hotspot/src/share/vm/opto/macro.hpp index 5cefbb1c063..3cb2e8a2bcf 100644 --- a/hotspot/src/share/vm/opto/macro.hpp +++ b/hotspot/src/share/vm/opto/macro.hpp @@ -37,7 +37,7 @@ class PhaseMacroExpand : public Phase { private: PhaseIterGVN &_igvn; - // Helper methods roughly modelled after GraphKit: + // Helper methods roughly modeled after GraphKit: Node* top() const { return C->top(); } Node* intcon(jint con) const { return _igvn.intcon(con); } Node* longcon(jlong con) const { return _igvn.longcon(con); } @@ -101,6 +101,86 @@ private: void expand_lock_node(LockNode *lock); void expand_unlock_node(UnlockNode *unlock); + // More helper methods modeled after GraphKit for array copy + void insert_mem_bar(Node** ctrl, Node** mem, int opcode, Node* precedent = NULL); + Node* array_element_address(Node* ary, Node* idx, BasicType elembt); + Node* ConvI2L(Node* offset); + Node* make_leaf_call(Node* ctrl, Node* mem, + const TypeFunc* call_type, address call_addr, + const char* call_name, + const TypePtr* adr_type, + Node* parm0 = NULL, Node* parm1 = NULL, + Node* parm2 = NULL, Node* parm3 = NULL, + Node* parm4 = NULL, Node* parm5 = NULL, + Node* parm6 = NULL, Node* parm7 = NULL); + + // helper methods modeled after LibraryCallKit for array copy + Node* generate_guard(Node** ctrl, Node* test, RegionNode* region, float true_prob); + Node* generate_slow_guard(Node** ctrl, Node* test, RegionNode* region); + void generate_negative_guard(Node** ctrl, Node* index, RegionNode* region); + void generate_limit_guard(Node** ctrl, Node* offset, Node* subseq_length, Node* array_length, RegionNode* region); + + // More helper methods for array copy + Node* generate_nonpositive_guard(Node** ctrl, Node* index, bool never_negative); + void finish_arraycopy_call(Node* call, Node** ctrl, MergeMemNode** mem, const TypePtr* adr_type); + address basictype2arraycopy(BasicType t, + Node* src_offset, + Node* dest_offset, + bool disjoint_bases, + const char* &name, + bool dest_uninitialized); + Node* generate_arraycopy(ArrayCopyNode *ac, + AllocateArrayNode* alloc, + Node** ctrl, MergeMemNode* mem, Node** io, + const TypePtr* adr_type, + BasicType basic_elem_type, + Node* src, Node* src_offset, + Node* dest, Node* dest_offset, + Node* copy_length, + bool disjoint_bases = false, + bool length_never_negative = false, + RegionNode* slow_region = NULL); + void generate_clear_array(Node* ctrl, MergeMemNode* merge_mem, + const TypePtr* adr_type, + Node* dest, + BasicType basic_elem_type, + Node* slice_idx, + Node* slice_len, + Node* dest_size); + bool generate_block_arraycopy(Node** ctrl, MergeMemNode** mem, Node* io, + const TypePtr* adr_type, + BasicType basic_elem_type, + AllocateNode* alloc, + Node* src, Node* src_offset, + Node* dest, Node* dest_offset, + Node* dest_size, bool dest_uninitialized); + MergeMemNode* generate_slow_arraycopy(ArrayCopyNode *ac, + Node** ctrl, Node* mem, Node** io, + const TypePtr* adr_type, + Node* src, Node* src_offset, + Node* dest, Node* dest_offset, + Node* copy_length, bool dest_uninitialized); + Node* generate_checkcast_arraycopy(Node** ctrl, MergeMemNode** mem, + const TypePtr* adr_type, + Node* dest_elem_klass, + Node* src, Node* src_offset, + Node* dest, Node* dest_offset, + Node* copy_length, bool dest_uninitialized); + Node* generate_generic_arraycopy(Node** ctrl, MergeMemNode** mem, + const TypePtr* adr_type, + Node* src, Node* src_offset, + Node* dest, Node* dest_offset, + Node* copy_length, bool dest_uninitialized); + void generate_unchecked_arraycopy(Node** ctrl, MergeMemNode** mem, + const TypePtr* adr_type, + BasicType basic_elem_type, + bool disjoint_bases, + Node* src, Node* src_offset, + Node* dest, Node* dest_offset, + Node* copy_length, bool dest_uninitialized); + + void expand_arraycopy_node(ArrayCopyNode *ac); + int replace_input(Node *use, Node *oldref, Node *newref); void copy_call_debug_info(CallNode *oldcall, CallNode * newcall); Node* opt_bits_test(Node* ctrl, Node* region, int edge, Node* word, int mask, int bits, bool return_fast_path = false); diff --git a/hotspot/src/share/vm/opto/macroArrayCopy.cpp b/hotspot/src/share/vm/opto/macroArrayCopy.cpp new file mode 100644 index 00000000000..e2676651e5d --- /dev/null +++ b/hotspot/src/share/vm/opto/macroArrayCopy.cpp @@ -0,0 +1,1233 @@ +/* + * Copyright (c) 2012, 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. + * + */ + +#include "precompiled.hpp" +#include "oops/objArrayKlass.hpp" +#include "opto/convertnode.hpp" +#include "opto/graphKit.hpp" +#include "opto/macro.hpp" +#include "opto/runtime.hpp" + + +void PhaseMacroExpand::insert_mem_bar(Node** ctrl, Node** mem, int opcode, Node* precedent) { + MemBarNode* mb = MemBarNode::make(C, opcode, Compile::AliasIdxBot, precedent); + mb->init_req(TypeFunc::Control, *ctrl); + mb->init_req(TypeFunc::Memory, *mem); + transform_later(mb); + *ctrl = new ProjNode(mb,TypeFunc::Control); + transform_later(*ctrl); + Node* mem_proj = new ProjNode(mb,TypeFunc::Memory); + transform_later(mem_proj); + *mem = mem_proj; +} + +Node* PhaseMacroExpand::array_element_address(Node* ary, Node* idx, BasicType elembt) { + uint shift = exact_log2(type2aelembytes(elembt)); + uint header = arrayOopDesc::base_offset_in_bytes(elembt); + Node* base = basic_plus_adr(ary, header); +#ifdef _LP64 + // see comment in GraphKit::array_element_address + int index_max = max_jint - 1; // array size is max_jint, index is one less + const TypeLong* lidxtype = TypeLong::make(CONST64(0), index_max, Type::WidenMax); + idx = transform_later( new ConvI2LNode(idx, lidxtype) ); +#endif + Node* scale = new LShiftXNode(idx, intcon(shift)); + transform_later(scale); + return basic_plus_adr(ary, base, scale); +} + +Node* PhaseMacroExpand::ConvI2L(Node* offset) { + return transform_later(new ConvI2LNode(offset)); +} + +Node* PhaseMacroExpand::make_leaf_call(Node* ctrl, Node* mem, + const TypeFunc* call_type, address call_addr, + const char* call_name, + const TypePtr* adr_type, + Node* parm0, Node* parm1, + Node* parm2, Node* parm3, + Node* parm4, Node* parm5, + Node* parm6, Node* parm7) { + int size = call_type->domain()->cnt(); + Node* call = new CallLeafNoFPNode(call_type, call_addr, call_name, adr_type); + call->init_req(TypeFunc::Control, ctrl); + call->init_req(TypeFunc::I_O , top()); + call->init_req(TypeFunc::Memory , mem); + call->init_req(TypeFunc::ReturnAdr, top()); + call->init_req(TypeFunc::FramePtr, top()); + + // Hook each parm in order. Stop looking at the first NULL. + if (parm0 != NULL) { call->init_req(TypeFunc::Parms+0, parm0); + if (parm1 != NULL) { call->init_req(TypeFunc::Parms+1, parm1); + if (parm2 != NULL) { call->init_req(TypeFunc::Parms+2, parm2); + if (parm3 != NULL) { call->init_req(TypeFunc::Parms+3, parm3); + if (parm4 != NULL) { call->init_req(TypeFunc::Parms+4, parm4); + if (parm5 != NULL) { call->init_req(TypeFunc::Parms+5, parm5); + if (parm6 != NULL) { call->init_req(TypeFunc::Parms+6, parm6); + if (parm7 != NULL) { call->init_req(TypeFunc::Parms+7, parm7); + /* close each nested if ===> */ } } } } } } } } + assert(call->in(call->req()-1) != NULL, "must initialize all parms"); + + return call; +} + + +//------------------------------generate_guard--------------------------- +// Helper function for generating guarded fast-slow graph structures. +// The given 'test', if true, guards a slow path. If the test fails +// then a fast path can be taken. (We generally hope it fails.) +// In all cases, GraphKit::control() is updated to the fast path. +// The returned value represents the control for the slow path. +// The return value is never 'top'; it is either a valid control +// or NULL if it is obvious that the slow path can never be taken. +// Also, if region and the slow control are not NULL, the slow edge +// is appended to the region. +Node* PhaseMacroExpand::generate_guard(Node** ctrl, Node* test, RegionNode* region, float true_prob) { + if ((*ctrl)->is_top()) { + // Already short circuited. + return NULL; + } + // Build an if node and its projections. + // If test is true we take the slow path, which we assume is uncommon. + if (_igvn.type(test) == TypeInt::ZERO) { + // The slow branch is never taken. No need to build this guard. + return NULL; + } + + IfNode* iff = new IfNode(*ctrl, test, true_prob, COUNT_UNKNOWN); + transform_later(iff); + + Node* if_slow = new IfTrueNode(iff); + transform_later(if_slow); + + if (region != NULL) { + region->add_req(if_slow); + } + + Node* if_fast = new IfFalseNode(iff); + transform_later(if_fast); + + *ctrl = if_fast; + + return if_slow; +} + +inline Node* PhaseMacroExpand::generate_slow_guard(Node** ctrl, Node* test, RegionNode* region) { + return generate_guard(ctrl, test, region, PROB_UNLIKELY_MAG(3)); +} + +void PhaseMacroExpand::generate_negative_guard(Node** ctrl, Node* index, RegionNode* region) { + if ((*ctrl)->is_top()) + return; // already stopped + if (_igvn.type(index)->higher_equal(TypeInt::POS)) // [0,maxint] + return; // index is already adequately typed + Node* cmp_lt = new CmpINode(index, intcon(0)); + transform_later(cmp_lt); + Node* bol_lt = new BoolNode(cmp_lt, BoolTest::lt); + transform_later(bol_lt); + generate_guard(ctrl, bol_lt, region, PROB_MIN); +} + +void PhaseMacroExpand::generate_limit_guard(Node** ctrl, Node* offset, Node* subseq_length, Node* array_length, RegionNode* region) { + if ((*ctrl)->is_top()) + return; // already stopped + bool zero_offset = _igvn.type(offset) == TypeInt::ZERO; + if (zero_offset && subseq_length->eqv_uncast(array_length)) + return; // common case of whole-array copy + Node* last = subseq_length; + if (!zero_offset) { // last += offset + last = new AddINode(last, offset); + transform_later(last); + } + Node* cmp_lt = new CmpUNode(array_length, last); + transform_later(cmp_lt); + Node* bol_lt = new BoolNode(cmp_lt, BoolTest::lt); + transform_later(bol_lt); + generate_guard(ctrl, bol_lt, region, PROB_MIN); +} + +Node* PhaseMacroExpand::generate_nonpositive_guard(Node** ctrl, Node* index, bool never_negative) { + if ((*ctrl)->is_top()) return NULL; + + if (_igvn.type(index)->higher_equal(TypeInt::POS1)) // [1,maxint] + return NULL; // index is already adequately typed + Node* cmp_le = new CmpINode(index, intcon(0)); + transform_later(cmp_le); + BoolTest::mask le_or_eq = (never_negative ? BoolTest::eq : BoolTest::le); + Node* bol_le = new BoolNode(cmp_le, le_or_eq); + transform_later(bol_le); + Node* is_notp = generate_guard(ctrl, bol_le, NULL, PROB_MIN); + + return is_notp; +} + +void PhaseMacroExpand::finish_arraycopy_call(Node* call, Node** ctrl, MergeMemNode** mem, const TypePtr* adr_type) { + transform_later(call); + + *ctrl = new ProjNode(call,TypeFunc::Control); + transform_later(*ctrl); + Node* newmem = new ProjNode(call, TypeFunc::Memory); + transform_later(newmem); + + uint alias_idx = C->get_alias_index(adr_type); + if (alias_idx != Compile::AliasIdxBot) { + *mem = MergeMemNode::make(*mem); + (*mem)->set_memory_at(alias_idx, newmem); + } else { + *mem = MergeMemNode::make(newmem); + } + transform_later(*mem); +} + +address PhaseMacroExpand::basictype2arraycopy(BasicType t, + Node* src_offset, + Node* dest_offset, + bool disjoint_bases, + const char* &name, + bool dest_uninitialized) { + const TypeInt* src_offset_inttype = _igvn.find_int_type(src_offset);; + const TypeInt* dest_offset_inttype = _igvn.find_int_type(dest_offset);; + + bool aligned = false; + bool disjoint = disjoint_bases; + + // if the offsets are the same, we can treat the memory regions as + // disjoint, because either the memory regions are in different arrays, + // or they are identical (which we can treat as disjoint.) We can also + // treat a copy with a destination index less that the source index + // as disjoint since a low->high copy will work correctly in this case. + if (src_offset_inttype != NULL && src_offset_inttype->is_con() && + dest_offset_inttype != NULL && dest_offset_inttype->is_con()) { + // both indices are constants + int s_offs = src_offset_inttype->get_con(); + int d_offs = dest_offset_inttype->get_con(); + int element_size = type2aelembytes(t); + aligned = ((arrayOopDesc::base_offset_in_bytes(t) + s_offs * element_size) % HeapWordSize == 0) && + ((arrayOopDesc::base_offset_in_bytes(t) + d_offs * element_size) % HeapWordSize == 0); + if (s_offs >= d_offs) disjoint = true; + } else if (src_offset == dest_offset && src_offset != NULL) { + // This can occur if the offsets are identical non-constants. + disjoint = true; + } + + return StubRoutines::select_arraycopy_function(t, aligned, disjoint, name, dest_uninitialized); +} + +#define COMMA , +#define XTOP LP64_ONLY(COMMA top()) + +// Generate an optimized call to arraycopy. +// Caller must guard against non-arrays. +// Caller must determine a common array basic-type for both arrays. +// Caller must validate offsets against array bounds. +// The slow_region has already collected guard failure paths +// (such as out of bounds length or non-conformable array types). +// The generated code has this shape, in general: +// +// if (length == 0) return // via zero_path +// slowval = -1 +// if (types unknown) { +// slowval = call generic copy loop +// if (slowval == 0) return // via checked_path +// } else if (indexes in bounds) { +// if ((is object array) && !(array type check)) { +// slowval = call checked copy loop +// if (slowval == 0) return // via checked_path +// } else { +// call bulk copy loop +// return // via fast_path +// } +// } +// // adjust params for remaining work: +// if (slowval != -1) { +// n = -1^slowval; src_offset += n; dest_offset += n; length -= n +// } +// slow_region: +// call slow arraycopy(src, src_offset, dest, dest_offset, length) +// return // via slow_call_path +// +// This routine is used from several intrinsics: System.arraycopy, +// Object.clone (the array subcase), and Arrays.copyOf[Range]. +// +Node* PhaseMacroExpand::generate_arraycopy(ArrayCopyNode *ac, AllocateArrayNode* alloc, + Node** ctrl, MergeMemNode* mem, Node** io, + const TypePtr* adr_type, + BasicType basic_elem_type, + Node* src, Node* src_offset, + Node* dest, Node* dest_offset, + Node* copy_length, + bool disjoint_bases, + bool length_never_negative, + RegionNode* slow_region) { + if (slow_region == NULL) { + slow_region = new RegionNode(1); + transform_later(slow_region); + } + + Node* original_dest = dest; + bool dest_uninitialized = false; + + // See if this is the initialization of a newly-allocated array. + // If so, we will take responsibility here for initializing it to zero. + // (Note: Because tightly_coupled_allocation performs checks on the + // out-edges of the dest, we need to avoid making derived pointers + // from it until we have checked its uses.) + if (ReduceBulkZeroing + && !ZeroTLAB // pointless if already zeroed + && basic_elem_type != T_CONFLICT // avoid corner case + && !src->eqv_uncast(dest) + && alloc != NULL + && _igvn.find_int_con(alloc->in(AllocateNode::ALength), 1) > 0 + && alloc->maybe_set_complete(&_igvn)) { + // "You break it, you buy it." + InitializeNode* init = alloc->initialization(); + assert(init->is_complete(), "we just did this"); + init->set_complete_with_arraycopy(); + assert(dest->is_CheckCastPP(), "sanity"); + assert(dest->in(0)->in(0) == init, "dest pinned"); + adr_type = TypeRawPtr::BOTTOM; // all initializations are into raw memory + // From this point on, every exit path is responsible for + // initializing any non-copied parts of the object to zero. + // Also, if this flag is set we make sure that arraycopy interacts properly + // with G1, eliding pre-barriers. See CR 6627983. + dest_uninitialized = true; + } else { + // No zeroing elimination here. + alloc = NULL; + //original_dest = dest; + //dest_uninitialized = false; + } + + uint alias_idx = C->get_alias_index(adr_type); + + // Results are placed here: + enum { fast_path = 1, // normal void-returning assembly stub + checked_path = 2, // special assembly stub with cleanup + slow_call_path = 3, // something went wrong; call the VM + zero_path = 4, // bypass when length of copy is zero + bcopy_path = 5, // copy primitive array by 64-bit blocks + PATH_LIMIT = 6 + }; + RegionNode* result_region = new RegionNode(PATH_LIMIT); + PhiNode* result_i_o = new PhiNode(result_region, Type::ABIO); + PhiNode* result_memory = new PhiNode(result_region, Type::MEMORY, adr_type); + assert(adr_type != TypePtr::BOTTOM, "must be RawMem or a T[] slice"); + transform_later(result_region); + transform_later(result_i_o); + transform_later(result_memory); + + // The slow_control path: + Node* slow_control; + Node* slow_i_o = *io; + Node* slow_mem = mem->memory_at(alias_idx); + DEBUG_ONLY(slow_control = (Node*) badAddress); + + // Checked control path: + Node* checked_control = top(); + Node* checked_mem = NULL; + Node* checked_i_o = NULL; + Node* checked_value = NULL; + + if (basic_elem_type == T_CONFLICT) { + assert(!dest_uninitialized, ""); + Node* cv = generate_generic_arraycopy(ctrl, &mem, + adr_type, + src, src_offset, dest, dest_offset, + copy_length, dest_uninitialized); + if (cv == NULL) cv = intcon(-1); // failure (no stub available) + checked_control = *ctrl; + checked_i_o = *io; + checked_mem = mem->memory_at(alias_idx); + checked_value = cv; + *ctrl = top(); + } + + Node* not_pos = generate_nonpositive_guard(ctrl, copy_length, length_never_negative); + if (not_pos != NULL) { + Node* local_ctrl = not_pos, *local_io = *io; + MergeMemNode* local_mem = MergeMemNode::make(mem); + transform_later(local_mem); + + // (6) length must not be negative. + if (!length_never_negative) { + generate_negative_guard(&local_ctrl, copy_length, slow_region); + } + + // copy_length is 0. + if (dest_uninitialized) { + assert(!local_ctrl->is_top(), "no ctrl?"); + Node* dest_length = alloc->in(AllocateNode::ALength); + if (copy_length->eqv_uncast(dest_length) + || _igvn.find_int_con(dest_length, 1) <= 0) { + // There is no zeroing to do. No need for a secondary raw memory barrier. + } else { + // Clear the whole thing since there are no source elements to copy. + generate_clear_array(local_ctrl, local_mem, + adr_type, dest, basic_elem_type, + intcon(0), NULL, + alloc->in(AllocateNode::AllocSize)); + // Use a secondary InitializeNode as raw memory barrier. + // Currently it is needed only on this path since other + // paths have stub or runtime calls as raw memory barriers. + MemBarNode* mb = MemBarNode::make(C, Op_Initialize, + Compile::AliasIdxRaw, + top()); + transform_later(mb); + mb->set_req(TypeFunc::Control,local_ctrl); + mb->set_req(TypeFunc::Memory, local_mem->memory_at(Compile::AliasIdxRaw)); + local_ctrl = transform_later(new ProjNode(mb, TypeFunc::Control)); + local_mem->set_memory_at(Compile::AliasIdxRaw, transform_later(new ProjNode(mb, TypeFunc::Memory))); + + InitializeNode* init = mb->as_Initialize(); + init->set_complete(&_igvn); // (there is no corresponding AllocateNode) + } + } + + // Present the results of the fast call. + result_region->init_req(zero_path, local_ctrl); + result_i_o ->init_req(zero_path, local_io); + result_memory->init_req(zero_path, local_mem->memory_at(alias_idx)); + } + + if (!(*ctrl)->is_top() && dest_uninitialized) { + // We have to initialize the *uncopied* part of the array to zero. + // The copy destination is the slice dest[off..off+len]. The other slices + // are dest_head = dest[0..off] and dest_tail = dest[off+len..dest.length]. + Node* dest_size = alloc->in(AllocateNode::AllocSize); + Node* dest_length = alloc->in(AllocateNode::ALength); + Node* dest_tail = transform_later( new AddINode(dest_offset, copy_length)); + + // If there is a head section that needs zeroing, do it now. + if (_igvn.find_int_con(dest_offset, -1) != 0) { + generate_clear_array(*ctrl, mem, + adr_type, dest, basic_elem_type, + intcon(0), dest_offset, + NULL); + } + + // Next, perform a dynamic check on the tail length. + // It is often zero, and we can win big if we prove this. + // There are two wins: Avoid generating the ClearArray + // with its attendant messy index arithmetic, and upgrade + // the copy to a more hardware-friendly word size of 64 bits. + Node* tail_ctl = NULL; + if (!(*ctrl)->is_top() && !dest_tail->eqv_uncast(dest_length)) { + Node* cmp_lt = transform_later( new CmpINode(dest_tail, dest_length) ); + Node* bol_lt = transform_later( new BoolNode(cmp_lt, BoolTest::lt) ); + tail_ctl = generate_slow_guard(ctrl, bol_lt, NULL); + assert(tail_ctl != NULL || !(*ctrl)->is_top(), "must be an outcome"); + } + + // At this point, let's assume there is no tail. + if (!(*ctrl)->is_top() && alloc != NULL && basic_elem_type != T_OBJECT) { + // There is no tail. Try an upgrade to a 64-bit copy. + bool didit = false; + { + Node* local_ctrl = *ctrl, *local_io = *io; + MergeMemNode* local_mem = MergeMemNode::make(mem); + transform_later(local_mem); + + didit = generate_block_arraycopy(&local_ctrl, &local_mem, local_io, + adr_type, basic_elem_type, alloc, + src, src_offset, dest, dest_offset, + dest_size, dest_uninitialized); + if (didit) { + // Present the results of the block-copying fast call. + result_region->init_req(bcopy_path, local_ctrl); + result_i_o ->init_req(bcopy_path, local_io); + result_memory->init_req(bcopy_path, local_mem->memory_at(alias_idx)); + } + } + if (didit) { + *ctrl = top(); // no regular fast path + } + } + + // Clear the tail, if any. + if (tail_ctl != NULL) { + Node* notail_ctl = (*ctrl)->is_top() ? NULL : *ctrl; + *ctrl = tail_ctl; + if (notail_ctl == NULL) { + generate_clear_array(*ctrl, mem, + adr_type, dest, basic_elem_type, + dest_tail, NULL, + dest_size); + } else { + // Make a local merge. + Node* done_ctl = transform_later(new RegionNode(3)); + Node* done_mem = transform_later(new PhiNode(done_ctl, Type::MEMORY, adr_type)); + done_ctl->init_req(1, notail_ctl); + done_mem->init_req(1, mem->memory_at(alias_idx)); + generate_clear_array(*ctrl, mem, + adr_type, dest, basic_elem_type, + dest_tail, NULL, + dest_size); + done_ctl->init_req(2, *ctrl); + done_mem->init_req(2, mem->memory_at(alias_idx)); + *ctrl = done_ctl; + mem->set_memory_at(alias_idx, done_mem); + } + } + } + + BasicType copy_type = basic_elem_type; + assert(basic_elem_type != T_ARRAY, "caller must fix this"); + if (!(*ctrl)->is_top() && copy_type == T_OBJECT) { + // If src and dest have compatible element types, we can copy bits. + // Types S[] and D[] are compatible if D is a supertype of S. + // + // If they are not, we will use checked_oop_disjoint_arraycopy, + // which performs a fast optimistic per-oop check, and backs off + // further to JVM_ArrayCopy on the first per-oop check that fails. + // (Actually, we don't move raw bits only; the GC requires card marks.) + + // Get the klass* for both src and dest + Node* src_klass = ac->in(ArrayCopyNode::SrcKlass); + Node* dest_klass = ac->in(ArrayCopyNode::DestKlass); + + // Generate the subtype check. + // This might fold up statically, or then again it might not. + // + // Non-static example: Copying List.elements to a new String[]. + // The backing store for a List is always an Object[], + // but its elements are always type String, if the generic types + // are correct at the source level. + // + // Test S[] against D[], not S against D, because (probably) + // the secondary supertype cache is less busy for S[] than S. + // This usually only matters when D is an interface. + Node* not_subtype_ctrl = ac->is_arraycopy_notest() ? top() : Phase::gen_subtype_check(src_klass, dest_klass, ctrl, mem, &_igvn); + // Plug failing path into checked_oop_disjoint_arraycopy + if (not_subtype_ctrl != top()) { + Node* local_ctrl = not_subtype_ctrl; + MergeMemNode* local_mem = MergeMemNode::make(mem); + transform_later(local_mem); + + // (At this point we can assume disjoint_bases, since types differ.) + int ek_offset = in_bytes(ObjArrayKlass::element_klass_offset()); + Node* p1 = basic_plus_adr(dest_klass, ek_offset); + Node* n1 = LoadKlassNode::make(_igvn, C->immutable_memory(), p1, TypeRawPtr::BOTTOM); + Node* dest_elem_klass = transform_later(n1); + Node* cv = generate_checkcast_arraycopy(&local_ctrl, &local_mem, + adr_type, + dest_elem_klass, + src, src_offset, dest, dest_offset, + ConvI2X(copy_length), dest_uninitialized); + if (cv == NULL) cv = intcon(-1); // failure (no stub available) + checked_control = local_ctrl; + checked_i_o = *io; + checked_mem = local_mem->memory_at(alias_idx); + checked_value = cv; + } + // At this point we know we do not need type checks on oop stores. + + // Let's see if we need card marks: + if (alloc != NULL && GraphKit::use_ReduceInitialCardMarks()) { + // If we do not need card marks, copy using the jint or jlong stub. + copy_type = LP64_ONLY(UseCompressedOops ? T_INT : T_LONG) NOT_LP64(T_INT); + assert(type2aelembytes(basic_elem_type) == type2aelembytes(copy_type), + "sizes agree"); + } + } + + if (!(*ctrl)->is_top()) { + // Generate the fast path, if possible. + Node* local_ctrl = *ctrl; + MergeMemNode* local_mem = MergeMemNode::make(mem); + transform_later(local_mem); + + generate_unchecked_arraycopy(&local_ctrl, &local_mem, + adr_type, copy_type, disjoint_bases, + src, src_offset, dest, dest_offset, + ConvI2X(copy_length), dest_uninitialized); + + // Present the results of the fast call. + result_region->init_req(fast_path, local_ctrl); + result_i_o ->init_req(fast_path, *io); + result_memory->init_req(fast_path, local_mem->memory_at(alias_idx)); + } + + // Here are all the slow paths up to this point, in one bundle: + assert(slow_region != NULL, "allocated on entry"); + slow_control = slow_region; + DEBUG_ONLY(slow_region = (RegionNode*)badAddress); + + *ctrl = checked_control; + if (!(*ctrl)->is_top()) { + // Clean up after the checked call. + // The returned value is either 0 or -1^K, + // where K = number of partially transferred array elements. + Node* cmp = new CmpINode(checked_value, intcon(0)); + transform_later(cmp); + Node* bol = new BoolNode(cmp, BoolTest::eq); + transform_later(bol); + IfNode* iff = new IfNode(*ctrl, bol, PROB_MAX, COUNT_UNKNOWN); + transform_later(iff); + + // If it is 0, we are done, so transfer to the end. + Node* checks_done = new IfTrueNode(iff); + transform_later(checks_done); + result_region->init_req(checked_path, checks_done); + result_i_o ->init_req(checked_path, checked_i_o); + result_memory->init_req(checked_path, checked_mem); + + // If it is not zero, merge into the slow call. + *ctrl = new IfFalseNode(iff); + transform_later(*ctrl); + RegionNode* slow_reg2 = new RegionNode(3); + PhiNode* slow_i_o2 = new PhiNode(slow_reg2, Type::ABIO); + PhiNode* slow_mem2 = new PhiNode(slow_reg2, Type::MEMORY, adr_type); + transform_later(slow_reg2); + transform_later(slow_i_o2); + transform_later(slow_mem2); + slow_reg2 ->init_req(1, slow_control); + slow_i_o2 ->init_req(1, slow_i_o); + slow_mem2 ->init_req(1, slow_mem); + slow_reg2 ->init_req(2, *ctrl); + slow_i_o2 ->init_req(2, checked_i_o); + slow_mem2 ->init_req(2, checked_mem); + + slow_control = slow_reg2; + slow_i_o = slow_i_o2; + slow_mem = slow_mem2; + + if (alloc != NULL) { + // We'll restart from the very beginning, after zeroing the whole thing. + // This can cause double writes, but that's OK since dest is brand new. + // So we ignore the low 31 bits of the value returned from the stub. + } else { + // We must continue the copy exactly where it failed, or else + // another thread might see the wrong number of writes to dest. + Node* checked_offset = new XorINode(checked_value, intcon(-1)); + Node* slow_offset = new PhiNode(slow_reg2, TypeInt::INT); + transform_later(checked_offset); + transform_later(slow_offset); + slow_offset->init_req(1, intcon(0)); + slow_offset->init_req(2, checked_offset); + + // Adjust the arguments by the conditionally incoming offset. + Node* src_off_plus = new AddINode(src_offset, slow_offset); + transform_later(src_off_plus); + Node* dest_off_plus = new AddINode(dest_offset, slow_offset); + transform_later(dest_off_plus); + Node* length_minus = new SubINode(copy_length, slow_offset); + transform_later(length_minus); + + // Tweak the node variables to adjust the code produced below: + src_offset = src_off_plus; + dest_offset = dest_off_plus; + copy_length = length_minus; + } + } + *ctrl = slow_control; + if (!(*ctrl)->is_top()) { + Node* local_ctrl = *ctrl, *local_io = slow_i_o; + MergeMemNode* local_mem = MergeMemNode::make(mem); + transform_later(local_mem); + + // Generate the slow path, if needed. + local_mem->set_memory_at(alias_idx, slow_mem); + + if (dest_uninitialized) { + generate_clear_array(local_ctrl, local_mem, + adr_type, dest, basic_elem_type, + intcon(0), NULL, + alloc->in(AllocateNode::AllocSize)); + } + + local_mem = generate_slow_arraycopy(ac, + &local_ctrl, local_mem, &local_io, + adr_type, + src, src_offset, dest, dest_offset, + copy_length, /*dest_uninitialized*/false); + + result_region->init_req(slow_call_path, local_ctrl); + result_i_o ->init_req(slow_call_path, local_io); + result_memory->init_req(slow_call_path, local_mem->memory_at(alias_idx)); + } else { + ShouldNotReachHere(); // no call to generate_slow_arraycopy: + // projections were not extracted + } + + // Remove unused edges. + for (uint i = 1; i < result_region->req(); i++) { + if (result_region->in(i) == NULL) { + result_region->init_req(i, top()); + } + } + + // Finished; return the combined state. + *ctrl = result_region; + *io = result_i_o; + mem->set_memory_at(alias_idx, result_memory); + + // mem no longer guaranteed to stay a MergeMemNode + Node* out_mem = mem; + DEBUG_ONLY(mem = NULL); + + // The memory edges above are precise in order to model effects around + // array copies accurately to allow value numbering of field loads around + // arraycopy. Such field loads, both before and after, are common in Java + // collections and similar classes involving header/array data structures. + // + // But with low number of register or when some registers are used or killed + // by arraycopy calls it causes registers spilling on stack. See 6544710. + // The next memory barrier is added to avoid it. If the arraycopy can be + // optimized away (which it can, sometimes) then we can manually remove + // the membar also. + // + // Do not let reads from the cloned object float above the arraycopy. + if (alloc != NULL && !alloc->initialization()->does_not_escape()) { + // Do not let stores that initialize this object be reordered with + // a subsequent store that would make this object accessible by + // other threads. + insert_mem_bar(ctrl, &out_mem, Op_MemBarStoreStore); + } else if (InsertMemBarAfterArraycopy) { + insert_mem_bar(ctrl, &out_mem, Op_MemBarCPUOrder); + } + + _igvn.replace_node(_memproj_fallthrough, out_mem); + _igvn.replace_node(_ioproj_fallthrough, *io); + _igvn.replace_node(_fallthroughcatchproj, *ctrl); + + return out_mem; +} + +// Helper for initialization of arrays, creating a ClearArray. +// It writes zero bits in [start..end), within the body of an array object. +// The memory effects are all chained onto the 'adr_type' alias category. +// +// Since the object is otherwise uninitialized, we are free +// to put a little "slop" around the edges of the cleared area, +// as long as it does not go back into the array's header, +// or beyond the array end within the heap. +// +// The lower edge can be rounded down to the nearest jint and the +// upper edge can be rounded up to the nearest MinObjAlignmentInBytes. +// +// Arguments: +// adr_type memory slice where writes are generated +// dest oop of the destination array +// basic_elem_type element type of the destination +// slice_idx array index of first element to store +// slice_len number of elements to store (or NULL) +// dest_size total size in bytes of the array object +// +// Exactly one of slice_len or dest_size must be non-NULL. +// If dest_size is non-NULL, zeroing extends to the end of the object. +// If slice_len is non-NULL, the slice_idx value must be a constant. +void PhaseMacroExpand::generate_clear_array(Node* ctrl, MergeMemNode* merge_mem, + const TypePtr* adr_type, + Node* dest, + BasicType basic_elem_type, + Node* slice_idx, + Node* slice_len, + Node* dest_size) { + // one or the other but not both of slice_len and dest_size: + assert((slice_len != NULL? 1: 0) + (dest_size != NULL? 1: 0) == 1, ""); + if (slice_len == NULL) slice_len = top(); + if (dest_size == NULL) dest_size = top(); + + uint alias_idx = C->get_alias_index(adr_type); + + // operate on this memory slice: + Node* mem = merge_mem->memory_at(alias_idx); // memory slice to operate on + + // scaling and rounding of indexes: + int scale = exact_log2(type2aelembytes(basic_elem_type)); + int abase = arrayOopDesc::base_offset_in_bytes(basic_elem_type); + int clear_low = (-1 << scale) & (BytesPerInt - 1); + int bump_bit = (-1 << scale) & BytesPerInt; + + // determine constant starts and ends + const intptr_t BIG_NEG = -128; + assert(BIG_NEG + 2*abase < 0, "neg enough"); + intptr_t slice_idx_con = (intptr_t) _igvn.find_int_con(slice_idx, BIG_NEG); + intptr_t slice_len_con = (intptr_t) _igvn.find_int_con(slice_len, BIG_NEG); + if (slice_len_con == 0) { + return; // nothing to do here + } + intptr_t start_con = (abase + (slice_idx_con << scale)) & ~clear_low; + intptr_t end_con = _igvn.find_intptr_t_con(dest_size, -1); + if (slice_idx_con >= 0 && slice_len_con >= 0) { + assert(end_con < 0, "not two cons"); + end_con = round_to(abase + ((slice_idx_con + slice_len_con) << scale), + BytesPerLong); + } + + if (start_con >= 0 && end_con >= 0) { + // Constant start and end. Simple. + mem = ClearArrayNode::clear_memory(ctrl, mem, dest, + start_con, end_con, &_igvn); + } else if (start_con >= 0 && dest_size != top()) { + // Constant start, pre-rounded end after the tail of the array. + Node* end = dest_size; + mem = ClearArrayNode::clear_memory(ctrl, mem, dest, + start_con, end, &_igvn); + } else if (start_con >= 0 && slice_len != top()) { + // Constant start, non-constant end. End needs rounding up. + // End offset = round_up(abase + ((slice_idx_con + slice_len) << scale), 8) + intptr_t end_base = abase + (slice_idx_con << scale); + int end_round = (-1 << scale) & (BytesPerLong - 1); + Node* end = ConvI2X(slice_len); + if (scale != 0) + end = transform_later(new LShiftXNode(end, intcon(scale) )); + end_base += end_round; + end = transform_later(new AddXNode(end, MakeConX(end_base)) ); + end = transform_later(new AndXNode(end, MakeConX(~end_round)) ); + mem = ClearArrayNode::clear_memory(ctrl, mem, dest, + start_con, end, &_igvn); + } else if (start_con < 0 && dest_size != top()) { + // Non-constant start, pre-rounded end after the tail of the array. + // This is almost certainly a "round-to-end" operation. + Node* start = slice_idx; + start = ConvI2X(start); + if (scale != 0) + start = transform_later(new LShiftXNode( start, intcon(scale) )); + start = transform_later(new AddXNode(start, MakeConX(abase)) ); + if ((bump_bit | clear_low) != 0) { + int to_clear = (bump_bit | clear_low); + // Align up mod 8, then store a jint zero unconditionally + // just before the mod-8 boundary. + if (((abase + bump_bit) & ~to_clear) - bump_bit + < arrayOopDesc::length_offset_in_bytes() + BytesPerInt) { + bump_bit = 0; + assert((abase & to_clear) == 0, "array base must be long-aligned"); + } else { + // Bump 'start' up to (or past) the next jint boundary: + start = transform_later( new AddXNode(start, MakeConX(bump_bit)) ); + assert((abase & clear_low) == 0, "array base must be int-aligned"); + } + // Round bumped 'start' down to jlong boundary in body of array. + start = transform_later(new AndXNode(start, MakeConX(~to_clear)) ); + if (bump_bit != 0) { + // Store a zero to the immediately preceding jint: + Node* x1 = transform_later(new AddXNode(start, MakeConX(-bump_bit)) ); + Node* p1 = basic_plus_adr(dest, x1); + mem = StoreNode::make(_igvn, ctrl, mem, p1, adr_type, intcon(0), T_INT, MemNode::unordered); + mem = transform_later(mem); + } + } + Node* end = dest_size; // pre-rounded + mem = ClearArrayNode::clear_memory(ctrl, mem, dest, + start, end, &_igvn); + } else { + // Non-constant start, unrounded non-constant end. + // (Nobody zeroes a random midsection of an array using this routine.) + ShouldNotReachHere(); // fix caller + } + + // Done. + merge_mem->set_memory_at(alias_idx, mem); +} + +bool PhaseMacroExpand::generate_block_arraycopy(Node** ctrl, MergeMemNode** mem, Node* io, + const TypePtr* adr_type, + BasicType basic_elem_type, + AllocateNode* alloc, + Node* src, Node* src_offset, + Node* dest, Node* dest_offset, + Node* dest_size, bool dest_uninitialized) { + // See if there is an advantage from block transfer. + int scale = exact_log2(type2aelembytes(basic_elem_type)); + if (scale >= LogBytesPerLong) + return false; // it is already a block transfer + + // Look at the alignment of the starting offsets. + int abase = arrayOopDesc::base_offset_in_bytes(basic_elem_type); + + intptr_t src_off_con = (intptr_t) _igvn.find_int_con(src_offset, -1); + intptr_t dest_off_con = (intptr_t) _igvn.find_int_con(dest_offset, -1); + if (src_off_con < 0 || dest_off_con < 0) { + // At present, we can only understand constants. + return false; + } + + intptr_t src_off = abase + (src_off_con << scale); + intptr_t dest_off = abase + (dest_off_con << scale); + + if (((src_off | dest_off) & (BytesPerLong-1)) != 0) { + // Non-aligned; too bad. + // One more chance: Pick off an initial 32-bit word. + // This is a common case, since abase can be odd mod 8. + if (((src_off | dest_off) & (BytesPerLong-1)) == BytesPerInt && + ((src_off ^ dest_off) & (BytesPerLong-1)) == 0) { + Node* sptr = basic_plus_adr(src, src_off); + Node* dptr = basic_plus_adr(dest, dest_off); + uint alias_idx = C->get_alias_index(adr_type); + Node* sval = transform_later(LoadNode::make(_igvn, *ctrl, (*mem)->memory_at(alias_idx), sptr, adr_type, TypeInt::INT, T_INT, MemNode::unordered)); + Node* st = transform_later(StoreNode::make(_igvn, *ctrl, (*mem)->memory_at(alias_idx), dptr, adr_type, sval, T_INT, MemNode::unordered)); + (*mem)->set_memory_at(alias_idx, st); + src_off += BytesPerInt; + dest_off += BytesPerInt; + } else { + return false; + } + } + assert(src_off % BytesPerLong == 0, ""); + assert(dest_off % BytesPerLong == 0, ""); + + // Do this copy by giant steps. + Node* sptr = basic_plus_adr(src, src_off); + Node* dptr = basic_plus_adr(dest, dest_off); + Node* countx = dest_size; + countx = transform_later(new SubXNode(countx, MakeConX(dest_off))); + countx = transform_later(new URShiftXNode(countx, intcon(LogBytesPerLong))); + + bool disjoint_bases = true; // since alloc != NULL + generate_unchecked_arraycopy(ctrl, mem, + adr_type, T_LONG, disjoint_bases, + sptr, NULL, dptr, NULL, countx, dest_uninitialized); + + return true; +} + +// Helper function; generates code for the slow case. +// We make a call to a runtime method which emulates the native method, +// but without the native wrapper overhead. +MergeMemNode* PhaseMacroExpand::generate_slow_arraycopy(ArrayCopyNode *ac, + Node** ctrl, Node* mem, Node** io, + const TypePtr* adr_type, + Node* src, Node* src_offset, + Node* dest, Node* dest_offset, + Node* copy_length, bool dest_uninitialized) { + assert(!dest_uninitialized, "Invariant"); + + const TypeFunc* call_type = OptoRuntime::slow_arraycopy_Type(); + CallNode* call = new CallStaticJavaNode(call_type, OptoRuntime::slow_arraycopy_Java(), + "slow_arraycopy", + ac->jvms()->bci(), TypePtr::BOTTOM); + + call->init_req(TypeFunc::Control, *ctrl); + call->init_req(TypeFunc::I_O , *io); + call->init_req(TypeFunc::Memory , mem); + call->init_req(TypeFunc::ReturnAdr, top()); + call->init_req(TypeFunc::FramePtr, top()); + call->init_req(TypeFunc::Parms+0, src); + call->init_req(TypeFunc::Parms+1, src_offset); + call->init_req(TypeFunc::Parms+2, dest); + call->init_req(TypeFunc::Parms+3, dest_offset); + call->init_req(TypeFunc::Parms+4, copy_length); + copy_call_debug_info(ac, call); + + call->set_cnt(PROB_UNLIKELY_MAG(4)); // Same effect as RC_UNCOMMON. + _igvn.replace_node(ac, call); + transform_later(call); + + extract_call_projections(call); + *ctrl = _fallthroughcatchproj->clone(); + transform_later(*ctrl); + + Node* m = _memproj_fallthrough->clone(); + transform_later(m); + + uint alias_idx = C->get_alias_index(adr_type); + MergeMemNode* out_mem; + if (alias_idx != Compile::AliasIdxBot) { + out_mem = MergeMemNode::make(mem); + out_mem->set_memory_at(alias_idx, m); + } else { + out_mem = MergeMemNode::make(m); + } + transform_later(out_mem); + + *io = _ioproj_fallthrough->clone(); + transform_later(*io); + + return out_mem; +} + +// Helper function; generates code for cases requiring runtime checks. +Node* PhaseMacroExpand::generate_checkcast_arraycopy(Node** ctrl, MergeMemNode** mem, + const TypePtr* adr_type, + Node* dest_elem_klass, + Node* src, Node* src_offset, + Node* dest, Node* dest_offset, + Node* copy_length, bool dest_uninitialized) { + if ((*ctrl)->is_top()) return NULL; + + address copyfunc_addr = StubRoutines::checkcast_arraycopy(dest_uninitialized); + if (copyfunc_addr == NULL) { // Stub was not generated, go slow path. + return NULL; + } + + // Pick out the parameters required to perform a store-check + // for the target array. This is an optimistic check. It will + // look in each non-null element's class, at the desired klass's + // super_check_offset, for the desired klass. + int sco_offset = in_bytes(Klass::super_check_offset_offset()); + Node* p3 = basic_plus_adr(dest_elem_klass, sco_offset); + Node* n3 = new LoadINode(NULL, *mem /*memory(p3)*/, p3, _igvn.type(p3)->is_ptr(), TypeInt::INT, MemNode::unordered); + Node* check_offset = ConvI2X(transform_later(n3)); + Node* check_value = dest_elem_klass; + + Node* src_start = array_element_address(src, src_offset, T_OBJECT); + Node* dest_start = array_element_address(dest, dest_offset, T_OBJECT); + + const TypeFunc* call_type = OptoRuntime::checkcast_arraycopy_Type(); + Node* call = make_leaf_call(*ctrl, *mem, call_type, copyfunc_addr, "checkcast_arraycopy", adr_type, + src_start, dest_start, copy_length XTOP, check_offset XTOP, check_value); + + finish_arraycopy_call(call, ctrl, mem, adr_type); + + Node* proj = new ProjNode(call, TypeFunc::Parms); + transform_later(proj); + + return proj; +} + +// Helper function; generates code for cases requiring runtime checks. +Node* PhaseMacroExpand::generate_generic_arraycopy(Node** ctrl, MergeMemNode** mem, + const TypePtr* adr_type, + Node* src, Node* src_offset, + Node* dest, Node* dest_offset, + Node* copy_length, bool dest_uninitialized) { + if ((*ctrl)->is_top()) return NULL; + assert(!dest_uninitialized, "Invariant"); + + address copyfunc_addr = StubRoutines::generic_arraycopy(); + if (copyfunc_addr == NULL) { // Stub was not generated, go slow path. + return NULL; + } + + const TypeFunc* call_type = OptoRuntime::generic_arraycopy_Type(); + Node* call = make_leaf_call(*ctrl, *mem, call_type, copyfunc_addr, "generic_arraycopy", adr_type, + src, src_offset, dest, dest_offset, copy_length); + + finish_arraycopy_call(call, ctrl, mem, adr_type); + + Node* proj = new ProjNode(call, TypeFunc::Parms); + transform_later(proj); + + return proj; +} + +// Helper function; generates the fast out-of-line call to an arraycopy stub. +void PhaseMacroExpand::generate_unchecked_arraycopy(Node** ctrl, MergeMemNode** mem, + const TypePtr* adr_type, + BasicType basic_elem_type, + bool disjoint_bases, + Node* src, Node* src_offset, + Node* dest, Node* dest_offset, + Node* copy_length, bool dest_uninitialized) { + if ((*ctrl)->is_top()) return; + + Node* src_start = src; + Node* dest_start = dest; + if (src_offset != NULL || dest_offset != NULL) { + src_start = array_element_address(src, src_offset, basic_elem_type); + dest_start = array_element_address(dest, dest_offset, basic_elem_type); + } + + // Figure out which arraycopy runtime method to call. + const char* copyfunc_name = "arraycopy"; + address copyfunc_addr = + basictype2arraycopy(basic_elem_type, src_offset, dest_offset, + disjoint_bases, copyfunc_name, dest_uninitialized); + + const TypeFunc* call_type = OptoRuntime::fast_arraycopy_Type(); + Node* call = make_leaf_call(*ctrl, *mem, call_type, copyfunc_addr, copyfunc_name, adr_type, + src_start, dest_start, copy_length XTOP); + + finish_arraycopy_call(call, ctrl, mem, adr_type); +} + +void PhaseMacroExpand::expand_arraycopy_node(ArrayCopyNode *ac) { + Node* ctrl = ac->in(TypeFunc::Control); + Node* io = ac->in(TypeFunc::I_O); + Node* src = ac->in(ArrayCopyNode::Src); + Node* src_offset = ac->in(ArrayCopyNode::SrcPos); + Node* dest = ac->in(ArrayCopyNode::Dest); + Node* dest_offset = ac->in(ArrayCopyNode::DestPos); + Node* length = ac->in(ArrayCopyNode::Length); + MergeMemNode* merge_mem = NULL; + + if (ac->is_clonebasic()) { + assert (src_offset == NULL && dest_offset == NULL, "for clone offsets should be null"); + Node* mem = ac->in(TypeFunc::Memory); + const char* copyfunc_name = "arraycopy"; + address copyfunc_addr = + basictype2arraycopy(T_LONG, NULL, NULL, + true, copyfunc_name, true); + + const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM; + const TypeFunc* call_type = OptoRuntime::fast_arraycopy_Type(); + + Node* call = make_leaf_call(ctrl, mem, call_type, copyfunc_addr, copyfunc_name, raw_adr_type, src, dest, length XTOP); + transform_later(call); + + _igvn.replace_node(ac, call); + return; + } else if (ac->is_copyof() || ac->is_copyofrange() || ac->is_cloneoop()) { + Node* mem = ac->in(TypeFunc::Memory); + merge_mem = MergeMemNode::make(mem); + transform_later(merge_mem); + + RegionNode* slow_region = new RegionNode(1); + transform_later(slow_region); + + AllocateArrayNode* alloc = NULL; + if (ac->is_alloc_tightly_coupled()) { + alloc = AllocateArrayNode::Ideal_array_allocation(dest, &_igvn); + assert(alloc != NULL, "expect alloc"); + } + + generate_arraycopy(ac, alloc, &ctrl, merge_mem, &io, + TypeAryPtr::OOPS, T_OBJECT, + src, src_offset, dest, dest_offset, length, + true, !ac->is_copyofrange()); + + return; + } + + AllocateArrayNode* alloc = NULL; + if (ac->is_alloc_tightly_coupled()) { + alloc = AllocateArrayNode::Ideal_array_allocation(dest, &_igvn); + assert(alloc != NULL, "expect alloc"); + } + + assert(ac->is_arraycopy() || ac->is_arraycopy_notest(), "should be an arraycopy"); + + // Compile time checks. If any of these checks cannot be verified at compile time, + // we do not make a fast path for this call. Instead, we let the call remain as it + // is. The checks we choose to mandate at compile time are: + // + // (1) src and dest are arrays. + const Type* src_type = src->Value(&_igvn); + const Type* dest_type = dest->Value(&_igvn); + const TypeAryPtr* top_src = src_type->isa_aryptr(); + const TypeAryPtr* top_dest = dest_type->isa_aryptr(); + + if (top_src == NULL || top_src->klass() == NULL || + top_dest == NULL || top_dest->klass() == NULL) { + // Conservatively insert a memory barrier on all memory slices. + // Do not let writes into the source float below the arraycopy. + { + Node* mem = ac->in(TypeFunc::Memory); + insert_mem_bar(&ctrl, &mem, Op_MemBarCPUOrder); + + merge_mem = MergeMemNode::make(mem); + transform_later(merge_mem); + } + + // Call StubRoutines::generic_arraycopy stub. + Node* mem = generate_arraycopy(ac, NULL, &ctrl, merge_mem, &io, + TypeRawPtr::BOTTOM, T_CONFLICT, + src, src_offset, dest, dest_offset, length); + + // Do not let reads from the destination float above the arraycopy. + // Since we cannot type the arrays, we don't know which slices + // might be affected. We could restrict this barrier only to those + // memory slices which pertain to array elements--but don't bother. + if (!InsertMemBarAfterArraycopy) { + // (If InsertMemBarAfterArraycopy, there is already one in place.) + insert_mem_bar(&ctrl, &mem, Op_MemBarCPUOrder); + } + return; + } + // (2) src and dest arrays must have elements of the same BasicType + // Figure out the size and type of the elements we will be copying. + BasicType src_elem = top_src->klass()->as_array_klass()->element_type()->basic_type(); + BasicType dest_elem = top_dest->klass()->as_array_klass()->element_type()->basic_type(); + if (src_elem == T_ARRAY) src_elem = T_OBJECT; + if (dest_elem == T_ARRAY) dest_elem = T_OBJECT; + + if (src_elem != dest_elem || dest_elem == T_VOID) { + // The component types are not the same or are not recognized. Punt. + // (But, avoid the native method wrapper to JVM_ArrayCopy.) + { + Node* mem = ac->in(TypeFunc::Memory); + merge_mem = generate_slow_arraycopy(ac, &ctrl, mem, &io, TypePtr::BOTTOM, src, src_offset, dest, dest_offset, length, false); + } + + _igvn.replace_node(_memproj_fallthrough, merge_mem); + _igvn.replace_node(_ioproj_fallthrough, io); + _igvn.replace_node(_fallthroughcatchproj, ctrl); + return; + } + + //--------------------------------------------------------------------------- + // We will make a fast path for this call to arraycopy. + + // We have the following tests left to perform: + // + // (3) src and dest must not be null. + // (4) src_offset must not be negative. + // (5) dest_offset must not be negative. + // (6) length must not be negative. + // (7) src_offset + length must not exceed length of src. + // (8) dest_offset + length must not exceed length of dest. + // (9) each element of an oop array must be assignable + + { + Node* mem = ac->in(TypeFunc::Memory); + merge_mem = MergeMemNode::make(mem); + transform_later(merge_mem); + } + + RegionNode* slow_region = new RegionNode(1); + transform_later(slow_region); + + if (!ac->is_arraycopy_notest()) { + // (3) operands must not be null + // We currently perform our null checks with the null_check routine. + // This means that the null exceptions will be reported in the caller + // rather than (correctly) reported inside of the native arraycopy call. + // This should be corrected, given time. We do our null check with the + // stack pointer restored. + // null checks done library_call.cpp + + // (4) src_offset must not be negative. + generate_negative_guard(&ctrl, src_offset, slow_region); + + // (5) dest_offset must not be negative. + generate_negative_guard(&ctrl, dest_offset, slow_region); + + // (6) length must not be negative (moved to generate_arraycopy()). + // generate_negative_guard(length, slow_region); + + // (7) src_offset + length must not exceed length of src. + Node* alen = ac->in(ArrayCopyNode::SrcLen); + generate_limit_guard(&ctrl, + src_offset, length, + alen, + slow_region); + + // (8) dest_offset + length must not exceed length of dest. + alen = ac->in(ArrayCopyNode::DestLen); + generate_limit_guard(&ctrl, + dest_offset, length, + alen, + slow_region); + + // (9) each element of an oop array must be assignable + // The generate_arraycopy subroutine checks this. + } + // This is where the memory effects are placed: + const TypePtr* adr_type = TypeAryPtr::get_array_body_type(dest_elem); + generate_arraycopy(ac, alloc, &ctrl, merge_mem, &io, + adr_type, dest_elem, + src, src_offset, dest, dest_offset, length, + false, false, slow_region); +} diff --git a/hotspot/src/share/vm/opto/node.cpp b/hotspot/src/share/vm/opto/node.cpp index dd602600b45..c7cd9cd5c37 100644 --- a/hotspot/src/share/vm/opto/node.cpp +++ b/hotspot/src/share/vm/opto/node.cpp @@ -1083,6 +1083,9 @@ bool Node::has_special_unique_user() const { if( this->is_Store() ) { // Condition for back-to-back stores folding. return n->Opcode() == op && n->in(MemNode::Memory) == this; + } else if (this->is_Load()) { + // Condition for removing an unused LoadNode from the MemBarAcquire precedence input + return n->Opcode() == Op_MemBarAcquire; } else if( op == Op_AddL ) { // Condition for convL2I(addL(x,y)) ==> addI(convL2I(x),convL2I(y)) return n->Opcode() == Op_ConvL2I && n->in(1) == this; diff --git a/hotspot/src/share/vm/opto/node.hpp b/hotspot/src/share/vm/opto/node.hpp index b483e36c8bf..bcf6911df52 100644 --- a/hotspot/src/share/vm/opto/node.hpp +++ b/hotspot/src/share/vm/opto/node.hpp @@ -40,6 +40,7 @@ class AddPNode; class AliasInfo; class AllocateArrayNode; class AllocateNode; +class ArrayCopyNode; class Block; class BoolNode; class BoxLockNode; @@ -561,6 +562,7 @@ public: DEFINE_CLASS_ID(AbstractLock, Call, 3) DEFINE_CLASS_ID(Lock, AbstractLock, 0) DEFINE_CLASS_ID(Unlock, AbstractLock, 1) + DEFINE_CLASS_ID(ArrayCopy, Call, 4) DEFINE_CLASS_ID(MultiBranch, Multi, 1) DEFINE_CLASS_ID(PCTable, MultiBranch, 0) DEFINE_CLASS_ID(Catch, PCTable, 0) @@ -707,6 +709,7 @@ public: DEFINE_CLASS_QUERY(AddP) DEFINE_CLASS_QUERY(Allocate) DEFINE_CLASS_QUERY(AllocateArray) + DEFINE_CLASS_QUERY(ArrayCopy) DEFINE_CLASS_QUERY(Bool) DEFINE_CLASS_QUERY(BoxLock) DEFINE_CLASS_QUERY(Call) diff --git a/hotspot/src/share/vm/opto/phase.hpp b/hotspot/src/share/vm/opto/phase.hpp index b06e3470df4..df7f896f8ae 100644 --- a/hotspot/src/share/vm/opto/phase.hpp +++ b/hotspot/src/share/vm/opto/phase.hpp @@ -27,7 +27,10 @@ #include "runtime/timer.hpp" -class Compile; +class IfNode; +class MergeMemNode; +class Node; +class PhaseGVN; //------------------------------Phase------------------------------------------ // Most optimizations are done in Phases. Creating a phase does any long @@ -114,9 +117,20 @@ protected: static elapsedTimer _t_instrSched; static elapsedTimer _t_buildOopMaps; #endif + + // Generate a subtyping check. Takes as input the subtype and supertype. + // Returns 2 values: sets the default control() to the true path and + // returns the false path. Only reads from constant memory taken from the + // default memory; does not write anything. It also doesn't take in an + // Object; if you wish to check an Object you need to load the Object's + // class prior to coming here. + // Used in GraphKit and PhaseMacroExpand + static Node* gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, MergeMemNode* mem, PhaseGVN* gvn); + public: Compile * C; Phase( PhaseNumber pnum ); + #ifndef PRODUCT static void print_timers(); #endif diff --git a/hotspot/src/share/vm/opto/phaseX.hpp b/hotspot/src/share/vm/opto/phaseX.hpp index 53b7a03d458..c3749dbcf70 100644 --- a/hotspot/src/share/vm/opto/phaseX.hpp +++ b/hotspot/src/share/vm/opto/phaseX.hpp @@ -390,6 +390,9 @@ public: // in a faster or cheaper fashion. Node *transform( Node *n ); Node *transform_no_reclaim( Node *n ); + virtual void record_for_igvn(Node *n) { + C->record_for_igvn(n); + } void replace_with(PhaseGVN* gvn) { _table.replace_with(&gvn->_table); @@ -418,9 +421,6 @@ class PhaseIterGVN : public PhaseGVN { protected: - // Idealize new Node 'n' with respect to its inputs and its value - virtual Node *transform( Node *a_node ); - // Warm up hash table, type table and initial worklist void init_worklist( Node *a_root ); @@ -434,6 +434,10 @@ public: PhaseIterGVN( PhaseGVN *gvn ); // Used after Parser PhaseIterGVN( PhaseIterGVN *igvn, const char *dummy ); // Used after +VerifyOpto + // Idealize new Node 'n' with respect to its inputs and its value + virtual Node *transform( Node *a_node ); + virtual void record_for_igvn(Node *n) { } + virtual PhaseIterGVN *is_IterGVN() { return this; } Unique_Node_List _worklist; // Iterative worklist diff --git a/hotspot/src/share/vm/opto/subnode.cpp b/hotspot/src/share/vm/opto/subnode.cpp index c6593549398..1fe558c18d3 100644 --- a/hotspot/src/share/vm/opto/subnode.cpp +++ b/hotspot/src/share/vm/opto/subnode.cpp @@ -1201,6 +1201,54 @@ BoolNode* BoolNode::negate(PhaseGVN* phase) { return new BoolNode(in(1), _test.negate()); } +// Change "bool eq/ne (cmp (add/sub A B) C)" into false/true if add/sub +// overflows and we can prove that C is not in the two resulting ranges. +// This optimization is similar to the one performed by CmpUNode::Value(). +Node* BoolNode::fold_cmpI(PhaseGVN* phase, SubNode* cmp, Node* cmp1, int cmp_op, + int cmp1_op, const TypeInt* cmp2_type) { + // Only optimize eq/ne integer comparison of add/sub + if((_test._test == BoolTest::eq || _test._test == BoolTest::ne) && + (cmp_op == Op_CmpI) && (cmp1_op == Op_AddI || cmp1_op == Op_SubI)) { + // Skip cases were inputs of add/sub are not integers or of bottom type + const TypeInt* r0 = phase->type(cmp1->in(1))->isa_int(); + const TypeInt* r1 = phase->type(cmp1->in(2))->isa_int(); + if ((r0 != NULL) && (r0 != TypeInt::INT) && + (r1 != NULL) && (r1 != TypeInt::INT) && + (cmp2_type != TypeInt::INT)) { + // Compute exact (long) type range of add/sub result + jlong lo_long = r0->_lo; + jlong hi_long = r0->_hi; + if (cmp1_op == Op_AddI) { + lo_long += r1->_lo; + hi_long += r1->_hi; + } else { + lo_long -= r1->_hi; + hi_long -= r1->_lo; + } + // Check for over-/underflow by casting to integer + int lo_int = (int)lo_long; + int hi_int = (int)hi_long; + bool underflow = lo_long != (jlong)lo_int; + bool overflow = hi_long != (jlong)hi_int; + if ((underflow != overflow) && (hi_int < lo_int)) { + // Overflow on one boundary, compute resulting type ranges: + // tr1 [MIN_INT, hi_int] and tr2 [lo_int, MAX_INT] + int w = MAX2(r0->_widen, r1->_widen); // _widen does not matter here + const TypeInt* tr1 = TypeInt::make(min_jint, hi_int, w); + const TypeInt* tr2 = TypeInt::make(lo_int, max_jint, w); + // Compare second input of cmp to both type ranges + const Type* sub_tr1 = cmp->sub(tr1, cmp2_type); + const Type* sub_tr2 = cmp->sub(tr2, cmp2_type); + if (sub_tr1 == TypeInt::CC_LT && sub_tr2 == TypeInt::CC_GT) { + // The result of the add/sub will never equal cmp2. Replace BoolNode + // by false (0) if it tests for equality and by true (1) otherwise. + return ConINode::make((_test._test == BoolTest::eq) ? 0 : 1); + } + } + } + } + return NULL; +} //------------------------------Ideal------------------------------------------ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) { @@ -1294,6 +1342,9 @@ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) { return new BoolNode( ncmp, _test.commute() ); } + // Try to optimize signed integer comparison + return fold_cmpI(phase, cmp->as_Sub(), cmp1, cop, cmp1_op, cmp2_type); + // The transformation below is not valid for either signed or unsigned // comparisons due to wraparound concerns at MAX_VALUE and MIN_VALUE. // This transformation can be resurrected when we are able to @@ -1338,8 +1389,6 @@ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) { // phase->type( cmp2->in(2) ) == TypeInt::ONE ) // return clone_cmp( cmp, cmp1, cmp2->in(1), phase, BoolTest::le ); // } - - return NULL; } //------------------------------Value------------------------------------------ diff --git a/hotspot/src/share/vm/opto/subnode.hpp b/hotspot/src/share/vm/opto/subnode.hpp index da5d7e378cd..f809a3b90c7 100644 --- a/hotspot/src/share/vm/opto/subnode.hpp +++ b/hotspot/src/share/vm/opto/subnode.hpp @@ -286,6 +286,10 @@ class BoolNode : public Node { virtual uint hash() const; virtual uint cmp( const Node &n ) const; virtual uint size_of() const; + + // Try to optimize signed integer comparison + Node* fold_cmpI(PhaseGVN* phase, SubNode* cmp, Node* cmp1, int cmp_op, + int cmp1_op, const TypeInt* cmp2_type); public: const BoolTest _test; BoolNode( Node *cc, BoolTest::mask t): _test(t), Node(0,cc) { diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index a64f3c21313..c404b4c7de5 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -3865,6 +3865,7 @@ void TestOldFreeSpaceCalculation_test(); void TestG1BiasedArray_test(); void TestBufferingOopClosure_test(); void TestCodeCacheRemSet_test(); +void FreeRegionList_test(); #endif void execute_internal_vm_tests() { @@ -3900,6 +3901,9 @@ void execute_internal_vm_tests() { run_unit_test(HeapRegionRemSet::test_prt()); run_unit_test(TestBufferingOopClosure_test()); run_unit_test(TestCodeCacheRemSet_test()); + if (UseG1GC) { + run_unit_test(FreeRegionList_test()); + } #endif tty->print_cr("All internal VM tests passed"); } diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 1970d715ebc..aa28aca328a 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -28,6 +28,10 @@ #include "classfile/javaClasses.hpp" #include "classfile/stringTable.hpp" #include "classfile/systemDictionary.hpp" +#if INCLUDE_CDS +#include "classfile/sharedClassUtil.hpp" +#include "classfile/systemDictionaryShared.hpp" +#endif #include "classfile/vmSymbols.hpp" #include "gc_interface/collectedHeap.inline.hpp" #include "interpreter/bytecode.hpp" @@ -993,7 +997,15 @@ JVM_ENTRY(jclass, JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name) h_loader, Handle(), CHECK_NULL); - +#if INCLUDE_CDS + if (k == NULL) { + // If the class is not already loaded, try to see if it's in the shared + // archive for the current classloader (h_loader). + instanceKlassHandle ik = SystemDictionaryShared::find_or_load_shared_class( + klass_name, h_loader, CHECK_NULL); + k = ik(); + } +#endif return (k == NULL) ? NULL : (jclass) JNIHandles::make_local(env, k->java_mirror()); JVM_END diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index d8971a48a0e..8cd30c31707 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -47,6 +47,7 @@ #include "utilities/exceptions.hpp" #if INCLUDE_ALL_GCS +#include "gc_implementation/parallelScavenge/parallelScavengeHeap.inline.hpp" #include "gc_implementation/g1/concurrentMark.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/heapRegionRemSet.hpp" @@ -227,6 +228,30 @@ WB_ENTRY(jint, WB_StressVirtualSpaceResize(JNIEnv* env, jobject o, (size_t) magnitude, (size_t) iterations); WB_END +WB_ENTRY(jboolean, WB_isObjectInOldGen(JNIEnv* env, jobject o, jobject obj)) + oop p = JNIHandles::resolve(obj); +#if INCLUDE_ALL_GCS + if (UseG1GC) { + G1CollectedHeap* g1 = G1CollectedHeap::heap(); + const HeapRegion* hr = g1->heap_region_containing(p); + if (hr == NULL) { + return false; + } + return !(hr->is_young()); + } else if (UseParallelGC) { + ParallelScavengeHeap* psh = ParallelScavengeHeap::heap(); + return !psh->is_in_young(p); + } +#endif // INCLUDE_ALL_GCS + GenCollectedHeap* gch = GenCollectedHeap::heap(); + return !gch->is_in_young(p); +WB_END + +WB_ENTRY(jlong, WB_GetObjectSize(JNIEnv* env, jobject o, jobject obj)) + oop p = JNIHandles::resolve(obj); + return p->size() * HeapWordSize; +WB_END + #if INCLUDE_ALL_GCS WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj)) G1CollectedHeap* g1 = G1CollectedHeap::heap(); @@ -237,7 +262,7 @@ WB_END WB_ENTRY(jlong, WB_G1NumFreeRegions(JNIEnv* env, jobject o)) G1CollectedHeap* g1 = G1CollectedHeap::heap(); - size_t nr = g1->free_regions(); + size_t nr = g1->num_free_regions(); return (jlong)nr; WB_END @@ -690,6 +715,9 @@ WB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o)) Universe::heap()->collect(GCCause::_last_ditch_collection); WB_END +WB_ENTRY(void, WB_YoungGC(JNIEnv* env, jobject o)) + Universe::heap()->collect(GCCause::_wb_young_gc); +WB_END WB_ENTRY(void, WB_ReadReservedMemory(JNIEnv* env, jobject o)) // static+volatile in order to force the read to happen @@ -841,6 +869,8 @@ bool WhiteBox::lookup_bool(const char* field_name, oop object) { static JNINativeMethod methods[] = { {CC"getObjectAddress", CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress }, + {CC"getObjectSize", CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectSize }, + {CC"isObjectInOldGen", CC"(Ljava/lang/Object;)Z", (void*)&WB_isObjectInOldGen }, {CC"getHeapOopSize", CC"()I", (void*)&WB_GetHeapOopSize }, {CC"isClassAlive0", CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive }, {CC"parseCommandLine", @@ -919,6 +949,7 @@ static JNINativeMethod methods[] = { (void*)&WB_GetStringVMFlag}, {CC"isInStringTable", CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable }, {CC"fullGC", CC"()V", (void*)&WB_FullGC }, + {CC"youngGC", CC"()V", (void*)&WB_YoungGC }, {CC"readReservedMemory", CC"()V", (void*)&WB_ReadReservedMemory }, {CC"allocateMetaspace", CC"(Ljava/lang/ClassLoader;J)J", (void*)&WB_AllocateMetaspace }, diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 0b7b2ca98c1..9ae78d32b06 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/classLoader.hpp" #include "classfile/javaAssertions.hpp" #include "classfile/stringTable.hpp" #include "classfile/symbolTable.hpp" @@ -43,6 +44,7 @@ #include "services/memTracker.hpp" #include "utilities/defaultStream.hpp" #include "utilities/macros.hpp" +#include "utilities/stringUtils.hpp" #include "utilities/taskqueue.hpp" #if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" @@ -1119,11 +1121,11 @@ void Arguments::set_mode_flags(Mode mode) { // Conflict: required to use shared spaces (-Xshare:on), but // incompatible command line options were chosen. -static void no_shared_spaces() { +static void no_shared_spaces(const char* message) { if (RequireSharedSpaces) { jio_fprintf(defaultStream::error_stream(), "Class data sharing is inconsistent with other specified options.\n"); - vm_exit_during_initialization("Unable to use shared archive.", NULL); + vm_exit_during_initialization("Unable to use shared archive.", message); } else { FLAG_SET_DEFAULT(UseSharedSpaces, false); } @@ -1585,7 +1587,7 @@ void Arguments::set_ergonomics_flags() { // at link time, or rewrite bytecodes in non-shared methods. if (!DumpSharedSpaces && !RequireSharedSpaces && (FLAG_IS_DEFAULT(UseSharedSpaces) || !UseSharedSpaces)) { - no_shared_spaces(); + no_shared_spaces("COMPILER2 default: -Xshare:auto | off, have to manually setup to on."); } #endif @@ -3306,6 +3308,15 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, } } + // PrintSharedArchiveAndExit will turn on + // -Xshare:on + // -XX:+TraceClassPaths + if (PrintSharedArchiveAndExit) { + FLAG_SET_CMDLINE(bool, UseSharedSpaces, true); + FLAG_SET_CMDLINE(bool, RequireSharedSpaces, true); + FLAG_SET_CMDLINE(bool, TraceClassPaths, true); + } + // Change the default value for flags which have different default values // when working with older JDKs. #ifdef LINUX @@ -3314,9 +3325,55 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, FLAG_SET_DEFAULT(UseLinuxPosixThreadCPUClocks, false); } #endif // LINUX + fix_appclasspath(); return JNI_OK; } +// Remove all empty paths from the app classpath (if IgnoreEmptyClassPaths is enabled) +// +// This is necessary because some apps like to specify classpath like -cp foo.jar:${XYZ}:bar.jar +// in their start-up scripts. If XYZ is empty, the classpath will look like "-cp foo.jar::bar.jar". +// Java treats such empty paths as if the user specified "-cp foo.jar:.:bar.jar". I.e., an empty +// path is treated as the current directory. +// +// This causes problems with CDS, which requires that all directories specified in the classpath +// must be empty. In most cases, applications do NOT want to load classes from the current +// directory anyway. Adding -XX:+IgnoreEmptyClassPaths will make these applications' start-up +// scripts compatible with CDS. +void Arguments::fix_appclasspath() { + if (IgnoreEmptyClassPaths) { + const char separator = *os::path_separator(); + const char* src = _java_class_path->value(); + + // skip over all the leading empty paths + while (*src == separator) { + src ++; + } + + char* copy = AllocateHeap(strlen(src) + 1, mtInternal); + strncpy(copy, src, strlen(src) + 1); + + // trim all trailing empty paths + for (char* tail = copy + strlen(copy) - 1; tail >= copy && *tail == separator; tail--) { + *tail = '\0'; + } + + char from[3] = {separator, separator, '\0'}; + char to [2] = {separator, '\0'}; + while (StringUtils::replace_no_expand(copy, from, to) > 0) { + // Keep replacing "::" -> ":" until we have no more "::" (non-windows) + // Keep replacing ";;" -> ";" until we have no more ";;" (windows) + } + + _java_class_path->set_value(copy); + FreeHeap(copy); // a copy was made by set_value, so don't need this anymore + } + + if (!PrintSharedArchiveAndExit) { + ClassLoader::trace_class_path("[classpath: ", _java_class_path->value()); + } +} + jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_required) { // This must be done after all -D arguments have been processed. scp_p->expand_endorsed(); @@ -3487,9 +3544,8 @@ void Arguments::set_shared_spaces_flags() { "Cannot dump shared archive when UseCompressedOops or UseCompressedClassPointers is off.", NULL); } } else { - // UseCompressedOops and UseCompressedClassPointers must be on for UseSharedSpaces. if (!UseCompressedOops || !UseCompressedClassPointers) { - no_shared_spaces(); + no_shared_spaces("UseCompressedOops and UseCompressedClassPointers must be on for UseSharedSpaces."); } #endif } @@ -3600,9 +3656,9 @@ jint Arguments::parse(const JavaVMInitArgs* args) { #if INCLUDE_NMT if (match_option(option, "-XX:NativeMemoryTracking", &tail)) { // The launcher did not setup nmt environment variable properly. -// if (!MemTracker::check_launcher_nmt_support(tail)) { -// warning("Native Memory Tracking did not setup properly, using wrong launcher?"); -// } + if (!MemTracker::check_launcher_nmt_support(tail)) { + warning("Native Memory Tracking did not setup properly, using wrong launcher?"); + } // Verify if nmt option is valid. if (MemTracker::verify_nmt_option()) { @@ -3729,7 +3785,7 @@ jint Arguments::parse(const JavaVMInitArgs* args) { FLAG_SET_DEFAULT(UseSharedSpaces, false); FLAG_SET_DEFAULT(PrintSharedSpaces, false); } - no_shared_spaces(); + no_shared_spaces("CDS Disabled"); #endif // INCLUDE_CDS return JNI_OK; diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp index 64cdc5ca72d..28608e2ba1a 100644 --- a/hotspot/src/share/vm/runtime/arguments.hpp +++ b/hotspot/src/share/vm/runtime/arguments.hpp @@ -579,12 +579,15 @@ class Arguments : AllStatic { _meta_index_dir = meta_index_dir; } - static char *get_java_home() { return _java_home->value(); } - static char *get_dll_dir() { return _sun_boot_library_path->value(); } - static char *get_endorsed_dir() { return _java_endorsed_dirs->value(); } - static char *get_sysclasspath() { return _sun_boot_class_path->value(); } + static char* get_java_home() { return _java_home->value(); } + static char* get_dll_dir() { return _sun_boot_library_path->value(); } + static char* get_endorsed_dir() { return _java_endorsed_dirs->value(); } + static char* get_sysclasspath() { return _sun_boot_class_path->value(); } static char* get_meta_index_path() { return _meta_index_path; } static char* get_meta_index_dir() { return _meta_index_dir; } + static char* get_ext_dirs() { return _java_ext_dirs->value(); } + static char* get_appclasspath() { return _java_class_path->value(); } + static void fix_appclasspath(); // Operation modi static Mode mode() { return _mode; } diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 3534ee41d31..372f6c720ab 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -2345,6 +2345,12 @@ class CommandLineFlags { notproduct(bool, TraceScavenge, false, \ "Trace scavenge") \ \ + product(bool, IgnoreEmptyClassPaths, false, \ + "Ignore empty path elements in -classpath") \ + \ + product(bool, TraceClassPaths, false, \ + "Trace processing of class paths") \ + \ product_rw(bool, TraceClassLoading, false, \ "Trace all classes loaded") \ \ @@ -3779,6 +3785,13 @@ class CommandLineFlags { product(bool, PrintSharedSpaces, false, \ "Print usage of shared spaces") \ \ + product(bool, PrintSharedArchiveAndExit, false, \ + "Print shared archive file contents") \ + \ + product(bool, PrintSharedDictionary, false, \ + "If PrintSharedArchiveAndExit is true, also print the shared " \ + "dictionary") \ + \ product(uintx, SharedReadWriteSize, NOT_LP64(12*M) LP64_ONLY(16*M), \ "Size of read-write space for metadata (in bytes)") \ \ @@ -3795,6 +3808,10 @@ class CommandLineFlags { NOT_LP64(LINUX_ONLY(2*G) NOT_LINUX(0)), \ "Address to allocate shared memory region for class data") \ \ + diagnostic(bool, IgnoreUnverifiableClassesDuringDump, false, \ + "Do not quit -Xshare:dump even if we encounter unverifiable " \ + "classes. Just exclude them from the shared dictionary.") \ + \ diagnostic(bool, PrintMethodHandleStubs, false, \ "Print generated stub code for method handles") \ \ @@ -3885,9 +3902,19 @@ class CommandLineFlags { product(bool , AllowNonVirtualCalls, false, \ "Obey the ACC_SUPER flag and allow invokenonvirtual calls") \ \ + product(ccstr, DumpLoadedClassList, NULL, \ + "Dump the names all loaded classes, that could be stored into " \ + "the CDS archive, in the specified file") \ + \ + product(ccstr, SharedClassListFile, NULL, \ + "Override the default CDS class list") \ + \ diagnostic(ccstr, SharedArchiveFile, NULL, \ "Override the default location of the CDS archive file") \ \ + product(ccstr, ExtraSharedClassListFile, NULL, \ + "Extra classlist for building the CDS archive file") \ + \ experimental(size_t, ArrayAllocatorMallocLimit, \ SOLARIS_ONLY(64*K) NOT_SOLARIS((size_t)-1), \ "Allocation less than this value will be allocated " \ diff --git a/hotspot/src/share/vm/runtime/javaCalls.cpp b/hotspot/src/share/vm/runtime/javaCalls.cpp index 24f84978fe2..3cb4053f893 100644 --- a/hotspot/src/share/vm/runtime/javaCalls.cpp +++ b/hotspot/src/share/vm/runtime/javaCalls.cpp @@ -309,6 +309,10 @@ void JavaCalls::call(JavaValue* result, methodHandle method, JavaCallArguments* } void JavaCalls::call_helper(JavaValue* result, methodHandle* m, JavaCallArguments* args, TRAPS) { + // During dumping, Java execution environment is not fully initialized. Also, Java execution + // may cause undesirable side-effects in the class metadata. + assert(!DumpSharedSpaces, "must not execute Java bytecodes when dumping"); + methodHandle method = *m; JavaThread* thread = (JavaThread*)THREAD; assert(thread->is_Java_thread(), "must be called by a java thread"); diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 72f7896f5e9..aa6d5558f51 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -314,7 +314,7 @@ typedef TwoOopHashtable SymbolTwoOopHashtable; nonstatic_field(InstanceKlass, _jni_ids, JNIid*) \ nonstatic_field(InstanceKlass, _osr_nmethods_head, nmethod*) \ nonstatic_field(InstanceKlass, _breakpoints, BreakpointInfo*) \ - nonstatic_field(InstanceKlass, _generic_signature_index, u2) \ + nonstatic_field(InstanceKlass, _generic_signature_index, u2) \ nonstatic_field(InstanceKlass, _methods_jmethod_ids, jmethodID*) \ volatile_nonstatic_field(InstanceKlass, _idnum_allocated_count, u2) \ nonstatic_field(InstanceKlass, _annotations, Annotations*) \ @@ -662,6 +662,7 @@ typedef TwoOopHashtable SymbolTwoOopHashtable; static_field(SystemDictionary, WK_KLASS(StackOverflowError_klass), Klass*) \ static_field(SystemDictionary, WK_KLASS(ProtectionDomain_klass), Klass*) \ static_field(SystemDictionary, WK_KLASS(AccessControlContext_klass), Klass*) \ + static_field(SystemDictionary, WK_KLASS(SecureClassLoader_klass), Klass*) \ static_field(SystemDictionary, WK_KLASS(Reference_klass), Klass*) \ static_field(SystemDictionary, WK_KLASS(SoftReference_klass), Klass*) \ static_field(SystemDictionary, WK_KLASS(WeakReference_klass), Klass*) \ diff --git a/hotspot/src/share/vm/services/mallocSiteTable.hpp b/hotspot/src/share/vm/services/mallocSiteTable.hpp index e291211cac8..cff98161449 100644 --- a/hotspot/src/share/vm/services/mallocSiteTable.hpp +++ b/hotspot/src/share/vm/services/mallocSiteTable.hpp @@ -32,13 +32,14 @@ #include "services/allocationSite.hpp" #include "services/mallocTracker.hpp" #include "services/nmtCommon.hpp" +#include "utilities/nativeCallStack.hpp" // MallocSite represents a code path that eventually calls // os::malloc() to allocate memory class MallocSite : public AllocationSite { public: MallocSite() : - AllocationSite(emptyStack) { } + AllocationSite(NativeCallStack::EMPTY_STACK) { } MallocSite(const NativeCallStack& stack) : AllocationSite(stack) { } diff --git a/hotspot/src/share/vm/services/memTracker.cpp b/hotspot/src/share/vm/services/memTracker.cpp index e66d6fe6be6..24644c8cc67 100644 --- a/hotspot/src/share/vm/services/memTracker.cpp +++ b/hotspot/src/share/vm/services/memTracker.cpp @@ -39,8 +39,6 @@ volatile NMT_TrackingLevel MemTracker::_tracking_level = NMT_unknown; NMT_TrackingLevel MemTracker::_cmdline_tracking_level = NMT_unknown; -NativeCallStack emptyStack(0, false); - MemBaseline MemTracker::_baseline; Mutex* MemTracker::_query_lock = NULL; bool MemTracker::_is_nmt_env_valid = true; @@ -69,6 +67,10 @@ NMT_TrackingLevel MemTracker::init_tracking_level() { os::unsetenv(buf); } + // Construct NativeCallStack::EMPTY_STACK. It may get constructed twice, + // but it is benign, the results are the same. + ::new ((void*)&NativeCallStack::EMPTY_STACK) NativeCallStack(0, false); + if (!MallocTracker::initialize(level) || !VirtualMemoryTracker::initialize(level)) { level = NMT_off; @@ -77,7 +79,12 @@ NMT_TrackingLevel MemTracker::init_tracking_level() { } void MemTracker::init() { - if (tracking_level() >= NMT_summary) { + NMT_TrackingLevel level = tracking_level(); + if (level >= NMT_summary) { + if (!VirtualMemoryTracker::late_initialize(level)) { + shutdown(); + return; + } _query_lock = new (std::nothrow) Mutex(Monitor::max_nonleaf, "NMT_queryLock"); // Already OOM. It is unlikely, but still have to handle it. if (_query_lock == NULL) { diff --git a/hotspot/src/share/vm/services/memTracker.hpp b/hotspot/src/share/vm/services/memTracker.hpp index c256c3e1042..de43b9f2b0e 100644 --- a/hotspot/src/share/vm/services/memTracker.hpp +++ b/hotspot/src/share/vm/services/memTracker.hpp @@ -26,14 +26,13 @@ #define SHARE_VM_SERVICES_MEM_TRACKER_HPP #include "services/nmtCommon.hpp" +#include "utilities/nativeCallStack.hpp" -class NativeCallStack; -extern NativeCallStack emptyStack; #if !INCLUDE_NMT -#define CURRENT_PC emptyStack -#define CALLER_PC emptyStack +#define CURRENT_PC NativeCallStack::EMPTY_STACK +#define CALLER_PC NativeCallStack::EMPTY_STACK class Tracker : public StackObj { public: @@ -83,9 +82,9 @@ class MemTracker : AllStatic { extern volatile bool NMT_stack_walkable; #define CURRENT_PC ((MemTracker::tracking_level() == NMT_detail && NMT_stack_walkable) ? \ - NativeCallStack(0, true) : emptyStack) + NativeCallStack(0, true) : NativeCallStack::EMPTY_STACK) #define CALLER_PC ((MemTracker::tracking_level() == NMT_detail && NMT_stack_walkable) ? \ - NativeCallStack(1, true) : emptyStack) + NativeCallStack(1, true) : NativeCallStack::EMPTY_STACK) class MemBaseline; class Mutex; diff --git a/hotspot/src/share/vm/services/nmtCommon.hpp b/hotspot/src/share/vm/services/nmtCommon.hpp index 78139411981..f057484074f 100644 --- a/hotspot/src/share/vm/services/nmtCommon.hpp +++ b/hotspot/src/share/vm/services/nmtCommon.hpp @@ -50,9 +50,6 @@ enum NMT_TrackingLevel { // build time decision. const int NMT_TrackingStackDepth = 4; -class NativeCallStack; -extern NativeCallStack emptyStack; - // A few common utilities for native memory tracking class NMTUtil : AllStatic { public: diff --git a/hotspot/src/share/vm/services/virtualMemoryTracker.cpp b/hotspot/src/share/vm/services/virtualMemoryTracker.cpp index 4e0476f9085..20c45363f6a 100644 --- a/hotspot/src/share/vm/services/virtualMemoryTracker.cpp +++ b/hotspot/src/share/vm/services/virtualMemoryTracker.cpp @@ -34,7 +34,7 @@ void VirtualMemorySummary::initialize() { ::new ((void*)_snapshot) VirtualMemorySnapshot(); } -SortedLinkedList VirtualMemoryTracker::_reserved_regions; +SortedLinkedList* VirtualMemoryTracker::_reserved_regions; int compare_committed_region(const CommittedMemoryRegion& r1, const CommittedMemoryRegion& r2) { return r1.compare(r2); @@ -167,7 +167,7 @@ bool ReservedMemoryRegion::remove_uncommitted_region(address addr, size_t sz) { // higher part address high_base = addr + sz; size_t high_size = top - high_base; - CommittedMemoryRegion high_rgn(high_base, high_size, emptyStack); + CommittedMemoryRegion high_rgn(high_base, high_size, NativeCallStack::EMPTY_STACK); return add_committed_region(high_rgn); } else { return false; @@ -283,17 +283,26 @@ bool VirtualMemoryTracker::initialize(NMT_TrackingLevel level) { return true; } +bool VirtualMemoryTracker::late_initialize(NMT_TrackingLevel level) { + if (level >= NMT_summary) { + _reserved_regions = new (std::nothrow, ResourceObj::C_HEAP, mtNMT) + SortedLinkedList(); + return (_reserved_regions != NULL); + } + return true; +} + bool VirtualMemoryTracker::add_reserved_region(address base_addr, size_t size, const NativeCallStack& stack, MEMFLAGS flag, bool all_committed) { assert(base_addr != NULL, "Invalid address"); assert(size > 0, "Invalid size"); - + assert(_reserved_regions != NULL, "Sanity check"); ReservedMemoryRegion rgn(base_addr, size, stack, flag); - ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn); + ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn); LinkedListNode* node; if (reserved_rgn == NULL) { VirtualMemorySummary::record_reserved_memory(size, flag); - node = _reserved_regions.add(rgn); + node = _reserved_regions->add(rgn); if (node != NULL) { node->data()->set_all_committed(all_committed); return true; @@ -328,19 +337,28 @@ bool VirtualMemoryTracker::add_reserved_region(address base_addr, size_t size, *reserved_rgn = rgn; return true; - } else { - ShouldNotReachHere(); - return false; } + + // CDS mapping region. + // CDS reserves the whole region for mapping CDS archive, then maps each section into the region. + // NMT reports CDS as a whole. + if (reserved_rgn->flag() == mtClassShared) { + assert(reserved_rgn->contain_region(base_addr, size), "Reserved CDS region should contain this mapping region"); + return true; + } + + ShouldNotReachHere(); + return false; } } } void VirtualMemoryTracker::set_reserved_region_type(address addr, MEMFLAGS flag) { assert(addr != NULL, "Invalid address"); + assert(_reserved_regions != NULL, "Sanity check"); ReservedMemoryRegion rgn(addr, 1); - ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn); + ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn); if (reserved_rgn != NULL) { assert(reserved_rgn->contain_address(addr), "Containment"); if (reserved_rgn->flag() != flag) { @@ -354,8 +372,10 @@ bool VirtualMemoryTracker::add_committed_region(address addr, size_t size, const NativeCallStack& stack) { assert(addr != NULL, "Invalid address"); assert(size > 0, "Invalid size"); + assert(_reserved_regions != NULL, "Sanity check"); + ReservedMemoryRegion rgn(addr, size); - ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn); + ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn); assert(reserved_rgn != NULL, "No reserved region"); assert(reserved_rgn->contain_region(addr, size), "Not completely contained"); @@ -365,8 +385,10 @@ bool VirtualMemoryTracker::add_committed_region(address addr, size_t size, bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size) { assert(addr != NULL, "Invalid address"); assert(size > 0, "Invalid size"); + assert(_reserved_regions != NULL, "Sanity check"); + ReservedMemoryRegion rgn(addr, size); - ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn); + ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn); assert(reserved_rgn != NULL, "No reserved region"); assert(reserved_rgn->contain_region(addr, size), "Not completely contained"); return reserved_rgn->remove_uncommitted_region(addr, size); @@ -375,9 +397,10 @@ bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size) bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) { assert(addr != NULL, "Invalid address"); assert(size > 0, "Invalid size"); + assert(_reserved_regions != NULL, "Sanity check"); ReservedMemoryRegion rgn(addr, size); - ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn); + ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn); assert(reserved_rgn != NULL, "No reserved region"); @@ -390,7 +413,7 @@ bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) { VirtualMemorySummary::record_released_memory(size, reserved_rgn->flag()); if (reserved_rgn->same_region(addr, size)) { - return _reserved_regions.remove(rgn); + return _reserved_regions->remove(rgn); } else { assert(reserved_rgn->contain_region(addr, size), "Not completely contained"); if (reserved_rgn->base() == addr || @@ -405,7 +428,7 @@ bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) { // use original region for lower region reserved_rgn->exclude_region(addr, top - addr); - LinkedListNode* new_rgn = _reserved_regions.add(high_rgn); + LinkedListNode* new_rgn = _reserved_regions->add(high_rgn); if (new_rgn == NULL) { return false; } else { @@ -418,8 +441,9 @@ bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) { bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) { + assert(_reserved_regions != NULL, "Sanity check"); ThreadCritical tc; - LinkedListNode* head = _reserved_regions.head(); + LinkedListNode* head = _reserved_regions->head(); while (head != NULL) { const ReservedMemoryRegion* rgn = head->peek(); if (!walker->do_allocation_site(rgn)) { @@ -439,7 +463,10 @@ bool VirtualMemoryTracker::transition(NMT_TrackingLevel from, NMT_TrackingLevel assert(from == NMT_summary || from == NMT_detail, "Just check"); // Clean up virtual memory tracking data structures. ThreadCritical tc; - _reserved_regions.clear(); + if (_reserved_regions != NULL) { + delete _reserved_regions; + _reserved_regions = NULL; + } } return true; diff --git a/hotspot/src/share/vm/services/virtualMemoryTracker.hpp b/hotspot/src/share/vm/services/virtualMemoryTracker.hpp index 982b1531fc9..bdb686c819f 100644 --- a/hotspot/src/share/vm/services/virtualMemoryTracker.hpp +++ b/hotspot/src/share/vm/services/virtualMemoryTracker.hpp @@ -320,7 +320,7 @@ class ReservedMemoryRegion : public VirtualMemoryRegion { ReservedMemoryRegion(address base, size_t size) : - VirtualMemoryRegion(base, size), _stack(emptyStack), _flag(mtNone), + VirtualMemoryRegion(base, size), _stack(NativeCallStack::EMPTY_STACK), _flag(mtNone), _all_committed(false) { } // Copy constructor @@ -414,6 +414,9 @@ class VirtualMemoryTracker : AllStatic { public: static bool initialize(NMT_TrackingLevel level); + // Late phase initialization + static bool late_initialize(NMT_TrackingLevel level); + static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack, MEMFLAGS flag = mtNone, bool all_committed = false); @@ -428,7 +431,7 @@ class VirtualMemoryTracker : AllStatic { static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to); private: - static SortedLinkedList _reserved_regions; + static SortedLinkedList* _reserved_regions; }; diff --git a/hotspot/src/share/vm/utilities/exceptions.cpp b/hotspot/src/share/vm/utilities/exceptions.cpp index 0759eda3789..5295c9b3608 100644 --- a/hotspot/src/share/vm/utilities/exceptions.cpp +++ b/hotspot/src/share/vm/utilities/exceptions.cpp @@ -85,9 +85,13 @@ bool Exceptions::special_exception(Thread* thread, const char* file, int line, H #endif // ASSERT if (thread->is_VM_thread() - || thread->is_Compiler_thread() ) { + || thread->is_Compiler_thread() + || DumpSharedSpaces ) { // We do not care what kind of exception we get for the vm-thread or a thread which // is compiling. We just install a dummy exception object + // + // We also cannot throw a proper exception when dumping, because we cannot run + // Java bytecodes now. A dummy exception will suffice. thread->set_pending_exception(Universe::vm_exception(), file, line); return true; } @@ -108,9 +112,13 @@ bool Exceptions::special_exception(Thread* thread, const char* file, int line, S } if (thread->is_VM_thread() - || thread->is_Compiler_thread() ) { + || thread->is_Compiler_thread() + || DumpSharedSpaces ) { // We do not care what kind of exception we get for the vm-thread or a thread which // is compiling. We just install a dummy exception object + // + // We also cannot throw a proper exception when dumping, because we cannot run + // Java bytecodes now. A dummy exception will suffice. thread->set_pending_exception(Universe::vm_exception(), file, line); return true; } diff --git a/hotspot/src/share/vm/utilities/nativeCallStack.cpp b/hotspot/src/share/vm/utilities/nativeCallStack.cpp index c50ff410921..aa3a1e67a5d 100644 --- a/hotspot/src/share/vm/utilities/nativeCallStack.cpp +++ b/hotspot/src/share/vm/utilities/nativeCallStack.cpp @@ -27,6 +27,7 @@ #include "utilities/globalDefinitions.hpp" #include "utilities/nativeCallStack.hpp" +const NativeCallStack NativeCallStack::EMPTY_STACK(0, false); NativeCallStack::NativeCallStack(int toSkip, bool fillStack) : _hash_value(0) { diff --git a/hotspot/src/share/vm/utilities/nativeCallStack.hpp b/hotspot/src/share/vm/utilities/nativeCallStack.hpp index 957090b61c7..b6d6a35303e 100644 --- a/hotspot/src/share/vm/utilities/nativeCallStack.hpp +++ b/hotspot/src/share/vm/utilities/nativeCallStack.hpp @@ -52,6 +52,9 @@ * from it. */ class NativeCallStack : public StackObj { + public: + static const NativeCallStack EMPTY_STACK; + private: address _stack[NMT_TrackingStackDepth]; int _hash_value; diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp index 59943c4b161..ceb5774fe81 100644 --- a/hotspot/src/share/vm/utilities/ostream.cpp +++ b/hotspot/src/share/vm/utilities/ostream.cpp @@ -352,6 +352,7 @@ stringStream::~stringStream() {} xmlStream* xtty; outputStream* tty; outputStream* gclog_or_tty; +CDS_ONLY(fileStream* classlist_file;) // Only dump the classes that can be stored into the CDS archive extern Mutex* tty_lock; #define EXTRACHARLEN 32 @@ -463,7 +464,8 @@ static const char* make_log_name_internal(const char* log_name, const char* forc return buf; } -// log_name comes from -XX:LogFile=log_name or -Xloggc:log_name +// log_name comes from -XX:LogFile=log_name, -Xloggc:log_name or +// -XX:DumpLoadedClassList= // in log_name, %p => pid1234 and // %t => YYYY-MM-DD_HH-MM-SS static const char* make_log_name(const char* log_name, const char* force_directory) { @@ -1103,6 +1105,16 @@ void ostream_init_log() { gclog_or_tty = gclog; } +#if INCLUDE_CDS + // For -XX:DumpLoadedClassList= option + if (DumpLoadedClassList != NULL) { + const char* list_name = make_log_name(DumpLoadedClassList, NULL); + classlist_file = new(ResourceObj::C_HEAP, mtInternal) + fileStream(list_name); + FREE_C_HEAP_ARRAY(char, list_name, mtInternal); + } +#endif + // If we haven't lazily initialized the logfile yet, do it now, // to avoid the possibility of lazy initialization during a VM // crash, which can affect the stability of the fatal error handler. @@ -1115,6 +1127,11 @@ void ostream_exit() { static bool ostream_exit_called = false; if (ostream_exit_called) return; ostream_exit_called = true; +#if INCLUDE_CDS + if (classlist_file != NULL) { + delete classlist_file; + } +#endif if (gclog_or_tty != tty) { delete gclog_or_tty; } diff --git a/hotspot/src/share/vm/utilities/ostream.hpp b/hotspot/src/share/vm/utilities/ostream.hpp index 86d8099caa9..5bf1ce43828 100644 --- a/hotspot/src/share/vm/utilities/ostream.hpp +++ b/hotspot/src/share/vm/utilities/ostream.hpp @@ -214,6 +214,8 @@ class fileStream : public outputStream { void flush(); }; +CDS_ONLY(extern fileStream* classlist_file;) + // unlike fileStream, fdStream does unbuffered I/O by calling // open() and write() directly. It is async-safe, but output // from multiple thread may be mixed together. Used by fatal diff --git a/hotspot/src/share/vm/utilities/stringUtils.cpp b/hotspot/src/share/vm/utilities/stringUtils.cpp new file mode 100644 index 00000000000..6d906249cec --- /dev/null +++ b/hotspot/src/share/vm/utilities/stringUtils.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014, 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. + * + */ + +#include "precompiled.hpp" +#include "utilities/stringUtils.hpp" + +int StringUtils::replace_no_expand(char* string, const char* from, const char* to) { + int replace_count = 0; + size_t from_len = strlen(from); + size_t to_len = strlen(to); + assert(from_len >= to_len, "must not expand input"); + + for (char* dst = string; *dst && (dst = strstr(dst, from)) != NULL;) { + char* left_over = dst + from_len; + memmove(dst, to, to_len); // does not copy trailing 0 of + dst += to_len; // skip over the replacement. + memmove(dst, left_over, strlen(left_over) + 1); // copies the trailing 0 of + ++ replace_count; + } + + return replace_count; +} diff --git a/jdk/test/java/lang/instrument/ilib/Options.java b/hotspot/src/share/vm/utilities/stringUtils.hpp similarity index 56% rename from jdk/test/java/lang/instrument/ilib/Options.java rename to hotspot/src/share/vm/utilities/stringUtils.hpp index 27c09288c8f..dfae74df8cd 100644 --- a/jdk/test/java/lang/instrument/ilib/Options.java +++ b/hotspot/src/share/vm/utilities/stringUtils.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -19,22 +19,24 @@ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. + * */ -package ilib; +#ifndef SHARE_VM_UTILITIES_STRINGUTILS_HPP +#define SHARE_VM_UTILITIES_STRINGUTILS_HPP -public class Options { - public boolean shouldInstrumentNew = false; - public boolean shouldInstrumentCall = false; - public boolean shouldInstrumentIndexed = false; - public boolean shouldInstrumentObject = false; - public boolean shouldInstrumentObjectInit = false; - public boolean shouldInstrumentNativeMethods = false; - public String targetMethod = null; - public int fixedIndex = 0; - public String trackerClassName = "MyTracker"; - public String allocTrackerMethodName = "allocTracker"; - public String callTrackerMethodName = "callTracker"; - public String wrappedTrackerMethodName = "wrappedTracker"; - public String wrappedPrefix = "wrapped_up_"; -} +#include "memory/allocation.hpp" + +class StringUtils : AllStatic { +public: + // Replace the substring with another string . must be + // no longer than . The input string is modified in-place. + // + // Replacement is done in a single pass left-to-right. So replace_no_expand("aaa", "aa", "a") + // will result in "aa", not "a". + // + // Returns the count of substrings that have been replaced. + static int replace_no_expand(char* string, const char* from, const char* to); +}; + +#endif // SHARE_VM_UTILITIES_STRINGUTILS_HPP diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index e4f1ee32d29..4f394f62aad 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -328,6 +328,21 @@ hotspot_gc = \ sanity/ExecuteInternalVMTests.java hotspot_runtime = \ + runtime/ \ + -runtime/6888954/vmerrors.sh \ + -runtime/RedefineObject/TestRedefineObject.java \ + -runtime/8003720/Test8003720.java \ + -runtime/Metaspace/FragmentMetaspace.java \ + -runtime/Metaspace/FragmentMetaspaceSimple.java \ + -runtime/Thread/TestThreadDumpMonitorContention.java \ + -runtime/SharedArchiveFile/SharedBaseAddress.java \ + -runtime/memory/ReserveMemory.java \ + -runtime/Unsafe/RangeCheck.java \ + -runtime/SharedArchiveFile/CdsSameObjectAlignment.java \ + -runtime/SharedArchiveFile/DefaultUseWithClient.java \ + -runtime/Thread/CancellableThreadTest.java + +hotspot_runtime_closed = \ sanity/ExecuteInternalVMTests.java hotspot_serviceability = \ diff --git a/hotspot/test/compiler/IntegerArithmetic/TestIntegerComparison.java b/hotspot/test/compiler/IntegerArithmetic/TestIntegerComparison.java new file mode 100644 index 00000000000..8d3c383a7ee --- /dev/null +++ b/hotspot/test/compiler/IntegerArithmetic/TestIntegerComparison.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2014, 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 TestIntegerComparison + * @bug 8043284 8042786 + * @summary "Tests optimizations of signed and unsigned integer comparison." + * @run main/othervm -server -Xcomp -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:CompileOnly=TestIntegerComparison::testSigned,TestIntegerComparison::testUnsigned TestIntegerComparison + */ +public class TestIntegerComparison { + /** + * Tests optimization of signed integer comparison (see BoolNode::Ideal). + * The body of the if statement is unreachable and should not be compiled. + * @param c Character (value in the integer range [0, 65535]) + */ + public static void testSigned(char c) { + // The following addition may overflow. The result is in one + // of the two ranges [IntMax] and [IntMin, IntMin + CharMax - 1]. + int result = c + Integer.MAX_VALUE; + // CmpINode has to consider both result ranges instead of only + // the general [IntMin, IntMax] range to be able to prove that + // result is always unequal to CharMax. + if (result == Character.MAX_VALUE) { + // Unreachable + throw new RuntimeException("Should not reach here!"); + } + } + + /** + * Tests optimization of unsigned integer comparison (see CmpUNode::Value). + * The body of the if statement is unreachable and should not be compiled. + * @param c Character (value in the integer range [0, 65535]) + */ + public static void testUnsigned(char c) { + /* + * The following if statement consisting of two CmpIs is replaced + * by a CmpU during optimization (see 'IfNode::fold_compares'). + * + * The signed (lo < i) and (i < hi) are replaced by the unsigned + * (i - (lo+1) < hi - (lo+1)). In this case the unsigned comparison + * equals (result - 2) < 98 leading to the following CmpUNode: + * + * CmpU (AddI result, -2) 98 + * + * With the value of result this is simplified to: + * + * CmpU (AddI c, -(CharMax - IntMin)) 98 + * + * The subtraction may underflow. The result is in one of the two + * ranges [IntMin], [IntMax - CharMax + 1]. Both ranges have to be + * considered instead of only the general [IntMin, IntMax] to prove + * that due to the overflow the signed comparison result < 98 is + * always false. + */ + int result = c - (Character.MAX_VALUE - Integer.MIN_VALUE) + 2; + if (1 < result && result < 100) { + // Unreachable + throw new RuntimeException("Should not reach here!"); + } + } + + /** + * Tests optimizations of signed and unsigned integer comparison. + */ + public static void main(String[] args) { + // We use characters to get a limited integer range for free + for (int i = Character.MIN_VALUE; i <= Character.MAX_VALUE; ++i) { + testSigned((char) i); + testUnsigned((char) i); + } + } +} diff --git a/hotspot/test/compiler/arraycopy/TestMissingControl.java b/hotspot/test/compiler/arraycopy/TestMissingControl.java new file mode 100644 index 00000000000..503e24be3b4 --- /dev/null +++ b/hotspot/test/compiler/arraycopy/TestMissingControl.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2014, 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 8055153 + * @summary missing control on LoadRange and LoadKlass when array copy macro node is expanded + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:-TieredCompilation TestMissingControl + * + */ +public class TestMissingControl { + + static int[] m1(int[] a2) { + int[] a1 = new int[10]; + System.arraycopy(a1, 0, a2, 0, 10); + return a1; + } + + static class A { + } + + static Object m2(Object[] a2) { + A[] a1 = new A[10]; + System.arraycopy(a1, 0, a2, 0, 10); + return a1; + } + + static void test1() { + int[] a2 = new int[10]; + int[] a3 = new int[5]; + + // compile m1 with arraycopy intrinsified + for (int i = 0; i < 20000; i++) { + m1(a2); + } + + // make m1 trap + for (int i = 0; i < 10; i++) { + try { + m1(a3); + } catch(IndexOutOfBoundsException ioobe) { + } + } + + // recompile m1 + for (int i = 0; i < 20000; i++) { + m1(a2); + } + + try { + m1(null); + } catch(NullPointerException npe) {} + } + + static void test2() { + A[] a2 = new A[10]; + A[] a3 = new A[5]; + + // compile m2 with arraycopy intrinsified + for (int i = 0; i < 20000; i++) { + m2(a2); + } + + // make m2 trap + for (int i = 0; i < 10; i++) { + try { + m2(a3); + } catch(IndexOutOfBoundsException ioobe) { + } + } + + // recompile m2 + for (int i = 0; i < 20000; i++) { + m2(a2); + } + + try { + m2(null); + } catch(NullPointerException npe) {} + } + + static public void main(String[] args) { + test1(); + test2(); + } +} diff --git a/hotspot/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java b/hotspot/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java new file mode 100644 index 00000000000..c8ebd48d3eb --- /dev/null +++ b/hotspot/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2014, 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 sun.hotspot.WhiteBox; +import sun.misc.Unsafe; +import sun.misc.IOUtils; + +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLConnection; + +/* + * @test TestAnonymousClassUnloading + * @bug 8054402 + * @summary "Tests unloading of anonymous classes." + * @library /testlibrary /testlibrary/whitebox + * @compile TestAnonymousClassUnloading.java + * @run main ClassFileInstaller TestAnonymousClassUnloading sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-BackgroundCompilation TestAnonymousClassUnloading + */ +public class TestAnonymousClassUnloading { + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); + private static int COMP_LEVEL_SIMPLE = 1; + private static int COMP_LEVEL_FULL_OPTIMIZATION = 4; + + /** + * We override hashCode here to be able to access this implementation + * via an Object reference (we cannot cast to TestAnonymousClassUnloading). + */ + @Override + public int hashCode() { + return 42; + } + + /** + * Does some work by using the anonymousClass. + * @param anonymousClass Class performing some work (will be unloaded) + */ + static private void doWork(Class anonymousClass) throws InstantiationException, IllegalAccessException { + // Create a new instance + Object anon = anonymousClass.newInstance(); + // We would like to call a method of anonymousClass here but we cannot cast because the class + // was loaded by a different class loader. One solution would be to use reflection but since + // we want C2 to implement the call as an IC we call Object::hashCode() here which actually + // calls anonymousClass::hashCode(). C2 will then implement this call as an IC. + if (anon.hashCode() != 42) { + new RuntimeException("Work not done"); + } + } + + /** + * Makes sure that method is compiled by forcing compilation if not yet compiled. + * @param m Method to be checked + */ + static private void makeSureIsCompiled(Method m) { + // Make sure background compilation is disabled + if (WHITE_BOX.getBooleanVMFlag("BackgroundCompilation")) { + throw new RuntimeException("Background compilation enabled"); + } + + // Check if already compiled + if (!WHITE_BOX.isMethodCompiled(m)) { + // If not, try to compile it with C2 + if(!WHITE_BOX.enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION)) { + // C2 compiler not available, try to compile with C1 + WHITE_BOX.enqueueMethodForCompilation(m, COMP_LEVEL_SIMPLE); + } + // Because background compilation is disabled, method should now be compiled + if(!WHITE_BOX.isMethodCompiled(m)) { + throw new RuntimeException(m + " not compiled"); + } + } + } + + /** + * This test creates stale Klass* metadata referenced by a compiled IC. + * + * The following steps are performed: + * (1) An anonymous version of TestAnonymousClassUnloading is loaded by a custom class loader + * (2) The method doWork that calls a method of the anonymous class is compiled. The call + * is implemented as an IC referencing Klass* metadata of the anonymous class. + * (3) Unloading of the anonymous class is enforced. The IC now references dead metadata. + */ + static public void main(String[] args) throws Exception { + // (1) Load an anonymous version of this class using the corresponding Unsafe method + URL classUrl = TestAnonymousClassUnloading.class.getResource("TestAnonymousClassUnloading.class"); + URLConnection connection = classUrl.openConnection(); + byte[] classBytes = IOUtils.readFully(connection.getInputStream(), connection.getContentLength(), true); + Class anonymousClass = UNSAFE.defineAnonymousClass(TestAnonymousClassUnloading.class, classBytes, null); + + // (2) Make sure all paths of doWork are profiled and compiled + for (int i = 0; i < 100000; ++i) { + doWork(anonymousClass); + } + + // Make sure doWork is compiled now + Method doWork = TestAnonymousClassUnloading.class.getDeclaredMethod("doWork", Class.class); + makeSureIsCompiled(doWork); + + // (3) Throw away reference to anonymousClass to allow unloading + anonymousClass = null; + + // Force garbage collection to trigger unloading of anonymousClass + // Dead metadata reference to anonymousClass triggers JDK-8054402 + WHITE_BOX.fullGC(); + } +} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/SourceListener.java b/hotspot/test/compiler/exceptions/TestRecursiveReplacedException.java similarity index 56% rename from jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/SourceListener.java rename to hotspot/test/compiler/exceptions/TestRecursiveReplacedException.java index 0379cad1f62..996d82a0feb 100644 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/SourceListener.java +++ b/hotspot/test/compiler/exceptions/TestRecursiveReplacedException.java @@ -1,12 +1,10 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. + * 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 @@ -24,16 +22,23 @@ */ /* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. + * @test + * @bug 8054224 + * @summary Recursive method compiled by C1 is unable to catch StackOverflowError + * @run main/othervm -Xcomp -XX:CompileOnly=Test.run -XX:+TieredCompilation -XX:TieredStopAtLevel=2 -Xss256K TestRecursiveReplacedException + * */ +public class TestRecursiveReplacedException { -package com.sun.tools.example.debug.gui; + public static void main(String args[]) { + new TestRecursiveReplacedException().run(); + } -public interface SourceListener { - void sourcepathChanged(SourcepathChangedEvent e); + public void run() { + try { + run(); + } catch (Throwable t) { + } + } } diff --git a/hotspot/test/compiler/membars/TestMemBarAcquire.java b/hotspot/test/compiler/membars/TestMemBarAcquire.java new file mode 100644 index 00000000000..e255cc1ebe7 --- /dev/null +++ b/hotspot/test/compiler/membars/TestMemBarAcquire.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014, 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 TestMemBarAcquire + * @bug 8048879 + * @summary "Tests optimization of MemBarAcquireNodes" + * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation TestMemBarAcquire + */ +public class TestMemBarAcquire { + private volatile static Object defaultObj = new Object(); + private Object obj; + + public TestMemBarAcquire(Object param) { + // Volatile load. MemBarAcquireNode is added after the + // load to prevent following loads from floating up past. + // StoreNode is added to store result of load in 'obj'. + this.obj = defaultObj; + // Overrides 'obj' and therefore makes previous StoreNode + // and the corresponding LoadNode useless. However, the + // LoadNode is still connected to the MemBarAcquireNode + // that should now release the reference. + this.obj = param; + } + + public static void main(String[] args) throws Exception { + // Make sure TestMemBarAcquire:: is compiled + for (int i = 0; i < 100000; ++i) { + TestMemBarAcquire p = new TestMemBarAcquire(new Object()); + } + } +} + diff --git a/hotspot/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java b/hotspot/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java index 2f2a9bbed3a..38c1e16cea1 100644 --- a/hotspot/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java +++ b/hotspot/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java @@ -46,6 +46,7 @@ public class TestCMSClassUnloadingEnabledHWM { private static OutputAnalyzer run(boolean enableUnloading) throws Exception { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-Xbootclasspath/a:.", + "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", "-XX:MetaspaceSize=" + MetaspaceSize, "-Xmn" + YoungGenSize, diff --git a/hotspot/test/gc/class_unloading/TestG1ClassUnloadingHWM.java b/hotspot/test/gc/class_unloading/TestG1ClassUnloadingHWM.java index b6e677be857..c2c17145762 100644 --- a/hotspot/test/gc/class_unloading/TestG1ClassUnloadingHWM.java +++ b/hotspot/test/gc/class_unloading/TestG1ClassUnloadingHWM.java @@ -46,6 +46,7 @@ public class TestG1ClassUnloadingHWM { private static OutputAnalyzer run(boolean enableUnloading) throws Exception { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-Xbootclasspath/a:.", + "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", "-XX:MetaspaceSize=" + MetaspaceSize, "-Xmn" + YoungGenSize, diff --git a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegions2.java b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegions2.java index 147dc48ef7b..dafbde0ed6f 100644 --- a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegions2.java +++ b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegions2.java @@ -46,6 +46,8 @@ class ObjectWithSomeRefs { } class ReclaimRegionFast { + public static final long MAX_MILLIS_FOR_RUN = 50 * 1000; // The maximum runtime for the actual test. + public static final int M = 1024*1024; public static LinkedList garbageList = new LinkedList(); @@ -83,7 +85,14 @@ class ReclaimRegionFast { Object ref_from_stack = large1; + long start_millis = System.currentTimeMillis(); + for (int i = 0; i < 20; i++) { + long current_millis = System.currentTimeMillis(); + if ((current_millis - start_millis) > MAX_MILLIS_FOR_RUN) { + System.out.println("Finishing test because maximum runtime exceeded"); + break; + } // A set of large objects that will be reclaimed eagerly - and hopefully marked. large1 = new int[M - 20]; large2 = new int[M - 20]; diff --git a/hotspot/test/runtime/7158988/FieldMonitor.java b/hotspot/test/runtime/7158988/FieldMonitor.java index 9b16fc3d798..07c40053d34 100644 --- a/hotspot/test/runtime/7158988/FieldMonitor.java +++ b/hotspot/test/runtime/7158988/FieldMonitor.java @@ -26,6 +26,7 @@ * @bug 7158988 * @key regression * @summary verify jvm does not crash while debugging + * @ignore 8055145 * @run compile TestPostFieldModification.java * @run main/othervm FieldMonitor * @author axel.siebenborn@sap.com diff --git a/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java b/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java index bb68a6ff074..0855913fe73 100644 --- a/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java +++ b/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java @@ -26,6 +26,7 @@ * @bug 8024927 * @summary Testing address of compressed class pointer space as best as possible. * @library /testlibrary + * @ignore 8055164 */ import com.oracle.java.testlibrary.*; diff --git a/hotspot/test/runtime/NMT/AutoshutdownNMT.java b/hotspot/test/runtime/NMT/AutoshutdownNMT.java index afb1df8a247..8739dc8d99f 100644 --- a/hotspot/test/runtime/NMT/AutoshutdownNMT.java +++ b/hotspot/test/runtime/NMT/AutoshutdownNMT.java @@ -26,7 +26,6 @@ * @key nmt * @summary Test for deprecated message if -XX:-AutoShutdownNMT is specified * @library /testlibrary - * @ignore */ import com.oracle.java.testlibrary.*; diff --git a/hotspot/test/runtime/NMT/BaselineWithParameter.java b/hotspot/test/runtime/NMT/BaselineWithParameter.java index ef34a11a416..ff10b28a060 100644 --- a/hotspot/test/runtime/NMT/BaselineWithParameter.java +++ b/hotspot/test/runtime/NMT/BaselineWithParameter.java @@ -27,7 +27,6 @@ * @key nmt jcmd regression * @summary Regression test for invoking a jcmd with baseline=false, result was that the target VM crashed * @library /testlibrary - * @ignore * @run main/othervm -XX:NativeMemoryTracking=detail BaselineWithParameter */ diff --git a/hotspot/test/runtime/NMT/CommandLineDetail.java b/hotspot/test/runtime/NMT/CommandLineDetail.java index b3ff104207f..01b0d0d3fae 100644 --- a/hotspot/test/runtime/NMT/CommandLineDetail.java +++ b/hotspot/test/runtime/NMT/CommandLineDetail.java @@ -26,7 +26,6 @@ * @key nmt * @summary Running with NMT detail should not result in an error * @library /testlibrary - * @ignore */ import com.oracle.java.testlibrary.*; diff --git a/hotspot/test/runtime/NMT/CommandLineEmptyArgument.java b/hotspot/test/runtime/NMT/CommandLineEmptyArgument.java index 1c05a195d44..fcfa18ab6f2 100644 --- a/hotspot/test/runtime/NMT/CommandLineEmptyArgument.java +++ b/hotspot/test/runtime/NMT/CommandLineEmptyArgument.java @@ -26,7 +26,7 @@ * @key nmt * @summary Empty argument to NMT should result in an informative error message * @library /testlibrary - * @ignore + * @ignore 8055051 */ import com.oracle.java.testlibrary.*; diff --git a/hotspot/test/runtime/NMT/CommandLineInvalidArgument.java b/hotspot/test/runtime/NMT/CommandLineInvalidArgument.java index 6cc45102397..79cc2de9442 100644 --- a/hotspot/test/runtime/NMT/CommandLineInvalidArgument.java +++ b/hotspot/test/runtime/NMT/CommandLineInvalidArgument.java @@ -26,7 +26,6 @@ * @key nmt * @summary Invalid argument to NMT should result in an informative error message * @library /testlibrary - * @ignore */ import com.oracle.java.testlibrary.*; diff --git a/hotspot/test/runtime/NMT/CommandLineSummary.java b/hotspot/test/runtime/NMT/CommandLineSummary.java index bef1ab9cb38..d07bc7eae63 100644 --- a/hotspot/test/runtime/NMT/CommandLineSummary.java +++ b/hotspot/test/runtime/NMT/CommandLineSummary.java @@ -26,7 +26,6 @@ * @key nmt * @summary Running with NMT summary should not result in an error * @library /testlibrary - * @ignore */ import com.oracle.java.testlibrary.*; diff --git a/hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java b/hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java index a33e2ca4aa3..4193c9775d4 100644 --- a/hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java +++ b/hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java @@ -26,7 +26,6 @@ * @key nmt * @summary Turning off NMT should not result in an error * @library /testlibrary - * @ignore */ import com.oracle.java.testlibrary.*; diff --git a/hotspot/test/runtime/NMT/JcmdBaselineDetail.java b/hotspot/test/runtime/NMT/JcmdBaselineDetail.java index dc802f2be0e..501b860f8bc 100644 --- a/hotspot/test/runtime/NMT/JcmdBaselineDetail.java +++ b/hotspot/test/runtime/NMT/JcmdBaselineDetail.java @@ -26,7 +26,6 @@ * @key nmt jcmd * @summary Verify that jcmd correctly reports that baseline succeeds with NMT enabled with detailed tracking. * @library /testlibrary - * @ignore * @run main/othervm -XX:NativeMemoryTracking=detail JcmdBaselineDetail */ diff --git a/hotspot/test/runtime/NMT/JcmdScale.java b/hotspot/test/runtime/NMT/JcmdScale.java index 42b7393df62..3d8a9518760 100644 --- a/hotspot/test/runtime/NMT/JcmdScale.java +++ b/hotspot/test/runtime/NMT/JcmdScale.java @@ -26,7 +26,6 @@ * @key nmt jcmd * @summary Test the NMT scale parameter * @library /testlibrary - * @ignore * @run main/othervm -XX:NativeMemoryTracking=summary JcmdScale */ diff --git a/hotspot/test/runtime/NMT/JcmdScaleDetail.java b/hotspot/test/runtime/NMT/JcmdScaleDetail.java index 9e2430ba1d9..97c809dc0a0 100644 --- a/hotspot/test/runtime/NMT/JcmdScaleDetail.java +++ b/hotspot/test/runtime/NMT/JcmdScaleDetail.java @@ -26,7 +26,6 @@ * @key nmt jcmd * @summary Test the NMT scale parameter with detail tracking level * @library /testlibrary - * @ignore * @run main/othervm -XX:NativeMemoryTracking=detail JcmdScaleDetail */ diff --git a/hotspot/test/runtime/NMT/JcmdSummaryDiff.java b/hotspot/test/runtime/NMT/JcmdSummaryDiff.java index 7ee6c9f8e47..93c13d7aa3c 100644 --- a/hotspot/test/runtime/NMT/JcmdSummaryDiff.java +++ b/hotspot/test/runtime/NMT/JcmdSummaryDiff.java @@ -27,7 +27,6 @@ * @key nmt jcmd * @library /testlibrary /testlibrary/whitebox * @build JcmdSummaryDiff - * @ignore * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=summary JcmdSummaryDiff */ diff --git a/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java b/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java index 086038eb233..9ef37434937 100644 --- a/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java +++ b/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java @@ -26,7 +26,6 @@ * @key nmt jcmd * @summary Verify that jcmd correctly reports that NMT is not enabled * @library /testlibrary - * @ignore * @run main JcmdWithNMTDisabled 1 */ diff --git a/hotspot/test/runtime/NMT/MallocRoundingReportTest.java b/hotspot/test/runtime/NMT/MallocRoundingReportTest.java index 2cf43bca8f4..f0a838a3200 100644 --- a/hotspot/test/runtime/NMT/MallocRoundingReportTest.java +++ b/hotspot/test/runtime/NMT/MallocRoundingReportTest.java @@ -27,7 +27,6 @@ * @key nmt jcmd * @library /testlibrary /testlibrary/whitebox * @build MallocRoundingReportTest - * @ignore * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocRoundingReportTest * diff --git a/hotspot/test/runtime/NMT/MallocTestType.java b/hotspot/test/runtime/NMT/MallocTestType.java index e7339a52b3d..d570c2fa6a5 100644 --- a/hotspot/test/runtime/NMT/MallocTestType.java +++ b/hotspot/test/runtime/NMT/MallocTestType.java @@ -27,7 +27,6 @@ * @key nmt jcmd * @library /testlibrary /testlibrary/whitebox * @build MallocTestType - * @ignore * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocTestType diff --git a/hotspot/test/runtime/NMT/NMTWithCDS.java b/hotspot/test/runtime/NMT/NMTWithCDS.java new file mode 100644 index 00000000000..4672d3d5f75 --- /dev/null +++ b/hotspot/test/runtime/NMT/NMTWithCDS.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014, 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 8055061 + * @key nmt + * @library /testlibrary + * @run main NMTWithCDS + */ +import com.oracle.java.testlibrary.*; + +public class NMTWithCDS { + + public static void main(String[] args) throws Exception { + ProcessBuilder pb; + pb = ProcessTools.createJavaProcessBuilder("-XX:SharedArchiveFile=./sample.jsa", "-Xshare:dump"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + try { + output.shouldContain("Loading classes to share"); + output.shouldHaveExitValue(0); + + pb = ProcessTools.createJavaProcessBuilder( + "-XX:NativeMemoryTracking=detail", "-XX:SharedArchiveFile=./sample.jsa", "-Xshare:on", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("sharing"); + output.shouldHaveExitValue(0); + + } catch (RuntimeException e) { + // Report 'passed' if CDS was turned off. + output.shouldContain("Unable to use shared archive"); + output.shouldHaveExitValue(1); + } + } +} diff --git a/hotspot/test/runtime/NMT/PrintNMTStatistics.java b/hotspot/test/runtime/NMT/PrintNMTStatistics.java index a188f740d4b..5a4b6b08f5d 100644 --- a/hotspot/test/runtime/NMT/PrintNMTStatistics.java +++ b/hotspot/test/runtime/NMT/PrintNMTStatistics.java @@ -28,7 +28,6 @@ * @summary Make sure PrintNMTStatistics works on normal JVM exit * @library /testlibrary /testlibrary/whitebox * @build PrintNMTStatistics - * @ignore * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main PrintNMTStatistics diff --git a/hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java b/hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java index cdc3ded942a..1c25f284d4b 100644 --- a/hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java +++ b/hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java @@ -26,7 +26,6 @@ * @key nmt * @summary Trying to enable PrintNMTStatistics should result in a warning * @library /testlibrary - * @ignore */ import com.oracle.java.testlibrary.*; diff --git a/hotspot/test/runtime/NMT/ReleaseCommittedMemory.java b/hotspot/test/runtime/NMT/ReleaseCommittedMemory.java index 8d18f50852b..64ef463e5c0 100644 --- a/hotspot/test/runtime/NMT/ReleaseCommittedMemory.java +++ b/hotspot/test/runtime/NMT/ReleaseCommittedMemory.java @@ -28,7 +28,6 @@ * @key nmt regression * @library /testlibrary /testlibrary/whitebox * @build ReleaseCommittedMemory - * @ignore * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ReleaseCommittedMemory diff --git a/hotspot/test/runtime/NMT/ReleaseNoCommit.java b/hotspot/test/runtime/NMT/ReleaseNoCommit.java index b7c2ea950b1..94fba371df6 100644 --- a/hotspot/test/runtime/NMT/ReleaseNoCommit.java +++ b/hotspot/test/runtime/NMT/ReleaseNoCommit.java @@ -27,7 +27,6 @@ * @key nmt regression * @library /testlibrary /testlibrary/whitebox * @build ReleaseNoCommit - * @ignore * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=summary ReleaseNoCommit */ diff --git a/hotspot/test/runtime/NMT/ShutdownTwice.java b/hotspot/test/runtime/NMT/ShutdownTwice.java index d6dcf8013e9..436e0c2c643 100644 --- a/hotspot/test/runtime/NMT/ShutdownTwice.java +++ b/hotspot/test/runtime/NMT/ShutdownTwice.java @@ -26,7 +26,6 @@ * @key nmt jcmd * @summary Run shutdown twice * @library /testlibrary - * @ignore * @run main/othervm -XX:NativeMemoryTracking=detail ShutdownTwice */ diff --git a/hotspot/test/runtime/NMT/SummaryAfterShutdown.java b/hotspot/test/runtime/NMT/SummaryAfterShutdown.java index 1baa484aa25..ea1f3a60737 100644 --- a/hotspot/test/runtime/NMT/SummaryAfterShutdown.java +++ b/hotspot/test/runtime/NMT/SummaryAfterShutdown.java @@ -26,7 +26,6 @@ * @key nmt jcmd * @summary Verify that jcmd correctly reports that NMT is not enabled after a shutdown * @library /testlibrary - * @ignore * @run main/othervm -XX:NativeMemoryTracking=detail SummaryAfterShutdown */ diff --git a/hotspot/test/runtime/NMT/SummarySanityCheck.java b/hotspot/test/runtime/NMT/SummarySanityCheck.java index e48123e8c8d..04185bb492d 100644 --- a/hotspot/test/runtime/NMT/SummarySanityCheck.java +++ b/hotspot/test/runtime/NMT/SummarySanityCheck.java @@ -27,7 +27,6 @@ * @summary Sanity check the output of NMT * @library /testlibrary /testlibrary/whitebox * @build SummarySanityCheck - * @ignore * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+WhiteBoxAPI SummarySanityCheck diff --git a/hotspot/test/runtime/NMT/ThreadedMallocTestType.java b/hotspot/test/runtime/NMT/ThreadedMallocTestType.java index c26f0b0e987..036db1ea3c0 100644 --- a/hotspot/test/runtime/NMT/ThreadedMallocTestType.java +++ b/hotspot/test/runtime/NMT/ThreadedMallocTestType.java @@ -26,7 +26,6 @@ * @key nmt jcmd * @library /testlibrary /testlibrary/whitebox * @build ThreadedMallocTestType - * @ignore * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ThreadedMallocTestType diff --git a/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java b/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java index 1bd30c11b3b..c0bb7616cbd 100644 --- a/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java +++ b/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java @@ -26,7 +26,6 @@ * @key nmt jcmd * @library /testlibrary /testlibrary/whitebox * @build ThreadedVirtualAllocTestType - * @ignore * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ThreadedVirtualAllocTestType diff --git a/hotspot/test/runtime/NMT/VirtualAllocTestType.java b/hotspot/test/runtime/NMT/VirtualAllocTestType.java index b298aedb332..579fba6b44f 100644 --- a/hotspot/test/runtime/NMT/VirtualAllocTestType.java +++ b/hotspot/test/runtime/NMT/VirtualAllocTestType.java @@ -26,7 +26,6 @@ * @summary Test Reserve/Commit/Uncommit/Release of virtual memory and that we track it correctly * @key nmt jcmd * @library /testlibrary /testlibrary/whitebox - * @ignore * @build VirtualAllocTestType * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/runtime/jsig/Test8017498.sh b/hotspot/test/runtime/jsig/Test8017498.sh index 3ef0dd77b43..315631d059c 100644 --- a/hotspot/test/runtime/jsig/Test8017498.sh +++ b/hotspot/test/runtime/jsig/Test8017498.sh @@ -31,6 +31,7 @@ ## @bug 8022301 ## @bug 8025519 ## @summary sigaction(sig) results in process hang/timed-out if sig is much greater than SIGRTMAX +## @ignore 8041727 ## @run shell/timeout=60 Test8017498.sh ## diff --git a/hotspot/test/sanity/WhiteBox.java b/hotspot/test/sanity/WhiteBox.java index 19e231aa139..b47d339f55e 100644 --- a/hotspot/test/sanity/WhiteBox.java +++ b/hotspot/test/sanity/WhiteBox.java @@ -29,7 +29,6 @@ * @library /testlibrary * @compile WhiteBox.java * @run main ClassFileInstaller sun.hotspot.WhiteBox - * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI sun.hotspot.WhiteBox * @clean sun.hotspot.WhiteBox */ diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/BuildHelper.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/BuildHelper.java new file mode 100644 index 00000000000..0297b2ca6a0 --- /dev/null +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/BuildHelper.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2014, 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. + */ + +package com.oracle.java.testlibrary; + +import java.io.File; +import java.io.FileReader; +import java.util.Properties; + +public class BuildHelper { + + /** + * Commercial builds should have the BUILD_TYPE set to commercial + * within the release file, found at the root of the JDK. + */ + public static boolean isCommercialBuild() throws Exception { + String buildType = getReleaseProperty("BUILD_TYPE","notFound"); + return buildType.equals("commercial"); + } + + + /** + * Return the value for property key, or defaultValue if no property not found. + * If present, double quotes are trimmed. + */ + public static String getReleaseProperty(String key, String defaultValue) throws Exception { + Properties properties = getReleaseProperties(); + String value = properties.getProperty(key, defaultValue); + return trimDoubleQuotes(value); + } + + /** + * Return the value for property key, or null if no property not found. + * If present, double quotes are trimmed. + */ + public static String getReleaseProperty(String key) throws Exception { + return getReleaseProperty(key, null); + } + + /** + * Get properties from the release file + */ + public static Properties getReleaseProperties() throws Exception { + Properties properties = new Properties(); + properties.load(new FileReader(getReleaseFile())); + return properties; + } + + /** + * Every JDK has a release file in its root. + * @return A handler to the release file. + */ + public static File getReleaseFile() throws Exception { + String jdkPath = getJDKRoot(); + File releaseFile = new File(jdkPath,"release"); + if ( ! releaseFile.canRead() ) { + throw new Exception("Release file is not readable, or it is absent: " + + releaseFile.getCanonicalPath()); + } + return releaseFile; + } + + /** + * Returns path to the JDK under test. + * This path is obtained through the test.jdk property, usually set by JTREG. + */ + public static String getJDKRoot() { + String jdkPath = System.getProperty("test.jdk"); + if (jdkPath == null) { + throw new RuntimeException("System property 'test.jdk' not set. This property is normally set by jtreg. " + + "When running test separately, set this property using '-Dtest.jdk=/path/to/jdk'."); + } + return jdkPath; + } + + /** + * Trim double quotes from the beginning and the end of the given string. + * @param original string to trim. + * @return a new trimmed string. + */ + public static String trimDoubleQuotes(String original) { + if (original == null) { return null; } + String trimmed = original.replaceAll("^\"+|\"+$", ""); + return trimmed; + } +} diff --git a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java index 84f97aafa01..605e42c1a98 100644 --- a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java +++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java @@ -73,6 +73,8 @@ public class WhiteBox { // Memory public native long getObjectAddress(Object o); public native int getHeapOopSize(); + public native boolean isObjectInOldGen(Object o); + public native long getObjectSize(Object o); // Runtime // Make sure class name is in the correct format @@ -150,6 +152,9 @@ public class WhiteBox { public native long allocateMetaspace(ClassLoader classLoader, long size); public native void freeMetaspace(ClassLoader classLoader, long addr, long size); + // force Young GC + public native void youngGC(); + // force Full GC public native void fullGC(); diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 13a0df7677e..40f6d552164 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -270,3 +270,4 @@ f9c82769a6bc2b219a8f01c24afe5c91039267d7 jdk9-b19 73757f4b8aa353ca8937abc07e79e7ece4c011a1 jdk9-b25 a5aea8318ae4a9c2105228568688875142d70344 jdk9-b26 2bfaf29cc90b19948938e3ef1a0983eee68806c7 jdk9-b27 +dc1e26434b3fd7e9b8eeab149103c1e30965f95c jdk9-b28 diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/Constants.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/Constants.java index 4e276fb6ad6..3a84797138b 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/Constants.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/Constants.java @@ -1,13 +1,10 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. - */ - -/* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -41,6 +38,9 @@ public final class Constants { public static final String NS_XMLSCHEMA = "http://www.w3.org/2001/XMLSchema".intern(); public static final String NS_DTD = "http://www.w3.org/TR/REC-xml".intern(); + // Schema Versions: + public static final String W3C_XML_SCHEMA10_NS_URI = "http://www.w3.org/XML/XMLSchema/v1.0".intern(); + // Schema features public static final String SUN_SCHEMA_FEATURE_PREFIX = "http://java.sun.com/xml/schema/features/"; public static final String SUN_REPORT_IGNORED_ELEMENT_CONTENT_WHITESPACE = "report-ignored-element-content-whitespace"; @@ -487,6 +487,40 @@ public final class Constants { /** XInclude fixup language feature ("xinclude/fixup-language"). */ public static final String XINCLUDE_FIXUP_LANGUAGE_FEATURE = "xinclude/fixup-language"; + /** + * Feature to ignore xsi:type attributes on elements during validation, + * until a global element declaration is found. ("validation/schema/ignore-xsi-type-until-elemdecl") + * If this feature is on when validating a document, then beginning at the validation root + * element, xsi:type attributes are ignored until a global element declaration is + * found for an element. Once a global element declaration has been found, xsi:type + * attributes will start being processed for the sub-tree beginning at the element for + * which the declaration was found. + * + * Suppose an element A has two element children, B and C. + * + * If a global element declaration is found for A, xsi:type attributes on A, B and C, + * and all of B and C's descendents, will be processed. + * + * If no global element declaration is found for A or B, but one is found for C, + * then xsi:type attributes will be ignored on A and B (and any descendents of B, + * until a global element declaration is found), but xsi:type attributes will be + * processed for C and all of C's descendents. + * + * Once xsi:type attributes stop being ignored for a subtree, they do not start + * being ignored again, even if more elements are encountered for which no global + * element declaration can be found. + */ + public static final String IGNORE_XSI_TYPE_FEATURE = "validation/schema/ignore-xsi-type-until-elemdecl"; + + /** Perform checking of ID/IDREFs ("validation/id-idref-checking") */ + public static final String ID_IDREF_CHECKING_FEATURE = "validation/id-idref-checking"; + + /** Feature to ignore errors caused by identity constraints ("validation/identity-constraint-checking") */ + public static final String IDC_CHECKING_FEATURE = "validation/identity-constraint-checking"; + + /** Feature to ignore errors caused by unparsed entities ("validation/unparsed-entity-checking") */ + public static final String UNPARSED_ENTITY_CHECKING_FEATURE = "validation/unparsed-entity-checking"; + /** * Internal feature. When set to true the schema validator will only use * schema components from the grammar pool provided. @@ -598,6 +632,8 @@ public final class Constants { /** Validation manager property ("internal/validation-manager"). */ public static final String VALIDATION_MANAGER_PROPERTY = "internal/validation-manager"; + /** Schema type of the root element in a document ("validation/schema/root-type-definition"). */ + public static final String ROOT_TYPE_DEFINITION_PROPERTY = "validation/schema/root-type-definition"; /** XPointer Schema property ("xpointer-schema"). */ public static final String XPOINTER_SCHEMA_PROPERTY = "xpointer-schema"; @@ -739,6 +775,10 @@ public final class Constants { XINCLUDE_FEATURE, XINCLUDE_FIXUP_BASE_URIS_FEATURE, XINCLUDE_FIXUP_LANGUAGE_FEATURE, + IGNORE_XSI_TYPE_FEATURE, + ID_IDREF_CHECKING_FEATURE, + IDC_CHECKING_FEATURE, + UNPARSED_ENTITY_CHECKING_FEATURE, NAMESPACE_GROWTH_FEATURE, TOLERATE_DUPLICATES_FEATURE, }; @@ -762,6 +802,7 @@ public final class Constants { VALIDATION_MANAGER_PROPERTY, BUFFER_SIZE_PROPERTY, SECURITY_MANAGER_PROPERTY, + ROOT_TYPE_DEFINITION_PROPERTY, LOCALE_PROPERTY, SCHEMA_DV_FACTORY_PROPERTY, }; diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/ValidatedInfo.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/ValidatedInfo.java index e6b8f267a5d..cc84353bd64 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/ValidatedInfo.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/ValidatedInfo.java @@ -1,13 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2001, 2002,2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -21,6 +18,7 @@ package com.sun.org.apache.xerces.internal.impl.dv; import com.sun.org.apache.xerces.internal.xs.ShortList; +import com.sun.org.apache.xerces.internal.xs.XSConstants; /** * Class to get the information back after content is validated. This info @@ -95,4 +93,60 @@ public class ValidatedInfo { else return actualValue.toString(); } + + /** + * Returns true if the two ValidatedInfo objects can be compared in the same + * value space. + */ + public static boolean isComparable(ValidatedInfo info1, ValidatedInfo info2) { + final short primitiveType1 = convertToPrimitiveKind(info1.actualValueType); + final short primitiveType2 = convertToPrimitiveKind(info2.actualValueType); + if (primitiveType1 != primitiveType2) { + return (primitiveType1 == XSConstants.ANYSIMPLETYPE_DT && primitiveType2 == XSConstants.STRING_DT || + primitiveType1 == XSConstants.STRING_DT && primitiveType2 == XSConstants.ANYSIMPLETYPE_DT); + } + else if (primitiveType1 == XSConstants.LIST_DT || primitiveType1 == XSConstants.LISTOFUNION_DT) { + final ShortList typeList1 = info1.itemValueTypes; + final ShortList typeList2 = info2.itemValueTypes; + final int typeList1Length = typeList1 != null ? typeList1.getLength() : 0; + final int typeList2Length = typeList2 != null ? typeList2.getLength() : 0; + if (typeList1Length != typeList2Length) { + return false; + } + for (int i = 0; i < typeList1Length; ++i) { + final short primitiveItem1 = convertToPrimitiveKind(typeList1.item(i)); + final short primitiveItem2 = convertToPrimitiveKind(typeList2.item(i)); + if (primitiveItem1 != primitiveItem2) { + if (primitiveItem1 == XSConstants.ANYSIMPLETYPE_DT && primitiveItem2 == XSConstants.STRING_DT || + primitiveItem1 == XSConstants.STRING_DT && primitiveItem2 == XSConstants.ANYSIMPLETYPE_DT) { + continue; + } + return false; + } + } + } + return true; + } + + /** + * Returns the primitive type of the given type. + * @param valueType A value type as defined in XSConstants. + * @return The primitive type from which valueType was derived. + */ + private static short convertToPrimitiveKind(short valueType) { + /** Primitive datatypes. */ + if (valueType <= XSConstants.NOTATION_DT) { + return valueType; + } + /** Types derived from string. */ + if (valueType <= XSConstants.ENTITY_DT) { + return XSConstants.STRING_DT; + } + /** Types derived from decimal. */ + if (valueType <= XSConstants.POSITIVEINTEGER_DT) { + return XSConstants.DECIMAL_DT; + } + /** Other types. */ + return valueType; + } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties index d986140a86e..5b73376eb50 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties @@ -14,20 +14,18 @@ # Identity constraints - AbsentKeyValue = Identity Constraint error (cvc-identity-constraint.4.2.1): element \"{0}\" has a key with no value. + AbsentKeyValue = cvc-identity-constraint.4.2.1.a: Element \"{0}\" has no value for the key \"{1}\". DuplicateField = Duplicate match in scope for field \"{0}\". - DuplicateKey = Duplicate key value [{0}] declared for identity constraint of element \"{1}\". - DuplicateUnique = Duplicate unique value [{0}] declared for identity constraint of element \"{1}\". - FieldMultipleMatch = Identity constraint error: field \"{0}\" matches more than one value within the scope of its selector; fields must match unique values. + DuplicateKey = cvc-identity-constraint.4.2.2: Duplicate key value [{0}] declared for identity constraint \"{2}\" of element \"{1}\". + DuplicateUnique = cvc-identity-constraint.4.1: Duplicate unique value [{0}] declared for identity constraint \"{2}\" of element \"{1}\". + FieldMultipleMatch = cvc-identity-constraint.3: Field \"{0}\" of identity constraint \"{1}\" matches more than one value within the scope of its selector; fields must match unique values. FixedDiffersFromActual = The content of this element is not equivalent to the value of the \"fixed\" attribute in the element's declaration in the schema. - KeyMatchesNillable = Identity Constraint error (cvc-identity-constraint.4.2.3): element \"{0}\" has a key which matches an element which has nillable set to true. - KeyNotEnoughValues = Not enough values specified for identity constraint specified for element \"{0}\". - KeyNotFound = Key ''{0}'' with value ''{1}'' not found for identity constraint of element ''{2}''. - KeyRefNotEnoughValues = Not enough values specified for identity constraint specified for element \"{0}\". + KeyMatchesNillable = cvc-identity-constraint.4.2.3: Element \"{0}\" has the key \"{1}\" which matches an element which has nillable set to true. + KeyNotEnoughValues = cvc-identity-constraint.4.2.1.b: Not enough values specified for identity constraint specified for element \"{0}\". + KeyNotFound = cvc-identity-constraint.4.3: Key ''{0}'' with value ''{1}'' not found for identity constraint of element ''{2}''. KeyRefOutOfScope = Identity Constraint error: identity constraint \"{0}\" has a keyref which refers to a key or unique that is out of scope. KeyRefReferNotFound = Key reference declaration \"{0}\" refers to unknown key with name \"{1}\". - UniqueNotEnoughValues = Not enough values specified for identity constraint specified for element \"{0}\". - UnknownField = Internal identity constraint error; unknown field \"{0}\". + UnknownField = Internal identity constraint error; unknown field \"{0}\" for identity constraint \"{2}\" specified for element \"{1}\". # Ideally, we should only use the following error keys, not the ones under # "Identity constraints". And we should cover all of the following errors. @@ -79,6 +77,7 @@ cvc-minLength-valid = cvc-minLength-valid: Value ''{0}'' with length = ''{1}'' is not facet-valid with respect to minLength ''{2}'' for type ''{3}''. cvc-pattern-valid = cvc-pattern-valid: Value ''{0}'' is not facet-valid with respect to pattern ''{1}'' for type ''{2}''. cvc-totalDigits-valid = cvc-totalDigits-valid: Value ''{0}'' has {1} total digits, but the number of total digits has been limited to {2}. + cvc-type.1 = cvc-type.1: The type definition ''{0}'' was not found. cvc-type.2 = cvc-type.2: The type definition cannot be abstract for element {0}. cvc-type.3.1.1 = cvc-type.3.1.1: Element ''{0}'' is a simple type, so it cannot have attributes, excepting those whose namespace name is identical to ''http://www.w3.org/2001/XMLSchema-instance'' and whose [local name] is one of ''type'', ''nil'', ''schemaLocation'' or ''noNamespaceSchemaLocation''. However, the attribute, ''{1}'' was found. cvc-type.3.1.2 = cvc-type.3.1.2: Element ''{0}'' is a simple type, so it must have no element information item [children]. diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/validation/ConfigurableValidationState.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/validation/ConfigurableValidationState.java new file mode 100644 index 00000000000..ac8406dd325 --- /dev/null +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/validation/ConfigurableValidationState.java @@ -0,0 +1,123 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.sun.org.apache.xerces.internal.impl.validation; + +/** + *

An extension of ValidationState which can be configured to turn + * off checking for ID/IDREF errors and unparsed entity errors.

+ * + * @xerces.internal + * + * @author Peter McCracken, IBM + */ +public final class ConfigurableValidationState extends ValidationState { + + /** + * Whether to check for ID/IDREF errors + */ + private boolean fIdIdrefChecking; + + /** + * Whether to check for unparsed entity errors + */ + private boolean fUnparsedEntityChecking; + + /** + * Creates a new ConfigurableValidationState. + * By default, error checking for both ID/IDREFs + * and unparsed entities are turned on. + */ + public ConfigurableValidationState() { + super(); + fIdIdrefChecking = true; + fUnparsedEntityChecking = true; + } + + /** + * Turns checking for ID/IDREF errors on and off. + * @param setting: true to turn on error checking + * false to turn off error checking + */ + public void setIdIdrefChecking(boolean setting) { + fIdIdrefChecking = setting; + } + + /** + * Turns checking for unparsed entity errors on and off. + * @param setting: true to turn on error checking + * false to turn off error checking + */ + public void setUnparsedEntityChecking(boolean setting) { + fUnparsedEntityChecking = setting; + } + + /** + * Checks if all IDREFs have a corresponding ID. + * @return null, if ID/IDREF checking is turned off + * otherwise, returns the value of the super implementation + */ + public String checkIDRefID() { + return (fIdIdrefChecking) ? super.checkIDRefID() : null; + } + + /** + * Checks if an ID has already been declared. + * @return false, if ID/IDREF checking is turned off + * otherwise, returns the value of the super implementation + */ + public boolean isIdDeclared(String name) { + return (fIdIdrefChecking) ? super.isIdDeclared(name) : false; + } + + /** + * Checks if an entity is declared. + * @return true, if unparsed entity checking is turned off + * otherwise, returns the value of the super implementation + */ + public boolean isEntityDeclared(String name) { + return (fUnparsedEntityChecking) ? super.isEntityDeclared(name) : true; + } + + /** + * Checks if an entity is unparsed. + * @return true, if unparsed entity checking is turned off + * otherwise, returns the value of the super implementation + */ + public boolean isEntityUnparsed(String name) { + return (fUnparsedEntityChecking) ? super.isEntityUnparsed(name) : true; + } + + /** + * Adds the ID, if ID/IDREF checking is enabled. + * @param the ID to add + */ + public void addId(String name) { + if (fIdIdrefChecking) { + super.addId(name); + } + } + + /** + * Adds the IDREF, if ID/IDREF checking is enabled. + * @param the IDREF to add + */ + public void addIdRef(String name) { + if (fIdIdrefChecking) { + super.addIdRef(name); + } + } +} diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaValidator.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaValidator.java index fd03b7a8f75..dbe788ac599 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaValidator.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaValidator.java @@ -1,13 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 1999-2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -38,6 +35,7 @@ import com.sun.org.apache.xerces.internal.impl.dv.DatatypeException; import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException; import com.sun.org.apache.xerces.internal.impl.dv.ValidatedInfo; import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType; +import com.sun.org.apache.xerces.internal.impl.validation.ConfigurableValidationState; import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager; import com.sun.org.apache.xerces.internal.impl.validation.ValidationState; import com.sun.org.apache.xerces.internal.impl.xs.identity.Field; @@ -185,6 +183,22 @@ public class XMLSchemaValidator protected static final String TOLERATE_DUPLICATES = Constants.XERCES_FEATURE_PREFIX + Constants.TOLERATE_DUPLICATES_FEATURE; + /** Feature identifier: whether to ignore xsi:type attributes until a global element declaration is encountered */ + protected static final String IGNORE_XSI_TYPE = + Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_XSI_TYPE_FEATURE; + + /** Feature identifier: whether to ignore ID/IDREF errors */ + protected static final String ID_IDREF_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.ID_IDREF_CHECKING_FEATURE; + + /** Feature identifier: whether to ignore unparsed entity errors */ + protected static final String UNPARSED_ENTITY_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.UNPARSED_ENTITY_CHECKING_FEATURE; + + /** Feature identifier: whether to ignore identity constraint errors */ + protected static final String IDENTITY_CONSTRAINT_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.IDC_CHECKING_FEATURE; + protected static final String REPORT_WHITESPACE = Constants.SUN_SCHEMA_FEATURE_PREFIX + Constants.SUN_REPORT_IGNORED_ELEMENT_CONTENT_WHITESPACE; @@ -228,6 +242,10 @@ public class XMLSchemaValidator protected static final String JAXP_SCHEMA_LANGUAGE = Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE; + /** Property identifier: root type definition. */ + protected static final String ROOT_TYPE_DEF = + Constants.XERCES_PROPERTY_PREFIX + Constants.ROOT_TYPE_DEFINITION_PROPERTY; + /** Property identifier: Schema DV Factory */ protected static final String SCHEMA_DV_FACTORY = Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY; @@ -254,6 +272,10 @@ public class XMLSchemaValidator VALIDATE_ANNOTATIONS, HONOUR_ALL_SCHEMALOCATIONS, USE_GRAMMAR_POOL_ONLY, + IGNORE_XSI_TYPE, + ID_IDREF_CHECKING, + IDENTITY_CONSTRAINT_CHECKING, + UNPARSED_ENTITY_CHECKING, NAMESPACE_GROWTH, TOLERATE_DUPLICATES, USE_SERVICE_MECHANISM @@ -267,6 +289,10 @@ public class XMLSchemaValidator // those set by the application. This goes against the // whole purpose of XMLComponent#getFeatureDefault but // it can't be helped in this case. -Ac + // NOTE: Instead of adding default values here, add them (and + // the corresponding recognized features) to the objects + // that have an XMLSchemaValidator instance as a member, + // such as the parser configurations. -PM null, //Boolean.FALSE, null, //Boolean.FALSE, null, //Boolean.FALSE, @@ -279,6 +305,10 @@ public class XMLSchemaValidator null, null, null, + null, + null, + null, + null, Boolean.TRUE }; @@ -293,13 +323,14 @@ public class XMLSchemaValidator SCHEMA_NONS_LOCATION, JAXP_SCHEMA_SOURCE, JAXP_SCHEMA_LANGUAGE, + ROOT_TYPE_DEF, SCHEMA_DV_FACTORY, XML_SECURITY_PROPERTY_MANAGER }; /** Property defaults. */ private static final Object[] PROPERTY_DEFAULTS = - { null, null, null, null, null, null, null, null, null, null, null, null, null}; + { null, null, null, null, null, null, null, null, null, null, null}; // this is the number of valuestores of each kind // we expect an element to have. It's almost @@ -482,7 +513,7 @@ public class XMLSchemaValidator // updated during reset protected ValidationManager fValidationManager = null; - protected ValidationState fValidationState = new ValidationState(); + protected ConfigurableValidationState fValidationState = new ConfigurableValidationState(); protected XMLGrammarPool fGrammarPool; // schema location property values @@ -562,6 +593,9 @@ public class XMLSchemaValidator * this exception. */ public void setProperty(String propertyId, Object value) throws XMLConfigurationException { + if (propertyId.equals(ROOT_TYPE_DEF)) { + fRootTypeQName = (javax.xml.namespace.QName)value; + } } // setProperty(String,Object) /** @@ -1234,6 +1268,12 @@ public class XMLSchemaValidator /** temporary qname */ private final QName fTempQName = new QName(); + private javax.xml.namespace.QName fRootTypeQName = null; + + private int fIgnoreXSITypeDepth; + + private boolean fIDCChecking; + /** temporary validated info */ private ValidatedInfo fValidatedInfo = new ValidatedInfo(); @@ -1384,6 +1424,38 @@ public class XMLSchemaValidator fValidationManager.addValidationState(fValidationState); fValidationState.setSymbolTable(fSymbolTable); + boolean ignoreXSIType; + try { + ignoreXSIType = componentManager.getFeature(IGNORE_XSI_TYPE); + } + catch (XMLConfigurationException e) { + ignoreXSIType = false; + } + // An initial value of -1 means that the root element considers itself + // below the depth where xsi:type stopped being ignored (which means that + // xsi:type attributes will not be ignored for the entire document) + fIgnoreXSITypeDepth = ignoreXSIType ? 0 : -1; + + try { + fIDCChecking = componentManager.getFeature(IDENTITY_CONSTRAINT_CHECKING); + } + catch (XMLConfigurationException e) { + fIDCChecking = true; + } + + try { + fValidationState.setIdIdrefChecking(componentManager.getFeature(ID_IDREF_CHECKING)); + } + catch (XMLConfigurationException e) { + fValidationState.setIdIdrefChecking(true); + } + + try { + fValidationState.setUnparsedEntityChecking(componentManager.getFeature(UNPARSED_ENTITY_CHECKING)); + } + catch (XMLConfigurationException e) { + fValidationState.setUnparsedEntityChecking(true); + } // get schema location properties try { @@ -1550,7 +1622,9 @@ public class XMLSchemaValidator // handle start document void handleStartDocument(XMLLocator locator, String encoding) { - fValueStoreCache.startDocument(); + if (fIDCChecking) { + fValueStoreCache.startDocument(); + } if (fAugPSVI) { fCurrentPSVI.fGrammars = null; fCurrentPSVI.fSchemaInformation = null; @@ -1558,7 +1632,9 @@ public class XMLSchemaValidator } // handleStartDocument(XMLLocator,String) void handleEndDocument() { - fValueStoreCache.endDocument(); + if (fIDCChecking) { + fValueStoreCache.endDocument(); + } } // handleEndDocument() // handle character contents @@ -1850,22 +1926,54 @@ public class XMLSchemaValidator return augs; } - // try again to get the element decl: - // case 1: find declaration for root element - // case 2: find declaration for element from another namespace - if (fCurrentElemDecl == null) { - if (sGrammar != null) { - fCurrentElemDecl = sGrammar.getGlobalElementDecl(element.localpart); + // 1.2.1.1 A type definition was stipulated by the processor + if (fElementDepth == 0 && fRootTypeQName != null) { + String rootTypeNamespace = fRootTypeQName.getNamespaceURI(); + if (rootTypeNamespace != null && rootTypeNamespace.equals(XMLConstants.NULL_NS_URI)) { + rootTypeNamespace = null; + } + SchemaGrammar grammarForRootType = + findSchemaGrammar( + XSDDescription.CONTEXT_ELEMENT, rootTypeNamespace, null, null, null); + if (grammarForRootType != null) { + fCurrentType = grammarForRootType.getGlobalTypeDecl(fRootTypeQName.getLocalPart()); + } + if (fCurrentType == null) { + String typeName = (fRootTypeQName.getPrefix().equals(XMLConstants.DEFAULT_NS_PREFIX)) ? + fRootTypeQName.getLocalPart() : + fRootTypeQName.getPrefix()+":"+fRootTypeQName.getLocalPart(); + reportSchemaError("cvc-type.1", new Object[] {typeName}); } } - if (fCurrentElemDecl != null) { - // then get the type - fCurrentType = fCurrentElemDecl.fType; + // if there was no processor stipulated type + if (fCurrentType == null) { + // try again to get the element decl: + // case 1: find declaration for root element + // case 2: find declaration for element from another namespace + if (fCurrentElemDecl == null) { + if (sGrammar != null) { + fCurrentElemDecl = sGrammar.getGlobalElementDecl(element.localpart); + } + } + + if (fCurrentElemDecl != null) { + // then get the type + fCurrentType = fCurrentElemDecl.fType; + } } - // get type from xsi:type - String xsiType = attributes.getValue(SchemaSymbols.URI_XSI, SchemaSymbols.XSI_TYPE); + + // check if we should be ignoring xsi:type on this element + if (fElementDepth == fIgnoreXSITypeDepth && fCurrentElemDecl == null) { + fIgnoreXSITypeDepth++; + } + + // process xsi:type attribute information + String xsiType = null; + if (fElementDepth >= fIgnoreXSITypeDepth) { + xsiType = attributes.getValue(SchemaSymbols.URI_XSI, SchemaSymbols.XSI_TYPE); + } // if no decl/type found for the current element if (fCurrentType == null && xsiType == null) { @@ -2044,13 +2152,17 @@ public class XMLSchemaValidator XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType; attrGrp = ctype.getAttrGrp(); } - // activate identity constraints - fValueStoreCache.startElement(); - fMatcherStack.pushContext(); - if (fCurrentElemDecl != null && fCurrentElemDecl.fIDCPos > 0) { - fIdConstraint = true; - // initialize when identity constrains are defined for the elem - fValueStoreCache.initValueStoresFor(fCurrentElemDecl, this); + + if (fIDCChecking) { + // activate identity constraints + fValueStoreCache.startElement(); + fMatcherStack.pushContext(); + //if (fCurrentElemDecl != null && fCurrentElemDecl.fIDCPos > 0 && !fIgnoreIDC) { + if (fCurrentElemDecl != null && fCurrentElemDecl.fIDCPos > 0) { + fIdConstraint = true; + // initialize when identity constrains are defined for the elem + fValueStoreCache.initValueStoresFor(fCurrentElemDecl, this); + } } processAttributes(element, attributes, attrGrp); @@ -2138,66 +2250,75 @@ public class XMLSchemaValidator // now validate the content of the element processElementContent(element); - // Element Locally Valid (Element) - // 6 The element information item must be valid with respect to each of the {identity-constraint definitions} as per Identity-constraint Satisfied (3.11.4). + if (fIDCChecking) { + // Element Locally Valid (Element) + // 6 The element information item must be valid with respect to each of the {identity-constraint definitions} as per Identity-constraint Satisfied (3.11.4). - // call matchers and de-activate context - int oldCount = fMatcherStack.getMatcherCount(); - for (int i = oldCount - 1; i >= 0; i--) { - XPathMatcher matcher = fMatcherStack.getMatcherAt(i); - if (fCurrentElemDecl == null) - matcher.endElement(element, null, false, fValidatedInfo.actualValue, fValidatedInfo.actualValueType, fValidatedInfo.itemValueTypes); + // call matchers and de-activate context + int oldCount = fMatcherStack.getMatcherCount(); + for (int i = oldCount - 1; i >= 0; i--) { + XPathMatcher matcher = fMatcherStack.getMatcherAt(i); + if (fCurrentElemDecl == null) + matcher.endElement(element, null, false, fValidatedInfo.actualValue, fValidatedInfo.actualValueType, fValidatedInfo.itemValueTypes); - else - matcher.endElement( - element, - fCurrentType, - fCurrentElemDecl.getNillable(), - fDefaultValue == null - ? fValidatedInfo.actualValue - : fCurrentElemDecl.fDefault.actualValue, - fDefaultValue == null - ? fValidatedInfo.actualValueType - : fCurrentElemDecl.fDefault.actualValueType, - fDefaultValue == null - ? fValidatedInfo.itemValueTypes - : fCurrentElemDecl.fDefault.itemValueTypes); - } + else + matcher.endElement( + element, + fCurrentType, + fCurrentElemDecl.getNillable(), + fDefaultValue == null + ? fValidatedInfo.actualValue + : fCurrentElemDecl.fDefault.actualValue, + fDefaultValue == null + ? fValidatedInfo.actualValueType + : fCurrentElemDecl.fDefault.actualValueType, + fDefaultValue == null + ? fValidatedInfo.itemValueTypes + : fCurrentElemDecl.fDefault.itemValueTypes); + } - if (fMatcherStack.size() > 0) { - fMatcherStack.popContext(); - } + if (fMatcherStack.size() > 0) { + fMatcherStack.popContext(); + } - int newCount = fMatcherStack.getMatcherCount(); - // handle everything *but* keyref's. - for (int i = oldCount - 1; i >= newCount; i--) { - XPathMatcher matcher = fMatcherStack.getMatcherAt(i); - if (matcher instanceof Selector.Matcher) { - Selector.Matcher selMatcher = (Selector.Matcher) matcher; - IdentityConstraint id; - if ((id = selMatcher.getIdentityConstraint()) != null - && id.getCategory() != IdentityConstraint.IC_KEYREF) { - fValueStoreCache.transplant(id, selMatcher.getInitialDepth()); + int newCount = fMatcherStack.getMatcherCount(); + // handle everything *but* keyref's. + for (int i = oldCount - 1; i >= newCount; i--) { + XPathMatcher matcher = fMatcherStack.getMatcherAt(i); + if (matcher instanceof Selector.Matcher) { + Selector.Matcher selMatcher = (Selector.Matcher) matcher; + IdentityConstraint id; + if ((id = selMatcher.getIdentityConstraint()) != null + && id.getCategory() != IdentityConstraint.IC_KEYREF) { + fValueStoreCache.transplant(id, selMatcher.getInitialDepth()); + } } } - } - // now handle keyref's/... - for (int i = oldCount - 1; i >= newCount; i--) { - XPathMatcher matcher = fMatcherStack.getMatcherAt(i); - if (matcher instanceof Selector.Matcher) { - Selector.Matcher selMatcher = (Selector.Matcher) matcher; - IdentityConstraint id; - if ((id = selMatcher.getIdentityConstraint()) != null - && id.getCategory() == IdentityConstraint.IC_KEYREF) { - ValueStoreBase values = - fValueStoreCache.getValueStoreFor(id, selMatcher.getInitialDepth()); - if (values != null) // nothing to do if nothing matched! - values.endDocumentFragment(); + // now handle keyref's/... + for (int i = oldCount - 1; i >= newCount; i--) { + XPathMatcher matcher = fMatcherStack.getMatcherAt(i); + if (matcher instanceof Selector.Matcher) { + Selector.Matcher selMatcher = (Selector.Matcher) matcher; + IdentityConstraint id; + if ((id = selMatcher.getIdentityConstraint()) != null + && id.getCategory() == IdentityConstraint.IC_KEYREF) { + ValueStoreBase values = + fValueStoreCache.getValueStoreFor(id, selMatcher.getInitialDepth()); + if (values != null) // nothing to do if nothing matched! + values.endDocumentFragment(); + } } } + fValueStoreCache.endElement(); + } + + // Check if we should modify the xsi:type ignore depth + // This check is independent of whether this is the validation root, + // and should be done before the element depth is decremented. + if (fElementDepth < fIgnoreXSITypeDepth) { + fIgnoreXSITypeDepth--; } - fValueStoreCache.endElement(); SchemaGrammar[] grammars = null; // have we reached the end tag of the validation root? @@ -2290,7 +2411,14 @@ public class XMLSchemaValidator // otherwise partial, and anything above this level will be partial else { fCurrentPSVI.fValidationAttempted = ElementPSVI.VALIDATION_PARTIAL; - fNFullValidationDepth = fNNoneValidationDepth = fElementDepth - 1; + } + + // this guarantees that depth settings do not cross-over between sibling nodes + if (fNFullValidationDepth == fElementDepth) { + fNFullValidationDepth = fElementDepth - 1; + } + if (fNNoneValidationDepth == fElementDepth) { + fNNoneValidationDepth = fElementDepth - 1; } if (fDefaultValue != null) @@ -2554,14 +2682,22 @@ public class XMLSchemaValidator // if there is no current type, set this one as current. // and we don't need to do extra checking if (fCurrentType != null) { + short block = XSConstants.DERIVATION_NONE; // 4.3 The local type definition must be validly derived from the {type definition} given the union of the {disallowed substitutions} and the {type definition}'s {prohibited substitutions}, as defined in Type Derivation OK (Complex) (3.4.6) (if it is a complex type definition), or given {disallowed substitutions} as defined in Type Derivation OK (Simple) (3.14.6) (if it is a simple type definition). - short block = fCurrentElemDecl.fBlock; - if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) + // Note: It's possible to have fCurrentType be non-null and fCurrentElemDecl + // be null, if the current type is set using the property "root-type-definition". + // In that case, we don't disallow any substitutions. -PM + if (fCurrentElemDecl != null) { + block = fCurrentElemDecl.fBlock; + } + if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) { block |= ((XSComplexTypeDecl) fCurrentType).fBlock; - if (!XSConstraints.checkTypeDerivationOk(type, fCurrentType, block)) + } + if (!XSConstraints.checkTypeDerivationOk(type, fCurrentType, block)) { reportSchemaError( - "cvc-elt.4.3", - new Object[] { element.rawname, xsiType, fCurrentType.getName()}); + "cvc-elt.4.3", + new Object[] { element.rawname, xsiType, fCurrentType.getName()}); + } } return type; @@ -2835,9 +2971,10 @@ public class XMLSchemaValidator } // get the value constraint from use or decl - // 4 The item's actual value must match the value of the {value constraint}, if it is present and fixed. // now check the value against the simpleType + // 4 The item's actual value must match the value of the {value constraint}, if it is present and fixed. + // now check the value against the simpleType if (actualValue != null && currDecl.getConstraintType() == XSConstants.VC_FIXED) { - if (!isComparable(fValidatedInfo, currDecl.fDefault) || !actualValue.equals(currDecl.fDefault.actualValue)) { + if (!ValidatedInfo.isComparable(fValidatedInfo, currDecl.fDefault) || !actualValue.equals(currDecl.fDefault.actualValue)) { reportSchemaError( "cvc-attribute.4", new Object[] { @@ -2852,7 +2989,7 @@ public class XMLSchemaValidator if (actualValue != null && currUse != null && currUse.fConstraintType == XSConstants.VC_FIXED) { - if (!isComparable(fValidatedInfo, currUse.fDefault) || !actualValue.equals(currUse.fDefault.actualValue)) { + if (!ValidatedInfo.isComparable(fValidatedInfo, currUse.fDefault) || !actualValue.equals(currUse.fDefault.actualValue)) { reportSchemaError( "cvc-complex-type.3.1", new Object[] { @@ -3083,7 +3220,7 @@ public class XMLSchemaValidator } // 5.2.2.2.2 If the {content type} of the actual type definition is a simple type definition, then the actual value of the item must match the canonical lexical representation of the {value constraint} value. else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) { - if (actualValue != null && (!isComparable(fValidatedInfo, fCurrentElemDecl.fDefault) + if (actualValue != null && (!ValidatedInfo.isComparable(fValidatedInfo, fCurrentElemDecl.fDefault) || !actualValue.equals(fCurrentElemDecl.fDefault.actualValue))) { reportSchemaError( "cvc-elt.5.2.2.2.2", @@ -3094,7 +3231,7 @@ public class XMLSchemaValidator } } } else if (fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) { - if (actualValue != null && (!isComparable(fValidatedInfo, fCurrentElemDecl.fDefault) + if (actualValue != null && (!ValidatedInfo.isComparable(fValidatedInfo, fCurrentElemDecl.fDefault) || !actualValue.equals(fCurrentElemDecl.fDefault.actualValue))) { // REVISIT: the spec didn't mention this case: fixed // value with simple type @@ -3240,53 +3377,6 @@ public class XMLSchemaValidator XMLErrorReporter.SEVERITY_ERROR); } - /** Returns true if the two ValidatedInfo objects can be compared in the same value space. **/ - private boolean isComparable(ValidatedInfo info1, ValidatedInfo info2) { - final short primitiveType1 = convertToPrimitiveKind(info1.actualValueType); - final short primitiveType2 = convertToPrimitiveKind(info2.actualValueType); - if (primitiveType1 != primitiveType2) { - return (primitiveType1 == XSConstants.ANYSIMPLETYPE_DT && primitiveType2 == XSConstants.STRING_DT || - primitiveType1 == XSConstants.STRING_DT && primitiveType2 == XSConstants.ANYSIMPLETYPE_DT); - } - else if (primitiveType1 == XSConstants.LIST_DT || primitiveType1 == XSConstants.LISTOFUNION_DT) { - final ShortList typeList1 = info1.itemValueTypes; - final ShortList typeList2 = info2.itemValueTypes; - final int typeList1Length = typeList1 != null ? typeList1.getLength() : 0; - final int typeList2Length = typeList2 != null ? typeList2.getLength() : 0; - if (typeList1Length != typeList2Length) { - return false; - } - for (int i = 0; i < typeList1Length; ++i) { - final short primitiveItem1 = convertToPrimitiveKind(typeList1.item(i)); - final short primitiveItem2 = convertToPrimitiveKind(typeList2.item(i)); - if (primitiveItem1 != primitiveItem2) { - if (primitiveItem1 == XSConstants.ANYSIMPLETYPE_DT && primitiveItem2 == XSConstants.STRING_DT || - primitiveItem1 == XSConstants.STRING_DT && primitiveItem2 == XSConstants.ANYSIMPLETYPE_DT) { - continue; - } - return false; - } - } - } - return true; - } - - private short convertToPrimitiveKind(short valueType) { - /** Primitive datatypes. */ - if (valueType <= XSConstants.NOTATION_DT) { - return valueType; - } - /** Types derived from string. */ - if (valueType <= XSConstants.ENTITY_DT) { - return XSConstants.STRING_DT; - } - /** Types derived from decimal. */ - if (valueType <= XSConstants.POSITIVEINTEGER_DT) { - return XSConstants.DECIMAL_DT; - } - /** Other types. */ - return valueType; - } private String expectedStr(Vector expected) { StringBuffer ret = new StringBuffer("{"); diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchema.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchema.java index 070086aa98b..5b05a6d1c28 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchema.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchema.java @@ -1,13 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -32,11 +29,19 @@ final class XMLSchema extends AbstractXMLSchema { /** The grammar pool is immutable */ private final XMLGrammarPool fGrammarPool; + /** Whether to consider this schema to be fully composed */ + private final boolean fFullyComposed; + /** Constructor */ public XMLSchema(XMLGrammarPool grammarPool) { - fGrammarPool = grammarPool; + this(grammarPool, true); } + public XMLSchema(XMLGrammarPool grammarPool, boolean fullyComposed) { + fGrammarPool = grammarPool; + fFullyComposed = fullyComposed; + } + /* * XSGrammarPoolContainer methods */ @@ -60,7 +65,7 @@ final class XMLSchema extends AbstractXMLSchema { * can be considered to be a fully composed schema */ public boolean isFullyComposed() { - return true; + return fFullyComposed; } } // XMLSchema diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java index a453dbf4227..3542750efaf 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java @@ -1,13 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -68,12 +65,21 @@ import org.xml.sax.SAXParseException; */ public final class XMLSchemaFactory extends SchemaFactory { - // property identifiers + // feature identifiers + + /** JAXP Source feature prefix. */ + private static final String JAXP_SOURCE_FEATURE_PREFIX = "http://javax.xml.transform"; /** Feature identifier: schema full checking. */ private static final String SCHEMA_FULL_CHECKING = Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_FULL_CHECKING; + /** Feature identifier: use grammar pool only. */ + private static final String USE_GRAMMAR_POOL_ONLY = + Constants.XERCES_FEATURE_PREFIX + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE; + + // property identifiers + /** Property identifier: grammar pool. */ private static final String XMLGRAMMAR_POOL = Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY; @@ -104,7 +110,7 @@ public final class XMLSchemaFactory extends SchemaFactory { private final DOMEntityResolverWrapper fDOMEntityResolverWrapper; /** The ErrorHandlerWrapper */ - private ErrorHandlerWrapper fErrorHandlerWrapper; + private final ErrorHandlerWrapper fErrorHandlerWrapper; /** The SecurityManager. */ private XMLSecurityManager fSecurityManager; @@ -113,7 +119,10 @@ public final class XMLSchemaFactory extends SchemaFactory { private XMLSecurityPropertyManager fSecurityPropertyMgr; /** The container for the real grammar pool. */ - private XMLGrammarPoolWrapper fXMLGrammarPoolWrapper; + private final XMLGrammarPoolWrapper fXMLGrammarPoolWrapper; + + /** Whether or not to allow new schemas to be added to the grammar pool */ + private boolean fUseGrammarPoolOnly; /** * Indicates whether implementation parts should use @@ -138,6 +147,7 @@ public final class XMLSchemaFactory extends SchemaFactory { fXMLSchemaLoader.setProperty(XMLGRAMMAR_POOL, fXMLGrammarPoolWrapper); fXMLSchemaLoader.setEntityResolver(fDOMEntityResolverWrapper); fXMLSchemaLoader.setErrorHandler(fErrorHandlerWrapper); + fUseGrammarPoolOnly = true; // Enable secure processing feature by default fSecurityManager = new XMLSecurityManager(true); @@ -170,7 +180,8 @@ public final class XMLSchemaFactory extends SchemaFactory { "SchemaLanguageLengthZero", null)); } // only W3C XML Schema 1.0 is supported - return schemaLanguage.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI); + return schemaLanguage.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI) || + schemaLanguage.equals(Constants.W3C_XML_SCHEMA10_NS_URI); } public LSResourceResolver getResourceResolver() { @@ -202,7 +213,7 @@ public final class XMLSchemaFactory extends SchemaFactory { XMLInputSource[] xmlInputSources = new XMLInputSource[schemas.length]; InputStream inputStream; Reader reader; - for( int i=0; i 1) { - schema = new XMLSchema(new ReadOnlyGrammarPool(pool)); - } - else if (grammarCount == 1) { - Grammar[] grammars = pool.retrieveInitialGrammarSet(XMLGrammarDescription.XML_SCHEMA); - schema = new SimpleXMLSchema(grammars[0]); + if (fUseGrammarPoolOnly) { + if (grammarCount > 1) { + schema = new XMLSchema(new ReadOnlyGrammarPool(pool)); + } + else if (grammarCount == 1) { + Grammar[] grammars = pool.retrieveInitialGrammarSet(XMLGrammarDescription.XML_SCHEMA); + schema = new SimpleXMLSchema(grammars[0]); + } + else { + schema = new EmptyXMLSchema(); + } } else { - schema = new EmptyXMLSchema(); + schema = new XMLSchema(new ReadOnlyGrammarPool(pool), false); } propagateFeatures(schema); propagateProperties(schema); @@ -286,6 +305,14 @@ public final class XMLSchemaFactory extends SchemaFactory { } public Schema newSchema() throws SAXException { + /* + * It would make sense to return an EmptyXMLSchema object here, if + * fUseGrammarPoolOnly is set to true. However, because the default + * value of this feature is true, doing so would change the default + * behaviour of this method. Thus, we return a WeakReferenceXMLSchema + * regardless of the value of fUseGrammarPoolOnly. -PM + */ + // Use a Schema that uses the system id as the equality source. AbstractXMLSchema schema = new WeakReferenceXMLSchema(); propagateFeatures(schema); @@ -293,15 +320,38 @@ public final class XMLSchemaFactory extends SchemaFactory { return schema; } + public Schema newSchema(XMLGrammarPool pool) throws SAXException { + // If the "use-grammar-pool-only" feature is set to true + // prevent the application's grammar pool from being mutated + // by wrapping it in a ReadOnlyGrammarPool. + final AbstractXMLSchema schema = (fUseGrammarPoolOnly) ? + new XMLSchema(new ReadOnlyGrammarPool(pool)) : + new XMLSchema(pool, false); + propagateFeatures(schema); + return schema; + } + public boolean getFeature(String name) throws SAXNotRecognizedException, SAXNotSupportedException { if (name == null) { throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), "FeatureNameNull", null)); } + if (name.startsWith(JAXP_SOURCE_FEATURE_PREFIX)) { + // Indicates to the caller that this SchemaFactory supports a specific JAXP Source. + if (name.equals(StreamSource.FEATURE) || + name.equals(SAXSource.FEATURE) || + name.equals(DOMSource.FEATURE) || + name.equals(StAXSource.FEATURE)) { + return true; + } + } if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { return (fSecurityManager != null && fSecurityManager.isSecureProcessing()); } + else if (name.equals(USE_GRAMMAR_POOL_ONLY)) { + return fUseGrammarPoolOnly; + } try { return fXMLSchemaLoader.getFeature(name); } @@ -358,6 +408,16 @@ public final class XMLSchemaFactory extends SchemaFactory { throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), "FeatureNameNull", null)); } + if (name.startsWith(JAXP_SOURCE_FEATURE_PREFIX)) { + if (name.equals(StreamSource.FEATURE) || + name.equals(SAXSource.FEATURE) || + name.equals(DOMSource.FEATURE) || + name.equals(StAXSource.FEATURE)) { + throw new SAXNotSupportedException( + SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), + "feature-read-only", new Object [] {name})); + } + } if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { if (System.getSecurityManager() != null && (!value)) { throw new SAXNotSupportedException( @@ -377,7 +437,12 @@ public final class XMLSchemaFactory extends SchemaFactory { fXMLSchemaLoader.setProperty(SECURITY_MANAGER, fSecurityManager); return; - } else if (name.equals(Constants.ORACLE_FEATURE_SERVICE_MECHANISM)) { + } + else if (name.equals(USE_GRAMMAR_POOL_ONLY)) { + fUseGrammarPoolOnly = value; + return; + } + else if (name.equals(Constants.ORACLE_FEATURE_SERVICE_MECHANISM)) { //in secure mode, let _useServicesMechanism be determined by the constructor if (System.getSecurityManager() != null) return; diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java index 58a74191cf0..807dc917908 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java @@ -1,13 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -69,13 +66,41 @@ final class XMLSchemaValidatorComponentManager extends ParserConfigurationSettin private static final String VALIDATION = Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE; + /** Feature identifier: use grammar pool only. */ + private static final String USE_GRAMMAR_POOL_ONLY = + Constants.XERCES_FEATURE_PREFIX + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE; + + /** Feature identifier: whether to ignore xsi:type attributes until a global element declaration is encountered */ + protected static final String IGNORE_XSI_TYPE = + Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_XSI_TYPE_FEATURE; + + /** Feature identifier: whether to ignore ID/IDREF errors */ + protected static final String ID_IDREF_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.ID_IDREF_CHECKING_FEATURE; + + /** Feature identifier: whether to ignore unparsed entity errors */ + protected static final String UNPARSED_ENTITY_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.UNPARSED_ENTITY_CHECKING_FEATURE; + + /** Feature identifier: whether to ignore identity constraint errors */ + protected static final String IDENTITY_CONSTRAINT_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.IDC_CHECKING_FEATURE; + + /** Feature identifier: disallow DOCTYPE declaration */ + private static final String DISALLOW_DOCTYPE_DECL_FEATURE = + Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE; + + /** Feature identifier: expose schema normalized value */ + private static final String NORMALIZE_DATA = + Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_NORMALIZED_VALUE; + /** Feature identifier: send element default value via characters() */ private static final String SCHEMA_ELEMENT_DEFAULT = Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_ELEMENT_DEFAULT; - /** Feature identifier: use grammar pool only. */ - private static final String USE_GRAMMAR_POOL_ONLY = - Constants.XERCES_FEATURE_PREFIX + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE; + /** Feature identifier: augment PSVI */ + private static final String SCHEMA_AUGMENT_PSVI = + Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_AUGMENT_PSVI; // property identifiers @@ -230,10 +255,32 @@ final class XMLSchemaValidatorComponentManager extends ParserConfigurationSettin fErrorReporter.putMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN, new XSMessageFormatter()); // add all recognized features and properties and apply their defaults + final String [] recognizedFeatures = { + DISALLOW_DOCTYPE_DECL_FEATURE, + NORMALIZE_DATA, + SCHEMA_ELEMENT_DEFAULT, + SCHEMA_AUGMENT_PSVI + }; + addRecognizedFeatures(recognizedFeatures); + fFeatures.put(DISALLOW_DOCTYPE_DECL_FEATURE, Boolean.FALSE); + fFeatures.put(NORMALIZE_DATA, Boolean.FALSE); + fFeatures.put(SCHEMA_ELEMENT_DEFAULT, Boolean.FALSE); + fFeatures.put(SCHEMA_AUGMENT_PSVI, Boolean.TRUE); + addRecognizedParamsAndSetDefaults(fEntityManager, grammarContainer); addRecognizedParamsAndSetDefaults(fErrorReporter, grammarContainer); addRecognizedParamsAndSetDefaults(fSchemaValidator, grammarContainer); + /* TODO: are other XMLSchemaValidator default values never set? + * Initial investigation indicates that they aren't set, but + * that they all have default values of false, so it works out + * anyway -PM + */ + fFeatures.put(IGNORE_XSI_TYPE, Boolean.FALSE); + fFeatures.put(ID_IDREF_CHECKING, Boolean.TRUE); + fFeatures.put(IDENTITY_CONSTRAINT_CHECKING, Boolean.TRUE); + fFeatures.put(UNPARSED_ENTITY_CHECKING, Boolean.TRUE); + boolean secureProcessing = grammarContainer.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING); if (System.getSecurityManager() != null) { _isSecureMode = true; diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/StandardParserConfiguration.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/StandardParserConfiguration.java index 5ac09f8f866..464f93e8c92 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/StandardParserConfiguration.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/StandardParserConfiguration.java @@ -1,13 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2001-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -109,6 +106,22 @@ public class StandardParserConfiguration protected static final String HONOUR_ALL_SCHEMALOCATIONS = Constants.XERCES_FEATURE_PREFIX + Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE; + /** Feature identifier: whether to ignore xsi:type attributes until a global element declaration is encountered */ + protected static final String IGNORE_XSI_TYPE = + Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_XSI_TYPE_FEATURE; + + /** Feature identifier: whether to ignore ID/IDREF errors */ + protected static final String ID_IDREF_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.ID_IDREF_CHECKING_FEATURE; + + /** Feature identifier: whether to ignore unparsed entity errors */ + protected static final String UNPARSED_ENTITY_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.UNPARSED_ENTITY_CHECKING_FEATURE; + + /** Feature identifier: whether to ignore identity constraint errors */ + protected static final String IDENTITY_CONSTRAINT_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.IDC_CHECKING_FEATURE; + /** Feature identifier: namespace growth */ protected static final String NAMESPACE_GROWTH = Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACE_GROWTH_FEATURE; @@ -135,6 +148,10 @@ public class StandardParserConfiguration protected static final String SCHEMA_DV_FACTORY = Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY; + /** Property identifier: root type definition. */ + protected static final String ROOT_TYPE_DEF = + Constants.XERCES_PROPERTY_PREFIX + Constants.ROOT_TYPE_DEFINITION_PROPERTY; + // // Data // @@ -211,6 +228,10 @@ public class StandardParserConfiguration // not-recognized exception to be thrown. -Ac XMLSCHEMA_VALIDATION, XMLSCHEMA_FULL_CHECKING, + IGNORE_XSI_TYPE, + ID_IDREF_CHECKING, + IDENTITY_CONSTRAINT_CHECKING, + UNPARSED_ENTITY_CHECKING, }; addRecognizedFeatures(recognizedFeatures); @@ -221,6 +242,10 @@ public class StandardParserConfiguration setFeature(GENERATE_SYNTHETIC_ANNOTATIONS, false); setFeature(VALIDATE_ANNOTATIONS, false); setFeature(HONOUR_ALL_SCHEMALOCATIONS, false); + setFeature(IGNORE_XSI_TYPE, false); + setFeature(ID_IDREF_CHECKING, true); + setFeature(IDENTITY_CONSTRAINT_CHECKING, true); + setFeature(UNPARSED_ENTITY_CHECKING, true); setFeature(NAMESPACE_GROWTH, false); setFeature(TOLERATE_DUPLICATES, false); @@ -233,11 +258,11 @@ public class StandardParserConfiguration // not-recognized exception to be thrown. -Ac SCHEMA_LOCATION, SCHEMA_NONS_LOCATION, + ROOT_TYPE_DEF, SCHEMA_DV_FACTORY, - }; - - addRecognizedProperties(recognizedProperties); + }; + addRecognizedProperties(recognizedProperties); } // (SymbolTable,XMLGrammarPool) // diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java index c0283f74e3c..975367eb2be 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java @@ -1,13 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2001-2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -184,7 +181,21 @@ public class XML11Configuration extends ParserConfigurationSettings protected static final String EXTERNAL_PARAMETER_ENTITIES = Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE; + /** Feature identifier: whether to ignore xsi:type attributes until a global element declaration is encountered */ + protected static final String IGNORE_XSI_TYPE = + Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_XSI_TYPE_FEATURE; + /** Feature identifier: whether to ignore ID/IDREF errors */ + protected static final String ID_IDREF_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.ID_IDREF_CHECKING_FEATURE; + + /** Feature identifier: whether to ignore unparsed entity errors */ + protected static final String UNPARSED_ENTITY_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.UNPARSED_ENTITY_CHECKING_FEATURE; + + /** Feature identifier: whether to ignore identity constraint errors */ + protected static final String IDENTITY_CONSTRAINT_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.IDC_CHECKING_FEATURE; // property identifiers @@ -267,6 +278,10 @@ public class XML11Configuration extends ParserConfigurationSettings protected static final String JAXP_SCHEMA_SOURCE = Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE; + /** Property identifier: root type definition. */ + protected static final String ROOT_TYPE_DEF = + Constants.XERCES_PROPERTY_PREFIX + Constants.ROOT_TYPE_DEFINITION_PROPERTY; + /** Property identifier: locale. */ protected static final String LOCALE = Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY; @@ -467,25 +482,27 @@ public class XML11Configuration extends ParserConfigurationSettings // add default recognized features final String[] recognizedFeatures = - { - CONTINUE_AFTER_FATAL_ERROR, LOAD_EXTERNAL_DTD, // from XMLDTDScannerImpl - VALIDATION, - NAMESPACES, - NORMALIZE_DATA, SCHEMA_ELEMENT_DEFAULT, SCHEMA_AUGMENT_PSVI, - GENERATE_SYNTHETIC_ANNOTATIONS, VALIDATE_ANNOTATIONS, - HONOUR_ALL_SCHEMALOCATIONS, NAMESPACE_GROWTH, - TOLERATE_DUPLICATES, - USE_GRAMMAR_POOL_ONLY, - // NOTE: These shouldn't really be here but since the XML Schema - // validator is constructed dynamically, its recognized - // features might not have been set and it would cause a - // not-recognized exception to be thrown. -Ac - XMLSCHEMA_VALIDATION, XMLSCHEMA_FULL_CHECKING, - EXTERNAL_GENERAL_ENTITIES, - EXTERNAL_PARAMETER_ENTITIES, - PARSER_SETTINGS, - XMLConstants.FEATURE_SECURE_PROCESSING - }; + { + CONTINUE_AFTER_FATAL_ERROR, LOAD_EXTERNAL_DTD, // from XMLDTDScannerImpl + VALIDATION, + NAMESPACES, + NORMALIZE_DATA, SCHEMA_ELEMENT_DEFAULT, SCHEMA_AUGMENT_PSVI, + GENERATE_SYNTHETIC_ANNOTATIONS, VALIDATE_ANNOTATIONS, + HONOUR_ALL_SCHEMALOCATIONS, IGNORE_XSI_TYPE, + ID_IDREF_CHECKING, IDENTITY_CONSTRAINT_CHECKING, + UNPARSED_ENTITY_CHECKING, + NAMESPACE_GROWTH, TOLERATE_DUPLICATES, + USE_GRAMMAR_POOL_ONLY, + // NOTE: These shouldn't really be here but since the XML Schema + // validator is constructed dynamically, its recognized + // features might not have been set and it would cause a + // not-recognized exception to be thrown. -Ac + XMLSCHEMA_VALIDATION, XMLSCHEMA_FULL_CHECKING, + EXTERNAL_GENERAL_ENTITIES, + EXTERNAL_PARAMETER_ENTITIES, + PARSER_SETTINGS, + XMLConstants.FEATURE_SECURE_PROCESSING + }; addRecognizedFeatures(recognizedFeatures); // set state for default features fFeatures.put(VALIDATION, Boolean.FALSE); @@ -500,6 +517,10 @@ public class XML11Configuration extends ParserConfigurationSettings fFeatures.put(GENERATE_SYNTHETIC_ANNOTATIONS, Boolean.FALSE); fFeatures.put(VALIDATE_ANNOTATIONS, Boolean.FALSE); fFeatures.put(HONOUR_ALL_SCHEMALOCATIONS, Boolean.FALSE); + fFeatures.put(IGNORE_XSI_TYPE, Boolean.FALSE); + fFeatures.put(ID_IDREF_CHECKING, Boolean.TRUE); + fFeatures.put(IDENTITY_CONSTRAINT_CHECKING, Boolean.TRUE); + fFeatures.put(UNPARSED_ENTITY_CHECKING, Boolean.TRUE); fFeatures.put(NAMESPACE_GROWTH, Boolean.FALSE); fFeatures.put(TOLERATE_DUPLICATES, Boolean.FALSE); fFeatures.put(USE_GRAMMAR_POOL_ONLY, Boolean.FALSE); @@ -508,41 +529,42 @@ public class XML11Configuration extends ParserConfigurationSettings // add default recognized properties final String[] recognizedProperties = - { - SYMBOL_TABLE, - ERROR_HANDLER, - ENTITY_RESOLVER, - ERROR_REPORTER, - ENTITY_MANAGER, - DOCUMENT_SCANNER, - DTD_SCANNER, - DTD_PROCESSOR, - DTD_VALIDATOR, - DATATYPE_VALIDATOR_FACTORY, - VALIDATION_MANAGER, - SCHEMA_VALIDATOR, - XML_STRING, - XMLGRAMMAR_POOL, - JAXP_SCHEMA_SOURCE, - JAXP_SCHEMA_LANGUAGE, - // NOTE: These shouldn't really be here but since the XML Schema - // validator is constructed dynamically, its recognized - // properties might not have been set and it would cause a - // not-recognized exception to be thrown. -Ac - SCHEMA_LOCATION, - SCHEMA_NONS_LOCATION, - LOCALE, - SCHEMA_DV_FACTORY, - SECURITY_MANAGER, - XML_SECURITY_PROPERTY_MANAGER + { + SYMBOL_TABLE, + ERROR_HANDLER, + ENTITY_RESOLVER, + ERROR_REPORTER, + ENTITY_MANAGER, + DOCUMENT_SCANNER, + DTD_SCANNER, + DTD_PROCESSOR, + DTD_VALIDATOR, + DATATYPE_VALIDATOR_FACTORY, + VALIDATION_MANAGER, + SCHEMA_VALIDATOR, + XML_STRING, + XMLGRAMMAR_POOL, + JAXP_SCHEMA_SOURCE, + JAXP_SCHEMA_LANGUAGE, + // NOTE: These shouldn't really be here but since the XML Schema + // validator is constructed dynamically, its recognized + // properties might not have been set and it would cause a + // not-recognized exception to be thrown. -Ac + SCHEMA_LOCATION, + SCHEMA_NONS_LOCATION, + ROOT_TYPE_DEF, + LOCALE, + SCHEMA_DV_FACTORY, + SECURITY_MANAGER, + XML_SECURITY_PROPERTY_MANAGER }; addRecognizedProperties(recognizedProperties); - if (symbolTable == null) { - symbolTable = new SymbolTable(); - } - fSymbolTable = symbolTable; - fProperties.put(SYMBOL_TABLE, fSymbolTable); + if (symbolTable == null) { + symbolTable = new SymbolTable(); + } + fSymbolTable = symbolTable; + fProperties.put(SYMBOL_TABLE, fSymbolTable); fGrammarPool = grammarPool; if (fGrammarPool != null) { @@ -597,8 +619,7 @@ public class XML11Configuration extends ParserConfigurationSettings // REVISIT: What is the right thing to do? -Ac } - fConfigUpdated = false; - + fConfigUpdated = false; } // (SymbolTable,XMLGrammarPool) // diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 6e435e07387..f1c5ee39bb4 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -273,3 +273,4 @@ ce19e0403ec8a80223cc47320c905b2a4d45881d jdk9-b23 ab8726a0fcde897e4cfd1ea581ed90b0d8a7cbb7 jdk9-b25 9b43f3993b96c2213428e95127a2d3fd0e709d3a jdk9-b26 dcaa586ab756420e9a62643793bacef2c84bf637 jdk9-b27 +5282a14f131f897cc9575872c0fae72d47dc4e65 jdk9-b28 diff --git a/jdk/.hgtags b/jdk/.hgtags index d14f384c507..51acdfa12e1 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -270,3 +270,4 @@ f87c5be90e01a7ffb47947108eb3e0b0b1920880 jdk9-b20 a31efe49556a7c12f9ea2c9ee8b4fae8aa67723a jdk9-b25 dde9f5cfde5f46e62ceb5fab81151578e5277aef jdk9-b26 f0870554049807d3392bd7976ab114f7f2b7bafa jdk9-b27 +1828f73b35cfe35e460e41fd6e087ab1f83e0621 jdk9-b28 diff --git a/jdk/make/Bundles.gmk b/jdk/make/Bundles.gmk index 57ab08784cf..470a1e9bfb5 100644 --- a/jdk/make/Bundles.gmk +++ b/jdk/make/Bundles.gmk @@ -35,7 +35,7 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) # JDK_BUNDLE_DIR and JRE_BUNDLE_DIR are defined in SPEC. - MACOSX_PLIST_SRC := $(JDK_TOPDIR)/make/bundle + MACOSX_PLIST_SRC := $(JDK_TOPDIR)/make/data/bundle # All these OPENJDK checks are needed since there is no coherency between # these values in open and closed. Should probably be fixed. diff --git a/jdk/make/CompileDemos.gmk b/jdk/make/CompileDemos.gmk index 531e61765a2..35bf0b4a691 100644 --- a/jdk/make/CompileDemos.gmk +++ b/jdk/make/CompileDemos.gmk @@ -29,9 +29,7 @@ include $(SPEC) include MakeBase.gmk include JavaCompilation.gmk include NativeCompilation.gmk - -# Setup the java compilers for the JDK build. -include SetupJava.gmk +include SetupJavaCompilers.gmk # Prepare the find cache. $(eval $(call FillCacheFind, $(JDK_TOPDIR)/src)) @@ -316,19 +314,6 @@ $(eval $(call SetupJVMTIDemo,compiledMethodLoad, agent_util)) $(eval $(call SetupJVMTIDemo,gctest, agent_util)) $(eval $(call SetupJVMTIDemo,heapTracker, agent_util java_crw_demo)) $(eval $(call SetupJVMTIDemo,heapViewer, agent_util)) - -# On AIX, hprof requires 'dladdr' from src/aix/porting/porting_aix.cpp -BUILD_LIBHPROF_AIX_EXTRA_SRC := -BUILD_LIBHPROF_AIX_EXTRA_CFLAGS := -ifeq ($(OPENJDK_TARGET_OS), aix) - BUILD_LIBHPROF_AIX_EXTRA_SRC += $(JDK_TOPDIR)/src/aix/porting - BUILD_LIBHPROF_AIX_EXTRA_CFLAGS += -I$(JDK_TOPDIR)/src/aix/porting -endif - -$(eval $(call SetupJVMTIDemo,hprof, java_crw_demo, \ - $(BUILD_LIBHPROF_AIX_EXTRA_CFLAGS), C, \ - -ldl, ws2_32.lib winmm.lib, -lsocket -lnsl, -lpthread, $(BUILD_LIBHPROF_AIX_EXTRA_SRC))) - $(eval $(call SetupJVMTIDemo,minst, agent_util java_crw_demo)) $(eval $(call SetupJVMTIDemo,mtrace, agent_util java_crw_demo)) $(eval $(call SetupJVMTIDemo,waiters, agent_util, , C++)) @@ -336,34 +321,6 @@ $(eval $(call SetupJVMTIDemo,versionCheck, agent_util)) ################################################################################################## -$(JDK_OUTPUTDIR)/demo/jpda/com/sun/tools/example/README: \ - $(JDK_TOPDIR)/src/demo/share/jpda/com/sun/tools/example/README - $(call install-file) - $(CHMOD) -f ug+w $@ - -$(eval $(call SetupArchive,JPDA_JAR, \ - $(JDK_OUTPUTDIR)/demo/jpda/com/sun/tools/example/README, \ - SRCS := $(JDK_TOPDIR)/src/demo/share/jpda \ - $(JDK_TOPDIR)/src/jdk.jdi/share/classes \ - $(JDK_OUTPUTDIR)/demo/jpda/com/sun/tools/example, \ - INCLUDES := com/sun/tools/example README, \ - SUFFIXES := .java .html .jj README, \ - JAR := $(JDK_OUTPUTDIR)/demo/jpda/examples.jar, \ - MANIFEST := $(JDK_TOPDIR)/make/data/mainmanifest/manifest.mf, \ - EXTRA_MANIFEST_ATTR := Main-Class:$$(SPACE), \ - SKIP_METAINF := true)) - -$(eval $(call SetupZipArchive,JPDA_ZIP, \ - SRC := $(JDK_TOPDIR)/src/demo/share/jpda \ - $(JDK_TOPDIR)/src/jdk.jdi/share/classes, \ - INCLUDES := com/sun/tools/example, \ - SUFFIXES := .java .html .jj README, \ - ZIP := $(JDK_OUTPUTDIR)/demo/jpda/src.zip)) - -BUILD_DEMOS += $(JPDA_JAR) $(JPDA_ZIP) - -################################################################################################## - $(JDK_OUTPUTDIR)/demo/management/index.html: $(DEMO_SHARE_SRC)/management/index.html $(call install-file) $(CHMOD) -f ug+w $@ diff --git a/jdk/make/CompileInterimRmic.gmk b/jdk/make/CompileInterimRmic.gmk index 74f789dfa61..79082cd415c 100644 --- a/jdk/make/CompileInterimRmic.gmk +++ b/jdk/make/CompileInterimRmic.gmk @@ -28,7 +28,7 @@ default: all include $(SPEC) include MakeBase.gmk include JavaCompilation.gmk -include SetupJava.gmk +include SetupJavaCompilers.gmk ########################################################################################## diff --git a/jdk/make/CopyIntoClasses.gmk b/jdk/make/CopyIntoClasses.gmk deleted file mode 100644 index c3420c0dcdf..00000000000 --- a/jdk/make/CopyIntoClasses.gmk +++ /dev/null @@ -1,202 +0,0 @@ -# -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# Copy icu and _dict files used by the text break iterator - -COPY_PATTERNS := .icu _dict .dat _options .js aliasmap .spp .wav .css \ - .png .gif .xml .dtd .txt oqlhelp.html content-types.properties - -# These directories should not be copied at all -EXCLUDES += \ - java/awt/doc-files \ - java/lang/doc-files \ - javax/swing/doc-files \ - javax/swing/text/doc-files \ - javax/swing/plaf/synth/doc-files \ - javax/swing/undo/doc-files \ - sun/awt/X11/doc-files \ - sun/util/cldr/resources \ - # - -# These files should never be included -EXFILES += build.xml README.txt version.txt - -# These icons are handled in GensrcIcons.gmk -EXFILES += \ - sun/awt/X11/java-icon16.png \ - sun/awt/X11/java-icon24.png \ - sun/awt/X11/java-icon32.png \ - sun/awt/X11/java-icon48.png \ - $(wildcard $(JDK_TOPDIR)/src/share/classes/sun/awt/resources/*.png) \ - # - -ifndef OPENJDK - # Theses icons have closed replacements - SWING_PLAF_MOTIF_RESOURCES_DIR := $(JDK_TOPDIR)/src/share/classes/com/sun/java/swing/plaf/motif - EXFILES += \ - $(JDK_TOPDIR)/src/share/classes/com/sun/java/swing/plaf/windows/icons/JavaCup32.png \ - $(JDK_TOPDIR)/src/share/classes/javax/swing/plaf/basic/icons/JavaCup16.png \ - $(wildcard $(SWING_PLAF_MOTIF_RESOURCES_DIR)/icons/*.gif) \ - $(wildcard $(SWING_PLAF_MOTIF_RESOURCES_DIR)/icons/*.png) \ - # - - EXFILES += mib_core.txt -endif - -ifeq ($(ENABLE_JFR), true) - JFR_CONFIGURATION_DIR_CLOSED := $(JDK_TOPDIR)/src/closed/share/classes/oracle/jrockit/jfr/settings - COPY_FILES += \ - $(JFR_CONFIGURATION_DIR_CLOSED)/jfc.xsd -endif - -SWING_BEANINFO_RESOURCES_SRC_DIR = $(JDK_TOPDIR)/make/data/swingbeaninfo/images -SWING_BEANINFO_RESOURCES_SRC = $(wildcard $(SWING_BEANINFO_RESOURCES_SRC_DIR)/*.gif) -OUT_BEANINFO_RESOURCES = $(patsubst $(SWING_BEANINFO_RESOURCES_SRC_DIR)%, \ - $(JDK_OUTPUTDIR)/classes/javax/swing/beaninfo/images/%, \ - $(SWING_BEANINFO_RESOURCES_SRC)) - -COPY_EXTRA += $(OUT_BEANINFO_RESOURCES) - -# The exception handling of swing beaninfo -# These resources violates the convention of having code and resources together under -# $(JDK_TOPDIR)/src/.../classes directories -$(JDK_OUTPUTDIR)/classes/javax/swing/beaninfo/images/%.gif: \ - $(JDK_TOPDIR)/make/data/swingbeaninfo/images/%.gif - $(call install-file) - -########################################################################################## -# -# Copy the META-INF/services configuration files that are scattered around the source tree -# into classes/META-INF/services. Be aware that META-INF directories that are located at a -# source root (.../classes/META-INF) are automatically copied verbatim by the -# SetupJavaCompilation macro. -# -# Any other META-INF/services configuration file is found here and platform specific comments -# are uncommented and the configuration file is stored in the output META-INF directory. - -# Make sure the output directory is created. -$(eval $(call MakeDir, $(JDK_OUTPUTDIR)/classes/META-INF/services)) -# Find all META-INF/services/* files -ALL_META-INF_DIRS_share := $(shell $(FIND) $(JDK_TOPDIR)/src/share/classes -type d -a -name META-INF) -ALL_META-INF_DIRS_targetapi := $(shell $(FIND) $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/classes -type d -a -name META-INF) -# Platform specific overrides shared -ifneq ($(ALL_META-INF_DIRS_targetapi), ) - ALL_META-INF_DIRS := $(ALL_META-INF_DIRS_targetapi) \ - $(filter-out %$(patsubst $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/classes%,%,$(ALL_META-INF_DIRS_targetapi)), \ - $(ALL_META-INF_DIRS_share)) -else - ALL_META-INF_DIRS := $(ALL_META-INF_DIRS_share) -endif - -SRC_SERVICES_FILES := $(wildcard $(addsuffix /services/*, $(ALL_META-INF_DIRS))) - -# The number of services files are relatively few. If the increase in numbers, then -# we have to use ListPathsSafelyNow here. -# Change $(JDK_TOPDIR)/src/.../META-INF/services/yyyy into $(JDK_OUTPUTDIR)/classes/META-INF/services/yyyy -# The \n in the printf command is needed to make sed work on Solaris. -OUT_SERVICES_FILES := $(addprefix $(JDK_OUTPUTDIR)/classes/META-INF/services/, \ - $(shell $(PRINTF) "$(SRC_SERVICES_FILES)\n" | $(SED) -e 's|/[^ ]*/META-INF/services/||g')) -OUT_SERVICES_FILES_COLON := $(addsuffix :, $(OUT_SERVICES_FILES)) -# Exception handling for print services with no META-INF directory -SRC_SERVICES_FILES_PRINT = $(wildcard $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/classes/sun/print/services/*) -OUT_SERVICES_FILES_PRINT = $(addprefix $(JDK_OUTPUTDIR)/classes/META-INF/services/, \ - $(patsubst $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/classes/sun/print/services/%, %, \ - $(SRC_SERVICES_FILES_PRINT))) -OUT_SERVICES_FILES_PRINT_COLON = $(addsuffix :, $(OUT_SERVICES_FILES_PRINT)) -RULES_SERVICES_PRINT = $(join $(OUT_SERVICES_FILES_PRINT_COLON), $(SRC_SERVICES_FILES_PRINT)) - -# Now setup the dependency rules to generate a META-INF/services/... from the correct source. -META-INF_RULES_SERVICES := $(RULES_SERVICES_PRINT) $(join $(OUT_SERVICES_FILES_COLON), $(SRC_SERVICES_FILES)) -# Eval the newly created rules to incorporate them into the make tree. -define addto_meta-inf_services - $1 - echo $(LOG_INFO) Installing META-INF/services/$$(@F) - $(CAT) $$< | $(SED) -e "s/^#\[$(OPENJDK_TARGET_OS)\]//" > $$@ -endef -$(foreach i, $(META-INF_RULES_SERVICES), $(eval $(call addto_meta-inf_services, $i))) -# Here is the generic rule, whose receipt the above rules will trigger. - -COPY_EXTRA += $(OUT_SERVICES_FILES) -COPY_EXTRA += $(OUT_SERVICES_FILES_PRINT) - -################################################################################ - -JAVAX_SOUND_SRC := $(JDK_TOPDIR)/src/share/classes/com/sun/media/sound/services - -JAVAX_SOUND_SRC_FILES := \ - javax.sound.midi.spi.MidiDeviceProvider \ - javax.sound.midi.spi.MidiFileReader \ - javax.sound.midi.spi.MidiFileWriter \ - javax.sound.midi.spi.SoundbankReader \ - javax.sound.sampled.spi.AudioFileReader \ - javax.sound.sampled.spi.AudioFileWriter \ - javax.sound.sampled.spi.FormatConversionProvider \ - javax.sound.sampled.spi.MixerProvider - -COPY_EXTRA += $(addprefix $(JDK_OUTPUTDIR)/classes/META-INF/services/, $(JAVAX_SOUND_SRC_FILES)) - -JAVAX_SOUND_RULES := $(foreach F, $(JAVAX_SOUND_SRC_FILES), $(JDK_OUTPUTDIR)/classes/META-INF/services/$(notdir $F):$(JAVAX_SOUND_SRC)/$F) - -$(foreach R, $(JAVAX_SOUND_RULES), $(eval $(call addto_meta-inf_services, $R))) - -################################################################################ - -ifneq ($(OPENJDK_TARGET_OS), macosx) - OPENJDK_TARGET_OS_FLAVORMAP_PROPERTIES = $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_API_DIR)/classes/sun/datatransfer/resources/flavormap.properties -else - OPENJDK_TARGET_OS_FLAVORMAP_PROPERTIES = $(JDK_TOPDIR)/src/java.desktop/macosx/classes/sun/datatransfer/resources/flavormap.properties -endif - -$(JDK_OUTPUTDIR)/classes/sun/datatransfer/resources/flavormap.properties: $(OPENJDK_TARGET_OS_FLAVORMAP_PROPERTIES) - $(install-file) - -COPY_EXTRA += $(JDK_OUTPUTDIR)/classes/sun/datatransfer/resources/flavormap.properties - -################################################################################ - -CLEAN_FILES := $(wildcard \ - $(JDK_TOPDIR)/src/share/classes/com/sun/imageio/plugins/common/*.properties \ - $(JDK_TOPDIR)/src/share/classes/com/sun/java/util/jar/pack/*.properties \ - $(JDK_TOPDIR)/src/share/classes/com/sun/jndi/cosnaming/jndiprovider.properties \ - $(JDK_TOPDIR)/src/share/classes/com/sun/jndi/ldap/jndiprovider.properties \ - $(JDK_TOPDIR)/src/share/classes/com/sun/org/apache/xml/internal/security/resource/*.properties \ - $(JDK_TOPDIR)/src/share/classes/com/sun/rowset/*.properties \ - $(JDK_TOPDIR)/src/share/classes/com/sun/tools/script/shell/*.properties \ - $(JDK_TOPDIR)/src/share/classes/javax/sql/rowset/*.properties \ - $(JDK_TOPDIR)/src/share/classes/sun/rmi/registry/resources/*.properties \ - $(JDK_TOPDIR)/src/share/classes/sun/rmi/rmic/resources/*.properties \ - $(JDK_TOPDIR)/src/share/classes/sun/rmi/server/resources/*.properties \ - $(JDK_TOPDIR)/src/share/classes/sun/tools/javac/resources/*.properties \ - $(JDK_TOPDIR)/src/share/classes/sun/tools/jconsole/resources/*.properties \ - $(JDK_TOPDIR)/src/share/classes/sun/tools/serialver/resources/*.properties \ - ) - -# Copy zh_HK files from zh_TW - -$(JDK_OUTPUTDIR)/classes/%_zh_HK.properties: $(JDK_OUTPUTDIR)/classes/%_zh_TW.properties - $(install-file) - -COPY_EXTRA += $(patsubst $(JDK_TOPDIR)/src/share/classes/%, $(JDK_OUTPUTDIR)/classes/%, \ - $(subst _zh_TW,_zh_HK, $(filter %_zh_TW.properties, $(CLEAN_FILES)))) diff --git a/jdk/make/CreateJars.gmk b/jdk/make/CreateJars.gmk index 1e250456507..d65fb7ea737 100644 --- a/jdk/make/CreateJars.gmk +++ b/jdk/make/CreateJars.gmk @@ -524,7 +524,6 @@ $(eval $(call SetupArchive,BUILD_TOOLS_JAR, , \ EXCLUDES := $(TOOLS_JAR_EXCLUDES), \ EXTRA_FILES := \ $(JDK_OUTPUTDIR)/modules/jdk.jdi/META-INF/services/com.sun.jdi.connect.Connector \ - $(JDK_OUTPUTDIR)/classes/META-INF/services/com.sun.jdi.connect.Connector \ META-INF/services/com.sun.jdi.connect.spi.TransportService \ META-INF/services/com.sun.tools.attach.spi.AttachProvider \ META-INF/services/com.sun.tools.internal.ws.wscompile.Plugin \ diff --git a/jdk/make/CreateSecurityJars.gmk b/jdk/make/CreateSecurityJars.gmk index 1a3d3343c53..097ac813821 100644 --- a/jdk/make/CreateSecurityJars.gmk +++ b/jdk/make/CreateSecurityJars.gmk @@ -32,8 +32,6 @@ include JavaCompilation.gmk # The jars created in this file are required for the exploded jdk image to function and # cannot wait to be built in the images target. -SECURITY_CLASSES_SUBDIR := modules - ########################################################################################## # Create manifest for security jars # @@ -67,7 +65,7 @@ SUNPKCS11_JAR_DST := $(JDK_OUTPUTDIR)/lib/ext/sunpkcs11.jar SUNPKCS11_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/jce/unsigned/sunpkcs11.jar $(eval $(call SetupArchive,BUILD_SUNPKCS11_JAR, , \ - SRCS := $(JDK_OUTPUTDIR)/$(SECURITY_CLASSES_SUBDIR)/jdk.crypto.pkcs11, \ + SRCS := $(JDK_OUTPUTDIR)/modules/jdk.crypto.pkcs11, \ SUFFIXES := .class, \ INCLUDES := sun/security/pkcs11, \ JAR := $(SUNPKCS11_JAR_UNSIGNED), \ @@ -94,7 +92,7 @@ SUNEC_JAR_DST := $(JDK_OUTPUTDIR)/lib/ext/sunec.jar SUNEC_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/jce/unsigned/sunec.jar $(eval $(call SetupArchive,BUILD_SUNEC_JAR, , \ - SRCS := $(JDK_OUTPUTDIR)/$(SECURITY_CLASSES_SUBDIR)/jdk.crypto.ec, \ + SRCS := $(JDK_OUTPUTDIR)/modules/jdk.crypto.ec, \ SUFFIXES := .class, \ INCLUDES := sun/security/ec, \ JAR := $(SUNEC_JAR_UNSIGNED), \ @@ -122,7 +120,7 @@ SUNJCE_PROVIDER_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/jce/unsigned/sunjce_provider.ja ifneq ($(BUILD_CRYPTO), no) $(eval $(call SetupArchive,BUILD_SUNJCE_PROVIDER_JAR, , \ - SRCS := $(JDK_OUTPUTDIR)/$(SECURITY_CLASSES_SUBDIR)/java.base, \ + SRCS := $(JDK_OUTPUTDIR)/modules/java.base, \ SUFFIXES := .class, \ INCLUDES := com/sun/crypto/provider, \ JAR := $(SUNJCE_PROVIDER_JAR_UNSIGNED), \ @@ -153,7 +151,7 @@ JCE_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/jce/unsigned/jce.jar ifneq ($(BUILD_CRYPTO), no) $(eval $(call SetupArchive,BUILD_JCE_JAR, , \ - SRCS := $(JDK_OUTPUTDIR)/$(SECURITY_CLASSES_SUBDIR)/java.base, \ + SRCS := $(JDK_OUTPUTDIR)/modules/java.base, \ SUFFIXES := .class, \ INCLUDES := javax/crypto sun/security/internal, \ JAR := $(JCE_JAR_UNSIGNED), \ @@ -185,7 +183,7 @@ ifeq ($(OPENJDK_TARGET_OS), windows) SUNMSCAPI_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/jce/unsigned/sunmscapi.jar $(eval $(call SetupArchive,BUILD_SUNMSCAPI_JAR, , \ - SRCS := $(JDK_OUTPUTDIR)/$(SECURITY_CLASSES_SUBDIR)/jdk.crypto.mscapi, \ + SRCS := $(JDK_OUTPUTDIR)/modules/jdk.crypto.mscapi, \ SUFFIXES := .class, \ INCLUDES := sun/security/mscapi, \ JAR := $(SUNMSCAPI_JAR_UNSIGNED), \ @@ -218,7 +216,7 @@ ifeq ($(OPENJDK_TARGET_OS), solaris) UCRYPTO_JAR_SRC := $(JDK_TOPDIR)/make/closed/tools/crypto/ucrypto/ucrypto.jar $(eval $(call SetupArchive,BUILD_UCRYPTO_JAR, , \ - SRCS := $(JDK_OUTPUTDIR)/$(SECURITY_CLASSES_SUBDIR)/jdk.crypto.ucrypto, \ + SRCS := $(JDK_OUTPUTDIR)/modules/jdk.crypto.ucrypto, \ SUFFIXES := .class, \ INCLUDES := com/oracle/security/ucrypto, \ JAR := $(UCRYPTO_JAR_UNSIGNED), \ diff --git a/jdk/make/Tools.gmk b/jdk/make/Tools.gmk index a61ac62d15b..b68d19c3d34 100644 --- a/jdk/make/Tools.gmk +++ b/jdk/make/Tools.gmk @@ -32,10 +32,7 @@ include $(SPEC) include MakeBase.gmk include JavaCompilation.gmk include NativeCompilation.gmk -include SetupJava.gmk - -# Cache all finds needed for this file. -$(eval $(call FillCacheFind, $(JDK_TOPDIR)/make/src/classes)) +include SetupJavaCompilers.gmk # The exception handling of swing beaninfo which have the own tool directory ifeq (, $(BUILD_TOOLS_JDK)) @@ -137,7 +134,7 @@ TOOL_CHECKDEPS = $(JAVA_SMALL) -Xbootclasspath/p:$(INTERIM_LANGTOOLS_JAR) \ TOOL_GENMODULESXML = $(JAVA_SMALL) -Xbootclasspath/p:$(INTERIM_LANGTOOLS_JAR) \ -cp "$(JDK_OUTPUTDIR)/btclasses$(PATH_SEP)$(JDK_OUTPUTDIR)" \ - build.tools.module.GenerateModulesXml + build.tools.module.GenJdepsModulesXml ########################################################################################## diff --git a/jdk/make/copy/Copy-java.base.gmk b/jdk/make/copy/Copy-java.base.gmk index 36a2c9da66a..c624ff80874 100644 --- a/jdk/make/copy/Copy-java.base.gmk +++ b/jdk/make/copy/Copy-java.base.gmk @@ -32,17 +32,17 @@ $(eval $(call IncludeCustomExtension, jdk, copy/Copy-java.base.gmk)) # Copy exported header files to outputdir. # JAVA_BASE_HEADERS := \ - $(INCLUDEDIR)/jni.h \ - $(INCLUDEDIR)/jvmti.h \ - $(INCLUDEDIR)/jvmticmlr.h \ - $(INCLUDEDIR)/classfile_constants.h \ - $(OPENJDK_TARGET_OS_INCLUDE)/jni_md.h \ + $(INCLUDE_DST_DIR)/jni.h \ + $(INCLUDE_DST_DIR)/jvmti.h \ + $(INCLUDE_DST_DIR)/jvmticmlr.h \ + $(INCLUDE_DST_DIR)/classfile_constants.h \ + $(INCLUDE_DST_OS_DIR)/jni_md.h \ # -$(INCLUDEDIR)/%.h: $(JDK_TOPDIR)/src/java.base/share/native/include/%.h +$(INCLUDE_DST_DIR)/%.h: $(JDK_TOPDIR)/src/java.base/share/native/include/%.h $(call install-file) -$(OPENJDK_TARGET_OS_INCLUDE)/%.h: \ +$(INCLUDE_DST_OS_DIR)/%.h: \ $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_EXPORT_DIR)/native/include/%.h $(call install-file) @@ -50,17 +50,17 @@ $(OPENJDK_TARGET_OS_INCLUDE)/%.h: \ CALENDARS_SRC := $(JDK_TOPDIR)/src/java.base/share/conf -$(LIBDIR)/calendars.properties: $(CALENDARS_SRC)/calendars.properties +$(LIB_DST_DIR)/calendars.properties: $(CALENDARS_SRC)/calendars.properties $(call install-file) -BASE_CONF_FILES += $(LIBDIR)/calendars.properties +BASE_CONF_FILES += $(LIB_DST_DIR)/calendars.properties -$(LIBDIR)/hijrah-config-umalqura.properties: $(CALENDARS_SRC)/hijrah-config-umalqura.properties +$(LIB_DST_DIR)/hijrah-config-umalqura.properties: $(CALENDARS_SRC)/hijrah-config-umalqura.properties $(MKDIR) -p $(@D) $(RM) $@ $(CP) $< $@ -BASE_CONF_FILES += $(LIBDIR)/hijrah-config-umalqura.properties +BASE_CONF_FILES += $(LIB_DST_DIR)/hijrah-config-umalqura.properties ################################################################################ @@ -68,10 +68,10 @@ ifneq ($(findstring $(OPENJDK_TARGET_OS), windows aix),) TZMAPPINGS_SRC := $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/conf - $(LIBDIR)/tzmappings: $(TZMAPPINGS_SRC)/tzmappings + $(LIB_DST_DIR)/tzmappings: $(TZMAPPINGS_SRC)/tzmappings $(call install-file) - BASE_CONF_FILES += $(LIBDIR)/tzmappings + BASE_CONF_FILES += $(LIB_DST_DIR)/tzmappings endif diff --git a/jdk/make/copy/Copy-java.desktop.gmk b/jdk/make/copy/Copy-java.desktop.gmk index e724a862b28..2460ffe6a54 100644 --- a/jdk/make/copy/Copy-java.desktop.gmk +++ b/jdk/make/copy/Copy-java.desktop.gmk @@ -30,20 +30,20 @@ $(eval $(call IncludeCustomExtension, jdk, copy/Copy-java.desktop.gmk)) ################################################################################ JAVA_DESKTOP_HEADERS := \ - $(INCLUDEDIR)/jawt.h \ - $(OPENJDK_TARGET_OS_INCLUDE)/jawt_md.h \ + $(INCLUDE_DST_DIR)/jawt.h \ + $(INCLUDE_DST_OS_DIR)/jawt_md.h \ # -$(INCLUDEDIR)/%.h: $(JDK_TOPDIR)/src/java.desktop/share/native/include/%.h +$(INCLUDE_DST_DIR)/%.h: $(JDK_TOPDIR)/src/java.desktop/share/native/include/%.h $(call install-file) -$(OPENJDK_TARGET_OS_INCLUDE)/%.h: \ +$(INCLUDE_DST_OS_DIR)/%.h: \ $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_EXPORT_DIR)/native/include/%.h $(call install-file) ################################################################################ -ICCPROFILE_DEST_DIR := $(LIBDIR)/cmm +ICCPROFILE_DEST_DIR := $(LIB_DST_DIR)/cmm ifdef OPENJDK ICCPROFILE_SRC_DIR := $(JDK_TOPDIR)/src/java.desktop/share/conf/cmm/lcms @@ -102,20 +102,20 @@ DESKTOP_CONF_FILES += $(JDK_OUTPUTDIR)/lib/sound.properties ################################################################################ # -# Copy property files from sun/print to LIBDIR +# Copy property files from sun/print to LIB_DST_DIR # PSFONTPROPFILE_SRC_DIR := $(JDK_TOPDIR)/src/java.desktop/share/conf PSFONTPROPFILE_SRCS := $(wildcard $(PSFONTPROPFILE_SRC_DIR)/psfont*.properties*) -PSFONTPROPFILE_TARGET_FILES := $(subst $(PSFONTPROPFILE_SRC_DIR),$(LIBDIR),$(PSFONTPROPFILE_SRCS)) +PSFONTPROPFILE_TARGET_FILES := $(subst $(PSFONTPROPFILE_SRC_DIR),$(LIB_DST_DIR),$(PSFONTPROPFILE_SRCS)) -$(LIBDIR)/%: $(PSFONTPROPFILE_SRC_DIR)/% +$(LIB_DST_DIR)/%: $(PSFONTPROPFILE_SRC_DIR)/% $(call install-file) DESKTOP_CONF_FILES += $(PSFONTPROPFILE_TARGET_FILES) ################################################################################ # -# Copy cursor.properties and cursors gif files to LIBDIR +# Copy cursor.properties and cursors gif files to LIB_DST_DIR # ifneq ($(OPENJDK_TARGET_OS), macosx) OPENJDK_TARGET_OS_LIB_SRC := $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_API_DIR)/conf @@ -123,7 +123,7 @@ else OPENJDK_TARGET_OS_LIB_SRC := $(JDK_TOPDIR)/src/java.desktop/macosx/conf endif -CURSORS_DEST_DIR := $(LIBDIR)/images/cursors +CURSORS_DEST_DIR := $(LIB_DST_DIR)/images/cursors CURSORS_OPENJDK_TARGET_OS_LIB_SRC := $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_API_DIR)/conf/images/cursors $(CURSORS_DEST_DIR)/cursors.properties: $(CURSORS_OPENJDK_TARGET_OS_LIB_SRC)/cursors.properties diff --git a/jdk/make/copy/Copy-java.logging.gmk b/jdk/make/copy/Copy-java.logging.gmk index f2644df1a17..da77f247276 100644 --- a/jdk/make/copy/Copy-java.logging.gmk +++ b/jdk/make/copy/Copy-java.logging.gmk @@ -29,10 +29,10 @@ include CopyCommon.gmk LOGGING_LIB_SRC := $(JDK_TOPDIR)/src/java.logging/share/conf -$(LIBDIR)/logging.properties: $(LOGGING_LIB_SRC)/logging.properties +$(LIB_DST_DIR)/logging.properties: $(LOGGING_LIB_SRC)/logging.properties $(call install-file) -LOGGING_CONF_FILES := $(LIBDIR)/logging.properties +LOGGING_CONF_FILES := $(LIB_DST_DIR)/logging.properties ################################################################################ diff --git a/jdk/make/copy/Copy-java.management.gmk b/jdk/make/copy/Copy-java.management.gmk index 55657a963ba..2352c909cad 100644 --- a/jdk/make/copy/Copy-java.management.gmk +++ b/jdk/make/copy/Copy-java.management.gmk @@ -27,7 +27,7 @@ include CopyCommon.gmk ################################################################################ -MGMT_LIBDIR := $(LIBDIR)/management +MGMT_LIBDIR := $(LIB_DST_DIR)/management MGMT_LIB_SRC := $(JDK_TOPDIR)/src/java.management/share/conf MGMT_SRC_FILES := $(wildcard $(MGMT_LIB_SRC)/*) MGMT_TARGET_FILES := $(subst $(MGMT_LIB_SRC),$(MGMT_LIBDIR),$(MGMT_SRC_FILES)) diff --git a/jdk/make/copy/Copy-jdk.hprof.agent.gmk b/jdk/make/copy/Copy-jdk.hprof.agent.gmk index ccec153a5b7..069e915514f 100644 --- a/jdk/make/copy/Copy-jdk.hprof.agent.gmk +++ b/jdk/make/copy/Copy-jdk.hprof.agent.gmk @@ -27,12 +27,12 @@ include CopyCommon.gmk ################################################################################ -HPROF_SRC := $(JDK_TOPDIR)/src/demo/share/jvmti/hprof/jvm.hprof.txt +HPROF_SRC := $(JDK_TOPDIR)/src/jdk.hprof.agent/share/native/libhprof/jvm.hprof.txt -$(LIBDIR)/jvm.hprof.txt: $(HPROF_SRC) +$(LIB_DST_DIR)/jvm.hprof.txt: $(HPROF_SRC) $(call install-file) -HPROF_CONF_FILES := $(LIBDIR)/jvm.hprof.txt +HPROF_CONF_FILES := $(LIB_DST_DIR)/jvm.hprof.txt ################################################################################ diff --git a/jdk/make/copy/Copy-jdk.jdwp.agent.gmk b/jdk/make/copy/Copy-jdk.jdwp.agent.gmk index c02ae7bd9be..dd7ccf01c44 100644 --- a/jdk/make/copy/Copy-jdk.jdwp.agent.gmk +++ b/jdk/make/copy/Copy-jdk.jdwp.agent.gmk @@ -28,9 +28,9 @@ include CopyCommon.gmk ################################################################################ -JDK_DEBUG_AGENT_HEADERS := $(INCLUDEDIR)/jdwpTransport.h +JDK_DEBUG_AGENT_HEADERS := $(INCLUDE_DST_DIR)/jdwpTransport.h -$(INCLUDEDIR)/%.h: $(JDK_TOPDIR)/src/jdk.jdwp.agent/share/native/include/%.h +$(INCLUDE_DST_DIR)/%.h: $(JDK_TOPDIR)/src/jdk.jdwp.agent/share/native/include/%.h $(call install-file) ################################################################################ diff --git a/jdk/make/copy/CopyCommon.gmk b/jdk/make/copy/CopyCommon.gmk index 3baefab75c8..f9c951287fc 100644 --- a/jdk/make/copy/CopyCommon.gmk +++ b/jdk/make/copy/CopyCommon.gmk @@ -28,13 +28,13 @@ default: all include $(SPEC) include MakeBase.gmk -INCLUDEDIR = $(JDK_OUTPUTDIR)/include -LIBDIR := $(JDK_OUTPUTDIR)/lib +INCLUDE_DST_DIR := $(JDK_OUTPUTDIR)/include +LIB_DST_DIR := $(JDK_OUTPUTDIR)/lib -OPENJDK_TARGET_OS_INCLUDE = $(INCLUDEDIR)/$(OPENJDK_TARGET_OS) +INCLUDE_DST_OS_DIR := $(INCLUDE_DST_DIR)/$(OPENJDK_TARGET_OS) ifeq ($(OPENJDK_TARGET_OS), windows) - OPENJDK_TARGET_OS_INCLUDE = $(INCLUDEDIR)/win32 + INCLUDE_DST_OS_DIR := $(INCLUDE_DST_DIR)/win32 else ifeq ($(OPENJDK_TARGET_OS), macosx) - OPENJDK_TARGET_OS_INCLUDE = $(INCLUDEDIR)/darwin + INCLUDE_DST_OS_DIR := $(INCLUDE_DST_DIR)/darwin endif diff --git a/jdk/make/bundle/JDK-Info.plist b/jdk/make/data/bundle/JDK-Info.plist similarity index 100% rename from jdk/make/bundle/JDK-Info.plist rename to jdk/make/data/bundle/JDK-Info.plist diff --git a/jdk/make/bundle/JRE-Info.plist b/jdk/make/data/bundle/JRE-Info.plist similarity index 100% rename from jdk/make/bundle/JRE-Info.plist rename to jdk/make/data/bundle/JRE-Info.plist diff --git a/jdk/make/data/fontconfig/aix.fontconfig.properties b/jdk/make/data/fontconfig/aix.fontconfig.properties index 29e7c7d9510..f203f759894 100644 --- a/jdk/make/data/fontconfig/aix.fontconfig.properties +++ b/jdk/make/data/fontconfig/aix.fontconfig.properties @@ -24,9 +24,14 @@ # questions. # -# Minimal version for AIX using the standard Latin Type1 Fonts from the -# package X11.fnt.iso_T1. These fonts are installed by default into -# "/usr/lpp/X11/lib/X11/fonts/Type1" and sym-linked to "/usr/lib/X11/fonts/Type1" +# +# Portions Copyright (c) 2014 IBM Corporation +# + +# This file references the standard Latin Type1 fonts from the AIX package +# X11.fnt.iso_T1 and the Unicode TrueType fonts from X11.fnt.ucs.ttf. They +# are located by default under "/usr/lpp/X11/lib/X11/fonts/{Type1,TrueType}" +# and sym-linked to "/usr/lib/X11/fonts/". # Version @@ -34,44 +39,381 @@ version=1 # Component Font Mappings -dialog.plain.latin-1=-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso10646-1 -dialog.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso10646-1 -dialog.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso10646-1 -dialog.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso10646-1 +allfonts.iso10646-extB=-monotype-sansmonowtextb-medium-r-normal--*-%d-75-75-m-*-unicode-2 -dialoginput.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso10646-1 -dialoginput.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso10646-1 -dialoginput.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso10646-1 -dialoginput.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso10646-1 -sansserif.plain.latin-1=-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso10646-1 -sansserif.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso10646-1 -sansserif.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso10646-1 -sansserif.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso10646-1 +dialog.plain.latin-1=-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso8859-1 +dialog.plain.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +dialog.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +dialog.plain.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialog.plain.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialog.plain.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialog.plain.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialog.plain.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialog.plain.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialog.plain.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialog.plain.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialog.plain.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 -serif.plain.latin-1=-*-times new roman-medium-r-normal--*-%d-100-100-p-*-iso10646-1 -serif.bold.latin-1=-*-times new roman-bold-r-normal--*-%d-100-100-p-*-iso10646-1 -serif.italic.latin-1=-*-times new roman-medium-i-normal--*-%d-100-100-p-*-iso10646-1 -serif.bolditalic.latin-1=-*-times new roman-bold-i-normal--*-%d-100-100-p-*-iso10646-1 +dialog.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso8859-1 +dialog.bold.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +dialog.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +dialog.bold.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialog.bold.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialog.bold.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialog.bold.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialog.bold.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialog.bold.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialog.bold.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialog.bold.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialog.bold.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 -monospaced.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso10646-1 -monospaced.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso10646-1 -monospaced.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso10646-1 -monospaced.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso10646-1 +dialog.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso8859-1 +dialog.italic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +dialog.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-p-*-ucs2.i18n-0 +dialog.italic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialog.italic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialog.italic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialog.italic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialog.italic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialog.italic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialog.italic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialog.italic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialog.italic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +dialog.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso8859-1 +dialog.bolditalic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +dialog.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +dialog.bolditalic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialog.bolditalic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialog.bolditalic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialog.bolditalic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialog.bolditalic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialog.bolditalic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialog.bolditalic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialog.bolditalic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialog.bolditalic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +dialoginput.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso8859-1 +dialoginput.plain.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +dialoginput.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0 +dialoginput.plain.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialoginput.plain.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialoginput.plain.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialoginput.plain.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialoginput.plain.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialoginput.plain.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialoginput.plain.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialoginput.plain.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialoginput.plain.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +dialoginput.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso8859-1 +dialoginput.bold.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +dialoginput.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-m-*-ucs2.i18n-0 +dialoginput.bold.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialoginput.bold.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialoginput.bold.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialoginput.bold.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialoginput.bold.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialoginput.bold.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialoginput.bold.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialoginput.bold.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialoginput.bold.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +dialoginput.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso8859-1 +dialoginput.italic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +dialoginput.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-m-*-ucs2.i18n-0 +dialoginput.italic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialoginput.italic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialoginput.italic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialoginput.italic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialoginput.italic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialoginput.italic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialoginput.italic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialoginput.italic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialoginput.italic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +dialoginput.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso8859-1 +dialoginput.bolditalic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +dialoginput.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0 +dialoginput.bolditalic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialoginput.bolditalic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialoginput.bolditalic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialoginput.bolditalic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialoginput.bolditalic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialoginput.bolditalic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialoginput.bolditalic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialoginput.bolditalic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialoginput.bolditalic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +sansserif.plain.latin-1=-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso8859-1 +sansserif.plain.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +sansserif.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +sansserif.plain.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +sansserif.plain.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +sansserif.plain.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +sansserif.plain.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +sansserif.plain.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +sansserif.plain.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +sansserif.plain.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +sansserif.plain.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +sansserif.plain.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +sansserif.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso8859-1 +sansserif.bold.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +sansserif.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +sansserif.bold.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +sansserif.bold.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +sansserif.bold.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +sansserif.bold.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +sansserif.bold.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +sansserif.bold.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +sansserif.bold.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +sansserif.bold.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +sansserif.bold.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +sansserif.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso8859-1 +sansserif.italic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +sansserif.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-p-*-ucs2.i18n-0 +sansserif.italic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +sansserif.italic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +sansserif.italic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +sansserif.italic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +sansserif.italic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +sansserif.italic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +sansserif.italic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +sansserif.italic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +sansserif.italic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +sansserif.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso8859-1 +sansserif.bolditalic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +sansserif.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +sansserif.bolditalic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +sansserif.bolditalic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +sansserif.bolditalic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +sansserif.bolditalic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +sansserif.bolditalic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +sansserif.bolditalic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +sansserif.bolditalic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +sansserif.bolditalic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +sansserif.bolditalic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +serif.plain.latin-1=-*-times new roman-medium-r-normal--*-%d-100-100-p-*-iso8859-1 +serif.plain.thai=-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +serif.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +serif.plain.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +serif.plain.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +serif.plain.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +serif.plain.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +serif.plain.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +serif.plain.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +serif.plain.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +serif.plain.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +serif.plain.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +serif.bold.latin-1=-*-times new roman-bold-r-normal--*-%d-100-100-p-*-iso8859-1 +serif.bold.thai=-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +serif.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +serif.bold.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +serif.bold.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +serif.bold.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +serif.bold.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +serif.bold.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +serif.bold.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +serif.bold.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +serif.bold.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +serif.bold.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + + +serif.italic.latin-1=-*-times new roman-medium-i-normal--*-%d-100-100-p-*-iso8859-1 +serif.italic.thai=-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +serif.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-p-*-ucs2.i18n-0 +serif.italic.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +serif.italic.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +serif.italic.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +serif.italic.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +serif.italic.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +serif.italic.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +serif.italic.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +serif.italic.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +serif.italic.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +serif.bolditalic.latin-1=-*-times new roman-bold-i-normal--*-%d-100-100-p-*-iso8859-1 +serif.bolditalic.thai=-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +serif.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +serif.bolditalic.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +serif.bolditalic.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +serif.bolditalic.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +serif.bolditalic.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +serif.bolditalic.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +serif.bolditalic.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +serif.bolditalic.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +serif.bolditalic.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +serif.bolditalic.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +monospaced.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso8859-1 +monospaced.plain.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +monospaced.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0 +monospaced.plain.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +monospaced.plain.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +monospaced.plain.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +monospaced.plain.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +monospaced.plain.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +monospaced.plain.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +monospaced.plain.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +monospaced.plain.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +monospaced.plain.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +monospaced.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso8859-1 +monospaced.bold.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +monospaced.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-m-*-ucs2.i18n-0 +monospaced.bold.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +monospaced.bold.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +monospaced.bold.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +monospaced.bold.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +monospaced.bold.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +monospaced.bold.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +monospaced.bold.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +monospaced.bold.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +monospaced.bold.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +monospaced.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso8859-1 +monospaced.italic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +monospaced.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-m-*-ucs2.i18n-0 +monospaced.italic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +monospaced.italic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +monospaced.italic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +monospaced.italic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +monospaced.italic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +monospaced.italic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +monospaced.italic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +monospaced.italic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +monospaced.italic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +monospaced.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso8859-1 +monospaced.bolditalic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +monospaced.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0 +monospaced.bolditalic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +monospaced.bolditalic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +monospaced.bolditalic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +monospaced.bolditalic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +monospaced.bolditalic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +monospaced.bolditalic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +monospaced.bolditalic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +monospaced.bolditalic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +monospaced.bolditalic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 # Search Sequences sequence.allfonts=latin-1 +sequence.allfonts.UTF-8=latin-1,japanese-iso10646 +# Uk_UA +sequence.allfonts.x-IBM1124=latin-1,ukranian-ibm1124 +# Japanese +sequence.allfonts.x-IBM943C=latin-1,japanese-x0201,japanese-x0208,japanese-udc +sequence.allfonts.x-IBM29626C=latin-1,japanese-x0201,japanese-x0208,japanese-udc +sequence.allfonts.UTF-8.ja=japanese-iso10646,latin-1,iso10646-extB +# Chinese +sequence.allfonts.x-EUC_CN=latin-1,chinese +sequence.allfonts.GB18030=latin-1,chinese-iso10646,iso10646-extB +sequence.allfonts.UTF-8.zh.CN=latin-1,chinese-iso10646,iso10646-extB +# Taiwanese +sequence.allfonts.x-IBM964=latin-1,taiwanese-iso10646 +sequence.allfonts.Big5=latin-1,taiwanese-iso10646 +sequence.allfonts.UTF-8.zh.TW=latin-1,taiwanese-iso10646 +# Korean +sequence.allfonts.x-IBM970=latin-1,korean +sequence.allfonts.UTF-8.ko=latin-1,korean-iso10646 +# Thai +sequence.allfonts.TIS-620=latin-1,thai +sequence.allfonts.UTF-8.th=latin-1,thai +# fallback +sequence.fallback=thai,chinese-iso10646,taiwanese-iso10646,japanese-iso10646,korean-iso10646,iso10646-extB + +# Exclusion Ranges +exclusion.japanese-iso10646=0000-00ff + +# Font File Names +filename.-*-courier-medium-r-normal--*-%d-100-100-m-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/cour.pfa +filename.-*-courier-bold-r-normal--*-%d-100-100-m-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/courb.pfa +filename.-*-courier-medium-o-normal--*-%d-100-100-m-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/couri.pfa +filename.-*-courier-bold-o-normal--*-%d-100-100-m-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/courbi.pfa +filename.-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/helv.pfa +filename.-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvb.pfa +filename.-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvi.pfa +filename.-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvbi.pfa +filename.-*-times_new_roman-medium-r-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnr.pfa +filename.-*-times_new_roman-bold-r-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnrb.pfa +filename.-*-times_new_roman-medium-i-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnri.pfa +filename.-*-times_new_roman-bold-i-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnrbi.pfa + + +filename.-monotype-sansmonowtextb-medium-r-normal--*-%d-75-75-m-*-unicode-2=/usr/lpp/X11/lib/X11/fonts/TrueType/MTSanXBA.ttf + +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_k.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_k.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_t.ttf + +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdk.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdk.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansds.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansds.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdt.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_k.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_k.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_s.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_s.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_t.ttf + +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-iso8859-15=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-iso8859-15=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf + +filename.-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0=/usr/lpp/X11/lib/X11/fonts/TrueType/courth.ttf +filename.-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0=/usr/lpp/X11/lib/X11/fonts/TrueType/helvth.ttf +filename.-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0=/usr/lpp/X11/lib/X11/fonts/TrueType/timeth.ttf + +filename.-*-*-medium-r-normal--*-%d-*-*-p-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-bold-r-normal--*-%d-*-*-p-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-medium-i-normal--*-%d-*-*-p-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-bold-i-normal--*-%d-*-*-p-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-medium-r-normal--*-%d-*-*-m-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-*-*-bold-r-normal--*-%d-*-*-m-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-*-*-medium-i-normal--*-%d-*-*-m-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-*-*-bold-i-normal--*-%d-*-*-m-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf + +filename.-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-bold-r-normal--*-%d-75-75-p-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-medium-i-normal--*-%d-75-75-p-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-*-*-bold-r-normal--*-%d-75-75-m-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-*-*-medium-i-normal--*-%d-75-75-m-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf + +# AWT font path +awtfontpath.japanese-x0201=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.japanese-x0208=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.japanese-udc=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.japanese-iso10646=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.korean=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.korean-iso10646=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.chinese=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.chinese-iso10646=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.taiwanese-iso10646=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.thai=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.iso10646-extB=/usr/lpp/X11/lib/X11/fonts/TrueType -filename.-*-courier-medium-r-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/cour.pfa -filename.-*-courier-bold-r-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/courb.pfa -filename.-*-courier-medium-o-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/couri.pfa -filename.-*-courier-bold-o-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/courbi.pfa -filename.-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helv.pfa -filename.-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvb.pfa -filename.-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvi.pfa -filename.-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvbi.pfa -filename.-*-times_new_roman-medium-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnr.pfa -filename.-*-times_new_roman-bold-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnrb.pfa -filename.-*-times_new_roman-medium-i-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnri.pfa -filename.-*-times_new_roman-bold-i-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnrbi.pfa diff --git a/jdk/make/gendata/Gendata-java.base.gmk b/jdk/make/gendata/Gendata-java.base.gmk index 4c7f7a55b2c..a7135abe563 100644 --- a/jdk/make/gendata/Gendata-java.base.gmk +++ b/jdk/make/gendata/Gendata-java.base.gmk @@ -64,15 +64,15 @@ GENDATA += $(GENDATA_CURDATA) GENDATA_JAVA_SECURITY_SRC := $(JDK_TOPDIR)/src/java.base/share/conf/security/java.security GENDATA_JAVA_SECURITY := $(JDK_OUTPUTDIR)/lib/security/java.security - + # RESTRICTED_PKGS_SRC is optionally set in custom extension for this makefile - + $(GENDATA_JAVA_SECURITY): $(BUILD_TOOLS) $(GENDATA_JAVA_SECURITY_SRC) $(RESTRICTED_PKGS_SRC) $(ECHO) "Generating java.security" $(MKDIR) -p $(@D) $(TOOL_MAKEJAVASECURITY) $(GENDATA_JAVA_SECURITY_SRC) $@ $(OPENJDK_TARGET_OS) \ $(RESTRICTED_PKGS_SRC) || exit 1 - + GENDATA += $(GENDATA_JAVA_SECURITY) ########################################################################################## diff --git a/jdk/make/gendata/Gendata-jdk.dev.gmk b/jdk/make/gendata/Gendata-jdk.dev.gmk new file mode 100644 index 00000000000..3c24cf4b703 --- /dev/null +++ b/jdk/make/gendata/Gendata-jdk.dev.gmk @@ -0,0 +1,46 @@ +# +# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +include GendataCommon.gmk + +$(eval $(call IncludeCustomExtension, jdk, gendata/Gendata-jdk.dev.gmk)) + +GENDATA := $(JDK_OUTPUTDIR)/modules/jdk.dev/com/sun/tools/jdeps/resources/jdeps-modules.xml +METADATA_FILES += $(TOPDIR)/modules.xml + +# +# Generate modules.xml for jdeps to use +# It augments $(TOPDIR)/modules.xml to include module membership +# +$(GENDATA): $(BUILD_TOOLS_JDK) $(METADATA_FILES) + $(MKDIR) -p $(@D) + $(RM) $@ + $(TOOL_GENMODULESXML) -o $@ -mp $(JDK_OUTPUTDIR)/modules $(METADATA_FILES) + +jdk.dev: $(GENDATA) + +all: $(GENDATA) + +.PHONY: all jdk.dev diff --git a/jdk/make/gendata/GendataCommon.gmk b/jdk/make/gendata/GendataCommon.gmk index c199a377378..e5e0336b325 100644 --- a/jdk/make/gendata/GendataCommon.gmk +++ b/jdk/make/gendata/GendataCommon.gmk @@ -28,9 +28,7 @@ default: all include $(SPEC) include MakeBase.gmk include JavaCompilation.gmk - -# Setup the java compilers for the JDK build. -include SetupJava.gmk +include SetupJavaCompilers.gmk # We need the tools. include Tools.gmk diff --git a/jdk/make/gensrc/GensrcCommon.gmk b/jdk/make/gensrc/GensrcCommon.gmk index 3c271c81d77..09819e19d57 100644 --- a/jdk/make/gensrc/GensrcCommon.gmk +++ b/jdk/make/gensrc/GensrcCommon.gmk @@ -30,9 +30,7 @@ include MakeBase.gmk include JavaCompilation.gmk include NativeCompilation.gmk include TextFileProcessing.gmk - -# Setup the java compilers for the JDK build. -include SetupJava.gmk +include SetupJavaCompilers.gmk # We need the tools. include Tools.gmk diff --git a/jdk/make/gensrc/GensrcLocaleDataMetaInfo.gmk b/jdk/make/gensrc/GensrcLocaleDataMetaInfo.gmk index 12b80d7fcbe..f4a3575218e 100644 --- a/jdk/make/gensrc/GensrcLocaleDataMetaInfo.gmk +++ b/jdk/make/gensrc/GensrcLocaleDataMetaInfo.gmk @@ -28,7 +28,8 @@ # into LocaleDataMetaInfo.java # First go look for all locale files -LOCALE_FILES := $(shell $(FIND) $(JDK_TOPDIR)/src/*/share/classes \ +LOCALE_FILES := $(shell $(FIND) $(JDK_TOPDIR)/src/java.base/share/classes \ + $(JDK_TOPDIR)/src/jdk.localedata/share/classes \ -name "FormatData_*.java" -o -name "FormatData_*.properties" -o \ -name "CollationData_*.java" -o -name "CollationData_*.properties" -o \ -name "TimeZoneNames_*.java" -o -name "TimeZoneNames_*.properties" -o \ diff --git a/jdk/make/gensrc/GensrcProperties.gmk b/jdk/make/gensrc/GensrcProperties.gmk index c387d52ffe2..a33015b150c 100644 --- a/jdk/make/gensrc/GensrcProperties.gmk +++ b/jdk/make/gensrc/GensrcProperties.gmk @@ -23,9 +23,6 @@ # questions. # -# Prepare the find cache. -$(eval $(call FillCacheFind, $(wildcard $(JDK_TOPDIR)/src/*/*/classes))) - # All .properties files to be compiled are appended to this variable. ALL_COMPILED_PROPSOURCES := # All generated .java files from compilation are appended to this variable. @@ -76,7 +73,6 @@ COMPILE_PROP_SRC_FILES := \ $(JDK_TOPDIR)/src/java.management/share/classes/sun/management/resources \ $(JDK_TOPDIR)/src/java.desktop/share/classes/sun/print/resources \ $(JDK_TOPDIR)/src/jdk.dev/share/classes/sun/tools/jar/resources \ - $(JDK_TOPDIR)/src/jdk.dev/share/classes/jdk/jigsaw/tools/jlink/resources \ $(JDK_TOPDIR)/src/java.logging/share/classes/sun/util/logging/resources)) \ # diff --git a/jdk/make/gensrc/GensrcProviders.gmk b/jdk/make/gensrc/GensrcProviders.gmk index 985f032169e..dca14083054 100644 --- a/jdk/make/gensrc/GensrcProviders.gmk +++ b/jdk/make/gensrc/GensrcProviders.gmk @@ -32,15 +32,6 @@ endef ################################################################################ -# Filter com.sun.tools.attach.spi.AttachProvider -$(JDK_OUTPUTDIR)/gensrc/jdk.attach/META-INF/services/com.sun.tools.attach.spi.AttachProvider: \ - $(JDK_TOPDIR)/src/jdk.attach/share/classes/META-INF/services/com.sun.tools.attach.spi.AttachProvider - $(process-provider) - -GENSRC_JDK_ATTACH += $(JDK_OUTPUTDIR)/gensrc/jdk.attach/META-INF/services/com.sun.tools.attach.spi.AttachProvider - -################################################################################ - # Filter com.sun.jdi.connect.Connector $(JDK_OUTPUTDIR)/gensrc/jdk.jdi/META-INF/services/com.sun.jdi.connect.Connector: \ $(JDK_TOPDIR)/src/jdk.jdi/share/classes/META-INF/services/com.sun.jdi.connect.Connector diff --git a/jdk/make/gensrc/GensrcSwing.gmk b/jdk/make/gensrc/GensrcSwing.gmk index 12e2445bb32..c7571269c98 100644 --- a/jdk/make/gensrc/GensrcSwing.gmk +++ b/jdk/make/gensrc/GensrcSwing.gmk @@ -78,11 +78,8 @@ $(JDK_OUTPUTDIR)/gensrc_no_srczip/_the.generated_beaninfo: $(BEANS_SRC) \ $(MKDIR) -p $(JDK_OUTPUTDIR)/gensrc_no_srczip/java.desktop/javax/swing $(JAVA) -Djava.awt.headless=true $(NEW_JAVADOC) \ -sourcepath "$(subst $(SPACE),$(PATH_SEP),\ - $(if $(SHUFFLED),$(wildcard $(JDK_TOPDIR)/src/*/*/classes) \ - $(JDK_OUTPUTDIR)/gensrc/java.base, \ - $(JDK_TOPDIR)/src/share/classes \ - $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/classes \ - $(JDK_OUTPUTDIR)/gensrc))" \ + $(wildcard $(JDK_TOPDIR)/src/*/*/classes) \ + $(JDK_OUTPUTDIR)/gensrc/java.base)" \ -doclet build.tools.swingbeaninfo.GenDocletBeanInfo \ -x $(SWINGBEAN_DEBUG_FLAG) -d $(JDK_OUTPUTDIR)/gensrc_no_srczip/java.desktop/javax/swing \ -t $(DOCLET_DATA_DIR)/SwingBeanInfo.template -docletpath $(JDK_OUTPUTDIR)/btclasses \ diff --git a/jdk/make/lib/Awt2dLibraries.gmk b/jdk/make/lib/Awt2dLibraries.gmk index 694db74f196..e5161a35552 100644 --- a/jdk/make/lib/Awt2dLibraries.gmk +++ b/jdk/make/lib/Awt2dLibraries.gmk @@ -23,12 +23,9 @@ # questions. # -# Hook to include the corresponding custom file, if present. -$(eval $(call IncludeCustomExtension, jdk, lib/Awt2dLibraries.gmk)) - WIN_AWT_LIB := $(JDK_OUTPUTDIR)/objs/libawt/awt.lib -########################################################################################## +################################################################################ BUILD_LIBMLIB_SRC := $(JDK_TOPDIR)/src/java.desktop/share/native/libmlib_image \ $(JDK_TOPDIR)/src/java.desktop/share/native/common/sun/awt/medialib @@ -76,7 +73,7 @@ $(BUILD_LIBMLIB_IMAGE): $(BUILD_LIBJAVA) DESKTOP_LIBRARIES += $(BUILD_LIBMLIB_IMAGE) -########################################################################################## +################################################################################ ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc) @@ -144,7 +141,7 @@ ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc) endif -########################################################################################## +################################################################################ LIBAWT_DIRS := $(JDK_TOPDIR)/src/java.desktop/share/native/libawt \ $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_API_DIR)/native/libawt \ @@ -152,13 +149,17 @@ LIBAWT_DIRS := $(JDK_TOPDIR)/src/java.desktop/share/native/libawt \ $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_API_DIR)/native/common/sun/awt \ # +ifeq ($(OPENJDK_TARGET_OS), aix) + LIBAWT_DIRS += $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS)/native/libawt +endif + ifeq ($(OPENJDK_TARGET_OS), windows) LIBAWT_DIRS += $(JDK_TOPDIR)/src/java.desktop/share/native/common/sun/awt/utility else LIBAWT_EXFILES := sun/java2d/ShaderList.c endif -ifneq ($(filter $(OPENJDK_TARGET_OS), solaris linux macosx), ) +ifneq ($(filter $(OPENJDK_TARGET_OS), solaris linux macosx aix), ) LIBAWT_EXFILES += awt_Font.c CUPSfuncs.c fontpath.c X11Color.c endif @@ -168,14 +169,11 @@ endif LIBAWT_CFLAGS += -I$(JDK_OUTPUTDIR)/gensrc_headers/java.desktop \ $(addprefix -I, $(shell find $(LIBAWT_DIRS) -type d)) \ - -I$(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_API_DIR)/native/common/sun/awt \ $(LIBJAVA_HEADER_FLAGS) \ $(addprefix -I, $(BUILD_LIBMLIB_IMAGE_SRC)) \ # -LIBAWT_CFLAGS += -D__MEDIALIB_OLD_NAMES -D__USE_J2D_NAMES \ - $(X_CFLAGS) \ - $(foreach dir, $(LIBAWT_DIRS), -I$(dir)) +LIBAWT_CFLAGS += -D__MEDIALIB_OLD_NAMES -D__USE_J2D_NAMES $(X_CFLAGS) ifeq ($(OPENJDK_TARGET_OS), macosx) endif @@ -296,7 +294,7 @@ endif DESKTOP_LIBRARIES += $(BUILD_LIBAWT) -########################################################################################## +################################################################################ ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),) ifndef BUILD_HEADLESS_ONLY @@ -388,7 +386,7 @@ ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),) endif endif -########################################################################################## +################################################################################ LIBLCMS_SRC := $(JDK_TOPDIR)/src/java.desktop/share/native/liblcms LIBLCMS_CPPFLAGS += -I$(JDK_OUTPUTDIR)/gensrc_headers/java.desktop \ @@ -441,7 +439,7 @@ DESKTOP_LIBRARIES += $(BUILD_LIBLCMS) $(BUILD_LIBLCMS): $(BUILD_LIBAWT) -########################################################################################## +################################################################################ ifdef OPENJDK BUILD_LIBJAVAJPEG_MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjpeg/mapfile-vers @@ -515,7 +513,7 @@ $(BUILD_LIBJAVAJPEG): $(BUILD_LIBJAVA) DESKTOP_LIBRARIES += $(BUILD_LIBJAVAJPEG) -########################################################################################## +################################################################################ LIBFONTMANAGER_SRC := $(JDK_TOPDIR)/src/java.desktop/share/native/libfontmanager \ $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_API_DIR)/native/libfontmanager @@ -607,54 +605,7 @@ endif DESKTOP_LIBRARIES += $(BUILD_LIBFONTMANAGER) -########################################################################################## - -ifndef OPENJDK - - LIBT2K_SRC := $(JDK_TOPDIR)/src/closed/java.desktop/share/native/libt2k - LIBT2K_CFLAGS := $(addprefix -I, $(LIBT2K_SRC)) \ - -I$(JDK_TOPDIR)/src/closed/java.desktop/share/native/libt2k/t2k \ - -I$(JDK_TOPDIR)/src/java.desktop/share/native/libfontmanager \ - -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/sun/java2d \ - -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/sun/java2d/loops \ - -I$(JDK_TOPDIR)/src/java.desktop/share/native/common/sun/font \ - -I$(JDK_TOPDIR)/src/java.base/share/native/libjava \ - -I$(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_API_DIR)/native/libjava \ - -I$(JDK_OUTPUTDIR)/gensrc_headers/java.desktop \ - # - - $(eval $(call SetupNativeCompilation,BUILD_LIBT2K, \ - LIBRARY := t2k, \ - OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ - SRC := $(LIBT2K_SRC), \ - EXCLUDE_FILES := t2k/orion.c, \ - LANG := C++, \ - OPTIMIZATION := HIGH, \ - CFLAGS := $(CFLAGS_JDKLIB) $(LIBT2K_CFLAGS), \ - CXXFLAGS := $(CXXFLAGS_JDKLIB) $(LIBT2K_CFLAGS), \ - CFLAGS_windows = -DCC_NOEX, \ - CXXFLAGS_windows = -DCC_NOEX, \ - MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libt2k/mapfile-vers, \ - LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \ - $(call SET_SHARED_LIBRARY_ORIGIN), \ - LDFLAGS_windows := user32.lib $(JDK_OUTPUTDIR)/objs/libfontmanager/fontmanager.lib, \ - LDFLAGS_SUFFIX_posix := $(LIBM) $(LIBCXX) -lfontmanager -ljava -ljvm -lc, \ - LDFLAGS_SUFFIX_solaris := -lawt -lawt_xawt, \ - VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \ - RC_FLAGS := $(RC_FLAGS) \ - -D "JDK_FNAME=t2k.dll" \ - -D "JDK_INTERNAL_NAME=t2k" \ - -D "JDK_FTYPE=0x2L", \ - OBJECT_DIR := $(JDK_OUTPUTDIR)/objs/libt2k, \ - DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES))) - - # t2k is linked against fontmanager - $(BUILD_LIBT2K): $(BUILD_LIBFONTMANAGER) - - DESKTOP_LIBRARIES += $(BUILD_LIBT2K) -endif - -########################################################################################## +################################################################################ ifeq ($(OPENJDK_TARGET_OS), windows) LIBJAWT_SRC := $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_API_DIR)/native/libjawt @@ -768,99 +719,7 @@ endif # OPENJDK_TARGET_OS DESKTOP_LIBRARIES += $(BUILD_LIBJAWT) -########################################################################################## - -ifndef OPENJDK - - LIBKCMS_SRC := $(JDK_TOPDIR)/src/closed/java.desktop/share/native/libkcms \ - $(JDK_TOPDIR)/src/closed/java.desktop/$(OPENJDK_TARGET_OS_API_DIR)/native/libkcms \ - # - LIBKCMS_CFLAGS += $(addprefix -I, $(LIBKCMS_SRC)) \ - -I$(JDK_TOPDIR)/src/java.base/share/native/libjava \ - -I$(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_API_DIR)/native/libjava \ - -I$(JDK_OUTPUTDIR)/gensrc_headers/java.desktop \ - # - LIBKCMS_VERSIONINFO_RESOURCE := $(JDK_TOPDIR)/src/closed/java.desktop/windows/native/libkcms/cmm.rc - - LIBKCMS_CFLAGS += $(CFLAGS_JDKLIB) - - ifeq ($(OPENJDK_TARGET_OS), solaris) - # This particular library uses a feature called PIC_CODE_SMALL (on solaris) - # implement it like this...since it's only used here - LIBKCMS_CFLAGS := $(patsubst -KPIC, -Kpic, $(LIBKCMS_CFLAGS)) - else ifeq ($(OPENJDK_TARGET_CPU_ARCH), ppc) - LIBKCMS_CFLAGS := $(patsubst -fPIC, -fpic, $(LIBKCMS_CFLAGS)) - endif - - $(eval $(call SetupNativeCompilation,BUILD_LIBKCMS, \ - LIBRARY := kcms, \ - OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ - SRC := $(LIBKCMS_SRC), \ - LANG := C, \ - EXCLUDE_FILES := $(BUILD_LIBKCMS_EXCLUDE_FILES), \ - OPTIMIZATION := LOW, \ - CFLAGS := $(LIBKCMS_CFLAGS) \ - -DJAVACMM -DFUT_CALC_EX -DNO_FUT_GCONST, \ - CFLAGS_linux := -Wno-missing-field-initializers, \ - MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libkcms/mapfile-vers, \ - LDFLAGS := $(LDFLAGS_JDKLIB) \ - $(call SET_SHARED_LIBRARY_ORIGIN), \ - LDFLAGS_SUFFIX_linux := -lc -lpthread, \ - LDFLAGS_SUFFIX_solaris := -lc, \ - LDFLAGS_SUFFIX_windows := $(WIN_JAVA_LIB) advapi32.lib user32.lib version.lib, \ - LDFLAGS_SUFFIX_posix := -lm -ljava -ljvm, \ - VERSIONINFO_RESOURCE := $(LIBKCMS_VERSIONINFO_RESOURCE), \ - RC_FLAGS := $(RC_FLAGS) \ - -D "JDK_FNAME=kcms.dll" \ - -D "JDK_INTERNAL_NAME=kcms" \ - -D "JDK_FTYPE=0x2L", \ - OBJECT_DIR := $(JDK_OUTPUTDIR)/objs/libkcms, \ - DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES))) - - $(BUILD_LIBKCMS): $(BUILD_LIBJAVA) - - DESKTOP_LIBRARIES += $(BUILD_LIBKCMS) - -endif - -########################################################################################## - -ifndef OPENJDK - ifeq ($(OPENJDK_TARGET_OS), solaris) - ifneq ($(OPENJDK_TARGET_CPU), x86_64) - - ifeq ($(shell if test "$(OS_VERSION_MAJOR)" -eq 5 -a "$(OS_VERSION_MINOR)" -le 10; then $(ECHO) ok; fi), ok) - - SUNWJDGA_MAPFILE := - ifeq ($(OPENJDK_TARGET_CPU_ARCH), sparc) - SUNWJDGA_MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjdga/mapfile-vers - endif - - $(eval $(call SetupNativeCompilation,BUILD_LIBSUNWJDGA, \ - LIBRARY := sunwjdga, \ - OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ - SRC := $(JDK_TOPDIR)/src/java.desktop/unix/native/libsunwjdga, \ - LANG := C, \ - OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - -I$(JDK_TOPDIR)/src/share/javavm/export \ - -I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/javavm/export \ - $(X_CFLAGS), \ - MAPFILE := $(SUNWJDGA_MAPFILE), \ - LDFLAGS := $(LDFLAGS_JDKLIB) \ - $(call SET_SHARED_LIBRARY_ORIGIN), \ - LDFLAGS_SUFFIX := $(X_LIBS) -ldga -lX11 $(LIBDL) -lc, \ - OBJECT_DIR := $(JDK_OUTPUTDIR)/objs/libsunwjdga, \ - DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES))) - - DESKTOP_LIBRARIES += $(BUILD_LIBSUNWJDGA) - - endif - endif - endif -endif - -########################################################################################## +################################################################################ ifeq ($(BUILD_HEADLESS), true) # Mac and Windows only use the native AWT lib, do not build libawt_headless @@ -932,7 +791,7 @@ ifeq ($(BUILD_HEADLESS), true) endif endif -########################################################################################## +################################################################################ ifndef BUILD_HEADLESS_ONLY @@ -1041,47 +900,7 @@ ifndef BUILD_HEADLESS_ONLY endif -########################################################################################## - -ifndef OPENJDK - - LIBDCPR_SRC_DIRS := $(JDK_TOPDIR)/src/closed/java.desktop/share/native/libdcpr - LIBDCPR_CFLAGS := $(addprefix -I, $(shell $(FIND) $(LIBDCPR_SRC_DIRS) -type d)) \ - -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/sun/java2d/pipe \ - -I$(JDK_TOPDIR)/src/java.base/share/native/libjava \ - -I$(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_API_DIR)/native/libjava \ - -I$(JDK_OUTPUTDIR)/gensrc_headers/java.desktop \ - # - - $(eval $(call SetupNativeCompilation,BUILD_LIBDCPR, \ - LIBRARY := dcpr, \ - OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ - SRC := $(LIBDCPR_SRC_DIRS), \ - LANG := C, \ - OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - $(LIBDCPR_CFLAGS), \ - MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libdcpr/mapfile-vers, \ - LDFLAGS := $(LDFLAGS_JDKLIB) \ - $(call SET_SHARED_LIBRARY_ORIGIN), \ - LDFLAGS_SUFFIX := $(LIBM) $(LDFLAGS_JDKLIB_SUFFIX), \ - LDFLAGS_SUFFIX_windows := $(WIN_JAVA_LIB), \ - LDFLAGS_SUFFIX_posix := -lm, \ - VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \ - RC_FLAGS := $(RC_FLAGS) \ - -D "JDK_FNAME=dcpr.dll" \ - -D "JDK_INTERNAL_NAME=dcpr" \ - -D "JDK_FTYPE=0x2L", \ - OBJECT_DIR := $(JDK_OUTPUTDIR)/objs/libdcpr, \ - DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES))) - - $(BUILD_LIBDCPR): $(BUILD_LIBJAVA) - - DESKTOP_LIBRARIES += $(BUILD_LIBDCPR) - -endif - -########################################################################################## +################################################################################ ifeq ($(OPENJDK_TARGET_OS), macosx) @@ -1158,7 +977,7 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) endif -########################################################################################## +################################################################################ ifeq ($(OPENJDK_TARGET_OS), macosx) @@ -1199,3 +1018,8 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) #$(BUILD_LIBOSXUI): $(BUILD_LIBJAVA) endif + +################################################################################ + +# Hook to include the corresponding custom file, if present. +$(eval $(call IncludeCustomExtension, jdk, lib/Awt2dLibraries.gmk)) diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk index 99a0c46f114..852879f09ee 100644 --- a/jdk/make/lib/CoreLibraries.gmk +++ b/jdk/make/lib/CoreLibraries.gmk @@ -26,6 +26,8 @@ WIN_VERIFY_LIB := $(JDK_OUTPUTDIR)/objs/libverify/verify.lib ########################################################################################## +# libfdlibm is statically linked with libjava below and not delivered into the +# product on its own. BUILD_LIBFDLIBM_OPTIMIZATION := HIGH diff --git a/jdk/make/lib/Lib-java.base.gmk b/jdk/make/lib/Lib-java.base.gmk index cf7f663d6fa..301e31c2df8 100644 --- a/jdk/make/lib/Lib-java.base.gmk +++ b/jdk/make/lib/Lib-java.base.gmk @@ -25,6 +25,10 @@ include LibCommon.gmk +# Prepare the find cache. +$(eval $(call FillCacheFind, $(wildcard $(JDK_TOPDIR)/src/java.base/*/native \ + $(JDK_TOPDIR)/src/*/java.base/*/native))) + include CoreLibraries.gmk include NetworkingLibraries.gmk include NioLibraries.gmk diff --git a/jdk/make/lib/Lib-java.desktop.gmk b/jdk/make/lib/Lib-java.desktop.gmk index bdd919cfeb7..e8661508e93 100644 --- a/jdk/make/lib/Lib-java.desktop.gmk +++ b/jdk/make/lib/Lib-java.desktop.gmk @@ -25,6 +25,10 @@ include LibCommon.gmk +# Prepare the find cache. +$(eval $(call FillCacheFind, $(wildcard $(JDK_TOPDIR)/src/java.desktop/*/native \ + $(JDK_TOPDIR)/src/*/java.desktop/*/native))) + include PlatformLibraries.gmk include Awt2dLibraries.gmk include SoundLibraries.gmk diff --git a/jdk/make/lib/Lib-jdk.attach.gmk b/jdk/make/lib/Lib-jdk.attach.gmk index 65b7b1397d7..2b58e173efb 100644 --- a/jdk/make/lib/Lib-jdk.attach.gmk +++ b/jdk/make/lib/Lib-jdk.attach.gmk @@ -27,33 +27,11 @@ include LibCommon.gmk ################################################################################ -ifeq ($(OPENJDK_TARGET_OS), aix) - LIBATTACH_OS_API_DIR := aix -else - LIBATTACH_OS_API_DIR := $(OPENJDK_TARGET_OS_API_DIR) -endif - -LIBATTACH_SRC := $(JDK_TOPDIR)/src/jdk.attach/$(LIBATTACH_OS_API_DIR)/native/libattach - -LIBATTACH_EXCLUDE_FILES := -ifneq ($(OPENJDK_TARGET_OS), solaris) - LIBATTACH_EXCLUDE_FILES += SolarisVirtualMachine.c -endif -ifneq ($(OPENJDK_TARGET_OS), linux) - LIBATTACH_EXCLUDE_FILES += LinuxVirtualMachine.c -endif -ifneq ($(OPENJDK_TARGET_OS), macosx) - LIBATTACH_EXCLUDE_FILES += BsdVirtualMachine.c -endif -ifneq ($(OPENJDK_TARGET_OS),aix) - LIBATTACH_EXCLUDE_FILES += AixVirtualMachine.c -endif $(eval $(call SetupNativeCompilation,BUILD_LIBATTACH, \ LIBRARY := attach, \ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ - SRC := $(LIBATTACH_SRC), \ - EXCLUDE_FILES := $(LIBATTACH_EXCLUDE_FILES), \ + SRC := $(JDK_TOPDIR)/src/jdk.attach/$(OPENJDK_TARGET_OS)/native/libattach, \ LANG := C, \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) \ diff --git a/jdk/make/lib/Lib-jdk.hprof.agent.gmk b/jdk/make/lib/Lib-jdk.hprof.agent.gmk index 7b7ef69b2e0..a58687da251 100644 --- a/jdk/make/lib/Lib-jdk.hprof.agent.gmk +++ b/jdk/make/lib/Lib-jdk.hprof.agent.gmk @@ -27,11 +27,11 @@ include LibCommon.gmk ################################################################################ -BUILD_LIBHPROF_SRC := $(JDK_TOPDIR)/src/demo/share/jvmti/hprof \ - $(JDK_TOPDIR)/src/demo/$(OPENJDK_TARGET_OS_API_DIR)/jvmti/hprof +BUILD_LIBHPROF_SRC := $(call FindSrcDirsForLib, jdk.hprof.agent, hprof) + BUILD_LIBHPROF_CFLAGS := $(addprefix -I, $(BUILD_LIBHPROF_SRC)) \ -I$(JDK_TOPDIR)/src/demo/share/jvmti/java_crw_demo - + BUILD_LIBHPROF_LDFLAGS := LIBHPROF_OPTIMIZATION := HIGHEST diff --git a/jdk/make/lib/LibCommon.gmk b/jdk/make/lib/LibCommon.gmk index 7fadd1c781f..885ba11c780 100644 --- a/jdk/make/lib/LibCommon.gmk +++ b/jdk/make/lib/LibCommon.gmk @@ -29,9 +29,6 @@ include $(SPEC) include MakeBase.gmk include NativeCompilation.gmk -# Prepare the find cache. -$(eval $(call FillCacheFind, $(wildcard $(JDK_TOPDIR)/src/*/*/native))) - # Build tools include Tools.gmk diff --git a/jdk/make/lib/NetworkingLibraries.gmk b/jdk/make/lib/NetworkingLibraries.gmk index e61f80be925..a0825b06ce2 100644 --- a/jdk/make/lib/NetworkingLibraries.gmk +++ b/jdk/make/lib/NetworkingLibraries.gmk @@ -44,7 +44,7 @@ ifneq ($(OPENJDK_TARGET_OS), macosx) endif ifeq ($(OPENJDK_TARGET_OS), aix) - LIBNET_SRC_DIRS += $(JDK_TOPDIR)/src/aix/native/java/net/ + LIBNET_SRC_DIRS += $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libnet/java/net/ endif $(eval $(call SetupNativeCompilation,BUILD_LIBNET, \ diff --git a/jdk/make/lib/NioLibraries.gmk b/jdk/make/lib/NioLibraries.gmk index 259517c2aad..722115fdee5 100644 --- a/jdk/make/lib/NioLibraries.gmk +++ b/jdk/make/lib/NioLibraries.gmk @@ -56,17 +56,8 @@ endif ifeq ($(OPENJDK_TARGET_OS), aix) BUILD_LIBNIO_MAPFILE:=$(JDK_TOPDIR)/make/mapfiles/libnio/mapfile-$(OPENJDK_TARGET_OS) - BUILD_LIBNIO_FILES += \ - AixPollPort.c \ - InheritedChannel.c \ - AixNativeThread.c \ - PollArrayWrapper.c \ - UnixAsynchronousServerSocketChannelImpl.c \ - UnixAsynchronousSocketChannelImpl.c \ - GnomeFileTypeDetector.c \ - UnixCopyFile.c \ - AixNativeDispatcher.c \ - UnixNativeDispatcher.c + BUILD_LIBNIO_EXFILES += \ + NativeThread.c endif $(eval $(call SetupNativeCompilation,BUILD_LIBNIO, \ diff --git a/jdk/make/mapfiles/libattach/mapfile-aix b/jdk/make/mapfiles/libattach/mapfile-aix index 4c02da01fce..10ca49534ba 100644 --- a/jdk/make/mapfiles/libattach/mapfile-aix +++ b/jdk/make/mapfiles/libattach/mapfile-aix @@ -27,13 +27,13 @@ SUNWprivate_1.1 { global: - Java_sun_tools_attach_AixVirtualMachine_socket - Java_sun_tools_attach_AixVirtualMachine_connect - Java_sun_tools_attach_AixVirtualMachine_sendQuitTo - Java_sun_tools_attach_AixVirtualMachine_checkPermissions - Java_sun_tools_attach_AixVirtualMachine_close - Java_sun_tools_attach_AixVirtualMachine_read - Java_sun_tools_attach_AixVirtualMachine_write + Java_sun_tools_attach_VirtualMachineImpl_socket + Java_sun_tools_attach_VirtualMachineImpl_connect + Java_sun_tools_attach_VirtualMachineImpl_sendQuitTo + Java_sun_tools_attach_VirtualMachineImpl_checkPermissions + Java_sun_tools_attach_VirtualMachineImpl_close + Java_sun_tools_attach_VirtualMachineImpl_read + Java_sun_tools_attach_VirtualMachineImpl_write local: *; }; diff --git a/jdk/make/mapfiles/libattach/mapfile-linux b/jdk/make/mapfiles/libattach/mapfile-linux index fbfdedfdad9..b569ae5e637 100644 --- a/jdk/make/mapfiles/libattach/mapfile-linux +++ b/jdk/make/mapfiles/libattach/mapfile-linux @@ -27,17 +27,17 @@ SUNWprivate_1.1 { global: - Java_sun_tools_attach_LinuxVirtualMachine_checkPermissions; - Java_sun_tools_attach_LinuxVirtualMachine_close; - Java_sun_tools_attach_LinuxVirtualMachine_connect; - Java_sun_tools_attach_LinuxVirtualMachine_getLinuxThreadsManager; - Java_sun_tools_attach_LinuxVirtualMachine_isLinuxThreads; - Java_sun_tools_attach_LinuxVirtualMachine_open; - Java_sun_tools_attach_LinuxVirtualMachine_sendQuitTo; - Java_sun_tools_attach_LinuxVirtualMachine_sendQuitToChildrenOf; - Java_sun_tools_attach_LinuxVirtualMachine_socket; - Java_sun_tools_attach_LinuxVirtualMachine_read; - Java_sun_tools_attach_LinuxVirtualMachine_write; + Java_sun_tools_attach_VirtualMachineImpl_checkPermissions; + Java_sun_tools_attach_VirtualMachineImpl_close; + Java_sun_tools_attach_VirtualMachineImpl_connect; + Java_sun_tools_attach_VirtualMachineImpl_getLinuxThreadsManager; + Java_sun_tools_attach_VirtualMachineImpl_isLinuxThreads; + Java_sun_tools_attach_VirtualMachineImpl_open; + Java_sun_tools_attach_VirtualMachineImpl_sendQuitTo; + Java_sun_tools_attach_VirtualMachineImpl_sendQuitToChildrenOf; + Java_sun_tools_attach_VirtualMachineImpl_socket; + Java_sun_tools_attach_VirtualMachineImpl_read; + Java_sun_tools_attach_VirtualMachineImpl_write; local: *; }; diff --git a/jdk/make/mapfiles/libattach/mapfile-solaris b/jdk/make/mapfiles/libattach/mapfile-solaris index 6e61f754b99..df71490fdb8 100644 --- a/jdk/make/mapfiles/libattach/mapfile-solaris +++ b/jdk/make/mapfiles/libattach/mapfile-solaris @@ -27,12 +27,12 @@ SUNWprivate_1.1 { global: - Java_sun_tools_attach_SolarisVirtualMachine_checkPermissions; - Java_sun_tools_attach_SolarisVirtualMachine_enqueue; - Java_sun_tools_attach_SolarisVirtualMachine_open; - Java_sun_tools_attach_SolarisVirtualMachine_close; - Java_sun_tools_attach_SolarisVirtualMachine_read; - Java_sun_tools_attach_SolarisVirtualMachine_sigquit; + Java_sun_tools_attach_VirtualMachineImpl_checkPermissions; + Java_sun_tools_attach_VirtualMachineImpl_enqueue; + Java_sun_tools_attach_VirtualMachineImpl_open; + Java_sun_tools_attach_VirtualMachineImpl_close; + Java_sun_tools_attach_VirtualMachineImpl_read; + Java_sun_tools_attach_VirtualMachineImpl_sigquit; local: *; }; diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers index ca99cc5c03b..3b1d894ff71 100644 --- a/jdk/make/mapfiles/libjava/mapfile-vers +++ b/jdk/make/mapfiles/libjava/mapfile-vers @@ -78,13 +78,13 @@ SUNWprivate_1.1 { Java_java_io_FileInputStream_available; Java_java_io_FileInputStream_close0; Java_java_io_FileInputStream_initIDs; - Java_java_io_FileInputStream_open; + Java_java_io_FileInputStream_open0; Java_java_io_FileInputStream_read0; Java_java_io_FileInputStream_readBytes; Java_java_io_FileInputStream_skip; Java_java_io_FileOutputStream_close0; Java_java_io_FileOutputStream_initIDs; - Java_java_io_FileOutputStream_open; + Java_java_io_FileOutputStream_open0; Java_java_io_FileOutputStream_write; Java_java_io_FileOutputStream_writeBytes; Java_java_io_ObjectInputStream_bytesToDoubles; @@ -97,7 +97,7 @@ SUNWprivate_1.1 { Java_java_io_RandomAccessFile_getFilePointer; Java_java_io_RandomAccessFile_initIDs; Java_java_io_RandomAccessFile_length; - Java_java_io_RandomAccessFile_open; + Java_java_io_RandomAccessFile_open0; Java_java_io_RandomAccessFile_read0; Java_java_io_RandomAccessFile_readBytes; Java_java_io_RandomAccessFile_seek0; diff --git a/jdk/make/mapfiles/libjava/reorder-sparc b/jdk/make/mapfiles/libjava/reorder-sparc index 4a5cbf45018..d10037652d1 100644 --- a/jdk/make/mapfiles/libjava/reorder-sparc +++ b/jdk/make/mapfiles/libjava/reorder-sparc @@ -44,7 +44,7 @@ text: .text%Java_java_io_UnixFileSystem_initIDs; text: .text%Java_java_io_UnixFileSystem_canonicalize; text: .text%JNU_GetStringPlatformChars; text: .text%JNU_ReleaseStringPlatformChars; -text: .text%Java_java_io_FileInputStream_open; +text: .text%Java_java_io_FileInputStream_open0; text: .text%fileOpen; text: .text%Java_java_io_FileInputStream_readBytes; text: .text%readBytes; diff --git a/jdk/make/mapfiles/libjava/reorder-sparcv9 b/jdk/make/mapfiles/libjava/reorder-sparcv9 index 81cbfcb2410..2609711c21f 100644 --- a/jdk/make/mapfiles/libjava/reorder-sparcv9 +++ b/jdk/make/mapfiles/libjava/reorder-sparcv9 @@ -47,7 +47,7 @@ text: .text%Java_java_io_UnixFileSystem_initIDs; text: .text%Java_java_io_UnixFileSystem_canonicalize; text: .text%JNU_GetStringPlatformChars; text: .text%JNU_ReleaseStringPlatformChars; -text: .text%Java_java_io_FileInputStream_open; +text: .text%Java_java_io_FileInputStream_open0; text: .text%fileOpen; text: .text%Java_java_io_FileInputStream_readBytes; text: .text%readBytes; diff --git a/jdk/make/mapfiles/libjava/reorder-x86 b/jdk/make/mapfiles/libjava/reorder-x86 index 1c971b80eda..b8ea2d43dae 100644 --- a/jdk/make/mapfiles/libjava/reorder-x86 +++ b/jdk/make/mapfiles/libjava/reorder-x86 @@ -57,7 +57,7 @@ text: .text%Java_java_lang_ClassLoader_00024NativeLibrary_load; text: .text%Java_java_lang_ClassLoader_00024NativeLibrary_find; text: .text%Java_java_lang_Float_floatToIntBits; text: .text%Java_java_lang_Double_doubleToLongBits; -text: .text%Java_java_io_FileInputStream_open; +text: .text%Java_java_io_FileInputStream_open0; text: .text%fileOpen; text: .text%Java_java_io_UnixFileSystem_getLength; text: .text%Java_java_io_FileInputStream_readBytes; @@ -90,7 +90,7 @@ text: .text%JNU_NotifyAll; text: .text%JNU_CallMethodByName; text: .text%JNU_CallMethodByNameV; text: .text%Java_java_util_logging_FileHandler_lockFile; -text: .text%Java_java_io_FileOutputStream_open; +text: .text%Java_java_io_FileOutputStream_open0; text: .text%Java_java_io_UnixFileSystem_createDirectory; text: .text%Java_java_io_UnixFileSystem_getLastModifiedTime; text: .text%Java_java_util_prefs_FileSystemPreferences_lockFile0; diff --git a/jdk/make/mapfiles/libnio/mapfile-linux b/jdk/make/mapfiles/libnio/mapfile-linux index 16f72e43cfa..53555c4763f 100644 --- a/jdk/make/mapfiles/libnio/mapfile-linux +++ b/jdk/make/mapfiles/libnio/mapfile-linux @@ -79,6 +79,7 @@ SUNWprivate_1.1 { Java_sun_nio_ch_InheritedChannel_close0; Java_sun_nio_ch_InheritedChannel_dup; Java_sun_nio_ch_InheritedChannel_dup2; + Java_sun_nio_ch_InheritedChannel_initIDs; Java_sun_nio_ch_InheritedChannel_open0; Java_sun_nio_ch_InheritedChannel_peerAddress0; Java_sun_nio_ch_InheritedChannel_peerPort0; diff --git a/jdk/make/mapfiles/libnio/mapfile-macosx b/jdk/make/mapfiles/libnio/mapfile-macosx index 4dd0dc513e4..d4b6dc5a219 100644 --- a/jdk/make/mapfiles/libnio/mapfile-macosx +++ b/jdk/make/mapfiles/libnio/mapfile-macosx @@ -62,6 +62,7 @@ SUNWprivate_1.1 { Java_sun_nio_ch_InheritedChannel_close0; Java_sun_nio_ch_InheritedChannel_dup; Java_sun_nio_ch_InheritedChannel_dup2; + Java_sun_nio_ch_InheritedChannel_initIDs; Java_sun_nio_ch_InheritedChannel_open0; Java_sun_nio_ch_InheritedChannel_peerAddress0; Java_sun_nio_ch_InheritedChannel_peerPort0; diff --git a/jdk/make/mapfiles/libnio/mapfile-solaris b/jdk/make/mapfiles/libnio/mapfile-solaris index 3933cef7ada..cdbb851bcad 100644 --- a/jdk/make/mapfiles/libnio/mapfile-solaris +++ b/jdk/make/mapfiles/libnio/mapfile-solaris @@ -67,6 +67,7 @@ SUNWprivate_1.1 { Java_sun_nio_ch_InheritedChannel_close0; Java_sun_nio_ch_InheritedChannel_dup; Java_sun_nio_ch_InheritedChannel_dup2; + Java_sun_nio_ch_InheritedChannel_initIDs; Java_sun_nio_ch_InheritedChannel_open0; Java_sun_nio_ch_InheritedChannel_peerAddress0; Java_sun_nio_ch_InheritedChannel_peerPort0; diff --git a/jdk/make/profile-rtjar-includes.txt b/jdk/make/profile-rtjar-includes.txt index 1e954ad625c..8ab7336fb17 100644 --- a/jdk/make/profile-rtjar-includes.txt +++ b/jdk/make/profile-rtjar-includes.txt @@ -201,6 +201,7 @@ FULL_JRE_RTJAR_INCLUDE_PACKAGES := \ sun/audio \ sun/awt \ sun/corba \ + sun/datatransfer \ sun/dc \ sun/font \ sun/java2d \ diff --git a/jdk/make/src/classes/build/tools/module/GenerateModulesXml.java b/jdk/make/src/classes/build/tools/module/GenJdepsModulesXml.java similarity index 90% rename from jdk/make/src/classes/build/tools/module/GenerateModulesXml.java rename to jdk/make/src/classes/build/tools/module/GenJdepsModulesXml.java index c2fdf4ae9d1..43ba458f326 100644 --- a/jdk/make/src/classes/build/tools/module/GenerateModulesXml.java +++ b/jdk/make/src/classes/build/tools/module/GenJdepsModulesXml.java @@ -25,6 +25,7 @@ package build.tools.module; +import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -49,47 +50,56 @@ import javax.xml.stream.events.Attribute; import javax.xml.stream.events.XMLEvent; /** - * This tool is used to generate com/sun/tools/jdeps/resources/modules.xml - * for jdeps to analyze dependencies and enforce module boundaries. + * GenJdepsModulesXml augments the input modules.xml file(s) + * to include the module membership from the given path to + * the JDK exploded image. The output file is used by jdeps + * to analyze dependencies and enforce module boundaries. * - * $ java build.tools.module.GenerateModulesXml \ - * com/sun/tools/jdeps/resources/modules.xml $OUTPUTDIR/modules + * The input modules.xml file defines the modular structure of + * the JDK as described in JEP 200: The Modular JDK + * (http://openjdk.java.net/jeps/200). * - * This will generate modules.xml as jdeps resources that extend - * the metadata to include module membership (jdeps needs the - * membership information to determine which module a type belongs to.) + * $ java build.tools.module.GenJdepsModulesXml \ + * -o com/sun/tools/jdeps/resources/modules.xml \ + * -mp $OUTPUTDIR/modules \ + * top/modules.xml */ -public final class GenerateModulesXml { +public final class GenJdepsModulesXml { private final static String USAGE = - "Usage: GenerateModulesXml build/modules"; + "Usage: GenJdepsModulesXml -o -mp build/modules path-to-modules-xml"; public static void main(String[] args) throws Exception { - if (args.length < 2) { + Path outfile = null; + Path modulepath = null; + int i = 0; + while (i < args.length) { + String arg = args[i]; + if (arg.equals("-o")) { + outfile = Paths.get(args[i+1]); + i = i+2; + } else if (arg.equals("-mp")) { + modulepath = Paths.get(args[i+1]); + i = i+2; + if (!Files.isDirectory(modulepath)) { + System.err.println(modulepath + " is not a directory"); + System.exit(1); + } + } else { + break; + } + } + if (outfile == null || modulepath == null || i >= args.length) { System.err.println(USAGE); System.exit(-1); } - Path outfile = Paths.get(args[0]); - Path modulepath = Paths.get(args[1]); - - if (!Files.isDirectory(modulepath)) { - System.err.println(modulepath + " is not a directory"); - System.exit(1); - } - GenerateModulesXml gentool = - new GenerateModulesXml(modulepath); - Set modules; - try (InputStream in = GenerateModulesXml.class.getResourceAsStream("modules.xml")) { - modules = gentool.load(in); - } - - InputStream in = GenerateModulesXml.class.getResourceAsStream("closed/modules.xml"); - if (in != null) { - try { + GenJdepsModulesXml gentool = new GenJdepsModulesXml(modulepath); + Set modules = new HashSet<>(); + for (; i < args.length; i++) { + Path p = Paths.get(args[i]); + try (InputStream in = new BufferedInputStream(Files.newInputStream(p))) { Set mods = gentool.load(in); modules.addAll(mods); - } finally { - in.close(); } } @@ -98,7 +108,7 @@ public final class GenerateModulesXml { } final Path modulepath; - public GenerateModulesXml(Path modulepath) { + public GenJdepsModulesXml(Path modulepath) { this.modulepath = modulepath; } @@ -275,7 +285,7 @@ public final class GenerateModulesXml { m.exports().keySet().stream() .filter(pn -> m.exports().get(pn).isEmpty()) .sorted() - .forEach(pn -> GenerateModulesXml.this.writeExportElement(xtw, pn, depth+1)); + .forEach(pn -> writeExportElement(xtw, pn, depth+1)); m.exports().entrySet().stream() .filter(e -> !e.getValue().isEmpty()) .sorted(Map.Entry.comparingByKey()) diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/README b/jdk/src/demo/share/jpda/com/sun/tools/example/README deleted file mode 100644 index 13e1540f14c..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/README +++ /dev/null @@ -1,3 +0,0 @@ -Please refer to the documentation in: - - doc/index.html diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/AccessWatchpointSpec.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/AccessWatchpointSpec.java deleted file mode 100644 index 0d9fe21a7d3..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/AccessWatchpointSpec.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import com.sun.jdi.*; - -public class AccessWatchpointSpec extends WatchpointSpec { - - AccessWatchpointSpec(EventRequestSpecList specs, - ReferenceTypeSpec refSpec, String fieldId) { - super(specs, refSpec, fieldId); - } - - /** - * The 'refType' is known to match. - */ - @Override - void resolve(ReferenceType refType) throws InvalidTypeException, - NoSuchFieldException { - if (!(refType instanceof ClassType)) { - throw new InvalidTypeException(); - } - Field field = refType.fieldByName(fieldId); - if (field == null) { - throw new NoSuchFieldException(fieldId); - } - setRequest(refType.virtualMachine().eventRequestManager() - .createAccessWatchpointRequest(field)); - } - - @Override - public boolean equals(Object obj) { - return (obj instanceof AccessWatchpointSpec) && super.equals(obj); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/AmbiguousMethodException.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/AmbiguousMethodException.java deleted file mode 100644 index 97d54dd32c8..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/AmbiguousMethodException.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -public class AmbiguousMethodException extends Exception -{ - - private static final long serialVersionUID = 7793370943251707514L; - - public AmbiguousMethodException() - { - super(); - } - - public AmbiguousMethodException(String s) - { - super(s); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/BreakpointSpec.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/BreakpointSpec.java deleted file mode 100644 index 50059c1ff49..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/BreakpointSpec.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -public abstract class BreakpointSpec extends EventRequestSpec { - - BreakpointSpec(EventRequestSpecList specs, ReferenceTypeSpec refSpec) { - super(specs, refSpec); - } - - @Override - void notifySet(SpecListener listener, SpecEvent evt) { - listener.breakpointSet(evt); - } - - @Override - void notifyDeferred(SpecListener listener, SpecEvent evt) { - listener.breakpointDeferred(evt); - } - - @Override - void notifyResolved(SpecListener listener, SpecEvent evt) { - listener.breakpointResolved(evt); - } - - @Override - void notifyDeleted(SpecListener listener, SpecEvent evt) { - listener.breakpointDeleted(evt); - } - - @Override - void notifyError(SpecListener listener, SpecErrorEvent evt) { - listener.breakpointError(evt); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ChildSession.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ChildSession.java deleted file mode 100644 index b6042a6e845..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ChildSession.java +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import com.sun.jdi.*; -import com.sun.jdi.connect.LaunchingConnector; -import com.sun.jdi.connect.Connector; -import com.sun.jdi.connect.VMStartException; -import com.sun.jdi.connect.IllegalConnectorArgumentsException; -import java.io.*; -import java.util.Map; -import javax.swing.SwingUtilities; - - -class ChildSession extends Session { - - private Process process; - - private PrintWriter in; - private BufferedReader out; - private BufferedReader err; - - private InputListener input; - private OutputListener output; - private OutputListener error; - - public ChildSession(ExecutionManager runtime, - String userVMArgs, String cmdLine, - InputListener input, - OutputListener output, - OutputListener error, - OutputListener diagnostics) { - this(runtime, getVM(diagnostics, userVMArgs, cmdLine), - input, output, error, diagnostics); - } - - public ChildSession(ExecutionManager runtime, - LaunchingConnector connector, - Map arguments, - InputListener input, - OutputListener output, - OutputListener error, - OutputListener diagnostics) { - this(runtime, generalGetVM(diagnostics, connector, arguments), - input, output, error, diagnostics); - } - - private ChildSession(ExecutionManager runtime, - VirtualMachine vm, - InputListener input, - OutputListener output, - OutputListener error, - OutputListener diagnostics) { - super(vm, runtime, diagnostics); - this.input = input; - this.output = output; - this.error = error; - } - - @Override - public boolean attach() { - - if (!connectToVMProcess()) { - diagnostics.putString("Could not launch VM"); - return false; - } - - /* - * Create a Thread that will retrieve and display any output. - * Needs to be high priority, else debugger may exit before - * it can be displayed. - */ - - //### Rename InputWriter and OutputReader classes - //### Thread priorities cribbed from ttydebug. Think about them. - - OutputReader outputReader = - new OutputReader("output reader", "output", - out, output, diagnostics); - outputReader.setPriority(Thread.MAX_PRIORITY-1); - outputReader.start(); - - OutputReader errorReader = - new OutputReader("error reader", "error", - err, error, diagnostics); - errorReader.setPriority(Thread.MAX_PRIORITY-1); - errorReader.start(); - - InputWriter inputWriter = - new InputWriter("input writer", in, input); - inputWriter.setPriority(Thread.MAX_PRIORITY-1); - inputWriter.start(); - - if (!super.attach()) { - if (process != null) { - process.destroy(); - process = null; - } - return false; - } - - //### debug - //System.out.println("IO after attach: "+ inputWriter + " " + outputReader + " "+ errorReader); - - return true; - } - - @Override - public void detach() { - - //### debug - //System.out.println("IO before detach: "+ inputWriter + " " + outputReader + " "+ errorReader); - - super.detach(); - - /* - inputWriter.quit(); - outputReader.quit(); - errorReader.quit(); - */ - - if (process != null) { - process.destroy(); - process = null; - } - - } - - /** - * Launch child java interpreter, return host:port - */ - - static private void dumpStream(OutputListener diagnostics, - InputStream stream) throws IOException { - BufferedReader in = - new BufferedReader(new InputStreamReader(stream)); - String line; - while ((line = in.readLine()) != null) { - diagnostics.putString(line); - } - } - - static private void dumpFailedLaunchInfo(OutputListener diagnostics, - Process process) { - try { - dumpStream(diagnostics, process.getErrorStream()); - dumpStream(diagnostics, process.getInputStream()); - } catch (IOException e) { - diagnostics.putString("Unable to display process output: " + - e.getMessage()); - } - } - - static private VirtualMachine getVM(OutputListener diagnostics, - String userVMArgs, - String cmdLine) { - VirtualMachineManager manager = Bootstrap.virtualMachineManager(); - LaunchingConnector connector = manager.defaultConnector(); - Map arguments = connector.defaultArguments(); - arguments.get("options").setValue(userVMArgs); - arguments.get("main").setValue(cmdLine); - return generalGetVM(diagnostics, connector, arguments); - } - - static private VirtualMachine generalGetVM(OutputListener diagnostics, - LaunchingConnector connector, - Map arguments) { - VirtualMachine vm = null; - try { - diagnostics.putString("Starting child."); - vm = connector.launch(arguments); - } catch (IOException ioe) { - diagnostics.putString("Unable to start child: " + ioe.getMessage()); - } catch (IllegalConnectorArgumentsException icae) { - diagnostics.putString("Unable to start child: " + icae.getMessage()); - } catch (VMStartException vmse) { - diagnostics.putString("Unable to start child: " + vmse.getMessage() + '\n'); - dumpFailedLaunchInfo(diagnostics, vmse.process()); - } - return vm; - } - - private boolean connectToVMProcess() { - if (vm == null) { - return false; - } - process = vm.process(); - in = new PrintWriter(new OutputStreamWriter(process.getOutputStream())); - //### Note small buffer sizes! - out = new BufferedReader(new InputStreamReader(process.getInputStream()), 1); - err = new BufferedReader(new InputStreamReader(process.getErrorStream()), 1); - return true; - } - - /** - * Threads to handle application input/output. - */ - - private static class OutputReader extends Thread { - - private String streamName; - private BufferedReader stream; - private OutputListener output; - private OutputListener diagnostics; - private boolean running = true; - private char[] buffer = new char[512]; - - OutputReader(String threadName, - String streamName, - BufferedReader stream, - OutputListener output, - OutputListener diagnostics) { - super(threadName); - this.streamName = streamName; - this.stream = stream; - this.output = output; - this.diagnostics = diagnostics; - } - - @Override - public void run() { - try { - int count; - while (running && (count = stream.read(buffer, 0, 512)) != -1) { - if (count > 0) { - // Run in Swing event dispatcher thread. - final String chars = new String(buffer, 0, count); - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - output.putString(chars); - } - }); - } - //### Should we sleep briefly here? - } - } catch (IOException e) { - // Run in Swing event dispatcher thread. - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - diagnostics.putString("IO error reading " + - streamName + - " stream of child java interpreter"); - } - }); - } - } - } - - private static class InputWriter extends Thread { - - private PrintWriter stream; - private InputListener input; - private boolean running = true; - - InputWriter(String threadName, - PrintWriter stream, - InputListener input) { - super(threadName); - this.stream = stream; - this.input = input; - } - - @Override - public void run() { - String line; - while (running) { - line = input.getLine(); - stream.println(line); - // Should not be needed for println above! - stream.flush(); - } - } - } - -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/EvaluationException.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/EvaluationException.java deleted file mode 100644 index b9a02c37117..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/EvaluationException.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -public class EvaluationException extends Exception { - - private static final long serialVersionUID = 4947109680354951694L; -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/EventRequestSpec.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/EventRequestSpec.java deleted file mode 100644 index 0ea58fb3ebd..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/EventRequestSpec.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import com.sun.jdi.*; -import com.sun.jdi.request.EventRequest; - -abstract public class EventRequestSpec { - - static final int STATUS_UNRESOLVED = 1; - static final int STATUS_RESOLVED = 2; - static final int STATUS_ERROR = 3; - - static final Object specPropertyKey = "spec"; - - final EventRequestSpecList specs; - final ReferenceTypeSpec refSpec; - EventRequest request = null; - - int status = STATUS_UNRESOLVED; - - EventRequestSpec(EventRequestSpecList specs, ReferenceTypeSpec refSpec) { - this.specs = specs; - this.refSpec = refSpec; - } - - void setRequest(EventRequest request) { - this.request = request; - request.putProperty(specPropertyKey, this); - request.enable(); - } - - /** - * The 'refType' is known to match. - */ - abstract void resolve(ReferenceType refType) throws Exception; - - abstract void notifySet(SpecListener listener, SpecEvent evt); - abstract void notifyDeferred(SpecListener listener, SpecEvent evt); - abstract void notifyResolved(SpecListener listener, SpecEvent evt); - abstract void notifyDeleted(SpecListener listener, SpecEvent evt); - abstract void notifyError(SpecListener listener, SpecErrorEvent evt); - - /** - * The 'refType' is known to match. - */ - void resolveNotify(ReferenceType refType) { - try { - resolve(refType); - status = STATUS_RESOLVED; - specs.notifyResolved(this); - } catch(Exception exc) { - status = STATUS_ERROR; - specs.notifyError(this, exc); - } - } - - /** - * See if 'refType' matches and resolve. - */ - void attemptResolve(ReferenceType refType) { - if (!isResolved() && refSpec.matches(refType)) { - resolveNotify(refType); - } - } - - void attemptImmediateResolve(VirtualMachine vm) { - // try to resolve immediately - for (ReferenceType refType : vm.allClasses()) { - if (refSpec.matches(refType)) { - try { - resolve(refType); - status = STATUS_RESOLVED; - specs.notifySet(this); - } catch(Exception exc) { - status = STATUS_ERROR; - specs.notifyError(this, exc); - } - return; - } - } - specs.notifyDeferred(this); - } - - public EventRequest getEventRequest() { - return request; - } - - /** - * @return true if this spec has been resolved. - */ - public boolean isResolved() { - return status == STATUS_RESOLVED; - } - - /** - * @return true if this spec has not yet been resolved. - */ - public boolean isUnresolved() { - return status == STATUS_UNRESOLVED; - } - - /** - * @return true if this spec is unresolvable due to error. - */ - public boolean isErroneous() { - return status == STATUS_ERROR; - } - - public String getStatusString() { - switch (status) { - case STATUS_RESOLVED: - return "resolved"; - case STATUS_UNRESOLVED: - return "deferred"; - case STATUS_ERROR: - return "erroneous"; - } - return "unknown"; - } - - boolean isJavaIdentifier(String s) { - return Utils.isJavaIdentifier(s); - } - - public String errorMessageFor(Exception e) { - if (e instanceof IllegalArgumentException) { - return ("Invalid command syntax"); - } else if (e instanceof RuntimeException) { - // A runtime exception that we were not expecting - throw (RuntimeException)e; - } else { - return ("Internal error; unable to set" + this); - } - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/EventRequestSpecList.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/EventRequestSpecList.java deleted file mode 100644 index 17c001483c7..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/EventRequestSpecList.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import com.sun.jdi.*; -import com.sun.jdi.request.*; - -import java.util.*; - -class EventRequestSpecList { - - // all specs - private List eventRequestSpecs = Collections.synchronizedList( - new ArrayList()); - - final ExecutionManager runtime; - - EventRequestSpecList(ExecutionManager runtime) { - this.runtime = runtime; - } - - /** - * Resolve all deferred eventRequests waiting for 'refType'. - */ - void resolve(ReferenceType refType) { - synchronized(eventRequestSpecs) { - for (EventRequestSpec spec : eventRequestSpecs) { - spec.attemptResolve(refType); - } - } - } - - void install(EventRequestSpec ers, VirtualMachine vm) { - synchronized (eventRequestSpecs) { - eventRequestSpecs.add(ers); - } - if (vm != null) { - ers.attemptImmediateResolve(vm); - } - } - - BreakpointSpec - createClassLineBreakpoint(String classPattern, int line) { - ReferenceTypeSpec refSpec = - new PatternReferenceTypeSpec(classPattern); - return new LineBreakpointSpec(this, refSpec, line); - } - - BreakpointSpec - createSourceLineBreakpoint(String sourceName, int line) { - ReferenceTypeSpec refSpec = - new SourceNameReferenceTypeSpec(sourceName, line); - return new LineBreakpointSpec(this, refSpec, line); - } - - BreakpointSpec - createMethodBreakpoint(String classPattern, - String methodId, List methodArgs) { - ReferenceTypeSpec refSpec = - new PatternReferenceTypeSpec(classPattern); - return new MethodBreakpointSpec(this, refSpec, - methodId, methodArgs); - } - - ExceptionSpec - createExceptionIntercept(String classPattern, - boolean notifyCaught, - boolean notifyUncaught) { - ReferenceTypeSpec refSpec = - new PatternReferenceTypeSpec(classPattern); - return new ExceptionSpec(this, refSpec, - notifyCaught, notifyUncaught); - } - - AccessWatchpointSpec - createAccessWatchpoint(String classPattern, String fieldId) { - ReferenceTypeSpec refSpec = - new PatternReferenceTypeSpec(classPattern); - return new AccessWatchpointSpec(this, refSpec, fieldId); - } - - ModificationWatchpointSpec - createModificationWatchpoint(String classPattern, String fieldId) { - ReferenceTypeSpec refSpec = - new PatternReferenceTypeSpec(classPattern); - return new ModificationWatchpointSpec(this, refSpec, fieldId); - } - - void delete(EventRequestSpec ers) { - EventRequest request = ers.getEventRequest(); - synchronized (eventRequestSpecs) { - eventRequestSpecs.remove(ers); - } - if (request != null) { - request.virtualMachine().eventRequestManager() - .deleteEventRequest(request); - } - notifyDeleted(ers); - //### notify delete - here? - } - - List eventRequestSpecs() { - // We need to make a copy to avoid synchronization problems - synchronized (eventRequestSpecs) { - return new ArrayList(eventRequestSpecs); - } - } - - // -------- notify routines -------------------- - - @SuppressWarnings("unchecked") - private Vector specListeners() { - return (Vector)runtime.specListeners.clone(); - } - - void notifySet(EventRequestSpec spec) { - Vector l = specListeners(); - SpecEvent evt = new SpecEvent(spec); - for (int i = 0; i < l.size(); i++) { - spec.notifySet(l.elementAt(i), evt); - } - } - - void notifyDeferred(EventRequestSpec spec) { - Vector l = specListeners(); - SpecEvent evt = new SpecEvent(spec); - for (int i = 0; i < l.size(); i++) { - spec.notifyDeferred(l.elementAt(i), evt); - } - } - - void notifyDeleted(EventRequestSpec spec) { - Vector l = specListeners(); - SpecEvent evt = new SpecEvent(spec); - for (int i = 0; i < l.size(); i++) { - spec.notifyDeleted(l.elementAt(i), evt); - } - } - - void notifyResolved(EventRequestSpec spec) { - Vector l = specListeners(); - SpecEvent evt = new SpecEvent(spec); - for (int i = 0; i < l.size(); i++) { - spec.notifyResolved(l.elementAt(i), evt); - } - } - - void notifyError(EventRequestSpec spec, Exception exc) { - Vector l = specListeners(); - SpecErrorEvent evt = new SpecErrorEvent(spec, exc); - for (int i = 0; i < l.size(); i++) { - spec.notifyError(l.elementAt(i), evt); - } - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ExceptionSpec.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ExceptionSpec.java deleted file mode 100644 index df87688152c..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ExceptionSpec.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import com.sun.jdi.ReferenceType; - -public class ExceptionSpec extends EventRequestSpec { - - boolean notifyCaught; - boolean notifyUncaught; - - ExceptionSpec(EventRequestSpecList specs, ReferenceTypeSpec refSpec, - boolean notifyCaught, boolean notifyUncaught) - { - super(specs, refSpec); - this.notifyCaught = notifyCaught; - this.notifyUncaught = notifyUncaught; - } - - @Override - void notifySet(SpecListener listener, SpecEvent evt) { - listener.exceptionInterceptSet(evt); - } - - @Override - void notifyDeferred(SpecListener listener, SpecEvent evt) { - listener.exceptionInterceptDeferred(evt); - } - - @Override - void notifyResolved(SpecListener listener, SpecEvent evt) { - listener.exceptionInterceptResolved(evt); - } - - @Override - void notifyDeleted(SpecListener listener, SpecEvent evt) { - listener.exceptionInterceptDeleted(evt); - } - - @Override - void notifyError(SpecListener listener, SpecErrorEvent evt) { - listener.exceptionInterceptError(evt); - } - - /** - * The 'refType' is known to match. - */ - @Override - void resolve(ReferenceType refType) { - setRequest(refType.virtualMachine().eventRequestManager() - .createExceptionRequest(refType, - notifyCaught, notifyUncaught)); - } - - @Override - public int hashCode() { - return refSpec.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof ExceptionSpec) { - ExceptionSpec es = (ExceptionSpec)obj; - - return refSpec.equals(es.refSpec); - } else { - return false; - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("exception catch "); - sb.append(refSpec.toString()); - return sb.toString(); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ExecutionManager.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ExecutionManager.java deleted file mode 100644 index b5bc053a3c3..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ExecutionManager.java +++ /dev/null @@ -1,824 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import com.sun.jdi.*; -import com.sun.jdi.request.*; -import com.sun.jdi.connect.*; -import com.sun.tools.example.debug.expr.ExpressionParser; -import com.sun.tools.example.debug.expr.ParseException; - -import java.io.*; -import java.util.*; - -import com.sun.tools.example.debug.event.*; - -import javax.swing.SwingUtilities; - -/** - * Move this towards being only state and functionality - * that spans across Sessions (and thus VMs). - */ -public class ExecutionManager { - - private Session session; - - /** - * Get/set JDI trace mode. - */ - int traceMode = VirtualMachine.TRACE_NONE; - - ////////////////// Listener registration ////////////////// - - // Session Listeners - - ArrayList sessionListeners = new ArrayList(); - - public void addSessionListener(SessionListener listener) { - sessionListeners.add(listener); - } - - public void removeSessionListener(SessionListener listener) { - sessionListeners.remove(listener); - } - - // Spec Listeners - - ArrayList specListeners = new ArrayList(); - - public void addSpecListener(SpecListener cl) { - specListeners.add(cl); - } - - public void removeSpecListener(SpecListener cl) { - specListeners.remove(cl); - } - - // JDI Listeners - - ArrayList jdiListeners = new ArrayList(); - - /** - * Adds a JDIListener - */ - public void addJDIListener(JDIListener jl) { - jdiListeners.add(jl); - } - - /** - * Adds a JDIListener - at the specified position - */ - public void addJDIListener(int index, JDIListener jl) { - jdiListeners.add(index, jl); - } - - /** - * Removes a JDIListener - */ - public void removeJDIListener(JDIListener jl) { - jdiListeners.remove(jl); - } - - // App Echo Listeners - - private ArrayList appEchoListeners = new ArrayList(); - - public void addApplicationEchoListener(OutputListener l) { - appEchoListeners.add(l); - } - - public void removeApplicationEchoListener(OutputListener l) { - appEchoListeners.remove(l); - } - - // App Output Listeners - - private ArrayList appOutputListeners = new ArrayList(); - - public void addApplicationOutputListener(OutputListener l) { - appOutputListeners.add(l); - } - - public void removeApplicationOutputListener(OutputListener l) { - appOutputListeners.remove(l); - } - - // App Error Listeners - - private ArrayList appErrorListeners = new ArrayList(); - - public void addApplicationErrorListener(OutputListener l) { - appErrorListeners.add(l); - } - - public void removeApplicationErrorListener(OutputListener l) { - appErrorListeners.remove(l); - } - - // Diagnostic Listeners - - private ArrayList diagnosticsListeners = new ArrayList(); - - public void addDiagnosticsListener(OutputListener l) { - diagnosticsListeners.add(l); - } - - public void removeDiagnosticsListener(OutputListener l) { - diagnosticsListeners.remove(l); - } - - /////////// End Listener Registration ////////////// - - //### We probably don't want this public - public VirtualMachine vm() { - return session == null ? null : session.vm; - } - - void ensureActiveSession() throws NoSessionException { - if (session == null) { - throw new NoSessionException(); - } - } - - public EventRequestManager eventRequestManager() { - return vm() == null ? null : vm().eventRequestManager(); - } - - /** - * Get JDI trace mode. - */ - public int getTraceMode(int mode) { - return traceMode; - } - - /** - * Set JDI trace mode. - */ - public void setTraceMode(int mode) { - traceMode = mode; - if (session != null) { - session.setTraceMode(mode); - } - } - - /** - * Determine if VM is interrupted, i.e, present and not running. - */ - public boolean isInterrupted() /* should: throws NoSessionException */ { -// ensureActiveSession(); - return session.interrupted; - } - - /** - * Return a list of ReferenceType objects for all - * currently loaded classes and interfaces. - * Array types are not returned. - */ - public List allClasses() throws NoSessionException { - ensureActiveSession(); - return vm().allClasses(); - } - - /** - * Return a ReferenceType object for the currently - * loaded class or interface whose fully-qualified - * class name is specified, else return null if there - * is none. - * - * In general, we must return a list of types, because - * multiple class loaders could have loaded a class - * with the same fully-qualified name. - */ - public List findClassesByName(String name) throws NoSessionException { - ensureActiveSession(); - return vm().classesByName(name); - } - - /** - * Return a list of ReferenceType objects for all - * currently loaded classes and interfaces whose name - * matches the given pattern. The pattern syntax is - * open to some future revision, but currently consists - * of a fully-qualified class name in which the first - * component may optionally be a "*" character, designating - * an arbitrary prefix. - */ - public List findClassesMatchingPattern(String pattern) - throws NoSessionException { - ensureActiveSession(); - List result = new ArrayList(); //### Is default size OK? - if (pattern.startsWith("*.")) { - // Wildcard matches any leading package name. - pattern = pattern.substring(1); - for (ReferenceType type : vm().allClasses()) { - if (type.name().endsWith(pattern)) { - result.add(type); - } - } - return result; - } else { - // It's a class name. - return vm().classesByName(pattern); - } - } - - /* - * Return a list of ThreadReference objects corresponding - * to the threads that are currently active in the VM. - * A thread is removed from the list just before the - * thread terminates. - */ - - public List allThreads() throws NoSessionException { - ensureActiveSession(); - return vm().allThreads(); - } - - /* - * Return a list of ThreadGroupReference objects corresponding - * to the top-level threadgroups that are currently active in the VM. - * Note that a thread group may be empty, or contain no threads as - * descendents. - */ - - public List topLevelThreadGroups() throws NoSessionException { - ensureActiveSession(); - return vm().topLevelThreadGroups(); - } - - /* - * Return the system threadgroup. - */ - - public ThreadGroupReference systemThreadGroup() - throws NoSessionException { - ensureActiveSession(); - return vm().topLevelThreadGroups().get(0); - } - - /* - * Evaluate an expression. - */ - - public Value evaluate(final StackFrame f, String expr) - throws ParseException, - InvocationException, - InvalidTypeException, - ClassNotLoadedException, - NoSessionException, - IncompatibleThreadStateException { - ExpressionParser.GetFrame frameGetter = null; - ensureActiveSession(); - if (f != null) { - frameGetter = new ExpressionParser.GetFrame() { - @Override - public StackFrame get() /* throws IncompatibleThreadStateException */ { - return f; - } - }; - } - return ExpressionParser.evaluate(expr, vm(), frameGetter); - } - - - /* - * Start a new VM. - */ - - public void run(boolean suspended, - String vmArgs, - String className, - String args) throws VMLaunchFailureException { - - endSession(); - - //### Set a breakpoint on 'main' method. - //### Would be cleaner if we could just bring up VM already suspended. - if (suspended) { - //### Set breakpoint at 'main(java.lang.String[])'. - List argList = new ArrayList(1); - argList.add("java.lang.String[]"); - createMethodBreakpoint(className, "main", argList); - } - - String cmdLine = className + " " + args; - - startSession(new ChildSession(this, vmArgs, cmdLine, - appInput, appOutput, appError, - diagnostics)); - } - - /* - * Attach to an existing VM. - */ - public void attach(String portName) throws VMLaunchFailureException { - endSession(); - - //### Changes made here for connectors have broken the - //### the 'Session' abstraction. The 'Session.attach()' - //### method is intended to encapsulate all of the various - //### ways in which session start-up can fail. (maddox 12/18/98) - - /* - * Now that attaches and launches both go through Connectors, - * it may be worth creating a new subclass of Session for - * attach sessions. - */ - VirtualMachineManager mgr = Bootstrap.virtualMachineManager(); - AttachingConnector connector = mgr.attachingConnectors().get(0); - Map arguments = connector.defaultArguments(); - arguments.get("port").setValue(portName); - - Session newSession = internalAttach(connector, arguments); - if (newSession != null) { - startSession(newSession); - } - } - - private Session internalAttach(AttachingConnector connector, - Map arguments) { - try { - VirtualMachine vm = connector.attach(arguments); - return new Session(vm, this, diagnostics); - } catch (IOException ioe) { - diagnostics.putString("\n Unable to attach to target VM: " + - ioe.getMessage()); - } catch (IllegalConnectorArgumentsException icae) { - diagnostics.putString("\n Invalid connector arguments: " + - icae.getMessage()); - } - return null; - } - - private Session internalListen(ListeningConnector connector, - Map arguments) { - try { - VirtualMachine vm = connector.accept(arguments); - return new Session(vm, this, diagnostics); - } catch (IOException ioe) { - diagnostics.putString( - "\n Unable to accept connection to target VM: " + - ioe.getMessage()); - } catch (IllegalConnectorArgumentsException icae) { - diagnostics.putString("\n Invalid connector arguments: " + - icae.getMessage()); - } - return null; - } - - /* - * Connect via user specified arguments - * @return true on success - */ - public boolean explictStart(Connector connector, Map arguments) - throws VMLaunchFailureException { - Session newSession = null; - - endSession(); - - if (connector instanceof LaunchingConnector) { - // we were launched, use ChildSession - newSession = new ChildSession(this, (LaunchingConnector)connector, - arguments, - appInput, appOutput, appError, - diagnostics); - } else if (connector instanceof AttachingConnector) { - newSession = internalAttach((AttachingConnector)connector, - arguments); - } else if (connector instanceof ListeningConnector) { - newSession = internalListen((ListeningConnector)connector, - arguments); - } else { - diagnostics.putString("\n Unknown connector: " + connector); - } - if (newSession != null) { - startSession(newSession); - } - return newSession != null; - } - - /* - * Detach from VM. If VM was started by debugger, terminate it. - */ - public void detach() throws NoSessionException { - ensureActiveSession(); - endSession(); - } - - private void startSession(Session s) throws VMLaunchFailureException { - if (!s.attach()) { - throw new VMLaunchFailureException(); - } - session = s; - EventRequestManager em = vm().eventRequestManager(); - ClassPrepareRequest classPrepareRequest = em.createClassPrepareRequest(); - //### We must allow the deferred breakpoints to be resolved before - //### we continue executing the class. We could optimize if there - //### were no deferred breakpoints outstanding for a particular class. - //### Can we do this with JDI? - classPrepareRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); - classPrepareRequest.enable(); - ClassUnloadRequest classUnloadRequest = em.createClassUnloadRequest(); - classUnloadRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE); - classUnloadRequest.enable(); - ThreadStartRequest threadStartRequest = em.createThreadStartRequest(); - threadStartRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE); - threadStartRequest.enable(); - ThreadDeathRequest threadDeathRequest = em.createThreadDeathRequest(); - threadDeathRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE); - threadDeathRequest.enable(); - ExceptionRequest exceptionRequest = - em.createExceptionRequest(null, false, true); - exceptionRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); - exceptionRequest.enable(); - validateThreadInfo(); - session.interrupted = true; - notifySessionStart(); - } - - void endSession() { - if (session != null) { - session.detach(); - session = null; - invalidateThreadInfo(); - notifySessionDeath(); - } - } - - /* - * Suspend all VM activity. - */ - - public void interrupt() throws NoSessionException { - ensureActiveSession(); - vm().suspend(); - //### Is it guaranteed that the interrupt has happened? - validateThreadInfo(); - session.interrupted = true; - notifyInterrupted(); - } - - /* - * Resume interrupted VM. - */ - - public void go() throws NoSessionException, VMNotInterruptedException { - ensureActiveSession(); - invalidateThreadInfo(); - session.interrupted = false; - notifyContinued(); - vm().resume(); - } - - /* - * Stepping. - */ - void clearPreviousStep(ThreadReference thread) { - /* - * A previous step may not have completed on this thread; - * if so, it gets removed here. - */ - EventRequestManager mgr = vm().eventRequestManager(); - for (StepRequest request : mgr.stepRequests()) { - if (request.thread().equals(thread)) { - mgr.deleteEventRequest(request); - break; - } - } - } - - private void generalStep(ThreadReference thread, int size, int depth) - throws NoSessionException { - ensureActiveSession(); - invalidateThreadInfo(); - session.interrupted = false; - notifyContinued(); - - clearPreviousStep(thread); - EventRequestManager reqMgr = vm().eventRequestManager(); - StepRequest request = reqMgr.createStepRequest(thread, - size, depth); - // We want just the next step event and no others - request.addCountFilter(1); - request.enable(); - vm().resume(); - } - - public void stepIntoInstruction(ThreadReference thread) - throws NoSessionException { - generalStep(thread, StepRequest.STEP_MIN, StepRequest.STEP_INTO); - } - - public void stepOverInstruction(ThreadReference thread) - throws NoSessionException { - generalStep(thread, StepRequest.STEP_MIN, StepRequest.STEP_OVER); - } - - public void stepIntoLine(ThreadReference thread) - throws NoSessionException, - AbsentInformationException { - generalStep(thread, StepRequest.STEP_LINE, StepRequest.STEP_INTO); - } - - public void stepOverLine(ThreadReference thread) - throws NoSessionException, - AbsentInformationException { - generalStep(thread, StepRequest.STEP_LINE, StepRequest.STEP_OVER); - } - - public void stepOut(ThreadReference thread) - throws NoSessionException { - generalStep(thread, StepRequest.STEP_MIN, StepRequest.STEP_OUT); - } - - /* - * Thread control. - */ - - public void suspendThread(ThreadReference thread) throws NoSessionException { - ensureActiveSession(); - thread.suspend(); - } - - public void resumeThread(ThreadReference thread) throws NoSessionException { - ensureActiveSession(); - thread.resume(); - } - - public void stopThread(ThreadReference thread) throws NoSessionException { - ensureActiveSession(); - //### Need an exception now. Which one to use? - //thread.stop(); - } - - /* - * ThreadInfo objects -- Allow query of thread status and stack. - */ - - private List threadInfoList = new LinkedList(); - //### Should be weak! (in the value, not the key) - private HashMap threadInfoMap = new HashMap(); - - public ThreadInfo threadInfo(ThreadReference thread) { - if (session == null || thread == null) { - return null; - } - ThreadInfo info = threadInfoMap.get(thread); - if (info == null) { - //### Should not hardcode initial frame count and prefetch here! - //info = new ThreadInfo(thread, 10, 10); - info = new ThreadInfo(thread); - if (session.interrupted) { - info.validate(); - } - threadInfoList.add(info); - threadInfoMap.put(thread, info); - } - return info; - } - - void validateThreadInfo() { - session.interrupted = true; - for (ThreadInfo threadInfo : threadInfoList) { - threadInfo.validate(); - } - } - - private void invalidateThreadInfo() { - if (session != null) { - session.interrupted = false; - for (ThreadInfo threadInfo : threadInfoList) { - threadInfo.invalidate(); - } - } - } - - void removeThreadInfo(ThreadReference thread) { - ThreadInfo info = threadInfoMap.get(thread); - if (info != null) { - info.invalidate(); - threadInfoMap.remove(thread); - threadInfoList.remove(info); - } - } - - /* - * Listen for Session control events. - */ - - private void notifyInterrupted() { - ArrayList l = new ArrayList(sessionListeners); - EventObject evt = new EventObject(this); - for (int i = 0; i < l.size(); i++) { - l.get(i).sessionInterrupt(evt); - } - } - - private void notifyContinued() { - ArrayList l = new ArrayList(sessionListeners); - EventObject evt = new EventObject(this); - for (int i = 0; i < l.size(); i++) { - l.get(i).sessionContinue(evt); - } - } - - private void notifySessionStart() { - ArrayList l = new ArrayList(sessionListeners); - EventObject evt = new EventObject(this); - for (int i = 0; i < l.size(); i++) { - l.get(i).sessionStart(evt); - } - } - - private void notifySessionDeath() { -/*** noop for now - ArrayList l = new ArrayList(sessionListeners); - EventObject evt = new EventObject(this); - for (int i = 0; i < l.size(); i++) { - ((SessionListener)l.get(i)).sessionDeath(evt); - } -****/ - } - - /* - * Listen for input and output requests from the application - * being debugged. These are generated only when the debuggee - * is spawned as a child of the debugger. - */ - - private Object inputLock = new Object(); - private LinkedList inputBuffer = new LinkedList(); - - private void resetInputBuffer() { - synchronized (inputLock) { - inputBuffer = new LinkedList(); - } - } - - public void sendLineToApplication(String line) { - synchronized (inputLock) { - inputBuffer.addFirst(line); - inputLock.notifyAll(); - } - } - - private InputListener appInput = new InputListener() { - @Override - public String getLine() { - // Don't allow reader to be interrupted -- catch and retry. - String line = null; - while (line == null) { - synchronized (inputLock) { - try { - while (inputBuffer.size() < 1) { - inputLock.wait(); - } - line = inputBuffer.removeLast(); - } catch (InterruptedException e) {} - } - } - // We must not be holding inputLock here, as the listener - // that we call to echo a line might call us re-entrantly - // to provide another line of input. - // Run in Swing event dispatcher thread. - final String input = line; - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - echoInputLine(input); - } - }); - return line; - } - }; - - private static String newline = System.getProperty("line.separator"); - - private void echoInputLine(String line) { - ArrayList l = new ArrayList(appEchoListeners); - for (int i = 0; i < l.size(); i++) { - OutputListener ol = l.get(i); - ol.putString(line); - ol.putString(newline); - } - } - - private OutputListener appOutput = new OutputListener() { - @Override - public void putString(String string) { - ArrayList l = new ArrayList(appEchoListeners); - for (int i = 0; i < l.size(); i++) { - l.get(i).putString(string); - } - } - }; - - private OutputListener appError = new OutputListener() { - @Override - public void putString(String string) { - ArrayList l = new ArrayList(appEchoListeners); - for (int i = 0; i < l.size(); i++) { - l.get(i).putString(string); - } - } - }; - - private OutputListener diagnostics = new OutputListener() { - @Override - public void putString(String string) { - ArrayList l = new ArrayList(diagnosticsListeners); - for (int i = 0; i < l.size(); i++) { - l.get(i).putString(string); - } - } - }; - - ///////////// Spec Request Creation/Deletion/Query /////////// - - private EventRequestSpecList specList = new EventRequestSpecList(this); - - public BreakpointSpec - createSourceLineBreakpoint(String sourceName, int line) { - return specList.createSourceLineBreakpoint(sourceName, line); - } - - public BreakpointSpec - createClassLineBreakpoint(String classPattern, int line) { - return specList.createClassLineBreakpoint(classPattern, line); - } - - public BreakpointSpec - createMethodBreakpoint(String classPattern, - String methodId, List methodArgs) { - return specList.createMethodBreakpoint(classPattern, - methodId, methodArgs); - } - - public ExceptionSpec - createExceptionIntercept(String classPattern, - boolean notifyCaught, - boolean notifyUncaught) { - return specList.createExceptionIntercept(classPattern, - notifyCaught, - notifyUncaught); - } - - public AccessWatchpointSpec - createAccessWatchpoint(String classPattern, String fieldId) { - return specList.createAccessWatchpoint(classPattern, fieldId); - } - - public ModificationWatchpointSpec - createModificationWatchpoint(String classPattern, String fieldId) { - return specList.createModificationWatchpoint(classPattern, - fieldId); - } - - public void delete(EventRequestSpec spec) { - specList.delete(spec); - } - - void resolve(ReferenceType refType) { - specList.resolve(refType); - } - - public void install(EventRequestSpec spec) { - specList.install(spec, vm()); - } - - public List eventRequestSpecs() { - return specList.eventRequestSpecs(); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/FrameIndexOutOfBoundsException.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/FrameIndexOutOfBoundsException.java deleted file mode 100644 index 57d4e2a6d9c..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/FrameIndexOutOfBoundsException.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -public class FrameIndexOutOfBoundsException extends IndexOutOfBoundsException { - - private static final long serialVersionUID = -4870148107027371437L; -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/JDIEventSource.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/JDIEventSource.java deleted file mode 100644 index 2d92094d0d5..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/JDIEventSource.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; - -import com.sun.tools.example.debug.event.*; - -import javax.swing.SwingUtilities; - -/** - */ -class JDIEventSource extends Thread { - - private /*final*/ EventQueue queue; - private /*final*/ Session session; - private /*final*/ ExecutionManager runtime; - private final JDIListener firstListener = new FirstListener(); - - private boolean wantInterrupt; //### Hack - - /** - * Create event source. - */ - JDIEventSource(Session session) { - super("JDI Event Set Dispatcher"); - this.session = session; - this.runtime = session.runtime; - this.queue = session.vm.eventQueue(); - } - - @Override - public void run() { - try { - runLoop(); - } catch (Exception exc) { - //### Do something different for InterruptedException??? - // just exit - } - session.running = false; - } - - private void runLoop() throws InterruptedException { - AbstractEventSet es; - do { - EventSet jdiEventSet = queue.remove(); - es = AbstractEventSet.toSpecificEventSet(jdiEventSet); - session.interrupted = es.suspendedAll(); - dispatchEventSet(es); - } while(!(es instanceof VMDisconnectEventSet)); - } - - //### Gross foul hackery! - private void dispatchEventSet(final AbstractEventSet es) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - boolean interrupted = es.suspendedAll(); - es.notify(firstListener); - boolean wantInterrupt = JDIEventSource.this.wantInterrupt; - for (JDIListener jl : session.runtime.jdiListeners) { - es.notify(jl); - } - if (interrupted && !wantInterrupt) { - session.interrupted = false; - //### Catch here is a hack - try { - session.vm.resume(); - } catch (VMDisconnectedException ee) {} - } - if (es instanceof ThreadDeathEventSet) { - ThreadReference t = ((ThreadDeathEventSet)es).getThread(); - session.runtime.removeThreadInfo(t); - } - } - }); - } - - private void finalizeEventSet(AbstractEventSet es) { - if (session.interrupted && !wantInterrupt) { - session.interrupted = false; - //### Catch here is a hack - try { - session.vm.resume(); - } catch (VMDisconnectedException ee) {} - } - if (es instanceof ThreadDeathEventSet) { - ThreadReference t = ((ThreadDeathEventSet)es).getThread(); - session.runtime.removeThreadInfo(t); - } - } - - //### This is a Hack, deal with it - private class FirstListener implements JDIListener { - - @Override - public void accessWatchpoint(AccessWatchpointEventSet e) { - session.runtime.validateThreadInfo(); - wantInterrupt = true; - } - - @Override - public void classPrepare(ClassPrepareEventSet e) { - wantInterrupt = false; - runtime.resolve(e.getReferenceType()); - } - - @Override - public void classUnload(ClassUnloadEventSet e) { - wantInterrupt = false; - } - - @Override - public void exception(ExceptionEventSet e) { - wantInterrupt = true; - } - - @Override - public void locationTrigger(LocationTriggerEventSet e) { - session.runtime.validateThreadInfo(); - wantInterrupt = true; - } - - @Override - public void modificationWatchpoint(ModificationWatchpointEventSet e) { - session.runtime.validateThreadInfo(); - wantInterrupt = true; - } - - @Override - public void threadDeath(ThreadDeathEventSet e) { - wantInterrupt = false; - } - - @Override - public void threadStart(ThreadStartEventSet e) { - wantInterrupt = false; - } - - @Override - public void vmDeath(VMDeathEventSet e) { - //### Should have some way to notify user - //### that VM died before the session ended. - wantInterrupt = false; - } - - @Override - public void vmDisconnect(VMDisconnectEventSet e) { - //### Notify user? - wantInterrupt = false; - session.runtime.endSession(); - } - - @Override - public void vmStart(VMStartEventSet e) { - //### Do we need to do anything with it? - wantInterrupt = false; - } - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/LineBreakpointSpec.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/LineBreakpointSpec.java deleted file mode 100644 index f7d66ce2d52..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/LineBreakpointSpec.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import com.sun.jdi.*; -import java.util.List; - -public class LineBreakpointSpec extends BreakpointSpec { - int lineNumber; - - LineBreakpointSpec(EventRequestSpecList specs, - ReferenceTypeSpec refSpec, int lineNumber) { - super(specs, refSpec); - this.lineNumber = lineNumber; - } - - /** - * The 'refType' is known to match. - */ - @Override - void resolve(ReferenceType refType) throws InvalidTypeException, - LineNotFoundException { - if (!(refType instanceof ClassType)) { - throw new InvalidTypeException(); - } - Location location = location((ClassType)refType); - setRequest(refType.virtualMachine().eventRequestManager() - .createBreakpointRequest(location)); - } - - private Location location(ClassType clazz) throws - LineNotFoundException { - Location location = null; - try { - List locs = clazz.locationsOfLine(lineNumber()); - if (locs.size() == 0) { - throw new LineNotFoundException(); - } - // TODO handle multiple locations - location = locs.get(0); - if (location.method() == null) { - throw new LineNotFoundException(); - } - } catch (AbsentInformationException e) { - /* - * TO DO: throw something more specific, or allow - * AbsentInfo exception to pass through. - */ - throw new LineNotFoundException(); - } - return location; - } - - public int lineNumber() { - return lineNumber; - } - - @Override - public int hashCode() { - return refSpec.hashCode() + lineNumber; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof LineBreakpointSpec) { - LineBreakpointSpec breakpoint = (LineBreakpointSpec)obj; - - return refSpec.equals(breakpoint.refSpec) && - (lineNumber == breakpoint.lineNumber); - } else { - return false; - } - } - - @Override - public String errorMessageFor(Exception e) { - if (e instanceof LineNotFoundException) { - return ("No code at line " + lineNumber() + " in " + refSpec); - } else if (e instanceof InvalidTypeException) { - return ("Breakpoints can be located only in classes. " + - refSpec + " is an interface or array"); - } else { - return super.errorMessageFor( e); - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("breakpoint "); - sb.append(refSpec.toString()); - sb.append(':'); - sb.append(lineNumber); - sb.append(" ("); - sb.append(getStatusString()); - sb.append(')'); - return sb.toString(); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/MalformedMemberNameException.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/MalformedMemberNameException.java deleted file mode 100644 index 1980893a361..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/MalformedMemberNameException.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -class MalformedMemberNameException extends Exception { - - private static final long serialVersionUID = -7726664097374844485L; - - public MalformedMemberNameException() { - super(); - } - - public MalformedMemberNameException(String s) { - super(s); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/MethodBreakpointSpec.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/MethodBreakpointSpec.java deleted file mode 100644 index b414443faf7..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/MethodBreakpointSpec.java +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import com.sun.jdi.*; -import java.util.ArrayList; -import java.util.List; - -public class MethodBreakpointSpec extends BreakpointSpec { - String methodId; - List methodArgs; - - MethodBreakpointSpec(EventRequestSpecList specs, - ReferenceTypeSpec refSpec, - String methodId, List methodArgs) { - super(specs, refSpec); - this.methodId = methodId; - this.methodArgs = methodArgs; - } - - /** - * The 'refType' is known to match. - */ - @Override - void resolve(ReferenceType refType) throws MalformedMemberNameException, - AmbiguousMethodException, - InvalidTypeException, - NoSuchMethodException, - NoSessionException { - if (!isValidMethodName(methodId)) { - throw new MalformedMemberNameException(methodId); - } - if (!(refType instanceof ClassType)) { - throw new InvalidTypeException(); - } - Location location = location((ClassType)refType); - setRequest(refType.virtualMachine().eventRequestManager() - .createBreakpointRequest(location)); - } - - private Location location(ClassType clazz) throws - AmbiguousMethodException, - NoSuchMethodException, - NoSessionException { - Method method = findMatchingMethod(clazz); - Location location = method.location(); - return location; - } - - public String methodName() { - return methodId; - } - - public List methodArgs() { - return methodArgs; - } - - @Override - public int hashCode() { - return refSpec.hashCode() + - ((methodId != null) ? methodId.hashCode() : 0) + - ((methodArgs != null) ? methodArgs.hashCode() : 0); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof MethodBreakpointSpec) { - MethodBreakpointSpec breakpoint = (MethodBreakpointSpec)obj; - - return methodId.equals(breakpoint.methodId) && - methodArgs.equals(breakpoint.methodArgs) && - refSpec.equals(breakpoint.refSpec); - } else { - return false; - } - } - - @Override - public String errorMessageFor(Exception e) { - if (e instanceof AmbiguousMethodException) { - return ("Method " + methodName() + " is overloaded; specify arguments"); - /* - * TO DO: list the methods here - */ - } else if (e instanceof NoSuchMethodException) { - return ("No method " + methodName() + " in " + refSpec); - } else if (e instanceof InvalidTypeException) { - return ("Breakpoints can be located only in classes. " + - refSpec + " is an interface or array"); - } else { - return super.errorMessageFor( e); - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("breakpoint "); - sb.append(refSpec.toString()); - sb.append('.'); - sb.append(methodId); - if (methodArgs != null) { - boolean first = true; - sb.append('('); - for (String name : methodArgs) { - if (!first) { - sb.append(','); - } - sb.append(name); - first = false; - } - sb.append(")"); - } - sb.append(" ("); - sb.append(getStatusString()); - sb.append(')'); - return sb.toString(); - } - - private boolean isValidMethodName(String s) { - return isJavaIdentifier(s) || - s.equals("") || - s.equals(""); - } - - /* - * Compare a method's argument types with a Vector of type names. - * Return true if each argument type has a name identical to the - * corresponding string in the vector (allowing for varargs) - * and if the number of arguments in the method matches the - * number of names passed - */ - private boolean compareArgTypes(Method method, List nameList) { - List argTypeNames = method.argumentTypeNames(); - - // If argument counts differ, we can stop here - if (argTypeNames.size() != nameList.size()) { - return false; - } - - // Compare each argument type's name - int nTypes = argTypeNames.size(); - for (int i = 0; i < nTypes; ++i) { - String comp1 = argTypeNames.get(i); - String comp2 = nameList.get(i); - if (! comp1.equals(comp2)) { - /* - * We have to handle varargs. EG, the - * method's last arg type is xxx[] - * while the nameList contains xxx... - * Note that the nameList can also contain - * xxx[] in which case we don't get here. - */ - if (i != nTypes - 1 || - !method.isVarArgs() || - !comp2.endsWith("...")) { - return false; - } - /* - * The last types differ, it is a varargs - * method and the nameList item is varargs. - * We just have to compare the type names, eg, - * make sure we don't have xxx[] for the method - * arg type and yyy... for the nameList item. - */ - int comp1Length = comp1.length(); - if (comp1Length + 1 != comp2.length()) { - // The type names are different lengths - return false; - } - // We know the two type names are the same length - if (!comp1.regionMatches(0, comp2, 0, comp1Length - 2)) { - return false; - } - // We do have xxx[] and xxx... as the last param type - return true; - } - } - - return true; - } - - private VirtualMachine vm() { - return request.virtualMachine(); - } - - /** - * Remove unneeded spaces and expand class names to fully - * qualified names, if necessary and possible. - */ - private String normalizeArgTypeName(String name) throws NoSessionException { - /* - * Separate the type name from any array modifiers, - * stripping whitespace after the name ends. - */ - int i = 0; - StringBuilder typePart = new StringBuilder(); - StringBuilder arrayPart = new StringBuilder(); - name = name.trim(); - int nameLength = name.length(); - /* - * For varargs, there can be spaces before the ... but not - * within the ... So, we will just ignore the ... - * while stripping blanks. - */ - boolean isVarArgs = name.endsWith("..."); - if (isVarArgs) { - nameLength -= 3; - } - - while (i < nameLength) { - char c = name.charAt(i); - if (Character.isWhitespace(c) || c == '[') { - break; // name is complete - } - typePart.append(c); - i++; - } - while (i < nameLength) { - char c = name.charAt(i); - if ( (c == '[') || (c == ']')) { - arrayPart.append(c); - } else if (!Character.isWhitespace(c)) { - throw new IllegalArgumentException( - "Invalid argument type name"); - - } - i++; - } - - name = typePart.toString(); - - /* - * When there's no sign of a package name already, - * try to expand the - * the name to a fully qualified class name - */ - if ((name.indexOf('.') == -1) || name.startsWith("*.")) { - try { - List refs = specs.runtime.findClassesMatchingPattern(name); - if (refs.size() > 0) { //### ambiguity??? - name = ((ReferenceType)(refs.get(0))).name(); - } - } catch (IllegalArgumentException e) { - // We'll try the name as is - } - } - name += arrayPart.toString(); - if (isVarArgs) { - name += "..."; - } - return name; - } - - /* - * Attempt an unambiguous match of the method name and - * argument specification to a method. If no arguments - * are specified, the method must not be overloaded. - * Otherwise, the argument types much match exactly - */ - private Method findMatchingMethod(ClassType clazz) - throws AmbiguousMethodException, - NoSuchMethodException, - NoSessionException { - - // Normalize the argument string once before looping below. - List argTypeNames = null; - if (methodArgs() != null) { - argTypeNames = new ArrayList(methodArgs().size()); - for (String name : methodArgs()) { - name = normalizeArgTypeName(name); - argTypeNames.add(name); - } - } - - // Check each method in the class for matches - Method firstMatch = null; // first method with matching name - Method exactMatch = null; // (only) method with same name & sig - int matchCount = 0; // > 1 implies overload - for (Method candidate : clazz.methods()) { - if (candidate.name().equals(methodName())) { - matchCount++; - - // Remember the first match in case it is the only one - if (matchCount == 1) { - firstMatch = candidate; - } - - // If argument types were specified, check against candidate - if ((argTypeNames != null) - && compareArgTypes(candidate, argTypeNames) == true) { - exactMatch = candidate; - break; - } - } - } - - // Determine method for breakpoint - Method method = null; - if (exactMatch != null) { - // Name and signature match - method = exactMatch; - } else if ((argTypeNames == null) && (matchCount > 0)) { - // At least one name matched and no arg types were specified - if (matchCount == 1) { - method = firstMatch; // Only one match; safe to use it - } else { - throw new AmbiguousMethodException(); - } - } else { - throw new NoSuchMethodException(methodName()); - } - return method; - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/MethodNotFoundException.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/MethodNotFoundException.java deleted file mode 100644 index 820c35cc61b..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/MethodNotFoundException.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -public class MethodNotFoundException extends Exception -{ - private static final long serialVersionUID = -2064968107599632609L; - - public MethodNotFoundException() - { - super(); - } - - public MethodNotFoundException(String s) - { - super(s); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ModificationWatchpointSpec.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ModificationWatchpointSpec.java deleted file mode 100644 index b8f2b86e65a..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ModificationWatchpointSpec.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import com.sun.jdi.*; - -public class ModificationWatchpointSpec extends WatchpointSpec { - - ModificationWatchpointSpec(EventRequestSpecList specs, - ReferenceTypeSpec refSpec, String fieldId) { - super(specs, refSpec, fieldId); - } - - /** - * The 'refType' is known to match. - */ - @Override - void resolve(ReferenceType refType) throws InvalidTypeException, - NoSuchFieldException { - if (!(refType instanceof ClassType)) { - throw new InvalidTypeException(); - } - Field field = refType.fieldByName(fieldId); - if (field == null) { - throw new NoSuchFieldException(fieldId); - } - setRequest(refType.virtualMachine().eventRequestManager() - .createModificationWatchpointRequest(field)); - } - - @Override - public boolean equals(Object obj) { - return (obj instanceof ModificationWatchpointSpec) && - super.equals(obj); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/NoThreadException.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/NoThreadException.java deleted file mode 100644 index 12512094f4d..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/NoThreadException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -public class NoThreadException extends Exception { - - private static final long serialVersionUID = 1846613539928921998L; - -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/OutputListener.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/OutputListener.java deleted file mode 100644 index 8bb6701595e..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/OutputListener.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -public interface OutputListener { - void putString(String str); - //void putLine(String line); -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ParseException.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ParseException.java deleted file mode 100644 index 3d407985635..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ParseException.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -// dummy placeholder for javaCC-generated code. - -public class ParseException extends Exception {} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/PatternReferenceTypeSpec.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/PatternReferenceTypeSpec.java deleted file mode 100644 index fa034aea3b4..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/PatternReferenceTypeSpec.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import com.sun.jdi.*; -import java.util.StringTokenizer; - -class PatternReferenceTypeSpec implements ReferenceTypeSpec { - final boolean isWild; - final String classId; - - PatternReferenceTypeSpec(String classId) -// throws ClassNotFoundException - { -// checkClassName(classId); - isWild = classId.startsWith("*."); - if (isWild) { - this.classId = classId.substring(1); - } else { - this.classId = classId; - } - } - - /** - * Does the specified ReferenceType match this spec. - */ - @Override - public boolean matches(ReferenceType refType) { - if (isWild) { - return refType.name().endsWith(classId); - } else { - return refType.name().equals(classId); - } - } - - @Override - public int hashCode() { - return classId.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof PatternReferenceTypeSpec) { - PatternReferenceTypeSpec spec = (PatternReferenceTypeSpec)obj; - - return classId.equals(spec.classId) && (isWild == spec.isWild); - } else { - return false; - } - } - - private void checkClassName(String className) throws ClassNotFoundException { - // Do stricter checking of class name validity on deferred - // because if the name is invalid, it will - // never match a future loaded class, and we'll be silent - // about it. - StringTokenizer tokenizer = new StringTokenizer(className, "."); - boolean first = true; - while (tokenizer.hasMoreTokens()) { - String token = tokenizer.nextToken(); - // Each dot-separated piece must be a valid identifier - // and the first token can also be "*". (Note that - // numeric class ids are not permitted. They must - // match a loaded class.) - if (!Utils.isJavaIdentifier(token) && !(first && token.equals("*"))) { - throw new ClassNotFoundException(); - } - first = false; - } - } - - @Override - public String toString() { - return isWild? "*" + classId : classId; - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ReferenceTypeSpec.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ReferenceTypeSpec.java deleted file mode 100644 index 7ad277e341f..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ReferenceTypeSpec.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import com.sun.jdi.*; - -interface ReferenceTypeSpec { - /** - * Does the specified ReferenceType match this spec. - */ - boolean matches(ReferenceType refType); - - @Override - int hashCode(); - - @Override - boolean equals(Object obj); -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/Session.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/Session.java deleted file mode 100644 index 883834a07a1..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/Session.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import com.sun.jdi.VirtualMachine; -import com.sun.jdi.VMDisconnectedException; - -/** - * Our repository of what we know about the state of one - * running VM. - */ -class Session { - - final VirtualMachine vm; - final ExecutionManager runtime; - final OutputListener diagnostics; - - boolean running = true; // Set false by JDIEventSource - boolean interrupted = false; // Set false by JDIEventSource - - private JDIEventSource eventSourceThread = null; - private int traceFlags; - private boolean dead = false; - - public Session(VirtualMachine vm, ExecutionManager runtime, - OutputListener diagnostics) { - this.vm = vm; - this.runtime = runtime; - this.diagnostics = diagnostics; - this.traceFlags = VirtualMachine.TRACE_NONE; - } - - /** - * Determine if VM is interrupted, i.e, present and not running. - */ - public boolean isInterrupted() { - return interrupted; - } - - public void setTraceMode(int traceFlags) { - this.traceFlags = traceFlags; - if (!dead) { - vm.setDebugTraceMode(traceFlags); - } - } - - public boolean attach() { - vm.setDebugTraceMode(traceFlags); - diagnostics.putString("Connected to VM"); - eventSourceThread = new JDIEventSource(this); - eventSourceThread.start(); - return true; - } - - public void detach() { - if (!dead) { - eventSourceThread.interrupt(); - eventSourceThread = null; - //### The VM may already be disconnected - //### if the debuggee did a System.exit(). - //### Exception handler here is a kludge, - //### Rather, there are many other places - //### where we need to handle this exception, - //### and initiate a detach due to an error - //### condition, e.g., connection failure. - try { - vm.dispose(); - } catch (VMDisconnectedException ee) {} - dead = true; - diagnostics.putString("Disconnected from VM"); - } - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SessionListener.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SessionListener.java deleted file mode 100644 index e13c4d70e72..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SessionListener.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import java.util.EventObject; -import java.util.EventListener; - -public interface SessionListener extends EventListener { - - void sessionStart(EventObject e); - - void sessionInterrupt(EventObject e); - void sessionContinue(EventObject e); -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SourceNameReferenceTypeSpec.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SourceNameReferenceTypeSpec.java deleted file mode 100644 index 36061bfc487..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SourceNameReferenceTypeSpec.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import com.sun.jdi.*; - -class SourceNameReferenceTypeSpec implements ReferenceTypeSpec { - final String sourceName; - final int linenumber; - - SourceNameReferenceTypeSpec(String sourceName, int linenumber) { - this.sourceName = sourceName; - this.linenumber = linenumber; - } - - /** - * Does the specified ReferenceType match this spec. - */ - @Override - public boolean matches(ReferenceType refType) { - try { - if (refType.sourceName().equals(sourceName)) { - try { - refType.locationsOfLine(linenumber); - // if we don't throw an exception then it was found - return true; - } catch(AbsentInformationException exc) { - } catch(ObjectCollectedException exc) { - } - } - } catch(AbsentInformationException exc) { - // for sourceName(), fall through - } - return false; - } - - @Override - public int hashCode() { - return sourceName.hashCode() + linenumber; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof SourceNameReferenceTypeSpec) { - SourceNameReferenceTypeSpec spec = (SourceNameReferenceTypeSpec)obj; - - return sourceName.equals(spec.sourceName) && - (linenumber == spec.linenumber); - } else { - return false; - } - } - - @Override - public String toString() { - return sourceName + "@" + linenumber; - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SpecErrorEvent.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SpecErrorEvent.java deleted file mode 100644 index baab1291d2d..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SpecErrorEvent.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -public class SpecErrorEvent extends SpecEvent { - - private static final long serialVersionUID = 8162634387866409578L; - private Exception reason; - - public SpecErrorEvent(EventRequestSpec eventRequestSpec, - Exception reason) { - super(eventRequestSpec); - this.reason = reason; - } - - public Exception getReason() { - return reason; - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SpecEvent.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SpecEvent.java deleted file mode 100644 index 7a321ef4aaa..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SpecEvent.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import java.util.EventObject; - -import com.sun.jdi.request.EventRequest; - -public class SpecEvent extends EventObject { - - private static final long serialVersionUID = 4820735456787276230L; - private EventRequestSpec eventRequestSpec; - - public SpecEvent(EventRequestSpec eventRequestSpec) { - super(eventRequestSpec.specs); - this.eventRequestSpec = eventRequestSpec; - } - - public EventRequestSpec getEventRequestSpec() { - return eventRequestSpec; - } - - public EventRequest getEventRequest() { - return eventRequestSpec.getEventRequest(); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SpecListener.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SpecListener.java deleted file mode 100644 index 2e5df596ea4..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SpecListener.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import java.util.EventListener; - -public interface SpecListener extends EventListener { - - void breakpointSet(SpecEvent e); - void breakpointDeferred(SpecEvent e); - void breakpointDeleted(SpecEvent e); - void breakpointResolved(SpecEvent e); - void breakpointError(SpecErrorEvent e); - - void watchpointSet(SpecEvent e); - void watchpointDeferred(SpecEvent e); - void watchpointDeleted(SpecEvent e); - void watchpointResolved(SpecEvent e); - void watchpointError(SpecErrorEvent e); - - void exceptionInterceptSet(SpecEvent e); - void exceptionInterceptDeferred(SpecEvent e); - void exceptionInterceptDeleted(SpecEvent e); - void exceptionInterceptResolved(SpecEvent e); - void exceptionInterceptError(SpecErrorEvent e); -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ThreadGroupIterator.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ThreadGroupIterator.java deleted file mode 100644 index dd8b0cb3f7e..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ThreadGroupIterator.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import com.sun.jdi.ThreadGroupReference; -import java.util.List; -import java.util.Stack; -import java.util.ArrayList; -import java.util.Iterator; - -/** - * Descend the tree of thread groups. - * @author Robert G. Field - */ -public class ThreadGroupIterator implements Iterator { - private final Stack> stack - = new Stack>(); - - public ThreadGroupIterator(List tgl) { - push(tgl); - } - - public ThreadGroupIterator(ThreadGroupReference tg) { - List tgl = new ArrayList(); - tgl.add(tg); - push(tgl); - } - -/* - ThreadGroupIterator() { - this(Env.vm().topLevelThreadGroups()); - } -*/ - - private Iterator top() { - return stack.peek(); - } - - /** - * The invariant in this class is that the top iterator - * on the stack has more elements. If the stack is - * empty, there is no top. This method assures - * this invariant. - */ - private void push(List tgl) { - stack.push(tgl.iterator()); - while (!stack.isEmpty() && !top().hasNext()) { - stack.pop(); - } - } - - @Override - public boolean hasNext() { - return !stack.isEmpty(); - } - - @Override - public ThreadGroupReference next() { - return nextThreadGroup(); - } - - public ThreadGroupReference nextThreadGroup() { - ThreadGroupReference tg = top().next(); - push(tg.threadGroups()); - return tg; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - -/* - static ThreadGroupReference find(String name) { - ThreadGroupIterator tgi = new ThreadGroupIterator(); - while (tgi.hasNext()) { - ThreadGroupReference tg = tgi.nextThreadGroup(); - if (tg.name().equals(name)) { - return tg; - } - } - return null; - } -*/ -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ThreadInfo.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ThreadInfo.java deleted file mode 100644 index 02626ac324f..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ThreadInfo.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import com.sun.jdi.*; - -//### Should handle target VM death or connection failure cleanly. - -public class ThreadInfo { - - private ThreadReference thread; - private int status; - - private int frameCount; - - Object userObject; // User-supplied annotation. - - private boolean interrupted = false; - - private void assureInterrupted() throws VMNotInterruptedException { - if (!interrupted) { - throw new VMNotInterruptedException(); - } - } - - ThreadInfo (ThreadReference thread) { - this.thread = thread; - this.frameCount = -1; - } - - public ThreadReference thread() { - return thread; - } - - public int getStatus() throws VMNotInterruptedException { - assureInterrupted(); - update(); - return status; - } - - public int getFrameCount() throws VMNotInterruptedException { - assureInterrupted(); - update(); - return frameCount; - } - - public StackFrame getFrame(int index) throws VMNotInterruptedException { - assureInterrupted(); - update(); - try { - return thread.frame(index); - } catch (IncompatibleThreadStateException e) { - // Should not happen - interrupted = false; - throw new VMNotInterruptedException(); - } - } - - public Object getUserObject() { - return userObject; - } - - public void setUserObject(Object obj) { - userObject = obj; - } - - // Refresh upon first access after cache is cleared. - - void update() throws VMNotInterruptedException { - if (frameCount == -1) { - try { - status = thread.status(); - frameCount = thread.frameCount(); - } catch (IncompatibleThreadStateException e) { - // Should not happen - interrupted = false; - throw new VMNotInterruptedException(); - } - } - } - - // Called from 'ExecutionManager'. - - void validate() { - interrupted = true; - } - - void invalidate() { - interrupted = false; - frameCount = -1; - status = ThreadReference.THREAD_STATUS_UNKNOWN; - } - -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ThreadIterator.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ThreadIterator.java deleted file mode 100644 index b82d88e6e1e..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ThreadIterator.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -import com.sun.jdi.ThreadGroupReference; -import com.sun.jdi.ThreadReference; -import java.util.List; -import java.util.Iterator; - -public class ThreadIterator implements Iterator { - Iterator it = null; - ThreadGroupIterator tgi; - - public ThreadIterator(ThreadGroupReference tg) { - tgi = new ThreadGroupIterator(tg); - } - - //### make this package access only? - public ThreadIterator(List tgl) { - tgi = new ThreadGroupIterator(tgl); - } - - @Override - public boolean hasNext() { - while (it == null || !it.hasNext()) { - if (!tgi.hasNext()) { - return false; // no more - } - it = tgi.nextThreadGroup().threads().iterator(); - } - return true; - } - - @Override - public ThreadReference next() { - return it.next(); - } - - public ThreadReference nextThread() { - return next(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/Utils.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/Utils.java deleted file mode 100644 index 34f1d724929..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/Utils.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; //### does it belong here? - -import com.sun.jdi.*; - -public class Utils { - - /** - * Return the thread status description. - */ - public static String getStatus(ThreadReference thr) { - int status = thr.status(); - String result; - switch (status) { - case ThreadReference.THREAD_STATUS_UNKNOWN: - result = "unknown status"; - break; - case ThreadReference.THREAD_STATUS_ZOMBIE: - result = "zombie"; - break; - case ThreadReference.THREAD_STATUS_RUNNING: - result = "running"; - break; - case ThreadReference.THREAD_STATUS_SLEEPING: - result = "sleeping"; - break; - case ThreadReference.THREAD_STATUS_MONITOR: - result = "waiting to acquire a monitor lock"; - break; - case ThreadReference.THREAD_STATUS_WAIT: - result = "waiting on a condition"; - break; - default: - result = ""; - } - if (thr.isSuspended()) { - result += " (suspended)"; - } - return result; - } - - /** - * Return a description of an object. - */ - public static String description(ObjectReference ref) { - ReferenceType clazz = ref.referenceType(); - long id = ref.uniqueID(); //### TODO use real id - if (clazz == null) { - return toHex(id); - } else { - return "(" + clazz.name() + ")" + toHex(id); - } - } - - /** - * Convert a long to a hexadecimal string. - */ - public static String toHex(long n) { - char s1[] = new char[16]; - char s2[] = new char[18]; - - // Store digits in reverse order. - int i = 0; - do { - long d = n & 0xf; - s1[i++] = (char)((d < 10) ? ('0' + d) : ('a' + d - 10)); - } while ((n >>>= 4) > 0); - - // Now reverse the array. - s2[0] = '0'; - s2[1] = 'x'; - int j = 2; - while (--i >= 0) { - s2[j++] = s1[i]; - } - return new String(s2, 0, j); - } - - /** - * Convert hexadecimal strings to longs. - */ - public static long fromHex(String hexStr) { - String str = hexStr.startsWith("0x") ? - hexStr.substring(2).toLowerCase() : hexStr.toLowerCase(); - if (hexStr.length() == 0) { - throw new NumberFormatException(); - } - - long ret = 0; - for (int i = 0; i < str.length(); i++) { - int c = str.charAt(i); - if (c >= '0' && c <= '9') { - ret = (ret * 16) + (c - '0'); - } else if (c >= 'a' && c <= 'f') { - ret = (ret * 16) + (c - 'a' + 10); - } else { - throw new NumberFormatException(); - } - } - return ret; - } - - - /* - * The next two methods are used by this class and by EventHandler - * to print consistent locations and error messages. - */ - public static String locationString(Location loc) { - return loc.declaringType().name() + - "." + loc.method().name() + "(), line=" + - loc.lineNumber(); - } - -//### UNUSED. -/************************ - private String typedName(Method method) { - // TO DO: Use method.signature() instead of method.arguments() so that - // we get sensible results for classes without debugging info - StringBuffer buf = new StringBuffer(); - buf.append(method.name()); - buf.append("("); - Iterator it = method.arguments().iterator(); - while (it.hasNext()) { - buf.append(((LocalVariable)it.next()).typeName()); - if (it.hasNext()) { - buf.append(","); - } - } - buf.append(")"); - return buf.toString(); - } -************************/ - - public static boolean isValidMethodName(String s) { - return isJavaIdentifier(s) || - s.equals("") || - s.equals(""); - } - - public static boolean isJavaIdentifier(String s) { - if (s.length() == 0) { - return false; - } - int cp = s.codePointAt(0); - if (! Character.isJavaIdentifierStart(cp)) { - return false; - } - for (int i = Character.charCount(cp); i < s.length(); i += Character.charCount(cp)) { - cp = s.codePointAt(i); - if (! Character.isJavaIdentifierPart(cp)) { - return false; - } - } - return true; - } - -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/VMLaunchFailureException.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/VMLaunchFailureException.java deleted file mode 100644 index c2429684d29..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/VMLaunchFailureException.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -public class VMLaunchFailureException extends Exception { - - private static final long serialVersionUID = -2439646729274310108L; -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/VMNotInterruptedException.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/VMNotInterruptedException.java deleted file mode 100644 index 489d88086cb..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/VMNotInterruptedException.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -public class VMNotInterruptedException extends Exception { - - private static final long serialVersionUID = 8111074582188765600L; -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/WatchpointSpec.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/WatchpointSpec.java deleted file mode 100644 index 367e38c7490..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/WatchpointSpec.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.bdi; - -public abstract class WatchpointSpec extends EventRequestSpec { - final String fieldId; - - WatchpointSpec(EventRequestSpecList specs, - ReferenceTypeSpec refSpec, String fieldId) { - super(specs, refSpec); - this.fieldId = fieldId; -// if (!isJavaIdentifier(fieldId)) { -// throw new MalformedMemberNameException(fieldId); -// } - } - - @Override - void notifySet(SpecListener listener, SpecEvent evt) { - listener.watchpointSet(evt); - } - - @Override - void notifyDeferred(SpecListener listener, SpecEvent evt) { - listener.watchpointDeferred(evt); - } - - @Override - void notifyResolved(SpecListener listener, SpecEvent evt) { - listener.watchpointResolved(evt); - } - - @Override - void notifyDeleted(SpecListener listener, SpecEvent evt) { - listener.watchpointDeleted(evt); - } - - @Override - void notifyError(SpecListener listener, SpecErrorEvent evt) { - listener.watchpointError(evt); - } - - @Override - public int hashCode() { - return refSpec.hashCode() + fieldId.hashCode() + - getClass().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof WatchpointSpec) { - WatchpointSpec watchpoint = (WatchpointSpec)obj; - - return fieldId.equals(watchpoint.fieldId) && - refSpec.equals(watchpoint.refSpec) && - getClass().equals(watchpoint.getClass()); - } else { - return false; - } - } - - @Override - public String errorMessageFor(Exception e) { - if (e instanceof NoSuchFieldException) { - return ("No field " + fieldId + " in " + refSpec); - } else { - return super.errorMessageFor(e); - } - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/AbstractEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/AbstractEventSet.java deleted file mode 100644 index 0a82f15ee0a..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/AbstractEventSet.java +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; -import com.sun.jdi.request.*; - -import java.util.*; - -public abstract class AbstractEventSet extends EventObject implements EventSet { - - private static final long serialVersionUID = 2772717574222076977L; - private final EventSet jdiEventSet; - final Event oneEvent; - - /** - */ - AbstractEventSet(EventSet jdiEventSet) { - super(jdiEventSet.virtualMachine()); - this.jdiEventSet = jdiEventSet; - this.oneEvent = eventIterator().nextEvent(); - } - - public static AbstractEventSet toSpecificEventSet(EventSet jdiEventSet) { - Event evt = jdiEventSet.eventIterator().nextEvent(); - if (evt instanceof LocatableEvent) { - if (evt instanceof ExceptionEvent) { - return new ExceptionEventSet(jdiEventSet); - } else if (evt instanceof WatchpointEvent) { - if (evt instanceof AccessWatchpointEvent) { - return new AccessWatchpointEventSet(jdiEventSet); - } else { - return new ModificationWatchpointEventSet(jdiEventSet); - } - } else { - return new LocationTriggerEventSet(jdiEventSet); - } - } else if (evt instanceof ClassPrepareEvent) { - return new ClassPrepareEventSet(jdiEventSet); - } else if (evt instanceof ClassUnloadEvent) { - return new ClassUnloadEventSet(jdiEventSet); - } else if (evt instanceof ThreadDeathEvent) { - return new ThreadDeathEventSet(jdiEventSet); - } else if (evt instanceof ThreadStartEvent) { - return new ThreadStartEventSet(jdiEventSet); - } else if (evt instanceof VMDeathEvent) { - return new VMDeathEventSet(jdiEventSet); - } else if (evt instanceof VMDisconnectEvent) { - return new VMDisconnectEventSet(jdiEventSet); - } else if (evt instanceof VMStartEvent) { - return new VMStartEventSet(jdiEventSet); - } else { - throw new IllegalArgumentException("Unknown event " + evt); - } - } - - public abstract void notify(JDIListener listener); - - // Implement Mirror - - @Override - public VirtualMachine virtualMachine() { - return jdiEventSet.virtualMachine(); - } - - public VirtualMachine getVirtualMachine() { - return jdiEventSet.virtualMachine(); - } - - // Implement EventSet - - /** - * Returns the policy used to suspend threads in the target VM - * for this event set. This policy is selected from the suspend - * policies for each event's request. The one that suspends the - * most threads is chosen when the event occurs in the target VM - * and that policy is returned here. See - * com.sun.jdi.request.EventRequest for the possible policy values. - * - * @return the integer suspendPolicy - */ - public int getSuspendPolicy() { - return jdiEventSet.suspendPolicy(); - } - - @Override - public void resume() { - jdiEventSet.resume(); - } - - @Override - public int suspendPolicy() { - return jdiEventSet.suspendPolicy(); - } - - public boolean suspendedAll() { - return jdiEventSet.suspendPolicy() == EventRequest.SUSPEND_ALL; - } - - public boolean suspendedEventThread() { - return jdiEventSet.suspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD; - } - - public boolean suspendedNone() { - return jdiEventSet.suspendPolicy() == EventRequest.SUSPEND_NONE; - } - - /** - * Return an iterator specific to {@link Event} objects. - */ - @Override - public EventIterator eventIterator() { - return jdiEventSet.eventIterator(); - } - - - // Implement java.util.Set (by pass through) - - /** - * Returns the number of elements in this set (its cardinality). If this - * set contains more than Integer.MAX_VALUE elements, returns - * Integer.MAX_VALUE. - * - * @return the number of elements in this set (its cardinality). - */ - @Override - public int size() { - return jdiEventSet.size(); - } - - /** - * Returns true if this set contains no elements. - * - * @return true if this set contains no elements. - */ - @Override - public boolean isEmpty() { - return jdiEventSet.isEmpty(); - } - - /** - * Returns true if this set contains the specified element. More - * formally, returns true if and only if this set contains an - * element e such that (o==null ? e==null : - * o.equals(e)). - * - * @return true if this set contains the specified element. - */ - @Override - public boolean contains(Object o) { - return jdiEventSet.contains(o); - } - - /** - * Returns an iterator over the elements in this set. The elements are - * returned in no particular order (unless this set is an instance of some - * class that provides a guarantee). - * - * @return an iterator over the elements in this set. - */ - @Override - public Iterator iterator() { - return jdiEventSet.iterator(); - } - - /** - * Returns an array containing all of the elements in this set. - * Obeys the general contract of the Collection.toArray method. - * - * @return an array containing all of the elements in this set. - */ - @Override - public Object[] toArray() { - return jdiEventSet.toArray(); - } - - /** - * Returns an array containing all of the elements in this set whose - * runtime type is that of the specified array. Obeys the general - * contract of the Collection.toArray(Object[]) method. - * - * @param a the array into which the elements of this set are to - * be stored, if it is big enough { - return jdiEventSet.XXX(); - } otherwise, a new array of the - * same runtime type is allocated for this purpose. - * @return an array containing the elements of this set. - * @throws ArrayStoreException the runtime type of a is not a supertype - * of the runtime type of every element in this set. - */ - @Override - public T[] toArray(T a[]) { - return jdiEventSet.toArray(a); - } - - // Bulk Operations - - /** - * Returns true if this set contains all of the elements of the - * specified collection. If the specified collection is also a set, this - * method returns true if it is a subset of this set. - * - * @param c collection to be checked for containment in this set. - * @return true if this set contains all of the elements of the - * specified collection. - */ - @Override - public boolean containsAll(Collection c) { - return jdiEventSet.containsAll(c); - } - - - // Make the rest of Set unmodifiable - - @Override - public boolean add(Event e){ - throw new UnsupportedOperationException(); - } - @Override - public boolean remove(Object o) { - throw new UnsupportedOperationException(); - } - @Override - public boolean addAll(Collection coll) { - throw new UnsupportedOperationException(); - } - @Override - public boolean removeAll(Collection coll) { - throw new UnsupportedOperationException(); - } - @Override - public boolean retainAll(Collection coll) { - throw new UnsupportedOperationException(); - } - @Override - public void clear() { - throw new UnsupportedOperationException(); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/AccessWatchpointEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/AccessWatchpointEventSet.java deleted file mode 100644 index 10462e3bbb4..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/AccessWatchpointEventSet.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.event.*; - -public class AccessWatchpointEventSet extends WatchpointEventSet { - - private static final long serialVersionUID = -2620394219156607673L; - - AccessWatchpointEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - @Override - public void notify(JDIListener listener) { - listener.accessWatchpoint(this); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ClassPrepareEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ClassPrepareEventSet.java deleted file mode 100644 index 9010415e362..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ClassPrepareEventSet.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; - -public class ClassPrepareEventSet extends AbstractEventSet { - - private static final long serialVersionUID = 5958493423581010491L; - - ClassPrepareEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - /** - * Returns the thread in which this event has occurred. - * - * @return a {@link ThreadReference} which mirrors the event's thread in - * the target VM. - */ - public ThreadReference getThread() { - return ((ClassPrepareEvent)oneEvent).thread(); - } - - - /** - * Returns the reference type for which this event was generated. - * - * @return a {@link ReferenceType} which mirrors the class, interface, or - * array which has been linked. - */ - public ReferenceType getReferenceType() { - return ((ClassPrepareEvent)oneEvent).referenceType(); - } - - @Override - public void notify(JDIListener listener) { - listener.classPrepare(this); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ClassUnloadEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ClassUnloadEventSet.java deleted file mode 100644 index ad57b70d059..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ClassUnloadEventSet.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.event.*; - -public class ClassUnloadEventSet extends AbstractEventSet { - - private static final long serialVersionUID = 8370341450345835866L; - - ClassUnloadEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - /** - * Returns the name of the class that has been unloaded. - */ - public String getClassName() { - return ((ClassUnloadEvent)oneEvent).className(); - } - - /** - * Returns the JNI-style signature of the class that has been unloaded. - */ - public String getClassSignature() { - return ((ClassUnloadEvent)oneEvent).classSignature(); - } - - @Override - public void notify(JDIListener listener) { - listener.classUnload(this); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ExceptionEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ExceptionEventSet.java deleted file mode 100644 index d59cce74d49..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ExceptionEventSet.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; - -public class ExceptionEventSet extends LocatableEventSet { - - private static final long serialVersionUID = 5328140167954640711L; - - ExceptionEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - /** - * Gets the thrown exception object. The exception object is - * an instance of java.lang.Throwable or a subclass in the - * target VM. - * - * @return an {@link ObjectReference} which mirrors the thrown object in - * the target VM. - */ - public ObjectReference getException() { - return ((ExceptionEvent)oneEvent).exception(); - } - - /** - * Gets the location where the exception will be caught. An exception - * is considered to be caught if, at the point of the throw, the - * current location is dynamically enclosed in a try statement that - * handles the exception. (See the JVM specification for details). - * If there is such a try statement, the catch location is the - * first code index of the appropriate catch clause. - *

- * If there are native methods in the call stack at the time of the - * exception, there are important restrictions to note about the - * returned catch location. In such cases, - * it is not possible to predict whether an exception will be handled - * by some native method on the call stack. - * Thus, it is possible that exceptions considered uncaught - * here will, in fact, be handled by a native method and not cause - * termination of the target VM. Also, it cannot be assumed that the - * catch location returned here will ever be reached by the throwing - * thread. If there is - * a native frame between the current location and the catch location, - * the exception might be handled and cleared in that native method - * instead. - * - * @return the {@link Location} where the exception will be caught or null if - * the exception is uncaught. - */ - public Location getCatchLocation() { - return ((ExceptionEvent)oneEvent).catchLocation(); - } - - @Override - public void notify(JDIListener listener) { - listener.exception(this); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/JDIAdapter.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/JDIAdapter.java deleted file mode 100644 index 056cd0933b5..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/JDIAdapter.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -/** - * The adapter which receives JDI event sets. The methods in this - * class are empty; this class is provided as a convenience for - * easily creating listeners by extending this class and overriding - * only the methods of interest. - */ -public class JDIAdapter implements JDIListener { - - @Override - public void accessWatchpoint(AccessWatchpointEventSet e) { - } - - @Override - public void classPrepare(ClassPrepareEventSet e) { - } - - @Override - public void classUnload(ClassUnloadEventSet e) { - } - - @Override - public void exception(ExceptionEventSet e) { - } - - @Override - public void locationTrigger(LocationTriggerEventSet e) { - } - - @Override - public void modificationWatchpoint(ModificationWatchpointEventSet e) { - } - - @Override - public void threadDeath(ThreadDeathEventSet e) { - } - - @Override - public void threadStart(ThreadStartEventSet e) { - } - - @Override - public void vmDeath(VMDeathEventSet e) { - } - - @Override - public void vmDisconnect(VMDisconnectEventSet e) { - } - - @Override - public void vmStart(VMStartEventSet e) { - } - -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/JDIListener.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/JDIListener.java deleted file mode 100644 index 18a37261ee4..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/JDIListener.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import java.util.EventListener; - -public interface JDIListener extends EventListener { - void accessWatchpoint(AccessWatchpointEventSet e); - void classPrepare(ClassPrepareEventSet e); - void classUnload(ClassUnloadEventSet e); - void exception(ExceptionEventSet e); - void locationTrigger(LocationTriggerEventSet e); - void modificationWatchpoint(ModificationWatchpointEventSet e); - void threadDeath(ThreadDeathEventSet e); - void threadStart(ThreadStartEventSet e); - void vmDeath(VMDeathEventSet e); - void vmDisconnect(VMDisconnectEventSet e); - void vmStart(VMStartEventSet e); -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/LocatableEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/LocatableEventSet.java deleted file mode 100644 index 6b4f607009c..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/LocatableEventSet.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; - -/** - * Abstract event set for events with location and thread. - */ -public abstract class LocatableEventSet extends AbstractEventSet { - - private static final long serialVersionUID = 1027131209997915620L; - - LocatableEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - /** - * Returns the {@link Location} of this mirror. Depending on context - * and on available debug information, this location will have - * varying precision. - * - * @return the {@link Location} of this mirror. - */ - public Location getLocation() { - return ((LocatableEvent)oneEvent).location(); - } - - /** - * Returns the thread in which this event has occurred. - * - * @return a {@link ThreadReference} which mirrors the event's thread in - * the target VM. - */ - public ThreadReference getThread() { - return ((LocatableEvent)oneEvent).thread(); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/LocationTriggerEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/LocationTriggerEventSet.java deleted file mode 100644 index 3d25a573883..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/LocationTriggerEventSet.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.event.*; - -public class LocationTriggerEventSet extends LocatableEventSet { - - private static final long serialVersionUID = -3674631710485872487L; - - LocationTriggerEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - @Override - public void notify(JDIListener listener) { - listener.locationTrigger(this); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ModificationWatchpointEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ModificationWatchpointEventSet.java deleted file mode 100644 index 41749efa705..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ModificationWatchpointEventSet.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; - -public class ModificationWatchpointEventSet extends WatchpointEventSet { - - private static final long serialVersionUID = -680889300856154719L; - - ModificationWatchpointEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - /** - * Value that will be assigned to the field when the instruction - * completes. - */ - public Value getValueToBe() { - return ((ModificationWatchpointEvent)oneEvent).valueToBe(); - } - - @Override - public void notify(JDIListener listener) { - listener.modificationWatchpoint(this); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ThreadDeathEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ThreadDeathEventSet.java deleted file mode 100644 index 893ec73fa97..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ThreadDeathEventSet.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; - -public class ThreadDeathEventSet extends AbstractEventSet { - - private static final long serialVersionUID = -8801604712308151331L; - - ThreadDeathEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - /** - * Returns the thread which is terminating. - * - * @return a {@link ThreadReference} which mirrors the event's thread in - * the target VM. - */ - public ThreadReference getThread() { - return ((ThreadDeathEvent)oneEvent).thread(); - } - - @Override - public void notify(JDIListener listener) { - listener.threadDeath(this); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ThreadStartEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ThreadStartEventSet.java deleted file mode 100644 index 657e9633c9c..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ThreadStartEventSet.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; - -public class ThreadStartEventSet extends AbstractEventSet { - - private static final long serialVersionUID = -3802096132294933502L; - - ThreadStartEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - /** - * Returns the thread which has started. - * - * @return a {@link ThreadReference} which mirrors the event's thread in - * the target VM. - */ - public ThreadReference getThread() { - return ((ThreadStartEvent)oneEvent).thread(); - } - - @Override - public void notify(JDIListener listener) { - listener.threadStart(this); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/VMDeathEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/VMDeathEventSet.java deleted file mode 100644 index b6f7eb31843..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/VMDeathEventSet.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.event.*; - -public class VMDeathEventSet extends AbstractEventSet { - - private static final long serialVersionUID = 1163097303940092229L; - - VMDeathEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - @Override - public void notify(JDIListener listener) { - listener.vmDeath(this); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/VMDisconnectEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/VMDisconnectEventSet.java deleted file mode 100644 index 5b7dc7953ac..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/VMDisconnectEventSet.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.event.*; - -public class VMDisconnectEventSet extends AbstractEventSet { - - private static final long serialVersionUID = 7968123152344675342L; - - VMDisconnectEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - @Override - public void notify(JDIListener listener) { - listener.vmDisconnect(this); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/VMStartEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/VMStartEventSet.java deleted file mode 100644 index f9381239fc8..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/VMStartEventSet.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; - -public class VMStartEventSet extends AbstractEventSet { - - private static final long serialVersionUID = -3384957227835478191L; - - VMStartEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - /** - * Returns the initial thread of the VM which has started. - * - * @return a {@link ThreadReference} which mirrors the event's - * thread in the target VM. - */ - public ThreadReference getThread() { - return ((VMStartEvent)oneEvent).thread(); - } - - @Override - public void notify(JDIListener listener) { - listener.vmStart(this); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/WatchpointEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/WatchpointEventSet.java deleted file mode 100644 index 76be4acf1da..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/WatchpointEventSet.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; - -public abstract class WatchpointEventSet extends LocatableEventSet { - - private static final long serialVersionUID = 5606285209703845409L; - - WatchpointEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - /** - * Returns the field that is about to be accessed/modified. - * - * @return a {@link Field} which mirrors the field - * in the target VM. - */ - public Field getField() { - return ((WatchpointEvent)oneEvent).field(); - } - - /** - * Returns the object whose field is about to be accessed/modified. - * Return null is the access is to a static field. - * - * @return a {@link ObjectReference} which mirrors the event's - * object in the target VM. - */ - public ObjectReference getObject() { - return ((WatchpointEvent)oneEvent).object(); - } - - /** - * Current value of the field. - */ - public Value getValueCurrent() { - return ((WatchpointEvent)oneEvent).valueCurrent(); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ApplicationTool.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ApplicationTool.java deleted file mode 100644 index 717a5b9390e..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ApplicationTool.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.gui; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.*; - -import com.sun.tools.example.debug.bdi.*; - -public class ApplicationTool extends JPanel { - - private static final long serialVersionUID = 310966063293205714L; - - private ExecutionManager runtime; - - private TypeScript script; - - private static final String PROMPT = "Input:"; - - public ApplicationTool(Environment env) { - - super(new BorderLayout()); - - this.runtime = env.getExecutionManager(); - - this.script = new TypeScript(PROMPT, false); // No implicit echo. - this.add(script); - - script.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - runtime.sendLineToApplication(script.readln()); - } - }); - - runtime.addApplicationEchoListener(new TypeScriptOutputListener(script)); - runtime.addApplicationOutputListener(new TypeScriptOutputListener(script)); - runtime.addApplicationErrorListener(new TypeScriptOutputListener(script)); - - //### should clean up on exit! - - } - - /****** - public void setFont(Font f) { - script.setFont(f); - } - ******/ - -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ClassManager.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ClassManager.java deleted file mode 100644 index 6e347376769..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ClassManager.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.gui; - -public class ClassManager { - - // This class is provided primarily for symmetry with - // SourceManager. Currently, it does very little. - // If we add facilities in the future that require that - // class files be read outside of the VM, for example, to - // provide a disassembled view of a class for bytecode-level - // debugging, the required class file management will be done - // here. - - private SearchPath classPath; - - public ClassManager(Environment env) { - this.classPath = new SearchPath(""); - } - - public ClassManager(SearchPath classPath) { - this.classPath = classPath; - } - - /* - * Set path for access to class files. - */ - - public void setClassPath(SearchPath sp) { - classPath = sp; - } - - /* - * Get path for access to class files. - */ - - public SearchPath getClassPath() { - return classPath; - } - -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ClassTreeTool.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ClassTreeTool.java deleted file mode 100644 index 995c414854c..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ClassTreeTool.java +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.gui; - -import java.util.*; - -import javax.swing.*; -import javax.swing.tree.*; -import java.awt.*; -import java.awt.event.*; - -import com.sun.jdi.*; -import com.sun.tools.example.debug.event.*; -import com.sun.tools.example.debug.bdi.*; - -public class ClassTreeTool extends JPanel { - - private static final long serialVersionUID = 526178912591739259L; - - private Environment env; - - private ExecutionManager runtime; - private SourceManager sourceManager; - private ClassManager classManager; - - private JTree tree; - private DefaultTreeModel treeModel; - private ClassTreeNode root; -// private SearchPath sourcePath; - - private CommandInterpreter interpreter; - - private static String HEADING = "CLASSES"; - - public ClassTreeTool(Environment env) { - - super(new BorderLayout()); - - this.env = env; - this.runtime = env.getExecutionManager(); - this.sourceManager = env.getSourceManager(); - - this.interpreter = new CommandInterpreter(env); - - root = createClassTree(HEADING); - treeModel = new DefaultTreeModel(root); - - // Create a tree that allows one selection at a time. - - tree = new JTree(treeModel); - tree.setSelectionModel(new SingleLeafTreeSelectionModel()); - - /****** - // Listen for when the selection changes. - tree.addTreeSelectionListener(new TreeSelectionListener() { - public void valueChanged(TreeSelectionEvent e) { - ClassTreeNode node = (ClassTreeNode) - (e.getPath().getLastPathComponent()); - if (node != null) { - interpreter.executeCommand("view " + node.getReferenceTypeName()); - } - } - }); - ******/ - - MouseListener ml = new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - int selRow = tree.getRowForLocation(e.getX(), e.getY()); - TreePath selPath = tree.getPathForLocation(e.getX(), e.getY()); - if(selRow != -1) { - if(e.getClickCount() == 1) { - ClassTreeNode node = - (ClassTreeNode)selPath.getLastPathComponent(); - // If user clicks on leaf, select it, and issue 'view' command. - if (node.isLeaf()) { - tree.setSelectionPath(selPath); - interpreter.executeCommand("view " + node.getReferenceTypeName()); - } - } - } - } - }; - tree.addMouseListener(ml); - - JScrollPane treeView = new JScrollPane(tree); - add(treeView); - - // Create listener. - ClassTreeToolListener listener = new ClassTreeToolListener(); - runtime.addJDIListener(listener); - runtime.addSessionListener(listener); - - //### remove listeners on exit! - } - - private class ClassTreeToolListener extends JDIAdapter - implements JDIListener, SessionListener { - - // SessionListener - - @Override - public void sessionStart(EventObject e) { - // Get system classes and any others loaded before attaching. - try { - for (ReferenceType type : runtime.allClasses()) { - root.addClass(type); - } - } catch (VMDisconnectedException ee) { - // VM terminated unexpectedly. - } catch (NoSessionException ee) { - // Ignore. Should not happen. - } - } - - @Override - public void sessionInterrupt(EventObject e) {} - @Override - public void sessionContinue(EventObject e) {} - - // JDIListener - - @Override - public void classPrepare(ClassPrepareEventSet e) { - root.addClass(e.getReferenceType()); - } - - @Override - public void classUnload(ClassUnloadEventSet e) { - root.removeClass(e.getClassName()); - } - - @Override - public void vmDisconnect(VMDisconnectEventSet e) { - // Clear contents of this view. - root = createClassTree(HEADING); - treeModel = new DefaultTreeModel(root); - tree.setModel(treeModel); - } - } - - ClassTreeNode createClassTree(String label) { - return new ClassTreeNode(label, null); - } - - class ClassTreeNode extends DefaultMutableTreeNode { - - private String name; - private ReferenceType refTy; // null for package - - ClassTreeNode(String name, ReferenceType refTy) { - this.name = name; - this.refTy = refTy; - } - - @Override - public String toString() { - return name; - } - - public ReferenceType getReferenceType() { - return refTy; - } - - public String getReferenceTypeName() { - return refTy.name(); - } - - private boolean isPackage() { - return (refTy == null); - } - - @Override - public boolean isLeaf() { - return !isPackage(); - } - - public void addClass(ReferenceType refTy) { - addClass(refTy.name(), refTy); - } - - private void addClass(String className, ReferenceType refTy) { - if (className.equals("")) { - return; - } - int pos = className.indexOf('.'); - if (pos < 0) { - insertNode(className, refTy); - } else { - String head = className.substring(0, pos); - String tail = className.substring(pos + 1); - ClassTreeNode child = insertNode(head, null); - child.addClass(tail, refTy); - } - } - - private ClassTreeNode insertNode(String name, ReferenceType refTy) { - for (int i = 0; i < getChildCount(); i++) { - ClassTreeNode child = (ClassTreeNode)getChildAt(i); - int cmp = name.compareTo(child.toString()); - if (cmp == 0) { - // like-named node already exists - return child; - } else if (cmp < 0) { - // insert new node before the child - ClassTreeNode newChild = new ClassTreeNode(name, refTy); - treeModel.insertNodeInto(newChild, this, i); - return newChild; - } - } - // insert new node after last child - ClassTreeNode newChild = new ClassTreeNode(name, refTy); - treeModel.insertNodeInto(newChild, this, getChildCount()); - return newChild; - } - - public void removeClass(String className) { - if (className.equals("")) { - return; - } - int pos = className.indexOf('.'); - if (pos < 0) { - ClassTreeNode child = findNode(className); - if (!isPackage()) { - treeModel.removeNodeFromParent(child); - } - } else { - String head = className.substring(0, pos); - String tail = className.substring(pos + 1); - ClassTreeNode child = findNode(head); - child.removeClass(tail); - if (isPackage() && child.getChildCount() < 1) { - // Prune non-leaf nodes with no children. - treeModel.removeNodeFromParent(child); - } - } - } - - private ClassTreeNode findNode(String name) { - for (int i = 0; i < getChildCount(); i++) { - ClassTreeNode child = (ClassTreeNode)getChildAt(i); - int cmp = name.compareTo(child.toString()); - if (cmp == 0) { - return child; - } else if (cmp > 0) { - // not found, since children are sorted - return null; - } - } - return null; - } - - } - -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/CommandInterpreter.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/CommandInterpreter.java deleted file mode 100644 index fbff95b2703..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/CommandInterpreter.java +++ /dev/null @@ -1,1468 +0,0 @@ -/* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.gui; - -import java.io.*; -import java.util.*; - -import com.sun.jdi.*; -import com.sun.tools.example.debug.bdi.*; - -public class CommandInterpreter { - - boolean echo; - - Environment env; - - private ContextManager context; - private ExecutionManager runtime; - private ClassManager classManager; - private SourceManager sourceManager; - - private OutputSink out; //### Hack! Should be local in each method used. - private String lastCommand = "help"; - - public CommandInterpreter(Environment env) { - this(env, true); - } - - public CommandInterpreter(Environment env, boolean echo) { - this.env = env; - this.echo = echo; - this.runtime = env.getExecutionManager(); - this.context = env.getContextManager(); - this.classManager = env.getClassManager(); - this.sourceManager = env.getSourceManager(); - } - - private ThreadReference[] threads = null; - - /* - * The numbering of threads is relative to the current set of threads, - * and may be affected by the creation and termination of new threads. - * Commands issued using such thread ids will only give reliable behavior - * relative to what was shown earlier in 'list' commands if the VM is interrupted. - * We need a better scheme. - */ - - private ThreadReference[] threads() throws NoSessionException { - if (threads == null) { - ThreadIterator ti = new ThreadIterator(getDefaultThreadGroup()); - List tlist = new ArrayList(); - while (ti.hasNext()) { - tlist.add(ti.nextThread()); - } - threads = tlist.toArray(new ThreadReference[tlist.size()]); - } - return threads; - } - - private ThreadReference findThread(String idToken) throws NoSessionException { - String id; - ThreadReference thread = null; - if (idToken.startsWith("t@")) { - id = idToken.substring(2); - } else { - id = idToken; - } - try { - ThreadReference[] threads = threads(); - long threadID = Long.parseLong(id, 16); - for (ThreadReference thread2 : threads) { - if (thread2.uniqueID() == threadID) { - thread = thread2; - break; - } - } - if (thread == null) { - //env.failure("No thread for id \"" + idToken + "\""); - env.failure("\"" + idToken + "\" is not a valid thread id."); - } - } catch (NumberFormatException e) { - env.error("Thread id \"" + idToken + "\" is ill-formed."); - thread = null; - } - return thread; - } - - private ThreadIterator allThreads() throws NoSessionException { - threads = null; - //### Why not use runtime.allThreads().iterator() ? - return new ThreadIterator(runtime.topLevelThreadGroups()); - } - - private ThreadIterator currentThreadGroupThreads() throws NoSessionException { - threads = null; - return new ThreadIterator(getDefaultThreadGroup()); - } - - private ThreadGroupIterator allThreadGroups() throws NoSessionException { - threads = null; - return new ThreadGroupIterator(runtime.topLevelThreadGroups()); - } - - private ThreadGroupReference defaultThreadGroup; - - private ThreadGroupReference getDefaultThreadGroup() throws NoSessionException { - if (defaultThreadGroup == null) { - defaultThreadGroup = runtime.systemThreadGroup(); - } - return defaultThreadGroup; - } - - private void setDefaultThreadGroup(ThreadGroupReference tg) { - defaultThreadGroup = tg; - } - - /* - * Command handlers. - */ - - // Command: classes - - private void commandClasses() throws NoSessionException { - OutputSink out = env.getOutputSink(); - //out.println("** classes list **"); - for (ReferenceType refType : runtime.allClasses()) { - out.println(refType.name()); - } - out.show(); - } - - - // Command: methods - - private void commandMethods(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - env.error("No class specified."); - return; - } - String idClass = t.nextToken(); - ReferenceType cls = findClass(idClass); - if (cls != null) { - List methods = cls.allMethods(); - OutputSink out = env.getOutputSink(); - for (int i = 0; i < methods.size(); i++) { - Method method = methods.get(i); - out.print(method.declaringType().name() + " " + - method.name() + "("); - Iterator it = method.argumentTypeNames().iterator(); - if (it.hasNext()) { - while (true) { - out.print(it.next()); - if (!it.hasNext()) { - break; - } - out.print(", "); - } - } - out.println(")"); - } - out.show(); - } else { - //### Should validate class name syntax. - env.failure("\"" + idClass + "\" is not a valid id or class name."); - } - } - - private ReferenceType findClass(String pattern) throws NoSessionException { - List results = runtime.findClassesMatchingPattern(pattern); - if (results.size() > 0) { - //### Should handle multiple results sensibly. - return results.get(0); - } - return null; - } - - // Command: threads - - private void commandThreads(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - OutputSink out = env.getOutputSink(); - printThreadGroup(out, getDefaultThreadGroup(), 0); - out.show(); - return; - } - String name = t.nextToken(); - ThreadGroupReference tg = findThreadGroup(name); - if (tg == null) { - env.failure(name + " is not a valid threadgroup name."); - } else { - OutputSink out = env.getOutputSink(); - printThreadGroup(out, tg, 0); - out.show(); - } - } - - private ThreadGroupReference findThreadGroup(String name) throws NoSessionException { - //### Issue: Uniqueness of thread group names is not enforced. - ThreadGroupIterator tgi = allThreadGroups(); - while (tgi.hasNext()) { - ThreadGroupReference tg = tgi.nextThreadGroup(); - if (tg.name().equals(name)) { - return tg; - } - } - return null; - } - - private int printThreadGroup(OutputSink out, ThreadGroupReference tg, int iThread) { - out.println("Group " + tg.name() + ":"); - List tlist = tg.threads(); - int maxId = 0; - int maxName = 0; - for (int i = 0 ; i < tlist.size() ; i++) { - ThreadReference thr = tlist.get(i); - int len = Utils.description(thr).length(); - if (len > maxId) { - maxId = len; - } - String name = thr.name(); - int iDot = name.lastIndexOf('.'); - if (iDot >= 0 && name.length() > iDot) { - name = name.substring(iDot + 1); - } - if (name.length() > maxName) { - maxName = name.length(); - } - } - String maxNumString = String.valueOf(iThread + tlist.size()); - int maxNumDigits = maxNumString.length(); - for (int i = 0 ; i < tlist.size() ; i++) { - ThreadReference thr = tlist.get(i); - char buf[] = new char[80]; - for (int j = 0; j < 79; j++) { - buf[j] = ' '; - } - buf[79] = '\0'; - StringBuilder sbOut = new StringBuilder(); - sbOut.append(buf); - - // Right-justify the thread number at start of output string - String numString = String.valueOf(iThread + i + 1); - sbOut.insert(maxNumDigits - numString.length(), - numString); - sbOut.insert(maxNumDigits, "."); - - int iBuf = maxNumDigits + 2; - sbOut.insert(iBuf, Utils.description(thr)); - iBuf += maxId + 1; - String name = thr.name(); - int iDot = name.lastIndexOf('.'); - if (iDot >= 0 && name.length() > iDot) { - name = name.substring(iDot + 1); - } - sbOut.insert(iBuf, name); - iBuf += maxName + 1; - sbOut.insert(iBuf, Utils.getStatus(thr)); - sbOut.setLength(79); - out.println(sbOut.toString()); - } - for (ThreadGroupReference tg0 : tg.threadGroups()) { - if (!tg.equals(tg0)) { // TODO ref mgt - iThread += printThreadGroup(out, tg0, iThread + tlist.size()); - } - } - return tlist.size(); - } - - // Command: threadgroups - - private void commandThreadGroups() throws NoSessionException { - ThreadGroupIterator it = allThreadGroups(); - int cnt = 0; - OutputSink out = env.getOutputSink(); - while (it.hasNext()) { - ThreadGroupReference tg = it.nextThreadGroup(); - ++cnt; - out.println("" + cnt + ". " + Utils.description(tg) + " " + tg.name()); - } - out.show(); - } - - // Command: thread - - private void commandThread(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - env.error("Thread number not specified."); - return; - } - ThreadReference thread = findThread(t.nextToken()); - if (thread != null) { - //### Should notify user. - context.setCurrentThread(thread); - } - } - - // Command: threadgroup - - private void commandThreadGroup(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - env.error("Threadgroup name not specified."); - return; - } - String name = t.nextToken(); - ThreadGroupReference tg = findThreadGroup(name); - if (tg == null) { - env.failure(name + " is not a valid threadgroup name."); - } else { - //### Should notify user. - setDefaultThreadGroup(tg); - } - } - - // Command: run - - private void commandRun(StringTokenizer t) throws NoSessionException { - if (doLoad(false, t)) { - env.notice("Running ..."); - } - } - - // Command: load - - private void commandLoad(StringTokenizer t) throws NoSessionException { - if (doLoad(true, t)) {} - } - - private boolean doLoad(boolean suspended, - StringTokenizer t) throws NoSessionException { - - String clname; - - if (!t.hasMoreTokens()) { - clname = context.getMainClassName(); - if (!clname.equals("")) { - // Run from prevously-set class name. - try { - String vmArgs = context.getVmArguments(); - runtime.run(suspended, - vmArgs, - clname, - context.getProgramArguments()); - return true; - } catch (VMLaunchFailureException e) { - env.failure("Attempt to launch main class \"" + clname + "\" failed."); - } - } else { - env.failure("No main class specified and no current default defined."); - } - } else { - clname = t.nextToken(); - StringBuilder str = new StringBuilder(); - // Allow VM arguments to be specified here? - while (t.hasMoreTokens()) { - String tok = t.nextToken(); - str.append(tok); - if (t.hasMoreTokens()) { - str.append(' '); - } - } - String args = str.toString(); - try { - String vmArgs = context.getVmArguments(); - runtime.run(suspended, vmArgs, clname, args); - context.setMainClassName(clname); - //context.setVmArguments(vmArgs); - context.setProgramArguments(args); - return true; - } catch (VMLaunchFailureException e) { - env.failure("Attempt to launch main class \"" + clname + "\" failed."); - } - } - return false; - } - - // Command: connect - - private void commandConnect(StringTokenizer t) { - try { - LaunchTool.queryAndLaunchVM(runtime); - } catch (VMLaunchFailureException e) { - env.failure("Attempt to connect failed."); - } - } - - // Command: attach - - private void commandAttach(StringTokenizer t) { - String portName; - if (!t.hasMoreTokens()) { - portName = context.getRemotePort(); - if (!portName.equals("")) { - try { - runtime.attach(portName); - } catch (VMLaunchFailureException e) { - env.failure("Attempt to attach to port \"" + portName + "\" failed."); - } - } else { - env.failure("No port specified and no current default defined."); - } - } else { - portName = t.nextToken(); - try { - runtime.attach(portName); - } catch (VMLaunchFailureException e) { - env.failure("Attempt to attach to port \"" + portName + "\" failed."); - } - context.setRemotePort(portName); - } - } - - // Command: detach - - private void commandDetach(StringTokenizer t) throws NoSessionException { - runtime.detach(); - } - - // Command: interrupt - - private void commandInterrupt(StringTokenizer t) throws NoSessionException { - runtime.interrupt(); - } - - // Command: suspend - - private void commandSuspend(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - // Suspend all threads in the current thread group. - //### Issue: help message says default is all threads. - //### Behavior here agrees with 'jdb', however. - ThreadIterator ti = currentThreadGroupThreads(); - while (ti.hasNext()) { - // TODO - don't suspend debugger threads - ti.nextThread().suspend(); - } - env.notice("All (non-system) threads suspended."); - } else { - while (t.hasMoreTokens()) { - ThreadReference thread = findThread(t.nextToken()); - if (thread != null) { - //thread.suspend(); - runtime.suspendThread(thread); - } - } - } - } - - // Command: resume - - private void commandResume(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - // Suspend all threads in the current thread group. - //### Issue: help message says default is all threads. - //### Behavior here agrees with 'jdb', however. - ThreadIterator ti = currentThreadGroupThreads(); - while (ti.hasNext()) { - // TODO - don't suspend debugger threads - ti.nextThread().resume(); - } - env.notice("All threads resumed."); - } else { - while (t.hasMoreTokens()) { - ThreadReference thread = findThread(t.nextToken()); - if (thread != null) { - //thread.resume(); - runtime.resumeThread(thread); - } - } - } - } - - // Command: cont - - private void commandCont() throws NoSessionException { - try { - runtime.go(); - } catch (VMNotInterruptedException e) { - //### failure? - env.notice("Target VM is already running."); - } - } - - // Command: step - - private void commandStep(StringTokenizer t) throws NoSessionException{ - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.failure("No current thread."); - return; - } - try { - if (t.hasMoreTokens() && - t.nextToken().toLowerCase().equals("up")) { - runtime.stepOut(current); - } else { - runtime.stepIntoLine(current); - } - } catch (AbsentInformationException e) { - env.failure("No linenumber information available -- " + - "Try \"stepi\" to step by instructions."); - } - } - - // Command: stepi - - private void commandStepi() throws NoSessionException { - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.failure("No current thread."); - return; - } - runtime.stepIntoInstruction(current); - } - - // Command: next - - private void commandNext() throws NoSessionException { - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.failure("No current thread."); - return; - } - try { - runtime.stepOverLine(current); - } catch (AbsentInformationException e) { - env.failure("No linenumber information available -- " + - "Try \"nexti\" to step by instructions."); - } - } - - // Command: nexti (NEW) - - private void commandNexti() throws NoSessionException { - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.failure("No current thread."); - return; - } - runtime.stepOverInstruction(current); - } - - // Command: kill - - private void commandKill(StringTokenizer t) throws NoSessionException { - //### Should change the way in which thread ids and threadgroup names - //### are distinguished. - if (!t.hasMoreTokens()) { - env.error("Usage: kill or "); - return; - } - while (t.hasMoreTokens()) { - String idToken = t.nextToken(); - ThreadReference thread = findThread(idToken); - if (thread != null) { - runtime.stopThread(thread); - env.notice("Thread " + thread.name() + " killed."); - return; - } else { - /* Check for threadgroup name, NOT skipping "system". */ - //### Should skip "system"? Classic 'jdb' does this. - //### Should deal with possible non-uniqueness of threadgroup names. - ThreadGroupIterator itg = allThreadGroups(); - while (itg.hasNext()) { - ThreadGroupReference tg = itg.nextThreadGroup(); - if (tg.name().equals(idToken)) { - ThreadIterator it = new ThreadIterator(tg); - while (it.hasNext()) { - runtime.stopThread(it.nextThread()); - } - env.notice("Threadgroup " + tg.name() + "killed."); - return; - } - } - env.failure("\"" + idToken + - "\" is not a valid threadgroup or id."); - } - } - } - - - /************* - // TODO - private void commandCatchException(StringTokenizer t) throws NoSessionException {} - // TODO - private void commandIgnoreException(StringTokenizer t) throws NoSessionException {} - *************/ - - // Command: up - - //### Print current frame after command? - - int readCount(StringTokenizer t) { - int cnt = 1; - if (t.hasMoreTokens()) { - String idToken = t.nextToken(); - try { - cnt = Integer.valueOf(idToken).intValue(); - } catch (NumberFormatException e) { - cnt = -1; - } - } - return cnt; - } - - void commandUp(StringTokenizer t) throws NoSessionException { - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.failure("No current thread."); - return; - } - int nLevels = readCount(t); - if (nLevels <= 0) { - env.error("usage: up [n frames]"); - return; - } - try { - int delta = context.moveCurrentFrameIndex(current, -nLevels); - if (delta == 0) { - env.notice("Already at top of stack."); - } else if (-delta < nLevels) { - env.notice("Moved up " + delta + " frames to top of stack."); - } - } catch (VMNotInterruptedException e) { - env.failure("Target VM must be in interrupted state."); - } - } - - private void commandDown(StringTokenizer t) throws NoSessionException { - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.failure("No current thread."); - return; - } - int nLevels = readCount(t); - if (nLevels <= 0) { - env.error("usage: down [n frames]"); - return; - } - try { - int delta = context.moveCurrentFrameIndex(current, nLevels); - if (delta == 0) { - env.notice("Already at bottom of stack."); - } else if (delta < nLevels) { - env.notice("Moved down " + delta + " frames to bottom of stack."); - } - } catch (VMNotInterruptedException e) { - env.failure("Target VM must be in interrupted state."); - } - } - - // Command: frame - - private void commandFrame(StringTokenizer t) throws NoSessionException { - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.failure("No current thread."); - return; - } - if (!t.hasMoreTokens()) { - env.error("usage: frame "); - return; - } - String idToken = t.nextToken(); - int n; - try { - n = Integer.valueOf(idToken).intValue(); - } catch (NumberFormatException e) { - n = 0; - } - if (n <= 0) { - env.error("use positive frame index"); - return; - } - try { - int delta = context.setCurrentFrameIndex(current, n); - if (delta == 0) { - env.notice("Frame unchanged."); - } else if (delta < 0) { - env.notice("Moved up " + -delta + " frames."); - } else { - env.notice("Moved down " + delta + " frames."); - } - } catch (VMNotInterruptedException e) { - env.failure("Target VM must be in interrupted state."); - } - } - - // Command: where - - //### Should we insist that VM be interrupted here? - //### There is an inconsistency between the 'where' command - //### and 'up' and 'down' in this respect. - - private void commandWhere(StringTokenizer t, boolean showPC) - throws NoSessionException { - ThreadReference current = context.getCurrentThread(); - if (!t.hasMoreTokens()) { - if (current == null) { - env.error("No thread specified."); - return; - } - dumpStack(current, showPC); - } else { - String token = t.nextToken(); - if (token.toLowerCase().equals("all")) { - ThreadIterator it = allThreads(); - while (it.hasNext()) { - ThreadReference thread = it.next(); - out.println(thread.name() + ": "); - dumpStack(thread, showPC); - } - } else { - ThreadReference thread = findThread(t.nextToken()); - //### Do we want to set current thread here? - //### Should notify user of change. - if (thread != null) { - context.setCurrentThread(thread); - } - dumpStack(thread, showPC); - } - } - } - - private void dumpStack(ThreadReference thread, boolean showPC) { - //### Check for these. - //env.failure("Thread no longer exists."); - //env.failure("Target VM must be in interrupted state."); - //env.failure("Current thread isn't suspended."); - //### Should handle extremely long stack traces sensibly for user. - List stack = null; - try { - stack = thread.frames(); - } catch (IncompatibleThreadStateException e) { - env.failure("Thread is not suspended."); - } - //### Fix this! - //### Previously mishandled cases where thread was not current. - //### Now, prints all of the stack regardless of current frame. - int frameIndex = 0; - //int frameIndex = context.getCurrentFrameIndex(); - if (stack == null) { - env.failure("Thread is not running (no stack)."); - } else { - OutputSink out = env.getOutputSink(); - int nFrames = stack.size(); - for (int i = frameIndex; i < nFrames; i++) { - StackFrame frame = stack.get(i); - Location loc = frame.location(); - Method meth = loc.method(); - out.print(" [" + (i + 1) + "] "); - out.print(meth.declaringType().name()); - out.print('.'); - out.print(meth.name()); - out.print(" ("); - if (meth.isNative()) { - out.print("native method"); - } else if (loc.lineNumber() != -1) { - try { - out.print(loc.sourceName()); - } catch (AbsentInformationException e) { - out.print(""); - } - out.print(':'); - out.print(loc.lineNumber()); - } - out.print(')'); - if (showPC) { - long pc = loc.codeIndex(); - if (pc != -1) { - out.print(", pc = " + pc); - } - } - out.println(); - } - out.show(); - } - } - - private void listEventRequests() throws NoSessionException { - // Print set breakpoints - List specs = runtime.eventRequestSpecs(); - if (specs.isEmpty()) { - env.notice("No breakpoints/watchpoints/exceptions set."); - } else { - OutputSink out = env.getOutputSink(); - out.println("Current breakpoints/watchpoints/exceptions set:"); - for (EventRequestSpec bp : specs) { - out.println("\t" + bp); - } - out.show(); - } - } - - private BreakpointSpec parseBreakpointSpec(String bptSpec) { - StringTokenizer t = new StringTokenizer(bptSpec); - BreakpointSpec bpSpec = null; -// try { - String token = t.nextToken("@:( \t\n\r"); - // We can't use hasMoreTokens here because it will cause any leading - // paren to be lost. - String rest; - try { - rest = t.nextToken("").trim(); - } catch (NoSuchElementException e) { - rest = null; - } - if ((rest != null) && rest.startsWith("@")) { - t = new StringTokenizer(rest.substring(1)); - String sourceName = token; - String lineToken = t.nextToken(); - int lineNumber = Integer.valueOf(lineToken).intValue(); - if (t.hasMoreTokens()) { - return null; - } - bpSpec = runtime.createSourceLineBreakpoint(sourceName, - lineNumber); - } else if ((rest != null) && rest.startsWith(":")) { - t = new StringTokenizer(rest.substring(1)); - String classId = token; - String lineToken = t.nextToken(); - int lineNumber = Integer.valueOf(lineToken).intValue(); - if (t.hasMoreTokens()) { - return null; - } - bpSpec = runtime.createClassLineBreakpoint(classId, lineNumber); - } else { - // Try stripping method from class.method token. - int idot = token.lastIndexOf('.'); - if ( (idot <= 0) || /* No dot or dot in first char */ - (idot >= token.length() - 1) ) { /* dot in last char */ - return null; - } - String methodName = token.substring(idot + 1); - String classId = token.substring(0, idot); - List argumentList = null; - if (rest != null) { - if (!rest.startsWith("(") || !rest.endsWith(")")) { - //### Should throw exception with error message - //out.println("Invalid method specification: " - // + methodName + rest); - return null; - } - // Trim the parens - //### What about spaces in arglist? - rest = rest.substring(1, rest.length() - 1); - argumentList = new ArrayList(); - t = new StringTokenizer(rest, ","); - while (t.hasMoreTokens()) { - argumentList.add(t.nextToken()); - } - } - bpSpec = runtime.createMethodBreakpoint(classId, - methodName, - argumentList); - } -// } catch (Exception e) { -// env.error("Exception attempting to create breakpoint: " + e); -// return null; -// } - return bpSpec; - } - - private void commandStop(StringTokenizer t) throws NoSessionException { - String token; - - if (!t.hasMoreTokens()) { - listEventRequests(); - } else { - token = t.nextToken(); - // Ignore optional "at" or "in" token. - // Allowed for backward compatibility. - if (token.equals("at") || token.equals("in")) { - if (t.hasMoreTokens()) { - token = t.nextToken(); - } else { - env.error("Missing breakpoint specification."); - return; - } - } - BreakpointSpec bpSpec = parseBreakpointSpec(token); - if (bpSpec != null) { - //### Add sanity-checks for deferred breakpoint. - runtime.install(bpSpec); - } else { - env.error("Ill-formed breakpoint specification."); - } - } - } - - private void commandClear(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - // Print set breakpoints - listEventRequests(); - return; - } - //### need 'clear all' - BreakpointSpec bpSpec = parseBreakpointSpec(t.nextToken()); - if (bpSpec != null) { - List specs = runtime.eventRequestSpecs(); - - if (specs.isEmpty()) { - env.notice("No breakpoints set."); - } else { - List toDelete = new ArrayList(); - for (EventRequestSpec spec : specs) { - if (spec.equals(bpSpec)) { - toDelete.add(spec); - } - } - // The request used for matching should be found - if (toDelete.size() <= 1) { - env.notice("No matching breakpoint set."); - } - for (EventRequestSpec spec : toDelete) { - runtime.delete(spec); - } - } - } else { - env.error("Ill-formed breakpoint specification."); - } - } - - // Command: list - - private void commandList(StringTokenizer t) throws NoSessionException { - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.error("No thread specified."); - return; - } - Location loc; - try { - StackFrame frame = context.getCurrentFrame(current); - if (frame == null) { - env.failure("Thread has not yet begun execution."); - return; - } - loc = frame.location(); - } catch (VMNotInterruptedException e) { - env.failure("Target VM must be in interrupted state."); - return; - } - SourceModel source = sourceManager.sourceForLocation(loc); - if (source == null) { - if (loc.method().isNative()) { - env.failure("Current method is native."); - return; - } - env.failure("No source available for " + Utils.locationString(loc) + "."); - return; - } - ReferenceType refType = loc.declaringType(); - int lineno = loc.lineNumber(); - if (t.hasMoreTokens()) { - String id = t.nextToken(); - // See if token is a line number. - try { - lineno = Integer.valueOf(id).intValue(); - } catch (NumberFormatException nfe) { - // It isn't -- see if it's a method name. - List meths = refType.methodsByName(id); - if (meths == null || meths.size() == 0) { - env.failure(id + - " is not a valid line number or " + - "method name for class " + - refType.name()); - return; - } else if (meths.size() > 1) { - env.failure(id + - " is an ambiguous method name in" + - refType.name()); - return; - } - loc = meths.get(0).location(); - lineno = loc.lineNumber(); - } - } - int startLine = (lineno > 4) ? lineno - 4 : 1; - int endLine = startLine + 9; - String sourceLine = source.sourceLine(lineno); - if (sourceLine == null) { - env.failure("" + - lineno + - " is an invalid line number for " + - refType.name()); - } else { - OutputSink out = env.getOutputSink(); - for (int i = startLine; i <= endLine; i++) { - sourceLine = source.sourceLine(i); - if (sourceLine == null) { - break; - } - out.print(i); - out.print("\t"); - if (i == lineno) { - out.print("=> "); - } else { - out.print(" "); - } - out.println(sourceLine); - } - out.show(); - } - } - - // Command: use - // Get or set the source file path list. - - private void commandUse(StringTokenizer t) { - if (!t.hasMoreTokens()) { - out.println(sourceManager.getSourcePath().asString()); - } else { - //### Should throw exception for invalid path. - //### E.g., vetoable property change. - sourceManager.setSourcePath(new SearchPath(t.nextToken())); - } - } - - // Command: sourcepath - // Get or set the source file path list. (Alternate to 'use'.) - - private void commandSourcepath(StringTokenizer t) { - if (!t.hasMoreTokens()) { - out.println(sourceManager.getSourcePath().asString()); - } else { - //### Should throw exception for invalid path. - //### E.g., vetoable property change. - sourceManager.setSourcePath(new SearchPath(t.nextToken())); - } - } - - // Command: classpath - // Get or set the class file path list. - - private void commandClasspath(StringTokenizer t) { - if (!t.hasMoreTokens()) { - out.println(classManager.getClassPath().asString()); - } else { - //### Should throw exception for invalid path. - //### E.g., vetoable property change. - classManager.setClassPath(new SearchPath(t.nextToken())); - } - } - - // Command: view - // Display source for source file or class. - - private void commandView(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - env.error("Argument required"); - } else { - String name = t.nextToken(); - if (name.endsWith(".java") || - name.indexOf(File.separatorChar) >= 0) { - env.viewSource(name); - } else { - //### JDI crashes taking line number for class. - /***** - ReferenceType cls = findClass(name); - if (cls != null) { - env.viewLocation(cls.location()); - } else { - env.failure("No such class"); - } - *****/ - String fileName = name.replace('.', File.separatorChar) + ".java"; - env.viewSource(fileName); - } - } - } - - // Command: locals - // Print all local variables in current stack frame. - - private void commandLocals() throws NoSessionException { - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.failure("No default thread specified: " + - "use the \"thread\" command first."); - return; - } - StackFrame frame; - try { - frame = context.getCurrentFrame(current); - if (frame == null) { - env.failure("Thread has not yet created any stack frames."); - return; - } - } catch (VMNotInterruptedException e) { - env.failure("Target VM must be in interrupted state."); - return; - } - - List vars; - try { - vars = frame.visibleVariables(); - if (vars == null || vars.size() == 0) { - env.failure("No local variables"); - return; - } - } catch (AbsentInformationException e) { - env.failure("Local variable information not available." + - " Compile with -g to generate variable information"); - return; - } - - OutputSink out = env.getOutputSink(); - out.println("Method arguments:"); - for (LocalVariable var : vars) { - if (var.isArgument()) { - printVar(out, var, frame); - } - } - out.println("Local variables:"); - for (LocalVariable var : vars) { - if (!var.isArgument()) { - printVar(out, var, frame); - } - } - out.show(); - return; - } - - /** - * Command: monitor - * Monitor an expression - */ - private void commandMonitor(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - env.error("Argument required"); - } else { - env.getMonitorListModel().add(t.nextToken("")); - } - } - - /** - * Command: unmonitor - * Unmonitor an expression - */ - private void commandUnmonitor(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - env.error("Argument required"); - } else { - env.getMonitorListModel().remove(t.nextToken("")); - } - } - - // Print a stack variable. - - private void printVar(OutputSink out, LocalVariable var, StackFrame frame) { - out.print(" " + var.name()); - if (var.isVisible(frame)) { - Value val = frame.getValue(var); - out.println(" = " + val.toString()); - } else { - out.println(" is not in scope"); - } - } - - // Command: print - // Evaluate an expression. - - private void commandPrint(StringTokenizer t, boolean dumpObject) throws NoSessionException { - if (!t.hasMoreTokens()) { - //### Probably confused if expresion contains whitespace. - env.error("No expression specified."); - return; - } - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.failure("No default thread specified: " + - "use the \"thread\" command first."); - return; - } - StackFrame frame; - try { - frame = context.getCurrentFrame(current); - if (frame == null) { - env.failure("Thread has not yet created any stack frames."); - return; - } - } catch (VMNotInterruptedException e) { - env.failure("Target VM must be in interrupted state."); - return; - } - while (t.hasMoreTokens()) { - String expr = t.nextToken(""); - Value val = null; - try { - val = runtime.evaluate(frame, expr); - } catch(Exception e) { - env.error("Exception: " + e); - //### Fix this! - } - if (val == null) { - return; // Error message already printed - } - OutputSink out = env.getOutputSink(); - if (dumpObject && (val instanceof ObjectReference) && - !(val instanceof StringReference)) { - ObjectReference obj = (ObjectReference)val; - ReferenceType refType = obj.referenceType(); - out.println(expr + " = " + val.toString() + " {"); - dump(out, obj, refType, refType); - out.println("}"); - } else { - out.println(expr + " = " + val.toString()); - } - out.show(); - } - } - - private void dump(OutputSink out, - ObjectReference obj, ReferenceType refType, - ReferenceType refTypeBase) { - for (Field field : refType.fields()) { - out.print(" "); - if (!refType.equals(refTypeBase)) { - out.print(refType.name() + "."); - } - out.print(field.name() + ": "); - Object o = obj.getValue(field); - out.println((o == null) ? "null" : o.toString()); // Bug ID 4374471 - } - if (refType instanceof ClassType) { - ClassType sup = ((ClassType)refType).superclass(); - if (sup != null) { - dump(out, obj, sup, refTypeBase); - } - } else if (refType instanceof InterfaceType) { - for (InterfaceType sup : ((InterfaceType)refType).superinterfaces()) { - dump(out, obj, sup, refTypeBase); - } - } - } - - /* - * Display help message. - */ - - private void help() { - out.println("** command list **"); - out.println("threads [threadgroup] -- list threads"); - out.println("thread -- set default thread"); - out.println("suspend [thread id(s)] -- suspend threads (default: all)"); - out.println("resume [thread id(s)] -- resume threads (default: all)"); - out.println("where [thread id] | all -- dump a thread's stack"); - out.println("wherei [thread id] | all -- dump a thread's stack, with pc info"); - out.println("threadgroups -- list threadgroups"); - out.println("threadgroup -- set current threadgroup\n"); -// out.println("print -- print value of expression"); - out.println("dump -- print all object information\n"); -// out.println("eval -- evaluate expression (same as print)"); - out.println("locals -- print all local variables in current stack frame\n"); - out.println("classes -- list currently known classes"); - out.println("methods -- list a class's methods\n"); - out.println("stop [in] .[(argument_type,...)] -- set a breakpoint in a method"); - out.println("stop [at] : -- set a breakpoint at a line"); - out.println("up [n frames] -- move up a thread's stack"); - out.println("down [n frames] -- move down a thread's stack"); - out.println("frame -- to a frame"); - out.println("clear .[(argument_type,...)] -- clear a breakpoint in a method"); - out.println("clear : -- clear a breakpoint at a line"); - out.println("clear -- list breakpoints"); - out.println("step -- execute current line"); - out.println("step up -- execute until the current method returns to its caller"); - out.println("stepi -- execute current instruction"); - out.println("next -- step one line (step OVER calls)"); - out.println("nexti -- step one instruction (step OVER calls)"); - out.println("cont -- continue execution from breakpoint\n"); -// out.println("catch -- break for the specified exception"); -// out.println("ignore -- ignore when the specified exception\n"); - out.println("view classname|filename -- display source file"); - out.println("list [line number|method] -- print source code context at line or method"); - out.println("use -- display or change the source path\n"); -//### new - out.println("sourcepath -- display or change the source path\n"); -//### new - out.println("classpath -- display or change the class path\n"); - out.println("monitor -- evaluate an expression each time the program stops\n"); - out.println("unmonitor -- delete a monitor\n"); - out.println("read -- read and execute a command file\n"); -// out.println("memory -- report memory usage"); -// out.println("gc -- free unused objects\n"); - out.println("run [args] -- start execution of a Java class"); - out.println("run -- re-execute last class run"); - out.println("load [args] -- start execution of a Java class, initially suspended"); - out.println("load -- re-execute last class run, initially suspended"); - out.println("attach -- debug existing process\n"); - out.println("detach -- detach from debuggee process\n"); - out.println("kill -- kill a thread or threadgroup\n"); - out.println("!! -- repeat last command"); - out.println("help (or ?) -- list commands"); - out.println("exit (or quit) -- exit debugger"); - } - - /* - * Execute a command. - */ - - public void executeCommand(String command) { - //### Treatment of 'out' here is dirty... - out = env.getOutputSink(); - if (echo) { - out.println(">>> " + command); - } - StringTokenizer t = new StringTokenizer(command); - try { - String cmd; - if (t.hasMoreTokens()) { - cmd = t.nextToken().toLowerCase(); - lastCommand = cmd; - } else { - cmd = lastCommand; - } - if (cmd.equals("print")) { - commandPrint(t, false); - } else if (cmd.equals("eval")) { - commandPrint(t, false); - } else if (cmd.equals("dump")) { - commandPrint(t, true); - } else if (cmd.equals("locals")) { - commandLocals(); - } else if (cmd.equals("classes")) { - commandClasses(); - } else if (cmd.equals("methods")) { - commandMethods(t); - } else if (cmd.equals("threads")) { - commandThreads(t); - } else if (cmd.equals("thread")) { - commandThread(t); - } else if (cmd.equals("suspend")) { - commandSuspend(t); - } else if (cmd.equals("resume")) { - commandResume(t); - } else if (cmd.equals("cont")) { - commandCont(); - } else if (cmd.equals("threadgroups")) { - commandThreadGroups(); - } else if (cmd.equals("threadgroup")) { - commandThreadGroup(t); - } else if (cmd.equals("run")) { - commandRun(t); - } else if (cmd.equals("load")) { - commandLoad(t); - } else if (cmd.equals("connect")) { - commandConnect(t); - } else if (cmd.equals("attach")) { - commandAttach(t); - } else if (cmd.equals("detach")) { - commandDetach(t); - } else if (cmd.equals("interrupt")) { - commandInterrupt(t); -//### Not implemented. -// } else if (cmd.equals("catch")) { -// commandCatchException(t); -//### Not implemented. -// } else if (cmd.equals("ignore")) { -// commandIgnoreException(t); - } else if (cmd.equals("step")) { - commandStep(t); - } else if (cmd.equals("stepi")) { - commandStepi(); - } else if (cmd.equals("next")) { - commandNext(); - } else if (cmd.equals("nexti")) { - commandNexti(); - } else if (cmd.equals("kill")) { - commandKill(t); - } else if (cmd.equals("where")) { - commandWhere(t, false); - } else if (cmd.equals("wherei")) { - commandWhere(t, true); - } else if (cmd.equals("up")) { - commandUp(t); - } else if (cmd.equals("down")) { - commandDown(t); - } else if (cmd.equals("frame")) { - commandFrame(t); - } else if (cmd.equals("stop")) { - commandStop(t); - } else if (cmd.equals("clear")) { - commandClear(t); - } else if (cmd.equals("list")) { - commandList(t); - } else if (cmd.equals("use")) { - commandUse(t); - } else if (cmd.equals("sourcepath")) { - commandSourcepath(t); - } else if (cmd.equals("classpath")) { - commandClasspath(t); - } else if (cmd.equals("monitor")) { - commandMonitor(t); - } else if (cmd.equals("unmonitor")) { - commandUnmonitor(t); - } else if (cmd.equals("view")) { - commandView(t); -// } else if (cmd.equals("read")) { -// readCommand(t); - } else if (cmd.equals("help") || cmd.equals("?")) { - help(); - } else if (cmd.equals("quit") || cmd.equals("exit")) { - try { - runtime.detach(); - } catch (NoSessionException e) { - // ignore - } - env.terminate(); - } else { - //### Dubious repeat-count feature inherited from 'jdb' - if (t.hasMoreTokens()) { - try { - int repeat = Integer.parseInt(cmd); - String subcom = t.nextToken(""); - while (repeat-- > 0) { - executeCommand(subcom); - } - return; - } catch (NumberFormatException exc) { - } - } - out.println("huh? Try help..."); - out.flush(); - } - } catch (NoSessionException e) { - out.println("There is no currently attached VM session."); - out.flush(); - } catch (Exception e) { - out.println("Internal exception: " + e.toString()); - out.flush(); - System.out.println("JDB internal exception: " + e.toString()); - e.printStackTrace(); - } - out.show(); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/CommandTool.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/CommandTool.java deleted file mode 100644 index d010ec2f56b..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/CommandTool.java +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.gui; - -import java.io.*; -import java.util.*; - -import javax.swing.*; -import java.awt.BorderLayout; -import java.awt.event.*; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; - -import com.sun.tools.example.debug.bdi.*; -import com.sun.tools.example.debug.event.*; - -public class CommandTool extends JPanel { - - private static final long serialVersionUID = 8613516856378346415L; - - private Environment env; - - private ContextManager context; - private ExecutionManager runtime; - private SourceManager sourceManager; - - private TypeScript script; - - private static final String DEFAULT_CMD_PROMPT = "Command:"; - - public CommandTool(Environment env) { - - super(new BorderLayout()); - - this.env = env; - this.context = env.getContextManager(); - this.runtime = env.getExecutionManager(); - this.sourceManager = env.getSourceManager(); - - script = new TypeScript(DEFAULT_CMD_PROMPT, false); //no echo - this.add(script); - - final CommandInterpreter interpreter = - new CommandInterpreter(env); - - // Establish handler for incoming commands. - - script.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - interpreter.executeCommand(script.readln()); - } - }); - - // Establish ourselves as the listener for VM diagnostics. - - OutputListener diagnosticsListener = - new TypeScriptOutputListener(script, true); - runtime.addDiagnosticsListener(diagnosticsListener); - - // Establish ourselves as the shared debugger typescript. - - env.setTypeScript(new PrintWriter(new TypeScriptWriter(script))); - - // Handle VM events. - - TTYDebugListener listener = new TTYDebugListener(diagnosticsListener); - - runtime.addJDIListener(listener); - runtime.addSessionListener(listener); - runtime.addSpecListener(listener); - context.addContextListener(listener); - - //### remove listeners on exit! - - } - - private class TTYDebugListener implements - JDIListener, SessionListener, SpecListener, ContextListener { - - private OutputListener diagnostics; - - TTYDebugListener(OutputListener diagnostics) { - this.diagnostics = diagnostics; - } - - // JDIListener - - @Override - public void accessWatchpoint(AccessWatchpointEventSet e) { - setThread(e); - for (EventIterator it = e.eventIterator(); it.hasNext(); ) { - it.nextEvent(); - diagnostics.putString("Watchpoint hit: " + - locationString(e)); - } - } - - @Override - public void classPrepare(ClassPrepareEventSet e) { - if (context.getVerboseFlag()) { - String name = e.getReferenceType().name(); - diagnostics.putString("Class " + name + " loaded"); - } - } - - @Override - public void classUnload(ClassUnloadEventSet e) { - if (context.getVerboseFlag()) { - diagnostics.putString("Class " + e.getClassName() + - " unloaded."); - } - } - - @Override - public void exception(ExceptionEventSet e) { - setThread(e); - String name = e.getException().referenceType().name(); - diagnostics.putString("Exception: " + name); - } - - @Override - public void locationTrigger(LocationTriggerEventSet e) { - String locString = locationString(e); - setThread(e); - for (EventIterator it = e.eventIterator(); it.hasNext(); ) { - Event evt = it.nextEvent(); - if (evt instanceof BreakpointEvent) { - diagnostics.putString("Breakpoint hit: " + locString); - } else if (evt instanceof StepEvent) { - diagnostics.putString("Step completed: " + locString); - } else if (evt instanceof MethodEntryEvent) { - diagnostics.putString("Method entered: " + locString); - } else if (evt instanceof MethodExitEvent) { - diagnostics.putString("Method exited: " + locString); - } else { - diagnostics.putString("UNKNOWN event: " + e); - } - } - } - - @Override - public void modificationWatchpoint(ModificationWatchpointEventSet e) { - setThread(e); - for (EventIterator it = e.eventIterator(); it.hasNext(); ) { - it.nextEvent(); - diagnostics.putString("Watchpoint hit: " + - locationString(e)); - } - } - - @Override - public void threadDeath(ThreadDeathEventSet e) { - if (context.getVerboseFlag()) { - diagnostics.putString("Thread " + e.getThread() + - " ended."); - } - } - - @Override - public void threadStart(ThreadStartEventSet e) { - if (context.getVerboseFlag()) { - diagnostics.putString("Thread " + e.getThread() + - " started."); - } - } - - @Override - public void vmDeath(VMDeathEventSet e) { - script.setPrompt(DEFAULT_CMD_PROMPT); - diagnostics.putString("VM exited"); - } - - @Override - public void vmDisconnect(VMDisconnectEventSet e) { - script.setPrompt(DEFAULT_CMD_PROMPT); - diagnostics.putString("Disconnected from VM"); - } - - @Override - public void vmStart(VMStartEventSet e) { - script.setPrompt(DEFAULT_CMD_PROMPT); - diagnostics.putString("VM started"); - } - - // SessionListener - - @Override - public void sessionStart(EventObject e) {} - - @Override - public void sessionInterrupt(EventObject e) { - Thread.yield(); // fetch output - diagnostics.putString("VM interrupted by user."); - script.setPrompt(DEFAULT_CMD_PROMPT); - } - - @Override - public void sessionContinue(EventObject e) { - diagnostics.putString("Execution resumed."); - script.setPrompt(DEFAULT_CMD_PROMPT); - } - - // SpecListener - - @Override - public void breakpointSet(SpecEvent e) { - EventRequestSpec spec = e.getEventRequestSpec(); - diagnostics.putString("Breakpoint set at " + spec + "."); - } - @Override - public void breakpointDeferred(SpecEvent e) { - EventRequestSpec spec = e.getEventRequestSpec(); - diagnostics.putString("Breakpoint will be set at " + - spec + " when its class is loaded."); - } - @Override - public void breakpointDeleted(SpecEvent e) { - EventRequestSpec spec = e.getEventRequestSpec(); - diagnostics.putString("Breakpoint at " + spec.toString() + " deleted."); - } - @Override - public void breakpointResolved(SpecEvent e) { - EventRequestSpec spec = e.getEventRequestSpec(); - diagnostics.putString("Breakpoint resolved to " + spec.toString() + "."); - } - @Override - public void breakpointError(SpecErrorEvent e) { - EventRequestSpec spec = e.getEventRequestSpec(); - diagnostics.putString("Deferred breakpoint at " + - spec + " could not be resolved:" + - e.getReason()); - } - -//### Add info for watchpoints and exceptions - - @Override - public void watchpointSet(SpecEvent e) { - } - @Override - public void watchpointDeferred(SpecEvent e) { - } - @Override - public void watchpointDeleted(SpecEvent e) { - } - @Override - public void watchpointResolved(SpecEvent e) { - } - @Override - public void watchpointError(SpecErrorEvent e) { - } - - @Override - public void exceptionInterceptSet(SpecEvent e) { - } - @Override - public void exceptionInterceptDeferred(SpecEvent e) { - } - @Override - public void exceptionInterceptDeleted(SpecEvent e) { - } - @Override - public void exceptionInterceptResolved(SpecEvent e) { - } - @Override - public void exceptionInterceptError(SpecErrorEvent e) { - } - - - // ContextListener. - - // If the user selects a new current thread or frame, update prompt. - - @Override - public void currentFrameChanged(CurrentFrameChangedEvent e) { - // Update prompt only if affect thread is current. - ThreadReference thread = e.getThread(); - if (thread == context.getCurrentThread()) { - script.setPrompt(promptString(thread, e.getIndex())); - } - } - - } - - private String locationString(LocatableEventSet e) { - Location loc = e.getLocation(); - return "thread=\"" + e.getThread().name() + - "\", " + Utils.locationString(loc); - } - - private void setThread(LocatableEventSet e) { - if (!e.suspendedNone()) { - Thread.yield(); // fetch output - script.setPrompt(promptString(e.getThread(), 0)); - //### Current thread should be set elsewhere, e.g., - //### in ContextManager - //### context.setCurrentThread(thread); - } - } - - private String promptString(ThreadReference thread, int frameIndex) { - if (thread == null) { - return DEFAULT_CMD_PROMPT; - } else { - // Frame indices are presented to user as indexed from 1. - return (thread.name() + "[" + (frameIndex + 1) + "]:"); - } - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ContextListener.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ContextListener.java deleted file mode 100644 index 27143fac83a..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ContextListener.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.gui; - -public interface ContextListener { - void currentFrameChanged(CurrentFrameChangedEvent e); -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ContextManager.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ContextManager.java deleted file mode 100644 index fb2416789e8..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ContextManager.java +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.gui; - -import java.io.*; -import java.util.*; - -import com.sun.jdi.*; -import com.sun.tools.example.debug.event.*; -import com.sun.tools.example.debug.bdi.*; - -public class ContextManager { - - private ClassManager classManager; - private ExecutionManager runtime; - - private String mainClassName; - private String vmArguments; - private String commandArguments; - private String remotePort; - - private ThreadReference currentThread; - - private boolean verbose; - - private ArrayList contextListeners = new ArrayList(); - - public ContextManager(Environment env) { - classManager = env.getClassManager(); - runtime = env.getExecutionManager(); - mainClassName = ""; - vmArguments = ""; - commandArguments = ""; - currentThread = null; - - ContextManagerListener listener = new ContextManagerListener(); - runtime.addJDIListener(listener); - runtime.addSessionListener(listener); - } - - // Program execution defaults. - - //### Should there be change listeners for these? - //### They would be needed if we expected a dialog to be - //### synchronized with command input while it was open. - - public String getMainClassName() { - return mainClassName; - } - - public void setMainClassName(String mainClassName) { - this.mainClassName = mainClassName; - } - - public String getVmArguments() { - return processClasspathDefaults(vmArguments); - } - - public void setVmArguments(String vmArguments) { - this.vmArguments = vmArguments; - } - - public String getProgramArguments() { - return commandArguments; - } - - public void setProgramArguments(String commandArguments) { - this.commandArguments = commandArguments; - } - - public String getRemotePort() { - return remotePort; - } - - public void setRemotePort(String remotePort) { - this.remotePort = remotePort; - - } - - - // Miscellaneous debugger session preferences. - - public boolean getVerboseFlag() { - return verbose; - } - - public void setVerboseFlag(boolean verbose) { - this.verbose = verbose; - } - - - // Thread focus. - - public ThreadReference getCurrentThread() { - return currentThread; - } - - public void setCurrentThread(ThreadReference t) { - if (t != currentThread) { - currentThread = t; - notifyCurrentThreadChanged(t); - } - } - - public void setCurrentThreadInvalidate(ThreadReference t) { - currentThread = t; - notifyCurrentFrameChanged(runtime.threadInfo(t), - 0, true); - } - - public void invalidateCurrentThread() { - notifyCurrentFrameChanged(null, 0, true); - } - - - // If a view is displaying the current thread, it may - // choose to indicate which frame is current in the - // sense of the command-line UI. It may also "warp" the - // selection to that frame when changed by an 'up' or 'down' - // command. Hence, a notifier is provided. - - /****** - public int getCurrentFrameIndex() { - return getCurrentFrameIndex(currentThreadInfo); - } - ******/ - - public int getCurrentFrameIndex(ThreadReference t) { - return getCurrentFrameIndex(runtime.threadInfo(t)); - } - - //### Used in StackTraceTool. - public int getCurrentFrameIndex(ThreadInfo tinfo) { - if (tinfo == null) { - return 0; - } - Integer currentFrame = (Integer)tinfo.getUserObject(); - if (currentFrame == null) { - return 0; - } else { - return currentFrame.intValue(); - } - } - - public int moveCurrentFrameIndex(ThreadReference t, int count) throws VMNotInterruptedException { - return setCurrentFrameIndex(t,count, true); - } - - public int setCurrentFrameIndex(ThreadReference t, int newIndex) throws VMNotInterruptedException { - return setCurrentFrameIndex(t, newIndex, false); - } - - public int setCurrentFrameIndex(int newIndex) throws VMNotInterruptedException { - if (currentThread == null) { - return 0; - } else { - return setCurrentFrameIndex(currentThread, newIndex, false); - } - } - - private int setCurrentFrameIndex(ThreadReference t, int x, boolean relative) throws VMNotInterruptedException { - boolean sameThread = t.equals(currentThread); - ThreadInfo tinfo = runtime.threadInfo(t); - if (tinfo == null) { - return 0; - } - int maxIndex = tinfo.getFrameCount()-1; - int oldIndex = getCurrentFrameIndex(tinfo); - int newIndex = relative? oldIndex + x : x; - if (newIndex > maxIndex) { - newIndex = maxIndex; - } else if (newIndex < 0) { - newIndex = 0; - } - if (!sameThread || newIndex != oldIndex) { // don't recurse - setCurrentFrameIndex(tinfo, newIndex); - } - return newIndex - oldIndex; - } - - private void setCurrentFrameIndex(ThreadInfo tinfo, int index) { - tinfo.setUserObject(index); - //### In fact, the value may not have changed at this point. - //### We need to signal that the user attempted to change it, - //### however, so that the selection can be "warped" to the - //### current location. - notifyCurrentFrameChanged(tinfo.thread(), index); - } - - public StackFrame getCurrentFrame() throws VMNotInterruptedException { - return getCurrentFrame(runtime.threadInfo(currentThread)); - } - - public StackFrame getCurrentFrame(ThreadReference t) throws VMNotInterruptedException { - return getCurrentFrame(runtime.threadInfo(t)); - } - - public StackFrame getCurrentFrame(ThreadInfo tinfo) throws VMNotInterruptedException { - int index = getCurrentFrameIndex(tinfo); - try { - // It is possible, though unlikely, that the VM was interrupted - // before the thread created its Java stack. - return tinfo.getFrame(index); - } catch (FrameIndexOutOfBoundsException e) { - return null; - } - } - - public void addContextListener(ContextListener cl) { - contextListeners.add(cl); - } - - public void removeContextListener(ContextListener cl) { - contextListeners.remove(cl); - } - - //### These notifiers are fired only in response to USER-INITIATED changes - //### to the current thread and current frame. When the current thread is set automatically - //### after a breakpoint hit or step completion, no event is generated. Instead, - //### interested parties are expected to listen for the BreakpointHit and StepCompleted - //### events. This convention is unclean, and I believe that it reflects a defect in - //### in the current architecture. Unfortunately, however, we cannot guarantee the - //### order in which various listeners receive a given event, and the handlers for - //### the very same events that cause automatic changes to the current thread may also - //### need to know the current thread. - - private void notifyCurrentThreadChanged(ThreadReference t) { - ThreadInfo tinfo = null; - int index = 0; - if (t != null) { - tinfo = runtime.threadInfo(t); - index = getCurrentFrameIndex(tinfo); - } - notifyCurrentFrameChanged(tinfo, index, false); - } - - private void notifyCurrentFrameChanged(ThreadReference t, int index) { - notifyCurrentFrameChanged(runtime.threadInfo(t), - index, false); - } - - private void notifyCurrentFrameChanged(ThreadInfo tinfo, int index, - boolean invalidate) { - ArrayList l = new ArrayList(contextListeners); - CurrentFrameChangedEvent evt = - new CurrentFrameChangedEvent(this, tinfo, index, invalidate); - for (int i = 0; i < l.size(); i++) { - l.get(i).currentFrameChanged(evt); - } - } - - private class ContextManagerListener extends JDIAdapter - implements SessionListener, JDIListener { - - // SessionListener - - @Override - public void sessionStart(EventObject e) { - invalidateCurrentThread(); - } - - @Override - public void sessionInterrupt(EventObject e) { - setCurrentThreadInvalidate(currentThread); - } - - @Override - public void sessionContinue(EventObject e) { - invalidateCurrentThread(); - } - - // JDIListener - - @Override - public void locationTrigger(LocationTriggerEventSet e) { - setCurrentThreadInvalidate(e.getThread()); - } - - @Override - public void exception(ExceptionEventSet e) { - setCurrentThreadInvalidate(e.getThread()); - } - - @Override - public void vmDisconnect(VMDisconnectEventSet e) { - invalidateCurrentThread(); - } - - } - - - /** - * Add a -classpath argument to the arguments passed to the exec'ed - * VM with the contents of CLASSPATH environment variable, - * if -classpath was not already specified. - * - * @param javaArgs the arguments to the VM being exec'd that - * potentially has a user specified -classpath argument. - * @return a javaArgs whose -classpath option has been added - */ - - private String processClasspathDefaults(String javaArgs) { - if (javaArgs.indexOf("-classpath ") == -1) { - StringBuilder munged = new StringBuilder(javaArgs); - SearchPath classpath = classManager.getClassPath(); - if (classpath.isEmpty()) { - String envcp = System.getProperty("env.class.path"); - if ((envcp != null) && (envcp.length() > 0)) { - munged.append(" -classpath " + envcp); - } - } else { - munged.append(" -classpath " + classpath.asString()); - } - return munged.toString(); - } else { - return javaArgs; - } - } - - private String appendPath(String path1, String path2) { - if (path1 == null || path1.length() == 0) { - return path2 == null ? "." : path2; - } else if (path2 == null || path2.length() == 0) { - return path1; - } else { - return path1 + File.pathSeparator + path2; - } - } - -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/CurrentFrameChangedEvent.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/CurrentFrameChangedEvent.java deleted file mode 100644 index b933e758f38..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/CurrentFrameChangedEvent.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.gui; - -import com.sun.jdi.*; -import com.sun.tools.example.debug.bdi.*; -import java.util.EventObject; - -public class CurrentFrameChangedEvent extends EventObject { - - private static final long serialVersionUID = 4214479486546762179L; - private ThreadInfo tinfo; - private int index; - private boolean invalidate; - - public CurrentFrameChangedEvent(Object source, ThreadInfo tinfo, - int index, boolean invalidate) { - super(source); - this.tinfo = tinfo; - this.index = index; - this.invalidate = invalidate; - } - - public ThreadReference getThread() { - return tinfo == null? null : tinfo.thread(); - } - - public ThreadInfo getThreadInfo() { - return tinfo; - } - - public int getIndex() { - return index; - } - - public boolean getInvalidate() { - return invalidate; - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/Environment.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/Environment.java deleted file mode 100644 index b06ae4d6c79..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/Environment.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.gui; - -import java.io.*; -import com.sun.jdi.*; -import com.sun.tools.example.debug.bdi.*; - -public class Environment { - - private SourceManager sourceManager; - private ClassManager classManager; - private ContextManager contextManager; - private MonitorListModel monitorListModel; - private ExecutionManager runtime; - - private PrintWriter typeScript; - - private boolean verbose; - - public Environment() { - this.classManager = new ClassManager(this); - //### Order of the next three lines is important! (FIX THIS) - this.runtime = new ExecutionManager(); - this.sourceManager = new SourceManager(this); - this.contextManager = new ContextManager(this); - this.monitorListModel = new MonitorListModel(this); - } - - // Services used by debugging tools. - - public SourceManager getSourceManager() { - return sourceManager; - } - - public ClassManager getClassManager() { - return classManager; - } - - public ContextManager getContextManager() { - return contextManager; - } - - public MonitorListModel getMonitorListModel() { - return monitorListModel; - } - - public ExecutionManager getExecutionManager() { - return runtime; - } - - //### TODO: - //### Tools should attach/detach from environment - //### via a property, which should call an 'addTool' - //### method when set to maintain a registry of - //### tools for exit-time cleanup, etc. Tool - //### class constructors should be argument-free, so - //### that they may be instantiated by bean builders. - //### Will also need 'removeTool' in case property - //### value is changed. - // - // public void addTool(Tool t); - // public void removeTool(Tool t); - - public void terminate() { - System.exit(0); - } - - // public void refresh(); // notify all tools to refresh their views - - - // public void addStatusListener(StatusListener l); - // public void removeStatusListener(StatusListener l); - - // public void addOutputListener(OutputListener l); - // public void removeOutputListener(OutputListener l); - - public void setTypeScript(PrintWriter writer) { - typeScript = writer; - } - - public void error(String message) { - if (typeScript != null) { - typeScript.println(message); - } else { - System.out.println(message); - } - } - - public void failure(String message) { - if (typeScript != null) { - typeScript.println(message); - } else { - System.out.println(message); - } - } - - public void notice(String message) { - if (typeScript != null) { - typeScript.println(message); - } else { - System.out.println(message); - } - } - - public OutputSink getOutputSink() { - return new OutputSink(typeScript); - } - - public void viewSource(String fileName) { - //### HACK ### - //### Should use listener here. - com.sun.tools.example.debug.gui.GUI.srcTool.showSourceFile(fileName); - } - - public void viewLocation(Location locn) { - //### HACK ### - //### Should use listener here. - //### Should we use sourceForLocation here? - com.sun.tools.example.debug.gui.GUI.srcTool.showSourceForLocation(locn); - } - - //### Also in 'ContextManager'. Do we need both? - - public boolean getVerboseFlag() { - return verbose; - } - - public void setVerboseFlag(boolean verbose) { - this.verbose = verbose; - } - -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/GUI.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/GUI.java deleted file mode 100644 index eefbcfa7b61..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/GUI.java +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.gui; - -import java.io.*; -import javax.swing.*; -import javax.swing.border.*; -import java.awt.*; -import java.awt.event.*; - -import com.sun.jdi.*; -import com.sun.tools.example.debug.bdi.*; - -public class GUI extends JPanel { - - private static final long serialVersionUID = 3292463234530679091L; - private CommandTool cmdTool; - private ApplicationTool appTool; - //###HACK## - //### There is currently dirty code in Environment that - //### accesses this directly. - //private SourceTool srcTool; - public static SourceTool srcTool; - - private SourceTreeTool sourceTreeTool; - private ClassTreeTool classTreeTool; - private ThreadTreeTool threadTreeTool; - private StackTraceTool stackTool; - private MonitorTool monitorTool; - - public static final String progname = "javadt"; - public static final String version = "1.0Beta"; //### FIX ME. - public static final String windowBanner = "Java(tm) platform Debug Tool"; - - private Font fixedFont = new Font("monospaced", Font.PLAIN, 10); - - private GUI(Environment env) { - setLayout(new BorderLayout()); - - setBorder(new EmptyBorder(5, 5, 5, 5)); - - add(new JDBToolBar(env), BorderLayout.NORTH); - - srcTool = new SourceTool(env); - srcTool.setPreferredSize(new java.awt.Dimension(500, 300)); - srcTool.setTextFont(fixedFont); - - stackTool = new StackTraceTool(env); - stackTool.setPreferredSize(new java.awt.Dimension(500, 100)); - - monitorTool = new MonitorTool(env); - monitorTool.setPreferredSize(new java.awt.Dimension(500, 50)); - - JSplitPane right = new JSplitPane(JSplitPane.VERTICAL_SPLIT, srcTool, - new JSplitPane(JSplitPane.VERTICAL_SPLIT, stackTool, monitorTool)); - - sourceTreeTool = new SourceTreeTool(env); - sourceTreeTool.setPreferredSize(new java.awt.Dimension(200, 450)); - - classTreeTool = new ClassTreeTool(env); - classTreeTool.setPreferredSize(new java.awt.Dimension(200, 450)); - - threadTreeTool = new ThreadTreeTool(env); - threadTreeTool.setPreferredSize(new java.awt.Dimension(200, 450)); - - JTabbedPane treePane = new JTabbedPane(SwingConstants.BOTTOM); - treePane.addTab("Source", null, sourceTreeTool); - treePane.addTab("Classes", null, classTreeTool); - treePane.addTab("Threads", null, threadTreeTool); - - JSplitPane centerTop = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treePane, right); - - cmdTool = new CommandTool(env); - cmdTool.setPreferredSize(new java.awt.Dimension(700, 150)); - - appTool = new ApplicationTool(env); - appTool.setPreferredSize(new java.awt.Dimension(700, 200)); - - JSplitPane centerBottom = new JSplitPane(JSplitPane.VERTICAL_SPLIT, cmdTool, appTool); - // centerBottom.setPreferredSize(new java.awt.Dimension(700, 350)); - - JSplitPane center = new JSplitPane(JSplitPane.VERTICAL_SPLIT, centerTop, centerBottom); - - add(center, BorderLayout.CENTER); - - - } - - private static void usage() { - String separator = File.pathSeparator; - System.out.println("Usage: " + progname + " "); - System.out.println(); - System.out.println("where options include:"); - System.out.println(" -help print out this message and exit"); - System.out.println(" -sourcepath "); - System.out.println(" list directories in which to look for source files"); - System.out.println(" -remote :"); - System.out.println(" host machine and port number of interpreter to attach to"); - System.out.println(" -dbgtrace [flags] print info for debugging " + progname); - System.out.println(); - System.out.println("options forwarded to debuggee process:"); - System.out.println(" -v -verbose[:class|gc|jni]"); - System.out.println(" turn on verbose mode"); - System.out.println(" -D= set a system property"); - System.out.println(" -classpath "); - System.out.println(" list directories in which to look for classes"); - System.out.println(" -X

Example JDI Applications

-This example download contains the source code and -documentation for three applications written using -the JavaTM Debug Interface (JDI) -of the Java Platform Debugger Architecture (JPDA). -They are provided as educational tools and as starting -points for debugger development. -

-In increasing order of complexity: -

    -
  • Trace displays traces -of program execution. It is very simple (less than 600 lines) -yet uses most of the basic JDI functionality. It is a -good starting point. -
  • Jdb is the command line debugger -distributed with the J2SE SDK. -
  • Javadt is the beginnings of -a GUI debugger. -
-

-Trace is in the trace directory. -Jdb and Javadt share a package, and are under the -debug directory. - -

Required Set-up

- -

Where is JPDA?

-New versions of the J2SE SDK have JPDA included. For -older versions JPDA must be separately downloaded. -
-
SDKs with JPDA included -
J2SE SDK v1.3 and later and J2SE SDK for Linux v1.2.2 -
SDKs requiring JPDA download -
J2SE SDK v1.2.1 and v1.2.2 for Solaris and Windows -
Other SDKs -
Check with vendor -
-

-

Set-up for J2SE SDKs with JPDA included

-Your classpath must include the JDI Library code, which is -in tools.jar in the lib directory. -This is needed for both compiling the example code and -executing it. -

-

Set-up for J2SE SDKs without JPDA - Solaris

-Download JPDA v1.0 from -http://java.sun.com/products/jpda. Follow the -Installation Instructions -found there. Pay particular attention to setting the library -path. -

-Your classpath must include the JDI Library code, which is -in jpda_home/lib/tools.jar. -This is needed for both compiling the example code and -executing it. -

-

Set-up for J2SE SDKs without JPDA - Windows

-Download JPDA v1.0 from -http://java.sun.com/products/jpda. Follow the -Installation Instructions -found there. Be sure to add: -
-        jpda_home\bin
-
-to your path. -

-Your classpath must include the JDI Library code, which is -in jpda_home\lib\tools.jar. -This is needed for both compiling the example code and -executing it. -

-


-
java-debugger@java.sun.com
-

-

-

- - - diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/doc/javadt.html b/jdk/src/demo/share/jpda/com/sun/tools/example/doc/javadt.html deleted file mode 100644 index f9d28a166bb..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/doc/javadt.html +++ /dev/null @@ -1,174 +0,0 @@ - - - Release notes for the javadt debugger - - -

Release notes for the javadt debugger

- -

-As a demonstration of the - -JavaTM Platform Debugger Architecture -we are providing source code for -a simple GUI debugging tool - javadt. -It is included as an example and demonstration of - -JDI. It is not a finished or polished debugger and is -missing many features of importance for real debugging work. -

- -

Invoking javadt

-

-javadt can be run by executing: -

-   java com.sun.tools.example.debug.gui.GUI <options>.. <class-name>
-
-where <class-name> is the name you would normally -place on the java command line. -Note: the path to the JDI Library and to -the compiled javadt class files must be on the class path -used to invoke gui.GUI. -

-For example, you can invoke the javadt debugger as follows: -

-   java com.sun.tools.example.debug.gui.GUI -classpath . Hello
-
-Note: this -classpath option controls the -class path for the Hello application. -Once the window appears, you can issue the 'run' command to begin -execution immediately. It is also -possible to give the class name in the 'run' command, in -which case it may be omitted when invoking the debugger from the -shell. -

-The classpath may also be set from within the debugger, using the -'classpath' command. Currently, other arguments to the VM must be -given on the shell command line when the debugger is initially -invoked. The most recently mentioned classpath, VM arguments, main -class name, and program arguments are retained as defaults for later -'run' and 'load' commands. (Unfortunately, at present, the debugger -will likely crash if you attempt to begin another debugging session -with another debuggee process from within the same invocation of the -debugger. You should exit to the shell and start a new debugger -process.) -

- -

Using javadt

-The javadt normally displays context related to the "current thread", -that is, the thread that most recently encountered a breakpoint, threw -an uncaught exception, or was single-stepped by the user. When -program execution is suspended on account of one of these events, a -current thread exists, and the javadt displays the following information -about it: -

-

    -
  • A stack backtrace. - -
  • The source code surrounding the line corresponding to the - instruction counter for the thread, if the source code is - available. -
-

-In addition, a tabbed pane allows the user to view one of three -additional views: -

-

    -
  • A tree of all source files available on the source path. - -
  • A tree of all loaded class files, organized hierarchically - by package. - -
  • A tree of all active threads, organized hierarchically - by thread group. -
-

-By clicking on the name of a source file, the source view can be -directed to display it. Likewise, clicking on a thread will make that -thread the current thread. These features are normally used while the -program is suspended, e.g, at a breakpoint. Upon resumption and -encountering another breakpoint, for example, the current thread will -be automatically reset and the views will be updated. The views tile -the javadt display, and are adjustable in size. -

-The javadt functionality is rather basic, thus a command-line interaction -window is also provided that allows access to functions that are not -yet exposed in the javadt. In particular, it is necessary to use the -command line in order to set breakpoints and examine variables. The -javadt debugger command interpreter implements roughly a subset of the -jdb - functionality, but adds a few commands of its own. The -'help' command lists the complete set of commands and their function. -Shortcuts for a set of the most common commands is provided on a -button-bar at the top of the display. -

-The program to be debugged may be started either as a child of the -debugger, or the debugger can be attached to an existing process, -provided that its VM is prepared to accept the connection. If the -debuggee is started by the debugger as a child, a line-oriented -interface to its standard input, output, and error streams is provided -in an application interaction pane. -

-The debugger expects to find the program source code on its -sourcepath, set with the 'use' or 'sourcepath' command. If you find -that sources are not being displayed because the sourcepath is -incorrect, you may change it at that time, and the source view will be -immediately updated. -

-The message "No current thread" is often encountered when stepping -through a program. This message does not mean that the thread or -the VM has died, merely that a current thread is undefined. This -situation can easily occur unexpectedly when the program being -stepped is waiting, eg., for input. The VM appears to be stopped, -as it would be after the successful completion of a step, but it -is considered to be "running", not "interrupted". The prompt -in the command interaction pane indicates the state by changing -to a thread name and frame number when the VM is interrupted. -When it is running, the prompt "Command:" is displayed. -

-

Source for javadt

-Full source code for javadt is included under the -debug directory of examples.jar. -Note: these directories also include the -source for jdb. -Source code for these example applications is included to provide concrete -examples for debugger developers. Example code may be used, modified -and redistributed by debugger developers providing they adhere to the -terms in the COPYRIGHT notice. -

-javadt uses the following packages (found under the -debug directory): -

-
gui -
User interface code -
bdi -
Debugger core code -
events -
Event Set code -
expr -
Expression processing code -
-

-

Building javadt

-To build the javadt classes from the -provided source files under the debug directory, -you need only to compile them. No special -options are required, aside from those which set your classpath to -include the JDI Library. -

-

-However, if you want to modify the expression parser in the file -Expr.jj, you will need the - -JavaCC parser generator. -It is available free from -Metamata -(now part of WebGain). -

-


-
java-debugger@java.sun.com
-

-

-

- - diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/doc/jdb.html b/jdk/src/demo/share/jpda/com/sun/tools/example/doc/jdb.html deleted file mode 100644 index a8232b0207d..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/doc/jdb.html +++ /dev/null @@ -1,104 +0,0 @@ - - - Release notes for the jdb debugger - - -  - - - - - -
-
-

Release notes for the jdb debugger

-
- -

-Home Page - -

-As a demonstration of the - -JavaTM Platform Debugger Architecture -we are providing source code for the jdb debugger, which was -re-written to use - -JDI. - -

-

jdb man pages

-
-jdb man pages for Windows -

-jdb man pages for Solaris -

-

-

Invoking jdb

-The jdb sample can be started by executing: -
-   java com.sun.tools.example.debug.tty.TTY <options>.. <class-name>
-
-where <class-name> is the name you would normally -place on the java command line. The -help -option provides information on options. -

-

-Note: the path to the JDI Library and to -the compiled jdb class files must be on the class path -used to invoke com.sun.tools.example.debug.tty.TTY. - -

-For more information on invoking and connecting, refer to the - -Connection and Invocation Details section of the - -JPDA documentation, -particularly the section on jdb. -

- - -

Source for jdb

-Full source code for jdb is included under the -debug directory of examples.jar. -Note: these directories also include the -source for javadt. -Source code for these example applications is included to provide concrete -examples for debugger developers. Example code may be used, modified -and redistributed by debugger developers providing they adhere to the -terms in the COPYRIGHT notice. -

-jdb uses the following packages (found under the -debug directory): -

-
tty -
Application code -
expr -
Expression processing code -
- -

-

Building jdb

-To completely rebuild the jdb classes from the -provided source files under the debug directory, -you need only to compile them. No special -options are required, aside from those which set your classpath to -include the JDI Library. -

-

-However, if you want to modify the expression parser in the file -Expr.jj, you will need the - -JavaCC parser generator. -It is available free from -Metamata -(now part of WebGain). -

-


-
java-debugger@java.sun.com
-

-

-

- - diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/doc/trace.html b/jdk/src/demo/share/jpda/com/sun/tools/example/doc/trace.html deleted file mode 100644 index 8cae84dfe1e..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/doc/trace.html +++ /dev/null @@ -1,71 +0,0 @@ - - - - trace example - - -

trace example

- -Trace runs the Java language program passed as an argument and -generates a trace of its execution. Trace is a simple command -line tool that uses the - -Java Debug Interface (JDI). Programs need -not be compiled for debugging since this information is not -used. -

-Trace can be invoked as follows: -

-        java com.sun.tools.example.trace.Trace options class args
-
-Your classpath must include the JDI Library -(see set-up), -the path to the compiled trace class files, -and the path for the application being traced. -

-Available options are: - -

-  -output filename   
-        Set destination for output trace. By default output
-        goes to the terminal.
-
-  -all                 
-        Include system classes in output.  By default
-        java.*, javax.*, sun.* and com.sun.* events are
-        not diplayed.
-
-  -fields
-        Also show assignments into fields.
-
-  -help              
-        Print a help message
-
-
-class is the program to trace. args are the arguments to class. -

- -

Source for trace

-Full source code for trace is included in the -trace directory of examples.jar. -Source code for these example applications is included to provide concrete -examples for debugger developers. Example code may be used, modified -and redistributed by debugger developers providing they adhere to the -terms in the COPYRIGHT notice. - -

-

Building trace

-To completely rebuild the trace classes from the -provided source files in the trace directory, -you need only to compile them. No special -options are required, aside from those which set your classpath to -include the JDI Library. - -

-


-
java-debugger@java.sun.com
-

-

-

- - diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/trace/EventThread.java b/jdk/src/demo/share/jpda/com/sun/tools/example/trace/EventThread.java deleted file mode 100644 index 11084df5dd2..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/trace/EventThread.java +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.trace; - -import com.sun.jdi.*; -import com.sun.jdi.request.*; -import com.sun.jdi.event.*; - -import java.util.*; -import java.io.PrintWriter; - -/** - * This class processes incoming JDI events and displays them - * - * @author Robert Field - */ -public class EventThread extends Thread { - - private final VirtualMachine vm; // Running VM - private final String[] excludes; // Packages to exclude - private final PrintWriter writer; // Where output goes - - static String nextBaseIndent = ""; // Starting indent for next thread - - private boolean connected = true; // Connected to VM - private boolean vmDied = true; // VMDeath occurred - - // Maps ThreadReference to ThreadTrace instances - private Map traceMap = - new HashMap<>(); - - EventThread(VirtualMachine vm, String[] excludes, PrintWriter writer) { - super("event-handler"); - this.vm = vm; - this.excludes = excludes; - this.writer = writer; - } - - /** - * Run the event handling thread. - * As long as we are connected, get event sets off - * the queue and dispatch the events within them. - */ - @Override - public void run() { - EventQueue queue = vm.eventQueue(); - while (connected) { - try { - EventSet eventSet = queue.remove(); - EventIterator it = eventSet.eventIterator(); - while (it.hasNext()) { - handleEvent(it.nextEvent()); - } - eventSet.resume(); - } catch (InterruptedException exc) { - // Ignore - } catch (VMDisconnectedException discExc) { - handleDisconnectedException(); - break; - } - } - } - - /** - * Create the desired event requests, and enable - * them so that we will get events. - * @param excludes Class patterns for which we don't want events - * @param watchFields Do we want to watch assignments to fields - */ - void setEventRequests(boolean watchFields) { - EventRequestManager mgr = vm.eventRequestManager(); - - // want all exceptions - ExceptionRequest excReq = mgr.createExceptionRequest(null, - true, true); - // suspend so we can step - excReq.setSuspendPolicy(EventRequest.SUSPEND_ALL); - excReq.enable(); - - MethodEntryRequest menr = mgr.createMethodEntryRequest(); - for (int i=0; i 0) { - indent.append("| "); - } - - EventRequestManager mgr = vm.eventRequestManager(); - mgr.deleteEventRequest(event.request()); - } - - void threadDeathEvent(ThreadDeathEvent event) { - indent = new StringBuffer(baseIndent); - println("====== " + thread.name() + " end ======"); - } - } - - /** - * Returns the ThreadTrace instance for the specified thread, - * creating one if needed. - */ - ThreadTrace threadTrace(ThreadReference thread) { - ThreadTrace trace = traceMap.get(thread); - if (trace == null) { - trace = new ThreadTrace(thread); - traceMap.put(thread, trace); - } - return trace; - } - - /** - * Dispatch incoming events - */ - private void handleEvent(Event event) { - if (event instanceof ExceptionEvent) { - exceptionEvent((ExceptionEvent)event); - } else if (event instanceof ModificationWatchpointEvent) { - fieldWatchEvent((ModificationWatchpointEvent)event); - } else if (event instanceof MethodEntryEvent) { - methodEntryEvent((MethodEntryEvent)event); - } else if (event instanceof MethodExitEvent) { - methodExitEvent((MethodExitEvent)event); - } else if (event instanceof StepEvent) { - stepEvent((StepEvent)event); - } else if (event instanceof ThreadDeathEvent) { - threadDeathEvent((ThreadDeathEvent)event); - } else if (event instanceof ClassPrepareEvent) { - classPrepareEvent((ClassPrepareEvent)event); - } else if (event instanceof VMStartEvent) { - vmStartEvent((VMStartEvent)event); - } else if (event instanceof VMDeathEvent) { - vmDeathEvent((VMDeathEvent)event); - } else if (event instanceof VMDisconnectEvent) { - vmDisconnectEvent((VMDisconnectEvent)event); - } else { - throw new Error("Unexpected event type"); - } - } - - /*** - * A VMDisconnectedException has happened while dealing with - * another event. We need to flush the event queue, dealing only - * with exit events (VMDeath, VMDisconnect) so that we terminate - * correctly. - */ - synchronized void handleDisconnectedException() { - EventQueue queue = vm.eventQueue(); - while (connected) { - try { - EventSet eventSet = queue.remove(); - EventIterator iter = eventSet.eventIterator(); - while (iter.hasNext()) { - Event event = iter.nextEvent(); - if (event instanceof VMDeathEvent) { - vmDeathEvent((VMDeathEvent)event); - } else if (event instanceof VMDisconnectEvent) { - vmDisconnectEvent((VMDisconnectEvent)event); - } - } - eventSet.resume(); // Resume the VM - } catch (InterruptedException exc) { - // ignore - } - } - } - - private void vmStartEvent(VMStartEvent event) { - writer.println("-- VM Started --"); - } - - // Forward event for thread specific processing - private void methodEntryEvent(MethodEntryEvent event) { - threadTrace(event.thread()).methodEntryEvent(event); - } - - // Forward event for thread specific processing - private void methodExitEvent(MethodExitEvent event) { - threadTrace(event.thread()).methodExitEvent(event); - } - - // Forward event for thread specific processing - private void stepEvent(StepEvent event) { - threadTrace(event.thread()).stepEvent(event); - } - - // Forward event for thread specific processing - private void fieldWatchEvent(ModificationWatchpointEvent event) { - threadTrace(event.thread()).fieldWatchEvent(event); - } - - void threadDeathEvent(ThreadDeathEvent event) { - ThreadTrace trace = traceMap.get(event.thread()); - if (trace != null) { // only want threads we care about - trace.threadDeathEvent(event); // Forward event - } - } - - /** - * A new class has been loaded. - * Set watchpoints on each of its fields - */ - private void classPrepareEvent(ClassPrepareEvent event) { - EventRequestManager mgr = vm.eventRequestManager(); - List fields = event.referenceType().visibleFields(); - for (Field field : fields) { - ModificationWatchpointRequest req = - mgr.createModificationWatchpointRequest(field); - for (int i=0; i= 0) { - out.write(cbuf, 0, count); - } - out.flush(); - } catch(IOException exc) { - System.err.println("Child I/O Transfer - " + exc); - } - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/trace/Trace.java b/jdk/src/demo/share/jpda/com/sun/tools/example/trace/Trace.java deleted file mode 100644 index 2ce99f97a01..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/trace/Trace.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.trace; - -import com.sun.jdi.VirtualMachine; -import com.sun.jdi.Bootstrap; -import com.sun.jdi.connect.*; - -import java.util.Map; -import java.util.List; - -import java.io.PrintWriter; -import java.io.FileWriter; -import java.io.IOException; - -/** - * This program traces the execution of another program. - * See "java Trace -help". - * It is a simple example of the use of the Java Debug Interface. - * - * @author Robert Field - */ -public class Trace { - - // Running remote VM - private final VirtualMachine vm; - - // Thread transferring remote error stream to our error stream - private Thread errThread = null; - - // Thread transferring remote output stream to our output stream - private Thread outThread = null; - - // Mode for tracing the Trace program (default= 0 off) - private int debugTraceMode = 0; - - // Do we want to watch assignments to fields - private boolean watchFields = false; - - // Class patterns for which we don't want events - private String[] excludes = {"java.*", "javax.*", "sun.*", - "com.sun.*"}; - - /** - * main - */ - public static void main(String[] args) { - new Trace(args); - } - - /** - * Parse the command line arguments. - * Launch target VM. - * Generate the trace. - */ - Trace(String[] args) { - PrintWriter writer = new PrintWriter(System.out); - int inx; - for (inx = 0; inx < args.length; ++inx) { - String arg = args[inx]; - if (arg.charAt(0) != '-') { - break; - } - if (arg.equals("-output")) { - try { - writer = new PrintWriter(new FileWriter(args[++inx])); - } catch (IOException exc) { - System.err.println("Cannot open output file: " + args[inx] - + " - " + exc); - System.exit(1); - } - } else if (arg.equals("-all")) { - excludes = new String[0]; - } else if (arg.equals("-fields")) { - watchFields = true; - } else if (arg.equals("-dbgtrace")) { - debugTraceMode = Integer.parseInt(args[++inx]); - } else if (arg.equals("-help")) { - usage(); - System.exit(0); - } else { - System.err.println("No option: " + arg); - usage(); - System.exit(1); - } - } - if (inx >= args.length) { - System.err.println(" missing"); - usage(); - System.exit(1); - } - StringBuilder sb = new StringBuilder(); - sb.append(args[inx]); - for (++inx; inx < args.length; ++inx) { - sb.append(' '); - sb.append(args[inx]); - } - vm = launchTarget(sb.toString()); - generateTrace(writer); - } - - - /** - * Generate the trace. - * Enable events, start thread to display events, - * start threads to forward remote error and output streams, - * resume the remote VM, wait for the final event, and shutdown. - */ - void generateTrace(PrintWriter writer) { - vm.setDebugTraceMode(debugTraceMode); - EventThread eventThread = new EventThread(vm, excludes, writer); - eventThread.setEventRequests(watchFields); - eventThread.start(); - redirectOutput(); - vm.resume(); - - // Shutdown begins when event thread terminates - try { - eventThread.join(); - errThread.join(); // Make sure output is forwarded - outThread.join(); // before we exit - } catch (InterruptedException exc) { - // we don't interrupt - } - writer.close(); - } - - /** - * Launch target VM. - * Forward target's output and error. - */ - VirtualMachine launchTarget(String mainArgs) { - LaunchingConnector connector = findLaunchingConnector(); - Map arguments = - connectorArguments(connector, mainArgs); - try { - return connector.launch(arguments); - } catch (IOException exc) { - throw new Error("Unable to launch target VM: " + exc); - } catch (IllegalConnectorArgumentsException exc) { - throw new Error("Internal error: " + exc); - } catch (VMStartException exc) { - throw new Error("Target VM failed to initialize: " + - exc.getMessage()); - } - } - - void redirectOutput() { - Process process = vm.process(); - - // Copy target's output and error to our output and error. - errThread = new StreamRedirectThread("error reader", - process.getErrorStream(), - System.err); - outThread = new StreamRedirectThread("output reader", - process.getInputStream(), - System.out); - errThread.start(); - outThread.start(); - } - - /** - * Find a com.sun.jdi.CommandLineLaunch connector - */ - LaunchingConnector findLaunchingConnector() { - List connectors = Bootstrap.virtualMachineManager().allConnectors(); - for (Connector connector : connectors) { - if (connector.name().equals("com.sun.jdi.CommandLineLaunch")) { - return (LaunchingConnector)connector; - } - } - throw new Error("No launching connector"); - } - - /** - * Return the launching connector's arguments. - */ - Map connectorArguments(LaunchingConnector connector, String mainArgs) { - Map arguments = connector.defaultArguments(); - Connector.Argument mainArg = - (Connector.Argument)arguments.get("main"); - if (mainArg == null) { - throw new Error("Bad launching connector"); - } - mainArg.setValue(mainArgs); - - if (watchFields) { - // We need a VM that supports watchpoints - Connector.Argument optionArg = - (Connector.Argument)arguments.get("options"); - if (optionArg == null) { - throw new Error("Bad launching connector"); - } - optionArg.setValue("-classic"); - } - return arguments; - } - - /** - * Print command line usage help - */ - void usage() { - System.err.println("Usage: java Trace "); - System.err.println(" are:"); - System.err.println( -" -output Output trace to "); - System.err.println( -" -all Include system classes in output"); - System.err.println( -" -help Print this help message"); - System.err.println(" is the program to trace"); - System.err.println(" are the arguments to "); - } -} diff --git a/jdk/src/demo/share/jvmti/hprof/sample.makefile.txt b/jdk/src/demo/share/jvmti/hprof/sample.makefile.txt deleted file mode 100644 index e8f84dc8577..00000000000 --- a/jdk/src/demo/share/jvmti/hprof/sample.makefile.txt +++ /dev/null @@ -1,205 +0,0 @@ -# -# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# - Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# - Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# - Neither the name of Oracle nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -######################################################################## -# -# Sample GNU Makefile for building -# -# Example uses: -# gnumake JDK= OSNAME=solaris [OPT=true] [LIBARCH=sparc] -# gnumake JDK= OSNAME=solaris [OPT=true] [LIBARCH=sparcv9] -# gnumake JDK= OSNAME=linux [OPT=true] -# gnumake JDK= OSNAME=win32 [OPT=true] -# -######################################################################## - -# Source lists -LIBNAME=hprof -SOURCES= \ - debug_malloc.c \ - hprof_blocks.c \ - hprof_class.c \ - hprof_cpu.c \ - hprof_error.c \ - hprof_event.c \ - hprof_frame.c \ - hprof_init.c \ - hprof_io.c \ - hprof_ioname.c \ - hprof_listener.c \ - hprof_loader.c \ - hprof_monitor.c \ - hprof_object.c \ - hprof_reference.c \ - hprof_site.c \ - hprof_stack.c \ - hprof_string.c \ - hprof_table.c \ - hprof_tag.c \ - hprof_tls.c \ - hprof_trace.c \ - hprof_tracker.c \ - hprof_util.c \ - hprof_md.c - -JAVA_SOURCES=Tracker.java - -# Name of jar file that needs to be created -#JARFILE=hprof.jar - -# Solaris Sun C Compiler Version 5.5 -ifeq ($(OSNAME), solaris) - # Sun Solaris Compiler options needed - COMMON_FLAGS=-mt -KPIC - # Options that help find errors - COMMON_FLAGS+= -Xa -v -xstrconst -xc99=%none - # To make hprof logging code available - COMMON_FLAGS+= -DHPROF_LOGGING - # Check LIBARCH for any special compiler options - LIBARCH=$(shell uname -p) - ifeq ($(LIBARCH), sparc) - COMMON_FLAGS+=-xarch=v8 -xregs=no%appl - endif - ifeq ($(LIBARCH), sparcv9) - COMMON_FLAGS+=-xarch=v9 -xregs=no%appl - endif - ifeq ($(OPT), true) - CFLAGS=-xO2 $(COMMON_FLAGS) -DNDEBUG - else - CFLAGS=-g $(COMMON_FLAGS) -DDEBUG - endif - # Object files needed to create library - OBJECTS=$(SOURCES:%.c=%.o) - # Library name and options needed to build it - LIBRARY=lib$(LIBNAME).so - LDFLAGS=-z defs -ztext - # Libraries we are dependent on - LIBRARIES=-lsocket -lnsl -ldl -lc - # Building a shared library - LINK_SHARED=$(LINK.c) -G -o $@ -endif - -# Linux GNU C Compiler -ifeq ($(OSNAME), linux) - # GNU Compiler options needed to build it - COMMON_FLAGS=-fno-strict-aliasing -fPIC -fno-omit-frame-pointer - # Options that help find errors - COMMON_FLAGS+= -W -Wall -Wno-unused -Wno-parentheses - # To allow access to dladdr() - COMMON_FLAGS+= -D_GNU_SOURCE - # To prevent include of procfs.h - COMMON_FLAGS+= -DLINUX - # To make sure code is reentrant - COMMON_FLAGS+= -D_REENTRANT - # To make hprof logging code available - COMMON_FLAGS+= -DHPROF_LOGGING - ifeq ($(OPT), true) - CFLAGS=-O2 $(COMMON_FLAGS) -DNDEBUG - else - CFLAGS=-g $(COMMON_FLAGS) -DDEBUG - endif - # Object files needed to create library - OBJECTS=$(SOURCES:%.c=%.o) - # Library name and options needed to build it - LIBRARY=lib$(LIBNAME).so - LDFLAGS=-Wl,-soname=$(LIBRARY) -static-libgcc - # Libraries we are dependent on - LIBRARIES= -ldl -lc - # Building a shared library - LINK_SHARED=$(LINK.c) -shared -o $@ -endif - -# Windows Microsoft C/C++ Optimizing Compiler Version 12 -ifeq ($(OSNAME), win32) - CC=cl - # Compiler options needed to build it - COMMON_FLAGS=-Gy -DWIN32 - # Options that help find errors - COMMON_FLAGS+=-W0 -WX - # To make hprof logging code available - COMMON_FLAGS+= -DHPROF_LOGGING - ifeq ($(OPT), true) - CFLAGS= -Ox -Op -Zi $(COMMON_FLAGS) -DNDEBUG - else - CFLAGS= -Od -Zi $(COMMON_FLAGS) -DDEBUG - endif - # Add java_crw_demo source - SOURCES += ../java_crw_demo.c - # Object files needed to create library - OBJECTS=$(SOURCES:%.c=%.obj) - # Library name and options needed to build it - LIBRARY=$(LIBNAME).dll - LDFLAGS= - # Libraries we are dependent on - LIBRARIES=wsock32.lib winmm.lib - # Building a shared library - LINK_SHARED=link -dll -out:$@ -endif - -# Common -I options -CFLAGS += -I. -CFLAGS += -I../java_crw_demo -CFLAGS += -I$(JDK)/include -I$(JDK)/include/$(OSNAME) - -# Default rule (build both native library and jar file) -all: hprof_md.c $(LIBRARY) $(JARFILE) - -# Get platform specific hprof_md.c -hprof_md.c: - rm -f $@ - cp $(OSNAME)/hprof_md.c $@ - -# Build native library -$(LIBRARY): $(OBJECTS) - $(LINK_SHARED) $(OBJECTS) $(LIBRARIES) - -# Build jar file -$(JARFILE): $(JAVA_SOURCES) - rm -f -r classes - mkdir -p classes - $(JDK)/bin/javac -d classes $(JAVA_SOURCES) - (cd classes; $(JDK)/bin/jar cf ../$@ *) - -# Cleanup the built bits -clean: - rm -f -r classes - rm -f $(LIBRARY) $(JARFILE) $(OBJECTS) - -# Simple tester -test: all - LD_LIBRARY_PATH=. $(JDK)/bin/java -agentlib:$(LIBNAME) -Xbootclasspath/a:./$(JARFILE) -version - -# Compilation rule only needed on Windows -ifeq ($(OSNAME), win32) -%.obj: %.c - $(COMPILE.c) $< -endif - diff --git a/jdk/src/demo/share/jvmti/index.html b/jdk/src/demo/share/jvmti/index.html index b66ac8d9bfa..4b479c12468 100644 --- a/jdk/src/demo/share/jvmti/index.html +++ b/jdk/src/demo/share/jvmti/index.html @@ -54,17 +54,16 @@ variable (Windows). This is system and platform specific. If you are using 64bit Solaris (e.g. 'java -d64'), you should use LD_LIBRARY_PATH64. -Some agents such as hprof (heap/cpu profiler) and jdwp (debugger backend) +Some agents such as the jdwp (debugger backend) are located inside the primary JDK directories and will always be found in those locations.

The agents that instrument classfiles (i.e. BCI, usually through the java_crw_demo library) -such as hprof, heapTracker, mtrace, and minst, +such as heapTracker, mtrace, and minst, also need to have the Java classes they use available in the bootclasspath. -The one used by hprof is already in the bootclasspath, and the -other agents will make attempts at automatically adding their jar file +The agents will make attempts at automatically adding their jar file (e.g. heapTracker.jar, mtrace.jar, or minst.jar) to the bootclasspath with AddToBootstrapClassLoaderSearch from JVM TI at startup (see the agent_util code). @@ -150,19 +149,6 @@ This is a small agent that gets information about threads waiting on monitors. -

  • -hprof -
    -This is a large agent that does heap and cpu profiling. -This demo agent is actually built into the - -Java Runtime Environment (JRE). -It uses Bytecode Instrumentation (BCI) via the java_crw_demo library. -
    -Note: hprof is NOT a small or simple agent, the other smaller demos -should be looked at first. -
  • - 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 71be2db3b47..3d199579249 100644 --- a/jdk/src/java.base/share/classes/java/io/ByteArrayOutputStream.java +++ b/jdk/src/java.base/share/classes/java/io/ByteArrayOutputStream.java @@ -93,6 +93,14 @@ public class ByteArrayOutputStream extends OutputStream { grow(minCapacity); } + /** + * The maximum size of array to allocate. + * Some VMs reserve some header words in an array. + * Attempts to allocate larger arrays may result in + * OutOfMemoryError: Requested array size exceeds VM limit + */ + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + /** * Increases the capacity to ensure that it can hold at least the * number of elements specified by the minimum capacity argument. @@ -105,14 +113,19 @@ public class ByteArrayOutputStream extends OutputStream { int newCapacity = oldCapacity << 1; if (newCapacity - minCapacity < 0) newCapacity = minCapacity; - if (newCapacity < 0) { - if (minCapacity < 0) // overflow - throw new OutOfMemoryError(); - newCapacity = Integer.MAX_VALUE; - } + if (newCapacity - MAX_ARRAY_SIZE > 0) + newCapacity = hugeCapacity(minCapacity); buf = Arrays.copyOf(buf, newCapacity); } + private static int hugeCapacity(int minCapacity) { + if (minCapacity < 0) // overflow + throw new OutOfMemoryError(); + return (minCapacity > MAX_ARRAY_SIZE) ? + Integer.MAX_VALUE : + MAX_ARRAY_SIZE; + } + /** * Writes the specified byte to this byte array output stream. * diff --git a/jdk/src/java.base/share/classes/java/io/FileInputStream.java b/jdk/src/java.base/share/classes/java/io/FileInputStream.java index 6f13156bf98..b501b45707f 100644 --- a/jdk/src/java.base/share/classes/java/io/FileInputStream.java +++ b/jdk/src/java.base/share/classes/java/io/FileInputStream.java @@ -184,7 +184,16 @@ class FileInputStream extends InputStream * Opens the specified file for reading. * @param name the name of the file */ - private native void open(String name) throws FileNotFoundException; + private native void open0(String name) throws FileNotFoundException; + + // wrap native call to allow instrumentation + /** + * Opens the specified file for reading. + * @param name the name of the file + */ + private void open(String name) throws FileNotFoundException { + open0(name); + } /** * Reads a byte of data from this input stream. This method blocks diff --git a/jdk/src/java.base/share/classes/java/io/FileOutputStream.java b/jdk/src/java.base/share/classes/java/io/FileOutputStream.java index 1f7cff54cfa..281a695e6df 100644 --- a/jdk/src/java.base/share/classes/java/io/FileOutputStream.java +++ b/jdk/src/java.base/share/classes/java/io/FileOutputStream.java @@ -256,9 +256,20 @@ class FileOutputStream extends OutputStream * @param name name of file to be opened * @param append whether the file is to be opened in append mode */ - private native void open(String name, boolean append) + private native void open0(String name, boolean append) throws FileNotFoundException; + // wrap native call to allow instrumentation + /** + * Opens a file, with the specified name, for overwriting or appending. + * @param name name of file to be opened + * @param append whether the file is to be opened in append mode + */ + private void open(String name, boolean append) + throws FileNotFoundException { + open0(name, append); + } + /** * Writes the specified byte to this file output stream. * diff --git a/jdk/src/java.base/share/classes/java/io/FilePermission.java b/jdk/src/java.base/share/classes/java/io/FilePermission.java index 0744ea28e4a..b008d4f933a 100644 --- a/jdk/src/java.base/share/classes/java/io/FilePermission.java +++ b/jdk/src/java.base/share/classes/java/io/FilePermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -31,6 +31,7 @@ import java.util.List; import java.util.ArrayList; import java.util.Vector; import java.util.Collections; +import java.util.StringJoiner; import sun.security.util.SecurityConstants; /** @@ -556,39 +557,25 @@ public final class FilePermission extends Permission implements Serializable { * @return the canonical string representation of the actions. */ private static String getActions(int mask) { - StringBuilder sb = new StringBuilder(); - boolean comma = false; + StringJoiner sj = new StringJoiner(","); if ((mask & READ) == READ) { - comma = true; - sb.append("read"); + sj.add("read"); } - if ((mask & WRITE) == WRITE) { - if (comma) sb.append(','); - else comma = true; - sb.append("write"); + sj.add("write"); } - if ((mask & EXECUTE) == EXECUTE) { - if (comma) sb.append(','); - else comma = true; - sb.append("execute"); + sj.add("execute"); } - if ((mask & DELETE) == DELETE) { - if (comma) sb.append(','); - else comma = true; - sb.append("delete"); + sj.add("delete"); } - if ((mask & READLINK) == READLINK) { - if (comma) sb.append(','); - else comma = true; - sb.append("readlink"); + sj.add("readlink"); } - return sb.toString(); + return sj.toString(); } /** 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 7dc6dde469f..e99e0257f31 100644 --- a/jdk/src/java.base/share/classes/java/io/ObjectOutputStream.java +++ b/jdk/src/java.base/share/classes/java/io/ObjectOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.StringJoiner; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import static java.io.ObjectStreamClass.processQueue; @@ -2465,15 +2466,11 @@ public class ObjectOutputStream * Returns a string representation of this object */ public String toString() { - StringBuilder buffer = new StringBuilder(); - if (!stack.isEmpty()) { - for(int i = stack.size(); i > 0; i-- ) { - buffer.append(stack.get(i - 1)); - if (i != 1) - buffer.append('\n'); - } + StringJoiner sj = new StringJoiner("\n"); + for (int i = stack.size() - 1; i >= 0; i--) { + sj.add(stack.get(i)); } - return buffer.toString(); + return sj.toString(); } } diff --git a/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java b/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java index ae1e530f168..d6b79b245cd 100644 --- a/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java +++ b/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java @@ -296,9 +296,26 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { * @param mode the mode flags, a combination of the O_ constants * defined above */ - private native void open(String name, int mode) + private native void open0(String name, int mode) throws FileNotFoundException; + // wrap native call to allow instrumentation + /** + * Opens a file and returns the file descriptor. The file is + * opened in read-write mode if the O_RDWR bit in {@code mode} + * is true, else the file is opened as read-only. + * If the {@code name} refers to a directory, an IOException + * is thrown. + * + * @param name the name of the file + * @param mode the mode flags, a combination of the O_ constants + * defined above + */ + private void open(String name, int mode) + throws FileNotFoundException { + open0(name, mode); + } + // 'Read' primitives /** diff --git a/jdk/src/java.base/share/classes/java/lang/Class.java b/jdk/src/java.base/share/classes/java/lang/Class.java index 1afbf5ea710..2179ee809f5 100644 --- a/jdk/src/java.base/share/classes/java/lang/Class.java +++ b/jdk/src/java.base/share/classes/java/lang/Class.java @@ -54,6 +54,7 @@ import java.util.Set; import java.util.Map; import java.util.HashMap; import java.util.Objects; +import java.util.StringJoiner; import sun.misc.Unsafe; import sun.reflect.CallerSensitive; import sun.reflect.ConstantPool; @@ -3141,19 +3142,14 @@ public final class Class implements java.io.Serializable, private native Class[] getDeclaredClasses0(); private static String argumentTypesToString(Class[] argTypes) { - StringBuilder buf = new StringBuilder(); - buf.append("("); + StringJoiner sj = new StringJoiner(", ", "(", ")"); if (argTypes != null) { for (int i = 0; i < argTypes.length; i++) { - if (i > 0) { - buf.append(", "); - } Class c = argTypes[i]; - buf.append((c == null) ? "null" : c.getName()); + sj.add((c == null) ? "null" : c.getName()); } } - buf.append(")"); - return buf.toString(); + return sj.toString(); } /** use serialVersionUID from JDK 1.1 for interoperability */ diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java index c26460048b0..2b20ae71935 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java @@ -33,6 +33,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.StringJoiner; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentHashMap; import sun.invoke.util.BytecodeDescriptor; @@ -717,15 +718,12 @@ class MethodType implements java.io.Serializable { */ @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("("); + StringJoiner sj = new StringJoiner(",", "(", + ")" + rtype.getSimpleName()); for (int i = 0; i < ptypes.length; i++) { - if (i > 0) sb.append(","); - sb.append(ptypes[i].getSimpleName()); + sj.add(ptypes[i].getSimpleName()); } - sb.append(")"); - sb.append(rtype.getSimpleName()); - return sb.toString(); + return sj.toString(); } diff --git a/jdk/src/java.base/share/classes/java/net/InetAddress.java b/jdk/src/java.base/share/classes/java/net/InetAddress.java index 09b645d4d85..eb72c091285 100644 --- a/jdk/src/java.base/share/classes/java/net/InetAddress.java +++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,8 @@ package java.net; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Random; +import java.util.NavigableSet; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.ArrayList; import java.util.ServiceLoader; @@ -41,6 +38,11 @@ import java.io.ObjectInputStream; import java.io.ObjectInputStream.GetField; import java.io.ObjectOutputStream; import java.io.ObjectOutputStream.PutField; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ConcurrentSkipListSet; +import java.util.concurrent.atomic.AtomicLong; + import sun.security.action.*; import sun.net.InetAddressCachePolicy; import sun.net.util.IPAddressUtil; @@ -705,195 +707,130 @@ class InetAddress implements java.io.Serializable { + "/" + getHostAddress(); } - /* - * Cached addresses - our own litle nis, not! - */ - private static Cache addressCache = new Cache(Cache.Type.Positive); + // mapping from host name to Addresses - either NameServiceAddresses (while + // still being looked-up by NameService(s)) or CachedAddresses when cached + private static final ConcurrentMap cache = + new ConcurrentHashMap<>(); - private static Cache negativeCache = new Cache(Cache.Type.Negative); + // CachedAddresses that have to expire are kept ordered in this NavigableSet + // which is scanned on each access + private static final NavigableSet expirySet = + new ConcurrentSkipListSet<>(); - private static boolean addressCacheInit = false; + // common interface + private interface Addresses { + InetAddress[] get() throws UnknownHostException; + } - static InetAddress[] unknown_array; // put THIS in cache + // a holder for cached addresses with required metadata + private static final class CachedAddresses implements Addresses, Comparable { + private static final AtomicLong seq = new AtomicLong(); + final String host; + final InetAddress[] inetAddresses; + final long expiryTime; // time of expiry (in terms of System.nanoTime()) + final long id = seq.incrementAndGet(); // each instance is unique + + CachedAddresses(String host, InetAddress[] inetAddresses, long expiryTime) { + this.host = host; + this.inetAddresses = inetAddresses; + this.expiryTime = expiryTime; + } + + @Override + public InetAddress[] get() throws UnknownHostException { + if (inetAddresses == null) { + throw new UnknownHostException(host); + } + return inetAddresses; + } + + @Override + public int compareTo(CachedAddresses other) { + // natural order is expiry time - + // compare difference of expiry times rather than + // expiry times directly, to avoid possible overflow. + // (see System.nanoTime() recommendations...) + long diff = this.expiryTime - other.expiryTime; + if (diff < 0L) return -1; + if (diff > 0L) return 1; + // ties are broken using unique id + return Long.compare(this.id, other.id); + } + } + + // a name service lookup based Addresses implementation which replaces itself + // in cache when the result is obtained + private static final class NameServiceAddresses implements Addresses { + private final String host; + private final InetAddress reqAddr; + + NameServiceAddresses(String host, InetAddress reqAddr) { + this.host = host; + this.reqAddr = reqAddr; + } + + @Override + public InetAddress[] get() throws UnknownHostException { + Addresses addresses; + // only one thread is doing lookup to name service + // for particular host at any time. + synchronized (this) { + // re-check that we are still us + re-install us if slot empty + addresses = cache.putIfAbsent(host, this); + if (addresses == null) { + // this can happen when we were replaced by CachedAddresses in + // some other thread, then CachedAddresses expired and were + // removed from cache while we were waiting for lock... + addresses = this; + } + // still us ? + if (addresses == this) { + // lookup name services + InetAddress[] inetAddresses; + UnknownHostException ex; + int cachePolicy; + try { + inetAddresses = getAddressesFromNameService(host, reqAddr); + ex = null; + cachePolicy = InetAddressCachePolicy.get(); + } catch (UnknownHostException uhe) { + inetAddresses = null; + ex = uhe; + cachePolicy = InetAddressCachePolicy.getNegative(); + } + // remove or replace us with cached addresses according to cachePolicy + if (cachePolicy == InetAddressCachePolicy.NEVER) { + cache.remove(host, this); + } else { + CachedAddresses cachedAddresses = new CachedAddresses( + host, + inetAddresses, + cachePolicy == InetAddressCachePolicy.FOREVER + ? 0L + // cachePolicy is in [s] - we need [ns] + : System.nanoTime() + 1000_000_000L * cachePolicy + ); + if (cache.replace(host, this, cachedAddresses) && + cachePolicy != InetAddressCachePolicy.FOREVER) { + // schedule expiry + expirySet.add(cachedAddresses); + } + } + if (inetAddresses == null) { + throw ex == null ? new UnknownHostException(host) : ex; + } + return inetAddresses; + } + // else addresses != this + } + // delegate to different addresses when we are already replaced + // but outside of synchronized block to avoid any chance of dead-locking + return addresses.get(); + } + } static InetAddressImpl impl; - private static final HashMap lookupTable = new HashMap<>(); - - /** - * Represents a cache entry - */ - static final class CacheEntry { - - CacheEntry(InetAddress[] addresses, long expiration) { - this.addresses = addresses; - this.expiration = expiration; - } - - InetAddress[] addresses; - long expiration; - } - - /** - * A cache that manages entries based on a policy specified - * at creation time. - */ - static final class Cache { - private LinkedHashMap cache; - private Type type; - - enum Type {Positive, Negative}; - - /** - * Create cache - */ - public Cache(Type type) { - this.type = type; - cache = new LinkedHashMap(); - } - - private int getPolicy() { - if (type == Type.Positive) { - return InetAddressCachePolicy.get(); - } else { - return InetAddressCachePolicy.getNegative(); - } - } - - /** - * Add an entry to the cache. If there's already an - * entry then for this host then the entry will be - * replaced. - */ - public Cache put(String host, InetAddress[] addresses) { - int policy = getPolicy(); - if (policy == InetAddressCachePolicy.NEVER) { - return this; - } - - // purge any expired entries - - if (policy != InetAddressCachePolicy.FOREVER) { - - // As we iterate in insertion order we can - // terminate when a non-expired entry is found. - LinkedList expired = new LinkedList<>(); - long now = System.currentTimeMillis(); - for (String key : cache.keySet()) { - CacheEntry entry = cache.get(key); - - if (entry.expiration >= 0 && entry.expiration < now) { - expired.add(key); - } else { - break; - } - } - - for (String key : expired) { - cache.remove(key); - } - } - - // create new entry and add it to the cache - // -- as a HashMap replaces existing entries we - // don't need to explicitly check if there is - // already an entry for this host. - long expiration; - if (policy == InetAddressCachePolicy.FOREVER) { - expiration = -1; - } else { - expiration = System.currentTimeMillis() + (policy * 1000); - } - CacheEntry entry = new CacheEntry(addresses, expiration); - cache.put(host, entry); - return this; - } - - /** - * Query the cache for the specific host. If found then - * return its CacheEntry, or null if not found. - */ - public CacheEntry get(String host) { - int policy = getPolicy(); - if (policy == InetAddressCachePolicy.NEVER) { - return null; - } - CacheEntry entry = cache.get(host); - - // check if entry has expired - if (entry != null && policy != InetAddressCachePolicy.FOREVER) { - if (entry.expiration >= 0 && - entry.expiration < System.currentTimeMillis()) { - cache.remove(host); - entry = null; - } - } - - return entry; - } - } - - /* - * Initialize cache and insert anyLocalAddress into the - * unknown array with no expiry. - */ - private static void cacheInitIfNeeded() { - assert Thread.holdsLock(addressCache); - if (addressCacheInit) { - return; - } - unknown_array = new InetAddress[1]; - unknown_array[0] = impl.anyLocalAddress(); - - addressCache.put(impl.anyLocalAddress().getHostName(), - unknown_array); - - addressCacheInit = true; - } - - /* - * Cache the given hostname and addresses. - */ - private static void cacheAddresses(String hostname, - InetAddress[] addresses, - boolean success) { - hostname = hostname.toLowerCase(); - synchronized (addressCache) { - cacheInitIfNeeded(); - if (success) { - addressCache.put(hostname, addresses); - } else { - negativeCache.put(hostname, addresses); - } - } - } - - /* - * Lookup hostname in cache (positive & negative cache). If - * found return addresses, null if not found. - */ - private static InetAddress[] getCachedAddresses(String hostname) { - hostname = hostname.toLowerCase(); - - // search both positive & negative caches - - synchronized (addressCache) { - cacheInitIfNeeded(); - - CacheEntry entry = addressCache.get(hostname); - if (entry == null) { - entry = negativeCache.get(hostname); - } - - if (entry != null) { - return entry.addresses; - } - } - - // not found - return null; - } - private static NameService createNSProvider(String provider) { if (provider == null) return null; @@ -1168,7 +1105,7 @@ class InetAddress implements java.io.Serializable { // We were expecting an IPv6 Litteral, but got something else throw new UnknownHostException("["+host+"]"); } - return getAllByName0(host, reqAddr, true); + return getAllByName0(host, reqAddr, true, true); } /** @@ -1229,14 +1166,27 @@ class InetAddress implements java.io.Serializable { */ static InetAddress[] getAllByName0 (String host, boolean check) throws UnknownHostException { - return getAllByName0 (host, null, check); + return getAllByName0 (host, null, check, true); } - private static InetAddress[] getAllByName0 (String host, InetAddress reqAddr, boolean check) + /** + * Designated lookup method. + * + * @param host host name to look up + * @param reqAddr requested address to be the 1st in returned array + * @param check perform security check + * @param useCache use cached value if not expired else always + * perform name service lookup (and cache the result) + * @return array of InetAddress(es) + * @throws UnknownHostException if host name is not found + */ + private static InetAddress[] getAllByName0(String host, + InetAddress reqAddr, + boolean check, + boolean useCache) throws UnknownHostException { /* If it gets here it is presumed to be a hostname */ - /* Cache.get can return: null, unknownAddress, or InetAddress[] */ /* make sure the connection to the host is allowed, before we * give out a hostname @@ -1248,155 +1198,106 @@ class InetAddress implements java.io.Serializable { } } - InetAddress[] addresses = getCachedAddresses(host); - - /* If no entry in cache, then do the host lookup */ - if (addresses == null) { - addresses = getAddressesFromNameService(host, reqAddr); + // remove expired addresses from cache - expirySet keeps them ordered + // by expiry time so we only need to iterate the prefix of the NavigableSet... + long now = System.nanoTime(); + for (CachedAddresses caddrs : expirySet) { + // compare difference of time instants rather than + // time instants directly, to avoid possible overflow. + // (see System.nanoTime() recommendations...) + if ((caddrs.expiryTime - now) < 0L) { + // ConcurrentSkipListSet uses weakly consistent iterator, + // so removing while iterating is OK... + if (expirySet.remove(caddrs)) { + // ... remove from cache + cache.remove(caddrs.host, caddrs); + } + } else { + // we encountered 1st element that expires in future + break; + } } - if (addresses == unknown_array) - throw new UnknownHostException(host); + // look-up or remove from cache + Addresses addrs; + if (useCache) { + addrs = cache.get(host); + } else { + addrs = cache.remove(host); + if (addrs != null) { + if (addrs instanceof CachedAddresses) { + // try removing from expirySet too if CachedAddresses + expirySet.remove(addrs); + } + addrs = null; + } + } - return addresses.clone(); + if (addrs == null) { + // create a NameServiceAddresses instance which will look up + // the name service and install it within cache... + Addresses oldAddrs = cache.putIfAbsent( + host, + addrs = new NameServiceAddresses(host, reqAddr) + ); + if (oldAddrs != null) { // lost putIfAbsent race + addrs = oldAddrs; + } + } + + // ask Addresses to get an array of InetAddress(es) and clone it + return addrs.get().clone(); } - private static InetAddress[] getAddressesFromNameService(String host, InetAddress reqAddr) + static InetAddress[] getAddressesFromNameService(String host, InetAddress reqAddr) throws UnknownHostException { InetAddress[] addresses = null; - boolean success = false; UnknownHostException ex = null; - // Check whether the host is in the lookupTable. - // 1) If the host isn't in the lookupTable when - // checkLookupTable() is called, checkLookupTable() - // would add the host in the lookupTable and - // return null. So we will do the lookup. - // 2) If the host is in the lookupTable when - // checkLookupTable() is called, the current thread - // would be blocked until the host is removed - // from the lookupTable. Then this thread - // should try to look up the addressCache. - // i) if it found the addresses in the - // addressCache, checkLookupTable() would - // return the addresses. - // ii) if it didn't find the addresses in the - // addressCache for any reason, - // it should add the host in the - // lookupTable and return null so the - // following code would do a lookup itself. - if ((addresses = checkLookupTable(host)) == null) { + for (NameService nameService : nameServices) { try { - // This is the first thread which looks up the addresses - // this host or the cache entry for this host has been - // expired so this thread should do the lookup. - for (NameService nameService : nameServices) { - try { - /* - * Do not put the call to lookup() inside the - * constructor. if you do you will still be - * allocating space when the lookup fails. - */ - - addresses = nameService.lookupAllHostAddr(host); - success = true; - break; - } catch (UnknownHostException uhe) { - if (host.equalsIgnoreCase("localhost")) { - InetAddress[] local = new InetAddress[] { impl.loopbackAddress() }; - addresses = local; - success = true; - break; - } - else { - addresses = unknown_array; - success = false; - ex = uhe; - } - } + addresses = nameService.lookupAllHostAddr(host); + break; + } catch (UnknownHostException uhe) { + if (host.equalsIgnoreCase("localhost")) { + addresses = new InetAddress[] { impl.loopbackAddress() }; + break; } - - // More to do? - if (reqAddr != null && addresses.length > 1 && !addresses[0].equals(reqAddr)) { - // Find it? - int i = 1; - for (; i < addresses.length; i++) { - if (addresses[i].equals(reqAddr)) { - break; - } - } - // Rotate - if (i < addresses.length) { - InetAddress tmp, tmp2 = reqAddr; - for (int j = 0; j < i; j++) { - tmp = addresses[j]; - addresses[j] = tmp2; - tmp2 = tmp; - } - addresses[i] = tmp2; - } - } - // Cache the address. - cacheAddresses(host, addresses, success); - - if (!success && ex != null) - throw ex; - - } finally { - // Delete host from the lookupTable and notify - // all threads waiting on the lookupTable monitor. - updateLookupTable(host); - } - } - - return addresses; - } - - - private static InetAddress[] checkLookupTable(String host) { - synchronized (lookupTable) { - // If the host isn't in the lookupTable, add it in the - // lookuptable and return null. The caller should do - // the lookup. - if (lookupTable.containsKey(host) == false) { - lookupTable.put(host, null); - return null; - } - - // If the host is in the lookupTable, it means that another - // thread is trying to look up the addresses of this host. - // This thread should wait. - while (lookupTable.containsKey(host)) { - try { - lookupTable.wait(); - } catch (InterruptedException e) { + else { + ex = uhe; } } } - // The other thread has finished looking up the addresses of - // the host. This thread should retry to get the addresses - // from the addressCache. If it doesn't get the addresses from - // the cache, it will try to look up the addresses itself. - InetAddress[] addresses = getCachedAddresses(host); if (addresses == null) { - synchronized (lookupTable) { - lookupTable.put(host, null); - return null; + throw ex == null ? new UnknownHostException(host) : ex; + } + + // More to do? + if (reqAddr != null && addresses.length > 1 && !addresses[0].equals(reqAddr)) { + // Find it? + int i = 1; + for (; i < addresses.length; i++) { + if (addresses[i].equals(reqAddr)) { + break; + } + } + // Rotate + if (i < addresses.length) { + InetAddress tmp, tmp2 = reqAddr; + for (int j = 0; j < i; j++) { + tmp = addresses[j]; + addresses[j] = tmp2; + tmp2 = tmp; + } + addresses[i] = tmp2; } } return addresses; } - private static void updateLookupTable(String host) { - synchronized (lookupTable) { - lookupTable.remove(host); - lookupTable.notifyAll(); - } - } - /** * Returns an {@code InetAddress} object given the raw IP address . * The argument is in network byte order: the highest order @@ -1418,10 +1319,18 @@ class InetAddress implements java.io.Serializable { return getByAddress(null, addr); } - private static InetAddress cachedLocalHost = null; - private static long cacheTime = 0; - private static final long maxCacheTime = 5000L; - private static final Object cacheLock = new Object(); + private static final class CachedLocalHost { + final String host; + final InetAddress addr; + final long expiryTime = System.nanoTime() + 5000_000_000L; // now + 5s; + + CachedLocalHost(String host, InetAddress addr) { + this.host = host; + this.addr = addr; + } + } + + private static volatile CachedLocalHost cachedLocalHost; /** * Returns the address of the local host. This is achieved by retrieving @@ -1450,47 +1359,41 @@ class InetAddress implements java.io.Serializable { SecurityManager security = System.getSecurityManager(); try { + // is cached data still valid? + CachedLocalHost clh = cachedLocalHost; + if (clh != null && (clh.expiryTime - System.nanoTime()) >= 0L) { + if (security != null) { + security.checkConnect(clh.host, -1); + } + return clh.addr; + } + String local = impl.getLocalHostName(); if (security != null) { security.checkConnect(local, -1); } + InetAddress localAddr; if (local.equals("localhost")) { - return impl.loopbackAddress(); - } - - InetAddress ret = null; - synchronized (cacheLock) { - long now = System.currentTimeMillis(); - if (cachedLocalHost != null) { - if ((now - cacheTime) < maxCacheTime) // Less than 5s old? - ret = cachedLocalHost; - else - cachedLocalHost = null; - } - - // we are calling getAddressesFromNameService directly - // to avoid getting localHost from cache - if (ret == null) { - InetAddress[] localAddrs; - try { - localAddrs = - InetAddress.getAddressesFromNameService(local, null); - } catch (UnknownHostException uhe) { - // Rethrow with a more informative error message. - UnknownHostException uhe2 = - new UnknownHostException(local + ": " + - uhe.getMessage()); - uhe2.initCause(uhe); - throw uhe2; - } - cachedLocalHost = localAddrs[0]; - cacheTime = now; - ret = localAddrs[0]; + // shortcut for "localhost" host name + localAddr = impl.loopbackAddress(); + } else { + // call getAllByName0 without security checks and + // without using cached data + try { + localAddr = getAllByName0(local, null, false, false)[0]; + } catch (UnknownHostException uhe) { + // Rethrow with a more informative error message. + UnknownHostException uhe2 = + new UnknownHostException(local + ": " + + uhe.getMessage()); + uhe2.initCause(uhe); + throw uhe2; } } - return ret; + cachedLocalHost = new CachedLocalHost(local, localAddr); + return localAddr; } catch (java.lang.SecurityException e) { return impl.loopbackAddress(); } diff --git a/jdk/src/java.base/share/classes/java/net/NetPermission.java b/jdk/src/java.base/share/classes/java/net/NetPermission.java index 9178f348723..dad3fb99f32 100644 --- a/jdk/src/java.base/share/classes/java/net/NetPermission.java +++ b/jdk/src/java.base/share/classes/java/net/NetPermission.java @@ -72,10 +72,10 @@ import java.util.StringTokenizer; * * * - * getNetworkInformation - * The ability to retrieve all information about local network interfaces. - * Malicious code can read information about network hardware such as - * MAC addresses, which could be used to construct local IPv6 addresses. + * getNetworkInformation + * The ability to retrieve all information about local network interfaces. + * Malicious code can read information about network hardware such as + * MAC addresses, which could be used to construct local IPv6 addresses. * * * @@ -98,8 +98,8 @@ import java.util.StringTokenizer; * * requestPasswordAuthentication * The ability - * to ask the authenticator registered with the system for - * a password + * to ask the authenticator registered with the system for + * a password * Malicious code may steal this password. * * @@ -116,11 +116,11 @@ import java.util.StringTokenizer; * * setDefaultAuthenticator * The ability to set the - * way authentication information is retrieved when - * a proxy or HTTP server asks for authentication + * way authentication information is retrieved when + * a proxy or HTTP server asks for authentication * Malicious - * code can set an authenticator that monitors and steals user - * authentication input as it retrieves the input from the user. + * code can set an authenticator that monitors and steals user + * authentication input as it retrieves the input from the user. * * * @@ -143,13 +143,13 @@ import java.util.StringTokenizer; * * specifyStreamHandler * The ability - * to specify a stream handler when constructing a URL + * to specify a stream handler when constructing a URL * Malicious code may create a URL with resources that it would -normally not have access to (like file:/foo/fum/), specifying a -stream handler that gets the actual bytes from someplace it does -have access to. Thus it might be able to trick the system into -creating a ProtectionDomain/CodeSource for a class even though -that class really didn't come from that location. + * normally not have access to (like file:/foo/fum/), specifying a + * stream handler that gets the actual bytes from someplace it does + * have access to. Thus it might be able to trick the system into + * creating a ProtectionDomain/CodeSource for a class even though + * that class really didn't come from that location. * * * diff --git a/jdk/src/java.base/share/classes/java/net/SocketInputStream.java b/jdk/src/java.base/share/classes/java/net/SocketInputStream.java index 224051ff608..41b18bdc7e0 100644 --- a/jdk/src/java.base/share/classes/java/net/SocketInputStream.java +++ b/jdk/src/java.base/share/classes/java/net/SocketInputStream.java @@ -96,6 +96,26 @@ class SocketInputStream extends FileInputStream int timeout) throws IOException; + // wrap native call to allow instrumentation + /** + * Reads into an array of bytes at the specified offset using + * the received socket primitive. + * @param fd the FileDescriptor + * @param b the buffer into which the data is read + * @param off the start offset of the data + * @param len the maximum number of bytes read + * @param timeout the read timeout in ms + * @return the actual number of bytes read, -1 is + * returned when the end of the stream is reached. + * @exception IOException If an I/O error has occurred. + */ + private int socketRead(FileDescriptor fd, + byte b[], int off, int len, + int timeout) + throws IOException { + return socketRead0(fd, b, off, len, timeout); + } + /** * Reads into a byte array data from the socket. * @param b the buffer into which the data is read @@ -147,7 +167,7 @@ class SocketInputStream extends FileInputStream // acquire file descriptor and do the read FileDescriptor fd = impl.acquireFD(); try { - n = socketRead0(fd, b, off, length, timeout); + n = socketRead(fd, b, off, length, timeout); if (n > 0) { return n; } @@ -165,7 +185,7 @@ class SocketInputStream extends FileInputStream impl.setConnectionResetPending(); impl.acquireFD(); try { - n = socketRead0(fd, b, off, length, timeout); + n = socketRead(fd, b, off, length, timeout); if (n > 0) { return n; } diff --git a/jdk/src/java.base/share/classes/java/net/SocketPermission.java b/jdk/src/java.base/share/classes/java/net/SocketPermission.java index 1f3248077be..8894152512b 100644 --- a/jdk/src/java.base/share/classes/java/net/SocketPermission.java +++ b/jdk/src/java.base/share/classes/java/net/SocketPermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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,6 +30,7 @@ import java.util.Vector; import java.util.List; import java.util.ArrayList; import java.util.Collections; +import java.util.StringJoiner; import java.util.StringTokenizer; import java.net.InetAddress; import java.security.Permission; @@ -1112,36 +1113,21 @@ public final class SocketPermission extends Permission * @param mask a specific integer action mask to translate into a string * @return the canonical string representation of the actions */ - private static String getActions(int mask) - { - StringBuilder sb = new StringBuilder(); - boolean comma = false; - + private static String getActions(int mask) { + StringJoiner sj = new StringJoiner(","); if ((mask & CONNECT) == CONNECT) { - comma = true; - sb.append("connect"); + sj.add("connect"); } - if ((mask & LISTEN) == LISTEN) { - if (comma) sb.append(','); - else comma = true; - sb.append("listen"); + sj.add("listen"); } - if ((mask & ACCEPT) == ACCEPT) { - if (comma) sb.append(','); - else comma = true; - sb.append("accept"); + sj.add("accept"); } - - if ((mask & RESOLVE) == RESOLVE) { - if (comma) sb.append(','); - else comma = true; - sb.append("resolve"); + sj.add("resolve"); } - - return sb.toString(); + return sj.toString(); } /** diff --git a/jdk/src/java.base/share/classes/java/net/URLClassLoader.java b/jdk/src/java.base/share/classes/java/net/URLClassLoader.java index e448a120bdc..6f4691404c3 100644 --- a/jdk/src/java.base/share/classes/java/net/URLClassLoader.java +++ b/jdk/src/java.base/share/classes/java/net/URLClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -407,6 +407,29 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { return pkg; } + // Also called by VM to define Package for classes loaded from the CDS + // archive + private void definePackageInternal(String pkgname, Manifest man, URL url) + { + if (getAndVerifyPackage(pkgname, man, url) == null) { + try { + if (man != null) { + definePackage(pkgname, man, url); + } else { + definePackage(pkgname, null, null, null, null, null, null, null); + } + } catch (IllegalArgumentException iae) { + // parallel-capable class loaders: re-verify in case of a + // race condition + if (getAndVerifyPackage(pkgname, man, url) == null) { + // Should never happen + throw new AssertionError("Cannot find package " + + pkgname); + } + } + } + } + /* * Defines a Class using the class bytes obtained from the specified * Resource. The resulting Class must be resolved before it can be @@ -420,23 +443,7 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { String pkgname = name.substring(0, i); // Check if package already loaded. Manifest man = res.getManifest(); - if (getAndVerifyPackage(pkgname, man, url) == null) { - try { - if (man != null) { - definePackage(pkgname, man, url); - } else { - definePackage(pkgname, null, null, null, null, null, null, null); - } - } catch (IllegalArgumentException iae) { - // parallel-capable class loaders: re-verify in case of a - // race condition - if (getAndVerifyPackage(pkgname, man, url) == null) { - // Should never happen - throw new AssertionError("Cannot find package " + - pkgname); - } - } - } + definePackageInternal(pkgname, man, url); } // Now read the class bytes and define the class java.nio.ByteBuffer bb = res.getByteBuffer(); diff --git a/jdk/src/java.base/share/classes/java/text/CalendarBuilder.java b/jdk/src/java.base/share/classes/java/text/CalendarBuilder.java index a8246b676ca..cb30a358ea4 100644 --- a/jdk/src/java.base/share/classes/java/text/CalendarBuilder.java +++ b/jdk/src/java.base/share/classes/java/text/CalendarBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package java.text; import java.util.Calendar; +import java.util.StringJoiner; import static java.util.GregorianCalendar.*; /** @@ -146,19 +147,13 @@ class CalendarBuilder { } public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("CalendarBuilder:["); + StringJoiner sj = new StringJoiner(",", "CalendarBuilder:[", "]"); for (int i = 0; i < field.length; i++) { if (isSet(i)) { - sb.append(i).append('=').append(field[MAX_FIELD + i]).append(','); + sj.add(i + "=" + field[MAX_FIELD + i]); } } - int lastIndex = sb.length() - 1; - if (sb.charAt(lastIndex) == ',') { - sb.setLength(lastIndex); - } - sb.append(']'); - return sb.toString(); + return sj.toString(); } static int toISODayOfWeek(int calendarDayOfWeek) { diff --git a/jdk/src/java.base/share/classes/java/util/Locale.java b/jdk/src/java.base/share/classes/java/util/Locale.java index fbcb2f75e66..cf29686e693 100644 --- a/jdk/src/java.base/share/classes/java/util/Locale.java +++ b/jdk/src/java.base/share/classes/java/util/Locale.java @@ -2059,14 +2059,11 @@ public final class Locale implements Cloneable, Serializable { // If we have no list patterns, compose the list in a simple, // non-localized way. if (listPattern == null || listCompositionPattern == null) { - StringBuilder result = new StringBuilder(); + StringJoiner sj = new StringJoiner(","); for (int i = 0; i < stringList.length; ++i) { - if (i > 0) { - result.append(','); - } - result.append(stringList[i]); + sj.add(stringList[i]); } - return result.toString(); + return sj.toString(); } // Compose the list down to three elements if necessary diff --git a/jdk/src/java.base/share/classes/java/util/PropertyPermission.java b/jdk/src/java.base/share/classes/java/util/PropertyPermission.java index d532bddabf6..7e818a90b64 100644 --- a/jdk/src/java.base/share/classes/java/util/PropertyPermission.java +++ b/jdk/src/java.base/share/classes/java/util/PropertyPermission.java @@ -324,20 +324,16 @@ public final class PropertyPermission extends BasicPermission { * @return the canonical string representation of the actions. */ static String getActions(int mask) { - StringBuilder sb = new StringBuilder(); - boolean comma = false; - - if ((mask & READ) == READ) { - comma = true; - sb.append("read"); + switch (mask & (READ|WRITE)) { + case READ: + return SecurityConstants.PROPERTY_READ_ACTION; + case WRITE: + return SecurityConstants.PROPERTY_WRITE_ACTION; + case READ|WRITE: + return SecurityConstants.PROPERTY_RW_ACTION; + default: + return ""; } - - if ((mask & WRITE) == WRITE) { - if (comma) sb.append(','); - else comma = true; - sb.append("write"); - } - return sb.toString(); } /** diff --git a/jdk/src/java.base/share/classes/sun/net/InetAddressCachePolicy.java b/jdk/src/java.base/share/classes/sun/net/InetAddressCachePolicy.java index 31578b50d78..f20feec8ae0 100644 --- a/jdk/src/java.base/share/classes/sun/net/InetAddressCachePolicy.java +++ b/jdk/src/java.base/share/classes/sun/net/InetAddressCachePolicy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, 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 @@ -56,7 +56,7 @@ public final class InetAddressCachePolicy { * caching. For security reasons, this caching is made forever when * a security manager is set. */ - private static int cachePolicy = FOREVER; + private static volatile int cachePolicy = FOREVER; /* The Java-level namelookup cache policy for negative lookups: * @@ -66,7 +66,7 @@ public final class InetAddressCachePolicy { * default value is 0. It can be set to some other value for * performance reasons. */ - private static int negativeCachePolicy = NEVER; + private static volatile int negativeCachePolicy = NEVER; /* * Whether or not the cache policy for successful lookups was set @@ -110,10 +110,7 @@ public final class InetAddressCachePolicy { }); if (tmp != null) { - cachePolicy = tmp.intValue(); - if (cachePolicy < 0) { - cachePolicy = FOREVER; - } + cachePolicy = tmp < 0 ? FOREVER : tmp; propertySet = true; } else { /* No properties defined for positive caching. If there is no @@ -148,19 +145,16 @@ public final class InetAddressCachePolicy { }); if (tmp != null) { - negativeCachePolicy = tmp.intValue(); - if (negativeCachePolicy < 0) { - negativeCachePolicy = FOREVER; - } + negativeCachePolicy = tmp < 0 ? FOREVER : tmp; propertyNegativeSet = true; } } - public static synchronized int get() { + public static int get() { return cachePolicy; } - public static synchronized int getNegative() { + public static int getNegative() { return negativeCachePolicy; } @@ -190,7 +184,7 @@ public final class InetAddressCachePolicy { * @param newPolicy the value in seconds for how long the lookup * should be cached */ - public static synchronized void setNegativeIfNotSet(int newPolicy) { + public static void setNegativeIfNotSet(int newPolicy) { /* * When setting the new value we may want to signal that the * cache should be flushed, though this doesn't seem strictly @@ -200,7 +194,8 @@ public final class InetAddressCachePolicy { // Negative caching does not seem to have any security // implications. // checkValue(newPolicy, negativeCachePolicy); - negativeCachePolicy = newPolicy; + // but we should normalize negative policy + negativeCachePolicy = newPolicy < 0 ? FOREVER : newPolicy; } } diff --git a/jdk/src/java.base/share/classes/sun/net/www/MimeEntry.java b/jdk/src/java.base/share/classes/sun/net/www/MimeEntry.java index 7a7bcce453c..f96953a42d4 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/MimeEntry.java +++ b/jdk/src/java.base/share/classes/sun/net/www/MimeEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package sun.net.www; import java.net.URL; import java.io.*; +import java.util.StringJoiner; import java.util.StringTokenizer; public class MimeEntry implements Cloneable { @@ -281,52 +282,34 @@ public class MimeEntry implements Cloneable { } public synchronized String toProperty() { - StringBuilder sb = new StringBuilder(); - - String separator = "; "; - boolean needSeparator = false; + StringJoiner sj = new StringJoiner("; "); int action = getAction(); if (action != MimeEntry.UNKNOWN) { - sb.append("action=" + actionKeywords[action]); - needSeparator = true; + sj.add("action=" + actionKeywords[action]); } String command = getLaunchString(); if (command != null && command.length() > 0) { - if (needSeparator) { - sb.append(separator); - } - sb.append("application=" + command); - needSeparator = true; + sj.add("application=" + command); } - if (getImageFileName() != null) { - if (needSeparator) { - sb.append(separator); - } - sb.append("icon=" + getImageFileName()); - needSeparator = true; + String image = getImageFileName(); + if (image != null) { + sj.add("icon=" + image); } String extensions = getExtensionsAsList(); if (extensions.length() > 0) { - if (needSeparator) { - sb.append(separator); - } - sb.append("file_extensions=" + extensions); - needSeparator = true; + sj.add("file_extensions=" + extensions); } String description = getDescription(); if (description != null && !description.equals(getType())) { - if (needSeparator) { - sb.append(separator); - } - sb.append("description=" + description); + sj.add("description=" + description); } - return sb.toString(); + return sj.toString(); } public String toString() { diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index 781f772c1ab..f4ade7e3dfd 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,6 +64,7 @@ import java.util.Iterator; import java.util.HashSet; import java.util.HashMap; import java.util.Set; +import java.util.StringJoiner; import sun.net.*; import sun.net.www.*; import sun.net.www.http.HttpClient; @@ -1386,16 +1387,11 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } List l = entry.getValue(); if (l != null && !l.isEmpty()) { - StringBuilder cookieValue = new StringBuilder(); + StringJoiner cookieValue = new StringJoiner("; "); for (String value : l) { - cookieValue.append(value).append("; "); - } - // strip off the trailing '; ' - try { - requests.add(key, cookieValue.substring(0, cookieValue.length() - 2)); - } catch (StringIndexOutOfBoundsException ignored) { - // no-op + cookieValue.add(value); } + requests.add(key, cookieValue.toString()); } } } @@ -2870,20 +2866,14 @@ public class HttpURLConnection extends java.net.HttpURLConnection { sun.misc.JavaNetHttpCookieAccess access = sun.misc.SharedSecrets.getJavaNetHttpCookieAccess(); - StringBuilder retValue = new StringBuilder(); + StringJoiner retValue = new StringJoiner(","); // RFC 2965, comma separated List cookies = access.parse(value); - boolean multipleCookies = false; for (HttpCookie cookie : cookies) { // skip HttpOnly cookies - if (cookie.isHttpOnly()) - continue; - if (multipleCookies) - retValue.append(','); // RFC 2965, comma separated - retValue.append(access.header(cookie)); - multipleCookies = true; + if (!cookie.isHttpOnly()) + retValue.add(access.header(cookie)); } - - return retValue.length() == 0 ? "" : retValue.toString(); + return retValue.toString(); } return value; diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java index 1ec1700ea67..c3067c044e0 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java @@ -501,7 +501,8 @@ public class HttpsURLConnectionImpl } public boolean equals(Object obj) { - return delegate.equals(obj); + return this == obj || ((obj instanceof HttpsURLConnectionImpl) && + delegate.equals(((HttpsURLConnectionImpl)obj).delegate)); } public int hashCode() { diff --git a/jdk/src/java.base/share/classes/sun/util/locale/BaseLocale.java b/jdk/src/java.base/share/classes/sun/util/locale/BaseLocale.java index 6eee5829095..137fd82f7dd 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/BaseLocale.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/BaseLocale.java @@ -32,6 +32,7 @@ package sun.util.locale; +import java.util.StringJoiner; public final class BaseLocale { @@ -120,33 +121,20 @@ public final class BaseLocale { @Override public String toString() { - StringBuilder buf = new StringBuilder(); + StringJoiner sj = new StringJoiner(", "); if (language.length() > 0) { - buf.append("language="); - buf.append(language); + sj.add("language=" + language); } if (script.length() > 0) { - if (buf.length() > 0) { - buf.append(", "); - } - buf.append("script="); - buf.append(script); + sj.add("script=" + script); } if (region.length() > 0) { - if (buf.length() > 0) { - buf.append(", "); - } - buf.append("region="); - buf.append(region); + sj.add("region=" + region); } if (variant.length() > 0) { - if (buf.length() > 0) { - buf.append(", "); - } - buf.append("variant="); - buf.append(variant); + sj.add("variant=" + variant); } - return buf.toString(); + return sj.toString(); } @Override diff --git a/jdk/src/java.base/share/classes/sun/util/locale/LanguageTag.java b/jdk/src/java.base/share/classes/sun/util/locale/LanguageTag.java index 2247398c400..3fd7f7dbe5e 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/LanguageTag.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/LanguageTag.java @@ -37,6 +37,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.StringJoiner; public class LanguageTag { // @@ -473,21 +474,18 @@ public class LanguageTag { } if (!varitr.isDone()) { // ill-formed variant subtags - StringBuilder buf = new StringBuilder(); + StringJoiner sj = new StringJoiner(SEP); while (!varitr.isDone()) { String prvv = varitr.current(); if (!isPrivateuseSubtag(prvv)) { // cannot use private use subtag - truncated break; } - if (buf.length() > 0) { - buf.append(SEP); - } - buf.append(prvv); + sj.add(prvv); varitr.next(); } - if (buf.length() > 0) { - privuseVar = buf.toString(); + if (sj.length() > 0) { + privuseVar = sj.toString(); } } } diff --git a/jdk/src/java.base/share/classes/sun/util/locale/UnicodeLocaleExtension.java b/jdk/src/java.base/share/classes/sun/util/locale/UnicodeLocaleExtension.java index cc5a5685cd0..51a723aea25 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/UnicodeLocaleExtension.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/UnicodeLocaleExtension.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2014, 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 @@ -38,6 +38,7 @@ import java.util.Map.Entry; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; +import java.util.StringJoiner; public class UnicodeLocaleExtension extends Extension { public static final char SINGLETON = 'u'; @@ -70,20 +71,20 @@ public class UnicodeLocaleExtension extends Extension { } if (!this.attributes.isEmpty() || !this.keywords.isEmpty()) { - StringBuilder sb = new StringBuilder(); + StringJoiner sj = new StringJoiner(LanguageTag.SEP); for (String attribute : this.attributes) { - sb.append(LanguageTag.SEP).append(attribute); + sj.add(attribute); } for (Entry keyword : this.keywords.entrySet()) { String key = keyword.getKey(); String value = keyword.getValue(); - sb.append(LanguageTag.SEP).append(key); + sj.add(key); if (value.length() > 0) { - sb.append(LanguageTag.SEP).append(value); + sj.add(value); } } - setValue(sb.substring(1)); // skip leading '-' + setValue(sj.toString()); } } diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java index f8c68fa35c2..a1962e463da 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java @@ -547,12 +547,7 @@ class RuleBasedBreakIterator extends BreakIterator { */ @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append('['); - sb.append("checksum=0x"); - sb.append(Long.toHexString(checksum)); - sb.append(']'); - return sb.toString(); + return "[checksum=0x" + Long.toHexString(checksum) + ']'; } /** diff --git a/jdk/src/java.base/share/native/libjava/FileInputStream.c b/jdk/src/java.base/share/native/libjava/FileInputStream.c index 092ddbf6f1f..dc1aea5cd64 100644 --- a/jdk/src/java.base/share/native/libjava/FileInputStream.c +++ b/jdk/src/java.base/share/native/libjava/FileInputStream.c @@ -57,7 +57,7 @@ Java_java_io_FileInputStream_initIDs(JNIEnv *env, jclass fdClass) { */ JNIEXPORT void JNICALL -Java_java_io_FileInputStream_open(JNIEnv *env, jobject this, jstring path) { +Java_java_io_FileInputStream_open0(JNIEnv *env, jobject this, jstring path) { fileOpen(env, this, path, fis_fd, O_RDONLY); } diff --git a/jdk/src/java.base/share/native/libjava/RandomAccessFile.c b/jdk/src/java.base/share/native/libjava/RandomAccessFile.c index 53b5f1aac1f..a44d8f39681 100644 --- a/jdk/src/java.base/share/native/libjava/RandomAccessFile.c +++ b/jdk/src/java.base/share/native/libjava/RandomAccessFile.c @@ -47,8 +47,8 @@ Java_java_io_RandomAccessFile_initIDs(JNIEnv *env, jclass fdClass) { JNIEXPORT void JNICALL -Java_java_io_RandomAccessFile_open(JNIEnv *env, - jobject this, jstring path, jint mode) +Java_java_io_RandomAccessFile_open0(JNIEnv *env, + jobject this, jstring path, jint mode) { int flags = 0; if (mode & java_io_RandomAccessFile_O_RDONLY) diff --git a/jdk/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java b/jdk/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java index e696d3eba07..2bb712e7867 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java +++ b/jdk/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java @@ -226,6 +226,7 @@ class InheritedChannel { // -- Native methods -- + private static native void initIDs(); private static native int dup(int fd) throws IOException; private static native void dup2(int fd, int fd2) throws IOException; private static native int open0(String path, int oflag) throws IOException; @@ -236,5 +237,6 @@ class InheritedChannel { static { IOUtil.load(); + initIDs(); } } diff --git a/jdk/src/java.base/unix/native/libjava/FileOutputStream_md.c b/jdk/src/java.base/unix/native/libjava/FileOutputStream_md.c index efd5864cd9c..22d80a22663 100644 --- a/jdk/src/java.base/unix/native/libjava/FileOutputStream_md.c +++ b/jdk/src/java.base/unix/native/libjava/FileOutputStream_md.c @@ -53,8 +53,8 @@ Java_java_io_FileOutputStream_initIDs(JNIEnv *env, jclass fdClass) { */ JNIEXPORT void JNICALL -Java_java_io_FileOutputStream_open(JNIEnv *env, jobject this, - jstring path, jboolean append) { +Java_java_io_FileOutputStream_open0(JNIEnv *env, jobject this, + jstring path, jboolean append) { fileOpen(env, this, path, fos_fd, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC)); } diff --git a/jdk/src/java.base/unix/native/libnio/ch/IOUtil.c b/jdk/src/java.base/unix/native/libnio/ch/IOUtil.c index d8bbe849252..438bf41ddea 100644 --- a/jdk/src/java.base/unix/native/libnio/ch/IOUtil.c +++ b/jdk/src/java.base/unix/native/libnio/ch/IOUtil.c @@ -35,7 +35,6 @@ #include "java_lang_Integer.h" #include "nio.h" #include "nio_util.h" -#include "net_util.h" static jfieldID fd_fdID; /* for jint 'fd' in java.io.FileDescriptor */ @@ -45,7 +44,6 @@ Java_sun_nio_ch_IOUtil_initIDs(JNIEnv *env, jclass clazz) { CHECK_NULL(clazz = (*env)->FindClass(env, "java/io/FileDescriptor")); CHECK_NULL(fd_fdID = (*env)->GetFieldID(env, clazz, "fd", "I")); - initInetAddressIDs(env); } JNIEXPORT jboolean JNICALL diff --git a/jdk/src/java.base/unix/native/libnio/ch/InheritedChannel.c b/jdk/src/java.base/unix/native/libnio/ch/InheritedChannel.c index 986348e5320..86d1b05baa2 100644 --- a/jdk/src/java.base/unix/native/libnio/ch/InheritedChannel.c +++ b/jdk/src/java.base/unix/native/libnio/ch/InheritedChannel.c @@ -47,6 +47,13 @@ static int matchFamily(struct sockaddr *sa) { return (family == AF_INET); } +JNIEXPORT void JNICALL +Java_sun_nio_ch_InheritedChannel_initIDs(JNIEnv *env, jclass cla) +{ + /* Initialize InetAddress IDs before later use of NET_XXX functions */ + initInetAddressIDs(env); +} + JNIEXPORT jobject JNICALL Java_sun_nio_ch_InheritedChannel_peerAddress0(JNIEnv *env, jclass cla, jint fd) { diff --git a/jdk/src/java.base/unix/native/libnio/ch/Net.c b/jdk/src/java.base/unix/native/libnio/ch/Net.c index 8887f59109c..197b23a7285 100644 --- a/jdk/src/java.base/unix/native/libnio/ch/Net.c +++ b/jdk/src/java.base/unix/native/libnio/ch/Net.c @@ -151,7 +151,7 @@ static jboolean isSourceFilterSupported(){ JNIEXPORT void JNICALL Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz) { - /* Here because Windows native code does need to init IDs */ + initInetAddressIDs(env); } JNIEXPORT jboolean JNICALL diff --git a/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c b/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c index d3ee3279e54..e8a1623a87d 100644 --- a/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c +++ b/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c @@ -333,7 +333,7 @@ Java_sun_nio_fs_UnixNativeDispatcher_dup(JNIEnv* env, jclass this, jint fd) { int res = -1; RESTARTABLE(dup((int)fd), res); - if (fd == -1) { + if (res == -1) { throwUnixException(env, errno); } return (jint)res; @@ -361,13 +361,14 @@ Java_sun_nio_fs_UnixNativeDispatcher_fopen0(JNIEnv* env, jclass this, JNIEXPORT void JNICALL Java_sun_nio_fs_UnixNativeDispatcher_fclose(JNIEnv* env, jclass this, jlong stream) { - int res; FILE* fp = jlong_to_ptr(stream); - do { - res = fclose(fp); - } while (res == EOF && errno == EINTR); - if (res == EOF) { + /* NOTE: fclose() wrapper is only used with read-only streams. + * If it ever is used with write streams, it might be better to add + * RESTARTABLE(fflush(fp)) before closing, to make sure the stream + * is completely written even if fclose() failed. + */ + if (fclose(fp) == EOF && errno != EINTR) { throwUnixException(env, errno); } } @@ -675,11 +676,9 @@ Java_sun_nio_fs_UnixNativeDispatcher_fdopendir(JNIEnv* env, jclass this, int dfd JNIEXPORT void JNICALL Java_sun_nio_fs_UnixNativeDispatcher_closedir(JNIEnv* env, jclass this, jlong dir) { - int err; DIR* dirp = jlong_to_ptr(dir); - RESTARTABLE(closedir(dirp), err); - if (errno == -1) { + if (closedir(dirp) == -1 && errno != EINTR) { throwUnixException(env, errno); } } diff --git a/jdk/src/java.base/windows/native/libjava/FileOutputStream_md.c b/jdk/src/java.base/windows/native/libjava/FileOutputStream_md.c index 567ebaa0c83..02ea15e89cb 100644 --- a/jdk/src/java.base/windows/native/libjava/FileOutputStream_md.c +++ b/jdk/src/java.base/windows/native/libjava/FileOutputStream_md.c @@ -54,8 +54,8 @@ Java_java_io_FileOutputStream_initIDs(JNIEnv *env, jclass fosClass) { */ JNIEXPORT void JNICALL -Java_java_io_FileOutputStream_open(JNIEnv *env, jobject this, - jstring path, jboolean append) { +Java_java_io_FileOutputStream_open0(JNIEnv *env, jobject this, + jstring path, jboolean append) { fileOpen(env, this, path, fos_fd, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC)); } diff --git a/jdk/src/java.base/windows/native/libjava/WinNTFileSystem_md.c b/jdk/src/java.base/windows/native/libjava/WinNTFileSystem_md.c index 6ecf818d3ff..3c280c0c9b4 100644 --- a/jdk/src/java.base/windows/native/libjava/WinNTFileSystem_md.c +++ b/jdk/src/java.base/windows/native/libjava/WinNTFileSystem_md.c @@ -572,10 +572,10 @@ Java_java_io_WinNTFileSystem_createFileExclusively(JNIEnv *env, jclass cls, SetLastError(error); JNU_ThrowIOExceptionWithLastError(env, "Could not open file"); } - } - free(pathbuf); - return JNI_FALSE; } + free(pathbuf); + return JNI_FALSE; + } free(pathbuf); CloseHandle(h); return JNI_TRUE; @@ -636,7 +636,7 @@ Java_java_io_WinNTFileSystem_list(JNIEnv *env, jobject this, jobject file) if (search_path == 0) { free (pathbuf); errno = ENOMEM; - JNU_ThrowOutOfMemoryError(env, "native memory allocation faiuled"); + JNU_ThrowOutOfMemoryError(env, "native memory allocation failed"); return NULL; } wcscpy(search_path, pathbuf); @@ -652,7 +652,7 @@ Java_java_io_WinNTFileSystem_list(JNIEnv *env, jobject this, jobject file) /* Remove trailing space chars from directory name */ len = (int)wcslen(search_path); - while (search_path[len-1] == ' ') { + while (search_path[len-1] == L' ') { len--; } search_path[len] = 0; @@ -713,13 +713,15 @@ Java_java_io_WinNTFileSystem_list(JNIEnv *env, jobject this, jobject file) return NULL; // error FindClose(handle); - /* Copy the final results into an appropriately-sized array */ - old = rv; - rv = (*env)->NewObjectArray(env, len, str_class, NULL); - if (rv == NULL) - return NULL; /* error */ - if (JNU_CopyObjectArray(env, rv, old, len) < 0) - return NULL; /* error */ + if (len < maxlen) { + /* Copy the final results into an appropriately-sized array */ + old = rv; + rv = (*env)->NewObjectArray(env, len, str_class, NULL); + if (rv == NULL) + return NULL; /* error */ + if (JNU_CopyObjectArray(env, rv, old, len) < 0) + return NULL; /* error */ + } return rv; } @@ -753,9 +755,7 @@ Java_java_io_WinNTFileSystem_rename0(JNIEnv *env, jobject this, jobject from, jboolean rv = JNI_FALSE; WCHAR *frompath = fileToNTPath(env, from, ids.path); WCHAR *topath = fileToNTPath(env, to, ids.path); - if (frompath == NULL || topath == NULL) - return JNI_FALSE; - if (_wrename(frompath, topath) == 0) { + if (frompath != NULL && topath != NULL && _wrename(frompath, topath) == 0) { rv = JNI_TRUE; } free(frompath); diff --git a/jdk/src/java.base/windows/native/libnio/ch/IOUtil.c b/jdk/src/java.base/windows/native/libnio/ch/IOUtil.c index 49de1eb89d7..5c33ac4de23 100644 --- a/jdk/src/java.base/windows/native/libnio/ch/IOUtil.c +++ b/jdk/src/java.base/windows/native/libnio/ch/IOUtil.c @@ -56,7 +56,6 @@ Java_sun_nio_ch_IOUtil_initIDs(JNIEnv *env, jclass clazz) CHECK_NULL(clazz = (*env)->FindClass(env, "java/io/FileDescriptor")); CHECK_NULL(fd_fdID = (*env)->GetFieldID(env, clazz, "fd", "I")); CHECK_NULL(handle_fdID = (*env)->GetFieldID(env, clazz, "handle", "J")); - initInetAddressIDs(env); } /************************************************************** diff --git a/jdk/src/java.base/windows/native/libnio/ch/Net.c b/jdk/src/java.base/windows/native/libnio/ch/Net.c index fb0faa87b84..b92e63ac11b 100644 --- a/jdk/src/java.base/windows/native/libnio/ch/Net.c +++ b/jdk/src/java.base/windows/native/libnio/ch/Net.c @@ -81,7 +81,7 @@ static void setConnectionReset(SOCKET s, BOOL enable) { JNIEXPORT void JNICALL Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz) { - /* nothing to do */ + initInetAddressIDs(env); } JNIEXPORT jboolean JNICALL diff --git a/jdk/src/java.smartcardio/share/classes/javax/smartcardio/CardPermission.java b/jdk/src/java.smartcardio/share/classes/javax/smartcardio/CardPermission.java index e803bbc9bb3..8086dbc7cd3 100644 --- a/jdk/src/java.smartcardio/share/classes/javax/smartcardio/CardPermission.java +++ b/jdk/src/java.smartcardio/share/classes/javax/smartcardio/CardPermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ package javax.smartcardio; import java.io.*; - +import java.util.StringJoiner; import java.security.Permission; /** @@ -180,20 +180,14 @@ public class CardPermission extends Permission { if (mask == A_ALL) { return S_ALL; } - boolean first = true; - StringBuilder sb = new StringBuilder(); + StringJoiner sj = new StringJoiner(","); for (int i = 0; i < ARRAY_MASKS.length; i++) { - int action = ARRAY_MASKS[i]; + final int action = ARRAY_MASKS[i]; if ((mask & action) == action) { - if (first == false) { - sb.append(","); - } else { - first = false; - } - sb.append(ARRAY_STRINGS[i]); + sj.add(ARRAY_STRINGS[i]); } } - return sb.toString(); + return sj.toString(); } diff --git a/jdk/src/jdk.attach/aix/classes/sun/tools/attach/AixAttachProvider.java b/jdk/src/jdk.attach/aix/classes/sun/tools/attach/AttachProviderImpl.java similarity index 89% rename from jdk/src/jdk.attach/aix/classes/sun/tools/attach/AixAttachProvider.java rename to jdk/src/jdk.attach/aix/classes/sun/tools/attach/AttachProviderImpl.java index a78c6609720..532c3db0a3d 100644 --- a/jdk/src/jdk.attach/aix/classes/sun/tools/attach/AixAttachProvider.java +++ b/jdk/src/jdk.attach/aix/classes/sun/tools/attach/AttachProviderImpl.java @@ -32,19 +32,18 @@ import com.sun.tools.attach.spi.AttachProvider; import java.io.IOException; -// Based on 'LinuxAttachProvider.java'. All occurrences of the string -// "Linux" have been textually replaced by "Aix" to avoid confusion. +// Based on linux/classes/sun/tools/attach/AttachProviderImpl.java. /* * An AttachProvider implementation for Aix that uses a UNIX domain * socket. */ -public class AixAttachProvider extends HotSpotAttachProvider { +public class AttachProviderImpl extends HotSpotAttachProvider { // perf counter for the JVM version private static final String JVM_VERSION = "java.property.java.vm.version"; - public AixAttachProvider() { + public AttachProviderImpl() { } public String name() { @@ -64,7 +63,7 @@ public class AixAttachProvider extends HotSpotAttachProvider { // to be not attachable. testAttachable(vmid); - return new AixVirtualMachine(this, vmid); + return new VirtualMachineImpl(this, vmid); } public VirtualMachine attachVirtualMachine(VirtualMachineDescriptor vmd) @@ -79,7 +78,7 @@ public class AixAttachProvider extends HotSpotAttachProvider { if (vmd instanceof HotSpotVirtualMachineDescriptor) { assert ((HotSpotVirtualMachineDescriptor)vmd).isAttachable(); checkAttachPermission(); - return new AixVirtualMachine(this, vmd.id()); + return new VirtualMachineImpl(this, vmd.id()); } else { return attachVirtualMachine(vmd.id()); } diff --git a/jdk/src/jdk.attach/aix/classes/sun/tools/attach/AixVirtualMachine.java b/jdk/src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java similarity index 95% rename from jdk/src/jdk.attach/aix/classes/sun/tools/attach/AixVirtualMachine.java rename to jdk/src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java index 714f5c0d570..a76d0a99771 100644 --- a/jdk/src/jdk.attach/aix/classes/sun/tools/attach/AixVirtualMachine.java +++ b/jdk/src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java @@ -34,13 +34,12 @@ import java.io.IOException; import java.io.File; import java.util.Properties; -// Based on 'LinuxVirtualMachine.java'. All occurrences of the string -// "Linux" have been textually replaced by "Aix" to avoid confusion. +// Based on linux/classes/sun/tools/attach/VirtualMachineImpl.java. /* * Aix implementation of HotSpotVirtualMachine */ -public class AixVirtualMachine extends HotSpotVirtualMachine { +public class VirtualMachineImpl extends HotSpotVirtualMachine { // "/tmp" is used as a global well-known location for the files // .java_pid. and .attach_pid. It is important that this // location is the same for all processes, otherwise the tools @@ -54,7 +53,7 @@ public class AixVirtualMachine extends HotSpotVirtualMachine { /** * Attaches to the target VM */ - AixVirtualMachine(AttachProvider provider, String vmid) + VirtualMachineImpl(AttachProvider provider, String vmid) throws AttachNotSupportedException, IOException { super(provider, vmid); @@ -241,11 +240,11 @@ public class AixVirtualMachine extends HotSpotVirtualMachine { } else if (len == 0) return 0; - return AixVirtualMachine.read(s, bs, off, len); + return VirtualMachineImpl.read(s, bs, off, len); } public void close() throws IOException { - AixVirtualMachine.close(s); + VirtualMachineImpl.close(s); } } @@ -287,7 +286,7 @@ public class AixVirtualMachine extends HotSpotVirtualMachine { } catch (java.io.UnsupportedEncodingException x) { throw new InternalError(x); } - AixVirtualMachine.write(fd, b, 0, b.length); + VirtualMachineImpl.write(fd, b, 0, b.length); } byte b[] = new byte[1]; b[0] = 0; diff --git a/jdk/src/jdk.attach/aix/native/libattach/AixVirtualMachine.c b/jdk/src/jdk.attach/aix/native/libattach/VirtualMachineImpl.c similarity index 89% rename from jdk/src/jdk.attach/aix/native/libattach/AixVirtualMachine.c rename to jdk/src/jdk.attach/aix/native/libattach/VirtualMachineImpl.c index 7422427803f..df330549d8d 100644 --- a/jdk/src/jdk.attach/aix/native/libattach/AixVirtualMachine.c +++ b/jdk/src/jdk.attach/aix/native/libattach/VirtualMachineImpl.c @@ -45,7 +45,7 @@ * occurrences of the string "Linux" have been replaced by "Aix". */ -#include "sun_tools_attach_AixVirtualMachine.h" +#include "sun_tools_attach_VirtualMachineImpl.h" #define RESTARTABLE(_cmd, _result) do { \ do { \ @@ -55,11 +55,11 @@ /* - * Class: sun_tools_attach_AixVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: socket * Signature: ()I */ -JNIEXPORT jint JNICALL Java_sun_tools_attach_AixVirtualMachine_socket +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_socket (JNIEnv *env, jclass cls) { int fd = socket(PF_UNIX, SOCK_STREAM, 0); @@ -79,11 +79,11 @@ JNIEXPORT jint JNICALL Java_sun_tools_attach_AixVirtualMachine_socket } /* - * Class: sun_tools_attach_AixVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: connect * Signature: (ILjava/lang/String;)I */ -JNIEXPORT void JNICALL Java_sun_tools_attach_AixVirtualMachine_connect +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_connect (JNIEnv *env, jclass cls, jint fd, jstring path) { jboolean isCopy; @@ -142,11 +142,11 @@ static void SendQuitCallback(const pid_t pid, void* user_data) { } /* - * Class: sun_tools_attach_AixVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: sendQuitTo * Signature: (I)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_AixVirtualMachine_sendQuitTo +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_sendQuitTo (JNIEnv *env, jclass cls, jint pid) { if (kill((pid_t)pid, SIGQUIT)) { @@ -155,11 +155,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_AixVirtualMachine_sendQuitTo } /* - * Class: sun_tools_attach_AixVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: checkPermissions * Signature: (Ljava/lang/String;)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_AixVirtualMachine_checkPermissions +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_checkPermissions (JNIEnv *env, jclass cls, jstring path) { jboolean isCopy; @@ -205,11 +205,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_AixVirtualMachine_checkPermissions } /* - * Class: sun_tools_attach_AixVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: close * Signature: (I)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_AixVirtualMachine_close +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_close (JNIEnv *env, jclass cls, jint fd) { int res; @@ -222,11 +222,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_AixVirtualMachine_close } /* - * Class: sun_tools_attach_AixVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: read * Signature: (I[BI)I */ -JNIEXPORT jint JNICALL Java_sun_tools_attach_AixVirtualMachine_read +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_read (JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint baLen) { unsigned char buf[128]; @@ -252,11 +252,11 @@ JNIEXPORT jint JNICALL Java_sun_tools_attach_AixVirtualMachine_read } /* - * Class: sun_tools_attach_AixVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: write * Signature: (I[B)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_AixVirtualMachine_write +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_write (JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint bufLen) { size_t remaining = bufLen; diff --git a/jdk/src/jdk.attach/unix/classes/sun/tools/attach/LinuxAttachProvider.java b/jdk/src/jdk.attach/linux/classes/sun/tools/attach/AttachProviderImpl.java similarity index 93% rename from jdk/src/jdk.attach/unix/classes/sun/tools/attach/LinuxAttachProvider.java rename to jdk/src/jdk.attach/linux/classes/sun/tools/attach/AttachProviderImpl.java index de3bf058bdf..adf8b01e6b4 100644 --- a/jdk/src/jdk.attach/unix/classes/sun/tools/attach/LinuxAttachProvider.java +++ b/jdk/src/jdk.attach/linux/classes/sun/tools/attach/AttachProviderImpl.java @@ -35,12 +35,12 @@ import java.io.IOException; * An AttachProvider implementation for Linux that uses a UNIX domain * socket. */ -public class LinuxAttachProvider extends HotSpotAttachProvider { +public class AttachProviderImpl extends HotSpotAttachProvider { // perf counter for the JVM version private static final String JVM_VERSION = "java.property.java.vm.version"; - public LinuxAttachProvider() { + public AttachProviderImpl() { } public String name() { @@ -60,7 +60,7 @@ public class LinuxAttachProvider extends HotSpotAttachProvider { // to be not attachable. testAttachable(vmid); - return new LinuxVirtualMachine(this, vmid); + return new VirtualMachineImpl(this, vmid); } public VirtualMachine attachVirtualMachine(VirtualMachineDescriptor vmd) @@ -75,7 +75,7 @@ public class LinuxAttachProvider extends HotSpotAttachProvider { if (vmd instanceof HotSpotVirtualMachineDescriptor) { assert ((HotSpotVirtualMachineDescriptor)vmd).isAttachable(); checkAttachPermission(); - return new LinuxVirtualMachine(this, vmd.id()); + return new VirtualMachineImpl(this, vmd.id()); } else { return attachVirtualMachine(vmd.id()); } diff --git a/jdk/src/jdk.attach/unix/classes/sun/tools/attach/LinuxVirtualMachine.java b/jdk/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java similarity index 97% rename from jdk/src/jdk.attach/unix/classes/sun/tools/attach/LinuxVirtualMachine.java rename to jdk/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java index 9dec425da0d..2bf3e74a8bd 100644 --- a/jdk/src/jdk.attach/unix/classes/sun/tools/attach/LinuxVirtualMachine.java +++ b/jdk/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java @@ -36,7 +36,7 @@ import java.io.File; /* * Linux implementation of HotSpotVirtualMachine */ -public class LinuxVirtualMachine extends HotSpotVirtualMachine { +public class VirtualMachineImpl extends HotSpotVirtualMachine { // "/tmp" is used as a global well-known location for the files // .java_pid. and .attach_pid. It is important that this // location is the same for all processes, otherwise the tools @@ -53,7 +53,7 @@ public class LinuxVirtualMachine extends HotSpotVirtualMachine { /** * Attaches to the target VM */ - LinuxVirtualMachine(AttachProvider provider, String vmid) + VirtualMachineImpl(AttachProvider provider, String vmid) throws AttachNotSupportedException, IOException { super(provider, vmid); @@ -262,11 +262,11 @@ public class LinuxVirtualMachine extends HotSpotVirtualMachine { } else if (len == 0) return 0; - return LinuxVirtualMachine.read(s, bs, off, len); + return VirtualMachineImpl.read(s, bs, off, len); } public void close() throws IOException { - LinuxVirtualMachine.close(s); + VirtualMachineImpl.close(s); } } @@ -308,7 +308,7 @@ public class LinuxVirtualMachine extends HotSpotVirtualMachine { } catch (java.io.UnsupportedEncodingException x) { throw new InternalError(x); } - LinuxVirtualMachine.write(fd, b, 0, b.length); + VirtualMachineImpl.write(fd, b, 0, b.length); } byte b[] = new byte[1]; b[0] = 0; diff --git a/jdk/src/jdk.attach/unix/native/libattach/LinuxVirtualMachine.c b/jdk/src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c similarity index 89% rename from jdk/src/jdk.attach/unix/native/libattach/LinuxVirtualMachine.c rename to jdk/src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c index 855ad9299f7..6f6c0793fb8 100644 --- a/jdk/src/jdk.attach/unix/native/libattach/LinuxVirtualMachine.c +++ b/jdk/src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c @@ -40,7 +40,7 @@ #include #include -#include "sun_tools_attach_LinuxVirtualMachine.h" +#include "sun_tools_attach_VirtualMachineImpl.h" #define RESTARTABLE(_cmd, _result) do { \ do { \ @@ -128,11 +128,11 @@ static pid_t getParent(pid_t pid) { /* - * Class: sun_tools_attach_LinuxVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: socket * Signature: ()I */ -JNIEXPORT jint JNICALL Java_sun_tools_attach_LinuxVirtualMachine_socket +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_socket (JNIEnv *env, jclass cls) { int fd = socket(PF_UNIX, SOCK_STREAM, 0); @@ -143,11 +143,11 @@ JNIEXPORT jint JNICALL Java_sun_tools_attach_LinuxVirtualMachine_socket } /* - * Class: sun_tools_attach_LinuxVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: connect * Signature: (ILjava/lang/String;)I */ -JNIEXPORT void JNICALL Java_sun_tools_attach_LinuxVirtualMachine_connect +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_connect (JNIEnv *env, jclass cls, jint fd, jstring path) { jboolean isCopy; @@ -189,11 +189,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_LinuxVirtualMachine_connect } /* - * Class: sun_tools_attach_LinuxVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: isLinuxThreads * Signature: ()V */ -JNIEXPORT jboolean JNICALL Java_sun_tools_attach_LinuxVirtualMachine_isLinuxThreads +JNIEXPORT jboolean JNICALL Java_sun_tools_attach_VirtualMachineImpl_isLinuxThreads (JNIEnv *env, jclass cls) { # ifndef _CS_GNU_LIBPTHREAD_VERSION @@ -250,11 +250,11 @@ static void ChildCountCallback(const pid_t pid, void* user_data) { } /* - * Class: sun_tools_attach_LinuxVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: getLinuxThreadsManager * Signature: (I)I */ -JNIEXPORT jint JNICALL Java_sun_tools_attach_LinuxVirtualMachine_getLinuxThreadsManager +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_getLinuxThreadsManager (JNIEnv *env, jclass cls, jint pid) { ChildCountContext context; @@ -312,11 +312,11 @@ static void SendQuitCallback(const pid_t pid, void* user_data) { } /* - * Class: sun_tools_attach_LinuxVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: sendQuitToChildrenOf * Signature: (I)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_LinuxVirtualMachine_sendQuitToChildrenOf +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_sendQuitToChildrenOf (JNIEnv *env, jclass cls, jint pid) { SendQuitContext context; @@ -329,11 +329,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_LinuxVirtualMachine_sendQuitToChild } /* - * Class: sun_tools_attach_LinuxVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: sendQuitTo * Signature: (I)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_LinuxVirtualMachine_sendQuitTo +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_sendQuitTo (JNIEnv *env, jclass cls, jint pid) { if (kill((pid_t)pid, SIGQUIT)) { @@ -342,11 +342,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_LinuxVirtualMachine_sendQuitTo } /* - * Class: sun_tools_attach_LinuxVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: checkPermissions * Signature: (Ljava/lang/String;)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_LinuxVirtualMachine_checkPermissions +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_checkPermissions (JNIEnv *env, jclass cls, jstring path) { jboolean isCopy; @@ -390,11 +390,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_LinuxVirtualMachine_checkPermission } /* - * Class: sun_tools_attach_LinuxVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: close * Signature: (I)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_LinuxVirtualMachine_close +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_close (JNIEnv *env, jclass cls, jint fd) { int res; @@ -402,11 +402,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_LinuxVirtualMachine_close } /* - * Class: sun_tools_attach_LinuxVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: read * Signature: (I[BI)I */ -JNIEXPORT jint JNICALL Java_sun_tools_attach_LinuxVirtualMachine_read +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_read (JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint baLen) { unsigned char buf[128]; @@ -432,11 +432,11 @@ JNIEXPORT jint JNICALL Java_sun_tools_attach_LinuxVirtualMachine_read } /* - * Class: sun_tools_attach_LinuxVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: write * Signature: (I[B)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_LinuxVirtualMachine_write +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_write (JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint bufLen) { size_t remaining = bufLen; diff --git a/jdk/src/jdk.attach/unix/classes/sun/tools/attach/BsdAttachProvider.java b/jdk/src/jdk.attach/macosx/classes/sun/tools/attach/AttachProviderImpl.java similarity index 93% rename from jdk/src/jdk.attach/unix/classes/sun/tools/attach/BsdAttachProvider.java rename to jdk/src/jdk.attach/macosx/classes/sun/tools/attach/AttachProviderImpl.java index c4f6a5cdc97..0f129769c0e 100644 --- a/jdk/src/jdk.attach/unix/classes/sun/tools/attach/BsdAttachProvider.java +++ b/jdk/src/jdk.attach/macosx/classes/sun/tools/attach/AttachProviderImpl.java @@ -35,12 +35,12 @@ import java.io.IOException; * An AttachProvider implementation for Bsd that uses a UNIX domain * socket. */ -public class BsdAttachProvider extends HotSpotAttachProvider { +public class AttachProviderImpl extends HotSpotAttachProvider { // perf counter for the JVM version private static final String JVM_VERSION = "java.property.java.vm.version"; - public BsdAttachProvider() { + public AttachProviderImpl() { } public String name() { @@ -60,7 +60,7 @@ public class BsdAttachProvider extends HotSpotAttachProvider { // to be not attachable. testAttachable(vmid); - return new BsdVirtualMachine(this, vmid); + return new VirtualMachineImpl(this, vmid); } public VirtualMachine attachVirtualMachine(VirtualMachineDescriptor vmd) @@ -75,7 +75,7 @@ public class BsdAttachProvider extends HotSpotAttachProvider { if (vmd instanceof HotSpotVirtualMachineDescriptor) { assert ((HotSpotVirtualMachineDescriptor)vmd).isAttachable(); checkAttachPermission(); - return new BsdVirtualMachine(this, vmd.id()); + return new VirtualMachineImpl(this, vmd.id()); } else { return attachVirtualMachine(vmd.id()); } diff --git a/jdk/src/jdk.attach/unix/classes/sun/tools/attach/BsdVirtualMachine.java b/jdk/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java similarity index 97% rename from jdk/src/jdk.attach/unix/classes/sun/tools/attach/BsdVirtualMachine.java rename to jdk/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java index ad344f1411e..0e304d0347d 100644 --- a/jdk/src/jdk.attach/unix/classes/sun/tools/attach/BsdVirtualMachine.java +++ b/jdk/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java @@ -36,7 +36,7 @@ import java.io.File; /* * Bsd implementation of HotSpotVirtualMachine */ -public class BsdVirtualMachine extends HotSpotVirtualMachine { +public class VirtualMachineImpl extends HotSpotVirtualMachine { // "tmpdir" is used as a global well-known location for the files // .java_pid. and .attach_pid. It is important that this // location is the same for all processes, otherwise the tools @@ -52,7 +52,7 @@ public class BsdVirtualMachine extends HotSpotVirtualMachine { /** * Attaches to the target VM */ - BsdVirtualMachine(AttachProvider provider, String vmid) + VirtualMachineImpl(AttachProvider provider, String vmid) throws AttachNotSupportedException, IOException { super(provider, vmid); @@ -247,11 +247,11 @@ public class BsdVirtualMachine extends HotSpotVirtualMachine { return 0; } - return BsdVirtualMachine.read(s, bs, off, len); + return VirtualMachineImpl.read(s, bs, off, len); } public void close() throws IOException { - BsdVirtualMachine.close(s); + VirtualMachineImpl.close(s); } } @@ -275,7 +275,7 @@ public class BsdVirtualMachine extends HotSpotVirtualMachine { } catch (java.io.UnsupportedEncodingException x) { throw new InternalError(); } - BsdVirtualMachine.write(fd, b, 0, b.length); + VirtualMachineImpl.write(fd, b, 0, b.length); } byte b[] = new byte[1]; b[0] = 0; diff --git a/jdk/src/jdk.attach/unix/native/libattach/BsdVirtualMachine.c b/jdk/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c similarity index 87% rename from jdk/src/jdk.attach/unix/native/libattach/BsdVirtualMachine.c rename to jdk/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c index 7735a90b4ba..8fa1e6abd78 100644 --- a/jdk/src/jdk.attach/unix/native/libattach/BsdVirtualMachine.c +++ b/jdk/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c @@ -41,7 +41,7 @@ #include #include -#include "sun_tools_attach_BsdVirtualMachine.h" +#include "sun_tools_attach_VirtualMachineImpl.h" #define RESTARTABLE(_cmd, _result) do { \ do { \ @@ -50,11 +50,11 @@ } while(0) /* - * Class: sun_tools_attach_BsdVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: socket * Signature: ()I */ -JNIEXPORT jint JNICALL Java_sun_tools_attach_BsdVirtualMachine_socket +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_socket (JNIEnv *env, jclass cls) { int fd = socket(PF_UNIX, SOCK_STREAM, 0); @@ -65,11 +65,11 @@ JNIEXPORT jint JNICALL Java_sun_tools_attach_BsdVirtualMachine_socket } /* - * Class: sun_tools_attach_BsdVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: connect * Signature: (ILjava/lang/String;)I */ -JNIEXPORT void JNICALL Java_sun_tools_attach_BsdVirtualMachine_connect +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_connect (JNIEnv *env, jclass cls, jint fd, jstring path) { jboolean isCopy; @@ -111,11 +111,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_BsdVirtualMachine_connect } /* - * Class: sun_tools_attach_BsdVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: sendQuitTo * Signature: (I)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_BsdVirtualMachine_sendQuitTo +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_sendQuitTo (JNIEnv *env, jclass cls, jint pid) { if (kill((pid_t)pid, SIGQUIT)) { @@ -124,11 +124,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_BsdVirtualMachine_sendQuitTo } /* - * Class: sun_tools_attach_BsdVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: checkPermissions * Signature: (Ljava/lang/String;)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_BsdVirtualMachine_checkPermissions +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_checkPermissions (JNIEnv *env, jclass cls, jstring path) { jboolean isCopy; @@ -172,11 +172,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_BsdVirtualMachine_checkPermissions } /* - * Class: sun_tools_attach_BsdVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: close * Signature: (I)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_BsdVirtualMachine_close +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_close (JNIEnv *env, jclass cls, jint fd) { int res; @@ -184,11 +184,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_BsdVirtualMachine_close } /* - * Class: sun_tools_attach_BsdVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: read * Signature: (I[BI)I */ -JNIEXPORT jint JNICALL Java_sun_tools_attach_BsdVirtualMachine_read +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_read (JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint baLen) { unsigned char buf[128]; @@ -214,11 +214,11 @@ JNIEXPORT jint JNICALL Java_sun_tools_attach_BsdVirtualMachine_read } /* - * Class: sun_tools_attach_BsdVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: write * Signature: (I[B)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_BsdVirtualMachine_write +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_write (JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint bufLen) { size_t remaining = bufLen; @@ -249,7 +249,7 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_BsdVirtualMachine_write * Method: createAttachFile * Signature: (Ljava.lang.String;)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_BsdVirtualMachine_createAttachFile(JNIEnv *env, jclass cls, jstring path) +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_createAttachFile(JNIEnv *env, jclass cls, jstring path) { const char* _path; jboolean isCopy; @@ -286,7 +286,7 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_BsdVirtualMachine_createAttachFile( * Method: getTempDir * Signature: (V)Ljava.lang.String; */ -JNIEXPORT jstring JNICALL Java_sun_tools_attach_BsdVirtualMachine_getTempDir(JNIEnv *env, jclass cls) +JNIEXPORT jstring JNICALL Java_sun_tools_attach_VirtualMachineImpl_getTempDir(JNIEnv *env, jclass cls) { // This must be hard coded because it's the system's temporary // directory not the java application's temp directory, ala java.io.tmpdir. diff --git a/jdk/src/jdk.attach/share/classes/META-INF/services/com.sun.tools.attach.spi.AttachProvider b/jdk/src/jdk.attach/share/classes/META-INF/services/com.sun.tools.attach.spi.AttachProvider index 4cb7f1d2c73..7ab9b79274a 100644 --- a/jdk/src/jdk.attach/share/classes/META-INF/services/com.sun.tools.attach.spi.AttachProvider +++ b/jdk/src/jdk.attach/share/classes/META-INF/services/com.sun.tools.attach.spi.AttachProvider @@ -22,13 +22,4 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -# List all Sun provided attach providers here. If there -# are providers that are only available on a particular OS -# then prefix the line with #[OS] and they will automatically -# uncommented by the build process. -# -#[solaris]sun.tools.attach.SolarisAttachProvider -#[windows]sun.tools.attach.WindowsAttachProvider -#[linux]sun.tools.attach.LinuxAttachProvider -#[macosx]sun.tools.attach.BsdAttachProvider -#[aix]sun.tools.attach.AixAttachProvider +sun.tools.attach.AttachProviderImpl diff --git a/jdk/src/jdk.attach/unix/classes/sun/tools/attach/SolarisAttachProvider.java b/jdk/src/jdk.attach/solaris/classes/sun/tools/attach/AttachProviderImpl.java similarity index 92% rename from jdk/src/jdk.attach/unix/classes/sun/tools/attach/SolarisAttachProvider.java rename to jdk/src/jdk.attach/solaris/classes/sun/tools/attach/AttachProviderImpl.java index 9fd6dd1e2bd..b044bb6965f 100644 --- a/jdk/src/jdk.attach/unix/classes/sun/tools/attach/SolarisAttachProvider.java +++ b/jdk/src/jdk.attach/solaris/classes/sun/tools/attach/AttachProviderImpl.java @@ -34,9 +34,9 @@ import java.io.IOException; * An AttachProvider implementation for Solaris that use the doors * interface to the VM. */ -public class SolarisAttachProvider extends HotSpotAttachProvider { +public class AttachProviderImpl extends HotSpotAttachProvider { - public SolarisAttachProvider() { + public AttachProviderImpl() { } public String name() { @@ -56,7 +56,7 @@ public class SolarisAttachProvider extends HotSpotAttachProvider { // to be not attachable. testAttachable(vmid); - return new SolarisVirtualMachine(this, vmid); + return new VirtualMachineImpl(this, vmid); } public VirtualMachine attachVirtualMachine(VirtualMachineDescriptor vmd) @@ -71,7 +71,7 @@ public class SolarisAttachProvider extends HotSpotAttachProvider { if (vmd instanceof HotSpotVirtualMachineDescriptor) { assert ((HotSpotVirtualMachineDescriptor)vmd).isAttachable(); checkAttachPermission(); - return new SolarisVirtualMachine(this, vmd.id()); + return new VirtualMachineImpl(this, vmd.id()); } else { return attachVirtualMachine(vmd.id()); } diff --git a/jdk/src/jdk.attach/unix/classes/sun/tools/attach/SolarisVirtualMachine.java b/jdk/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java similarity index 97% rename from jdk/src/jdk.attach/unix/classes/sun/tools/attach/SolarisVirtualMachine.java rename to jdk/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java index 3c57e4bda6a..b93f745475e 100644 --- a/jdk/src/jdk.attach/unix/classes/sun/tools/attach/SolarisVirtualMachine.java +++ b/jdk/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java @@ -37,7 +37,7 @@ import java.io.FileNotFoundException; /* * Solaris implementation of HotSpotVirtualMachine. */ -public class SolarisVirtualMachine extends HotSpotVirtualMachine { +public class VirtualMachineImpl extends HotSpotVirtualMachine { // "/tmp" is used as a global well-known location for the files // .java_pid. and .attach_pid. It is important that this // location is the same for all processes, otherwise the tools @@ -51,7 +51,7 @@ public class SolarisVirtualMachine extends HotSpotVirtualMachine { /** * Attaches to the target VM */ - SolarisVirtualMachine(AttachProvider provider, String vmid) + VirtualMachineImpl(AttachProvider provider, String vmid) throws AttachNotSupportedException, IOException { super(provider, vmid); @@ -190,11 +190,11 @@ public class SolarisVirtualMachine extends HotSpotVirtualMachine { } else if (len == 0) return 0; - return SolarisVirtualMachine.read(s, bs, off, len); + return VirtualMachineImpl.read(s, bs, off, len); } public void close() throws IOException { - SolarisVirtualMachine.close(s); + VirtualMachineImpl.close(s); } } diff --git a/jdk/src/jdk.attach/unix/native/libattach/SolarisVirtualMachine.c b/jdk/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c similarity index 92% rename from jdk/src/jdk.attach/unix/native/libattach/SolarisVirtualMachine.c rename to jdk/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c index 32dd249f321..7f0f0e37560 100644 --- a/jdk/src/jdk.attach/unix/native/libattach/SolarisVirtualMachine.c +++ b/jdk/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c @@ -36,7 +36,7 @@ #include "jni.h" #include "jni_util.h" -#include "sun_tools_attach_SolarisVirtualMachine.h" +#include "sun_tools_attach_VirtualMachineImpl.h" #define RESTARTABLE(_cmd, _result) do { \ do { \ @@ -45,11 +45,11 @@ } while(0) /* - * Class: sun_tools_attach_SolarisVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: open * Signature: (Ljava/lang/String;)I */ -JNIEXPORT jint JNICALL Java_sun_tools_attach_SolarisVirtualMachine_open +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_open (JNIEnv *env, jclass cls, jstring path) { jboolean isCopy; @@ -85,11 +85,11 @@ JNIEXPORT jint JNICALL Java_sun_tools_attach_SolarisVirtualMachine_open } /* - * Class: sun_tools_attach_SolarisVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: checkPermissions * Signature: (Ljava/lang/String;)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_SolarisVirtualMachine_checkPermissions +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_checkPermissions (JNIEnv *env, jclass cls, jstring path) { jboolean isCopy; @@ -133,11 +133,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_SolarisVirtualMachine_checkPermissi } /* - * Class: sun_tools_attach_SolarisVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: close * Signature: (I)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_SolarisVirtualMachine_close +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_close (JNIEnv *env, jclass cls, jint fd) { int ret; @@ -145,11 +145,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_SolarisVirtualMachine_close } /* - * Class: sun_tools_attach_SolarisVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: read * Signature: (I[BI)I */ -JNIEXPORT jint JNICALL Java_sun_tools_attach_SolarisVirtualMachine_read +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_read (JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint baLen) { unsigned char buf[128]; @@ -175,11 +175,11 @@ JNIEXPORT jint JNICALL Java_sun_tools_attach_SolarisVirtualMachine_read } /* - * Class: sun_tools_attach_SolarisVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: sigquit * Signature: (I)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_SolarisVirtualMachine_sigquit +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_sigquit (JNIEnv *env, jclass cls, jint pid) { if (kill((pid_t)pid, SIGQUIT) == -1) { @@ -224,11 +224,11 @@ static const char* translate_error(jint err) { static const char* PROTOCOL_VERSION = "1"; /* - * Class: sun_tools_attach_SolarisVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: enqueue * Signature: (JILjava/lang/String;[Ljava/lang/Object;)V */ -JNIEXPORT jint JNICALL Java_sun_tools_attach_SolarisVirtualMachine_enqueue +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_enqueue (JNIEnv *env, jclass cls, jint fd, jstring cmd, jobjectArray args) { jint arg_count, i; diff --git a/jdk/src/jdk.attach/windows/classes/sun/tools/attach/WindowsAttachProvider.java b/jdk/src/jdk.attach/windows/classes/sun/tools/attach/AttachProviderImpl.java similarity index 95% rename from jdk/src/jdk.attach/windows/classes/sun/tools/attach/WindowsAttachProvider.java rename to jdk/src/jdk.attach/windows/classes/sun/tools/attach/AttachProviderImpl.java index 76083a4d559..c094622e7db 100644 --- a/jdk/src/jdk.attach/windows/classes/sun/tools/attach/WindowsAttachProvider.java +++ b/jdk/src/jdk.attach/windows/classes/sun/tools/attach/AttachProviderImpl.java @@ -34,9 +34,9 @@ import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; -public class WindowsAttachProvider extends HotSpotAttachProvider { +public class AttachProviderImpl extends HotSpotAttachProvider { - public WindowsAttachProvider() { + public AttachProviderImpl() { String os = System.getProperty("os.name"); if (os.startsWith("Windows 9") || os.equals("Windows Me")) { throw new RuntimeException( @@ -66,7 +66,7 @@ public class WindowsAttachProvider extends HotSpotAttachProvider { // to be not attachable. testAttachable(vmid); - return new WindowsVirtualMachine(this, vmid); + return new VirtualMachineImpl(this, vmid); } public List listVirtualMachines() { @@ -84,7 +84,7 @@ public class WindowsAttachProvider extends HotSpotAttachProvider { */ private static boolean isTempPathSecure() { if (!wasTempPathChecked) { - synchronized (WindowsAttachProvider.class) { + synchronized (AttachProviderImpl.class) { if (!wasTempPathChecked) { // get the value of TMP/TEMP, ignoring UNC, and paths that // aren't absolute @@ -146,7 +146,7 @@ public class WindowsAttachProvider extends HotSpotAttachProvider { if (isLibraryLoadedByProcess("jvm.dll", processes[i])) { String pid = Integer.toString(processes[i]); try { - new WindowsVirtualMachine(this, pid).detach(); + new VirtualMachineImpl(this, pid).detach(); // FIXME - for now we don't have an appropriate display // name so we use pid@hostname diff --git a/jdk/src/jdk.attach/windows/classes/sun/tools/attach/WindowsVirtualMachine.java b/jdk/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java similarity index 96% rename from jdk/src/jdk.attach/windows/classes/sun/tools/attach/WindowsVirtualMachine.java rename to jdk/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java index 3b34c0d181a..8eabefa403c 100644 --- a/jdk/src/jdk.attach/windows/classes/sun/tools/attach/WindowsVirtualMachine.java +++ b/jdk/src/jdk.attach/windows/classes/sun/tools/attach/VirtualMachineImpl.java @@ -35,14 +35,14 @@ import java.io.IOException; import java.io.InputStream; import java.util.Random; -public class WindowsVirtualMachine extends HotSpotVirtualMachine { +public class VirtualMachineImpl extends HotSpotVirtualMachine { // the enqueue code stub (copied into each target VM) private static byte[] stub; private volatile long hProcess; // handle to the process - WindowsVirtualMachine(AttachProvider provider, String id) + VirtualMachineImpl(AttachProvider provider, String id) throws AttachNotSupportedException, IOException { super(provider, id); @@ -154,12 +154,12 @@ public class WindowsVirtualMachine extends HotSpotVirtualMachine { } else if (len == 0) return 0; - return WindowsVirtualMachine.readPipe(hPipe, bs, off, len); + return VirtualMachineImpl.readPipe(hPipe, bs, off, len); } public void close() throws IOException { if (hPipe != -1) { - WindowsVirtualMachine.closePipe(hPipe); + VirtualMachineImpl.closePipe(hPipe); hPipe = -1; } } diff --git a/jdk/src/jdk.attach/windows/native/libattach/WindowsAttachProvider.c b/jdk/src/jdk.attach/windows/native/libattach/AttachProviderImpl.c similarity index 87% rename from jdk/src/jdk.attach/windows/native/libattach/WindowsAttachProvider.c rename to jdk/src/jdk.attach/windows/native/libattach/AttachProviderImpl.c index e812b0f935f..7915d67d1c2 100644 --- a/jdk/src/jdk.attach/windows/native/libattach/WindowsAttachProvider.c +++ b/jdk/src/jdk.attach/windows/native/libattach/AttachProviderImpl.c @@ -30,15 +30,15 @@ #include "jni.h" #include "jni_util.h" -#include "sun_tools_attach_WindowsAttachProvider.h" +#include "sun_tools_attach_AttachProviderImpl.h" /* - * Class: sun_tools_attach_WindowsAttachProvider + * Class: sun_tools_attach_AttachProviderImpl * Method: tempPath * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL -Java_sun_tools_attach_WindowsAttachProvider_tempPath(JNIEnv *env, jclass cls) +Java_sun_tools_attach_AttachProviderImpl_tempPath(JNIEnv *env, jclass cls) { char buf[256]; DWORD bufLen, actualLen; @@ -64,12 +64,12 @@ Java_sun_tools_attach_WindowsAttachProvider_tempPath(JNIEnv *env, jclass cls) } /* - * Class: sun_tools_attach_WindowsAttachProvider + * Class: sun_tools_attach_AttachProviderImpl * Method: volumeFlags * Signature: ()J */ JNIEXPORT jlong JNICALL -Java_sun_tools_attach_WindowsAttachProvider_volumeFlags(JNIEnv *env, jclass cls, jstring str) +Java_sun_tools_attach_AttachProviderImpl_volumeFlags(JNIEnv *env, jclass cls, jstring str) { jboolean isCopy; const char* volume; @@ -98,13 +98,13 @@ Java_sun_tools_attach_WindowsAttachProvider_volumeFlags(JNIEnv *env, jclass cls, /* - * Class: sun_tools_attach_WindowsAttachProvider + * Class: sun_tools_attach_AttachProviderImpl * Method: enumProcesses * Signature: ([JI)I */ JNIEXPORT jint JNICALL -Java_sun_tools_attach_WindowsAttachProvider_enumProcesses(JNIEnv *env, jclass cls, - jintArray arr, jint max) +Java_sun_tools_attach_AttachProviderImpl_enumProcesses(JNIEnv *env, jclass cls, + jintArray arr, jint max) { DWORD size, bytesReturned; DWORD* ptr; @@ -124,13 +124,13 @@ Java_sun_tools_attach_WindowsAttachProvider_enumProcesses(JNIEnv *env, jclass cl } /* - * Class: sun_tools_attach_WindowsAttachProvider + * Class: sun_tools_attach_AttachProviderImpl * Method: isLibraryLoadedByProcess * Signature: (I[Ljava/lang/String;)Z */ JNIEXPORT jboolean JNICALL -Java_sun_tools_attach_WindowsAttachProvider_isLibraryLoadedByProcess(JNIEnv *env, jclass cls, - jstring str, jint processId) +Java_sun_tools_attach_AttachProviderImpl_isLibraryLoadedByProcess(JNIEnv *env, jclass cls, + jstring str, jint processId) { HANDLE hProcess; jboolean isCopy; diff --git a/jdk/src/jdk.attach/windows/native/libattach/WindowsVirtualMachine.c b/jdk/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c similarity index 93% rename from jdk/src/jdk.attach/windows/native/libattach/WindowsVirtualMachine.c rename to jdk/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c index 411d1777a54..2fc0438f82a 100644 --- a/jdk/src/jdk.attach/windows/native/libattach/WindowsVirtualMachine.c +++ b/jdk/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c @@ -28,7 +28,7 @@ #include "jni.h" #include "jni_util.h" -#include "sun_tools_attach_WindowsVirtualMachine.h" +#include "sun_tools_attach_VirtualMachineImpl.h" /* kernel32 */ @@ -124,11 +124,11 @@ void jvm_attach_thread_func_end (void) { /* - * Class: sun_tools_attach_WindowsVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: init * Signature: ()V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_WindowsVirtualMachine_init +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_init (JNIEnv *env, jclass cls) { // All following APIs exist on Windows XP with SP2/Windows Server 2008 @@ -139,11 +139,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_WindowsVirtualMachine_init /* - * Class: sun_tools_attach_WindowsVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: generateStub * Signature: ()[B */ -JNIEXPORT jbyteArray JNICALL Java_sun_tools_attach_WindowsVirtualMachine_generateStub +JNIEXPORT jbyteArray JNICALL Java_sun_tools_attach_VirtualMachineImpl_generateStub (JNIEnv *env, jclass cls) { /* @@ -161,11 +161,11 @@ JNIEXPORT jbyteArray JNICALL Java_sun_tools_attach_WindowsVirtualMachine_generat } /* - * Class: sun_tools_attach_WindowsVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: openProcess * Signature: (I)J */ -JNIEXPORT jlong JNICALL Java_sun_tools_attach_WindowsVirtualMachine_openProcess +JNIEXPORT jlong JNICALL Java_sun_tools_attach_VirtualMachineImpl_openProcess (JNIEnv *env, jclass cls, jint pid) { HANDLE hProcess = NULL; @@ -236,11 +236,11 @@ JNIEXPORT jlong JNICALL Java_sun_tools_attach_WindowsVirtualMachine_openProcess /* - * Class: sun_tools_attach_WindowsVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: closeProcess * Signature: (J)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_WindowsVirtualMachine_closeProcess +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_closeProcess (JNIEnv *env, jclass cls, jlong hProcess) { CloseHandle((HANDLE)hProcess); @@ -248,11 +248,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_WindowsVirtualMachine_closeProcess /* - * Class: sun_tools_attach_WindowsVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: createPipe * Signature: (Ljava/lang/String;)J */ -JNIEXPORT jlong JNICALL Java_sun_tools_attach_WindowsVirtualMachine_createPipe +JNIEXPORT jlong JNICALL Java_sun_tools_attach_VirtualMachineImpl_createPipe (JNIEnv *env, jclass cls, jstring pipename) { HANDLE hPipe; @@ -281,22 +281,22 @@ JNIEXPORT jlong JNICALL Java_sun_tools_attach_WindowsVirtualMachine_createPipe } /* - * Class: sun_tools_attach_WindowsVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: closePipe * Signature: (J)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_WindowsVirtualMachine_closePipe +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_closePipe (JNIEnv *env, jclass cls, jlong hPipe) { CloseHandle( (HANDLE)hPipe ); } /* - * Class: sun_tools_attach_WindowsVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: connectPipe * Signature: (J)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_WindowsVirtualMachine_connectPipe +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_connectPipe (JNIEnv *env, jclass cls, jlong hPipe) { BOOL fConnected; @@ -309,11 +309,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_WindowsVirtualMachine_connectPipe } /* - * Class: sun_tools_attach_WindowsVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: readPipe * Signature: (J[BII)I */ -JNIEXPORT jint JNICALL Java_sun_tools_attach_WindowsVirtualMachine_readPipe +JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_readPipe (JNIEnv *env, jclass cls, jlong hPipe, jbyteArray ba, jint off, jint baLen) { unsigned char buf[128]; @@ -352,11 +352,11 @@ JNIEXPORT jint JNICALL Java_sun_tools_attach_WindowsVirtualMachine_readPipe /* - * Class: sun_tools_attach_WindowsVirtualMachine + * Class: sun_tools_attach_VirtualMachineImpl * Method: enqueue * Signature: (JZLjava/lang/String;[Ljava/lang/Object;)V */ -JNIEXPORT void JNICALL Java_sun_tools_attach_WindowsVirtualMachine_enqueue +JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_enqueue (JNIEnv *env, jclass cls, jlong handle, jbyteArray stub, jstring cmd, jstring pipename, jobjectArray args) { diff --git a/jdk/src/demo/aix/jvmti/hprof/porting_aix.c b/jdk/src/jdk.hprof.agent/aix/native/libhprof/porting_aix.c similarity index 100% rename from jdk/src/demo/aix/jvmti/hprof/porting_aix.c rename to jdk/src/jdk.hprof.agent/aix/native/libhprof/porting_aix.c diff --git a/jdk/src/demo/aix/jvmti/hprof/porting_aix.h b/jdk/src/jdk.hprof.agent/aix/native/libhprof/porting_aix.h similarity index 100% rename from jdk/src/demo/aix/jvmti/hprof/porting_aix.h rename to jdk/src/jdk.hprof.agent/aix/native/libhprof/porting_aix.h diff --git a/jdk/src/demo/share/jvmti/hprof/README.txt b/jdk/src/jdk.hprof.agent/share/native/libhprof/README.txt similarity index 94% rename from jdk/src/demo/share/jvmti/hprof/README.txt rename to jdk/src/jdk.hprof.agent/share/native/libhprof/README.txt index cfefddb9b6a..b57b287c634 100644 --- a/jdk/src/demo/share/jvmti/hprof/README.txt +++ b/jdk/src/jdk.hprof.agent/share/native/libhprof/README.txt @@ -106,12 +106,8 @@ Design and Implementation: * Sources in the JDK workspace The sources and Makefiles live in: - src/share/classes/com/sun/demo/jvmti/hprof/* - src/share/demo/jvmti/hprof/* + src/jdk.hprof.agent/* src/share/demo/jvmti/java_crw_demo/* - src/solaris/demo/jvmti/hprof/* - src/windows/demo/jvmti/hprof/* - make/java/java_hprof_demo/* - make/java/java_crw_demo/* + make/lib/Lib-jdk.hprof.agent.gmk -------- diff --git a/jdk/src/demo/share/jvmti/hprof/debug_malloc.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/debug_malloc.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/debug_malloc.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/debug_malloc.c diff --git a/jdk/src/demo/share/jvmti/hprof/debug_malloc.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/debug_malloc.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/debug_malloc.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/debug_malloc.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_b_spec.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_b_spec.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_b_spec.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_b_spec.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_blocks.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_blocks.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_blocks.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_blocks.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_blocks.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_blocks.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_blocks.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_blocks.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_check.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_check.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_check.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_check.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_check.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_check.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_check.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_check.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_class.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_class.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_class.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_class.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_class.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_class.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_class.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_class.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_cpu.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_cpu.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_cpu.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_cpu.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_cpu.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_cpu.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_cpu.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_cpu.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_error.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_error.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_error.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_error.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_error.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_error.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_error.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_error.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_event.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_event.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_event.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_event.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_event.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_event.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_event.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_event.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_frame.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_frame.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_frame.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_frame.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_frame.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_frame.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_frame.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_frame.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_init.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_init.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_init.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_init.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_init.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_init.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_init.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_init.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_io.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_io.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_io.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_io.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_io.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_io.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_io.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_io.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_ioname.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_ioname.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_ioname.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_ioname.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_ioname.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_ioname.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_ioname.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_ioname.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_listener.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_listener.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_listener.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_listener.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_listener.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_listener.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_listener.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_listener.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_loader.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_loader.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_loader.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_loader.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_loader.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_loader.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_loader.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_loader.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_md.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_md.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_md.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_md.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_monitor.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_monitor.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_monitor.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_monitor.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_monitor.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_monitor.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_monitor.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_monitor.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_object.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_object.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_object.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_object.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_object.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_object.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_object.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_object.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_reference.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_reference.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_reference.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_reference.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_reference.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_reference.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_reference.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_reference.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_site.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_site.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_site.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_site.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_site.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_site.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_site.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_site.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_stack.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_stack.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_stack.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_stack.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_stack.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_stack.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_stack.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_stack.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_string.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_string.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_string.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_string.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_string.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_string.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_string.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_string.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_table.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_table.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_table.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_table.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_table.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_table.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_table.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_table.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_tag.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tag.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_tag.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tag.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_tag.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tag.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_tag.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tag.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_tls.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tls.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_tls.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tls.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_tls.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tls.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_tls.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tls.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_trace.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_trace.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_trace.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_trace.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_trace.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_trace.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_trace.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_trace.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_tracker.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tracker.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_tracker.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tracker.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_tracker.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tracker.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_tracker.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tracker.h diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_util.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_util.c similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_util.c rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_util.c diff --git a/jdk/src/demo/share/jvmti/hprof/hprof_util.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_util.h similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/hprof_util.h rename to jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_util.h diff --git a/jdk/src/demo/share/jvmti/hprof/jvm.hprof.txt b/jdk/src/jdk.hprof.agent/share/native/libhprof/jvm.hprof.txt similarity index 100% rename from jdk/src/demo/share/jvmti/hprof/jvm.hprof.txt rename to jdk/src/jdk.hprof.agent/share/native/libhprof/jvm.hprof.txt diff --git a/jdk/src/demo/share/jvmti/hprof/manual.html b/jdk/src/jdk.hprof.agent/share/native/libhprof/manual.html similarity index 99% rename from jdk/src/demo/share/jvmti/hprof/manual.html rename to jdk/src/jdk.hprof.agent/share/native/libhprof/manual.html index a62610dad66..f4ddc2ec6bc 100644 --- a/jdk/src/demo/share/jvmti/hprof/manual.html +++ b/jdk/src/jdk.hprof.agent/share/native/libhprof/manual.html @@ -1731,14 +1731,6 @@ stack depth

    -

    Source Code
    -

    -The source to HPROF is available in the JDK download in the -demo/jvmti/hprof directory. -

    *As used on this web site, the terms "Java -Virtual Machine" or "JVM" mean a virtual machine for the Java platform. -

    -


    Last modified: 2005 diff --git a/jdk/src/demo/unix/jvmti/hprof/hprof_md.c b/jdk/src/jdk.hprof.agent/unix/native/libhprof/hprof_md.c similarity index 100% rename from jdk/src/demo/unix/jvmti/hprof/hprof_md.c rename to jdk/src/jdk.hprof.agent/unix/native/libhprof/hprof_md.c diff --git a/jdk/src/demo/windows/jvmti/hprof/hprof_md.c b/jdk/src/jdk.hprof.agent/windows/native/libhprof/hprof_md.c similarity index 100% rename from jdk/src/demo/windows/jvmti/hprof/hprof_md.c rename to jdk/src/jdk.hprof.agent/windows/native/libhprof/hprof_md.c diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/expr/Expr.jj b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/expr/Expr.jj similarity index 100% rename from jdk/src/demo/share/jpda/com/sun/tools/example/debug/expr/Expr.jj rename to jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/expr/Expr.jj diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c index a1e366ec05f..8ae64d19f49 100644 --- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c +++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c @@ -993,7 +993,7 @@ static void atexit_finish_logging(void) { /* Normal exit(0) (not _exit()) may only reach here */ - finish_logging(0); /* Only first call matters */ + finish_logging(); /* Only first call matters */ } static jboolean @@ -1281,43 +1281,49 @@ bad_option_no_msg: void debugInit_exit(jvmtiError error, const char *msg) { - int exit_code = 0; + enum exit_codes { EXIT_NO_ERRORS = 0, EXIT_JVMTI_ERROR = 1, EXIT_TRANSPORT_ERROR = 2 }; - /* Pick an error code */ - if ( error != JVMTI_ERROR_NONE ) { - exit_code = 1; - if ( docoredump ) { - LOG_MISC(("Dumping core as requested by command line")); - finish_logging(exit_code); - abort(); - } + // Prepare to exit. Log error and finish logging + LOG_MISC(("Exiting with error %s(%d): %s", jvmtiErrorText(error), error, + ((msg == NULL) ? "" : msg))); + + // coredump requested by command line. Keep JVMTI data dirty + if (error != JVMTI_ERROR_NONE && docoredump) { + LOG_MISC(("Dumping core as requested by command line")); + finish_logging(); + abort(); } - if ( msg==NULL ) { - msg = ""; - } - - LOG_MISC(("Exiting with error %s(%d): %s", jvmtiErrorText(error), error, msg)); + finish_logging(); + // Cleanup the JVMTI if we have one if (gdata != NULL) { gdata->vmDead = JNI_TRUE; - - /* Let's try and cleanup the JVMTI, if we even have one */ - if ( gdata->jvmti != NULL ) { - /* Dispose of jvmti (gdata->jvmti becomes NULL) */ + if (gdata->jvmti != NULL) { + // Dispose of jvmti (gdata->jvmti becomes NULL) disposeEnvironment(gdata->jvmti); } } - /* Finish up logging. We reach here if JDWP is doing the exiting. */ - finish_logging(exit_code); /* Only first call matters */ - - /* Let's give the JNI a FatalError if non-exit 0, which is historic way */ - if ( exit_code != 0 ) { - JNIEnv *env = NULL; - jniFatalError(env, msg, error, exit_code); + // We are here with no errors. Kill entire process and exit with zero exit code + if (error == JVMTI_ERROR_NONE) { + forceExit(EXIT_NO_ERRORS); + return; } - /* Last chance to die, this kills the entire process. */ - forceExit(exit_code); + // No transport initilized. + // As we don't have any details here exiting with separate exit code + if (error == AGENT_ERROR_TRANSPORT_INIT) { + forceExit(EXIT_TRANSPORT_ERROR); + return; + } + + // We have JVMTI error. Call hotspot jni_FatalError handler + jniFatalError(NULL, msg, error, EXIT_JVMTI_ERROR); + + // hotspot calls os:abort() so we should never reach code below, + // but guard against possible hotspot changes + + // Last chance to die, this kills the entire process. + forceExit(EXIT_JVMTI_ERROR); } diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/log_messages.c b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/log_messages.c index 77b8876382d..a2607d1c568 100644 --- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/log_messages.c +++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/log_messages.c @@ -237,7 +237,7 @@ setup_logging(const char *filename, unsigned flags) /* Finish up logging, flush output to the logfile. */ void -finish_logging(int exit_code) +finish_logging() { #ifdef JDWP_LOGGING MUTEX_LOCK(my_mutex); diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/log_messages.h b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/log_messages.h index 0a442e943b7..129fab66cd5 100644 --- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/log_messages.h +++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/log_messages.h @@ -29,7 +29,7 @@ /* LOG: Must be called like: LOG_category(("anything")) or LOG_category((format,args)) */ void setup_logging(const char *, unsigned); -void finish_logging(int); +void finish_logging(); #define LOG_NULL ((void)0) diff --git a/jdk/src/jdk.runtime/share/classes/sun/security/tools/policytool/PolicyTool.java b/jdk/src/jdk.runtime/share/classes/sun/security/tools/policytool/PolicyTool.java index fa667841b28..7e2e8beea86 100644 --- a/jdk/src/jdk.runtime/share/classes/sun/security/tools/policytool/PolicyTool.java +++ b/jdk/src/jdk.runtime/share/classes/sun/security/tools/policytool/PolicyTool.java @@ -1695,6 +1695,7 @@ class ToolDialog extends JDialog { PERM_ARRAY.add(new MBeanSvrPerm()); PERM_ARRAY.add(new MBeanTrustPerm()); PERM_ARRAY.add(new NetPerm()); + PERM_ARRAY.add(new NetworkPerm()); PERM_ARRAY.add(new PrivCredPerm()); PERM_ARRAY.add(new PropPerm()); PERM_ARRAY.add(new ReflectPerm()); @@ -4321,9 +4322,11 @@ class NetPerm extends Perm { super("NetPermission", "java.net.NetPermission", new String[] { + "allowHttpTrace", "setDefaultAuthenticator", "requestPasswordAuthentication", "specifyStreamHandler", + "getNetworkInformation", "setProxySelector", "getProxySelector", "setCookieHandler", @@ -4335,6 +4338,18 @@ class NetPerm extends Perm { } } +class NetworkPerm extends Perm { + public NetworkPerm() { + super("NetworkPermission", + "jdk.net.NetworkPermission", + new String[] { + "setOption.SO_FLOW_SLA", + "getOption.SO_FLOW_SLA" + }, + null); + } +} + class PrivCredPerm extends Perm { public PrivCredPerm() { super("PrivateCredentialPermission", diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 494e4e0b482..fa11cfc642d 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -127,6 +127,8 @@ # 8046351 com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java generic-all com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationTest.java generic-all +# 8056143 +java/lang/management/MemoryMXBean/LowMemoryTest.java generic-all ############################################################################ @@ -274,9 +276,6 @@ com/sun/jdi/JdbReadTwiceTest.sh generic-all # jdk_instrument -# 8037082 -java/lang/instrument/NativeMethodPrefixAgent.java generic-all - ############################################################################ # svc_tools diff --git a/jdk/test/TEST.groups b/jdk/test/TEST.groups index 3cd7450172e..d361a3c5fcb 100644 --- a/jdk/test/TEST.groups +++ b/jdk/test/TEST.groups @@ -343,6 +343,7 @@ needs_jdk = \ java/io/Serializable/serialver \ java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java \ java/lang/invoke/lambda/LambdaAccessControlTest.java \ + java/lang/invoke/lambda/LambdaAsm.java \ java/lang/System/MacEncoding/TestFileEncoding.java \ java/net/URLClassLoader/closetest/GetResourceAsStream.java \ java/util/Collections/EmptyIterator.java \ @@ -397,6 +398,11 @@ needs_jre = \ java/text/Bidi/Bug7051769.java \ javax/crypto/Cipher/CipherStreamClose.java \ javax/management/monitor/AttributeArbitraryDataTypeTest.java \ + javax/management/mxbean/AmbiguousConstructorTest.java \ + javax/management/mxbean/ExceptionDiagnosisTest.java \ + javax/management/mxbean/LeakTest.java \ + javax/management/mxbean/MXBeanTest.java \ + javax/management/mxbean/PropertyNamesTest.java \ jdk/lambda/vm/InterfaceAccessFlagsTest.java \ sun/misc/URLClassPath/ClassnameCharTest.java @@ -492,6 +498,7 @@ needs_compact3 = \ sun/security/acl \ sun/security/jgss \ sun/security/krb5 \ + java/lang/annotation/AnnotationType/AnnotationTypeDeadlockTest.java \ java/lang/System/MacEncoding/TestFileEncoding.java \ java/nio/channels/AsynchronousSocketChannel/Leaky.java \ java/security/PermissionCollection/Concurrent.java \ @@ -499,6 +506,8 @@ needs_compact3 = \ java/security/cert/GetInstance.java \ java/util/logging/DrainFindDeadlockTest.java \ java/util/logging/LoggingMXBeanTest.java \ + java/util/logging/TestLogConfigurationDeadLock.java \ + java/util/logging/TestLoggerBundleSync.java \ sun/net/www/http/KeepAliveCache/B5045306.java \ sun/security/provider/PolicyFile/Alias.java \ sun/security/provider/PolicyFile/Comparator.java \ @@ -550,6 +559,7 @@ needs_compact2 = \ java/lang/PrimitiveSumMinMaxTest.java \ java/lang/String/StringJoinTest.java \ java/lang/Thread/StopThrowable.java \ + java/net/Authenticator/B4769350.java \ java/net/Authenticator/Deadlock.java \ java/net/CookieHandler/LocalHostCookie.java \ java/net/CookieHandler/CookieManagerTest.java \ @@ -600,7 +610,6 @@ needs_compact2 = \ java/util/zip/ZipFile/StreamZipEntriesTest.java \ java/util/zip/ZipFile/DeleteTempJar.java \ javax/crypto/Cipher/CipherStreamClose.java \ - sun/misc/URLClassPath/ClassnameCharTest.java \ sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java \ sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java diff --git a/jdk/test/com/sun/jdi/DoubleAgentTest.java b/jdk/test/com/sun/jdi/DoubleAgentTest.java index 3568f436ac1..0a0b5e8dcae 100644 --- a/jdk/test/com/sun/jdi/DoubleAgentTest.java +++ b/jdk/test/com/sun/jdi/DoubleAgentTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, 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,136 +21,39 @@ * questions. */ +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.Utils; + /* @test * @bug 6354345 - * @summary Check that a double agent request fails + * @summary Check that multiple -agentlib statements in command line fails * - * @build VMConnection DoubleAgentTest Exit0 + * @library /lib/testlibrary + * @build jdk.testlibarary.* + * @build DoubleAgentTest Exit0 * @run driver DoubleAgentTest - * */ -import java.io.InputStream; -import java.io.IOException; -import java.io.File; -import java.net.ServerSocket; public class DoubleAgentTest { - static Object locker = new Object(); - static String outputText = ""; + private static final String TEST_CLASSES = System.getProperty( + "test.classes", "."); - /* - * Helper class to redirect process output/error - */ - static class IOHandler implements Runnable { - InputStream in; + public static void main(String[] args) throws Throwable { + int port = Utils.getFreePort(); - IOHandler(InputStream in) { - this.in = in; - } - - static Thread handle(InputStream in) { - IOHandler handler = new IOHandler(in); - Thread thr = new Thread(handler); - thr.setDaemon(true); - thr.start(); - return thr; - } - - public void run() { - try { - byte b[] = new byte[100]; - for (;;) { - int n = in.read(b, 0, 100); - // The first thing that will get read is - // Listening for transport dt_socket at address: xxxxx - // which shows the debuggee is ready to accept connections. - synchronized(locker) { - locker.notify(); - } - if (n < 0) { - break; - } - String s = new String(b, 0, n, "UTF-8"); - System.out.print(s); - synchronized(outputText) { - outputText += s; - } - } - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } - - } - - /* - * Launch a server debuggee with the given address - */ - private static Process launch(String address, String class_name) throws IOException { - String exe = System.getProperty("java.home") - + File.separator + "bin" + File.separator + "java"; String jdwpOption = "-agentlib:jdwp=transport=dt_socket" - + ",server=y" + ",suspend=y" + ",address=" + address; - String cmd = exe + " " + VMConnection.getDebuggeeVMOptions() - + " " + jdwpOption - + " " + jdwpOption - + " " + class_name; + + ",server=y" + ",suspend=n" + ",address=*:" + String.valueOf(port); - System.out.println("Starting: " + cmd); - - Process p = Runtime.getRuntime().exec(cmd); - - return p; - } - - /* - * - pick a TCP port - * - Launch a server debuggee that should fail - * - verify we saw error - */ - public static void main(String args[]) throws Exception { - // find a free port - ServerSocket ss = new ServerSocket(0); - int port = ss.getLocalPort(); - ss.close(); - - String address = String.valueOf(port); - - // launch the server debuggee - Process process = launch(address, "Exit0"); - Thread t1 = IOHandler.handle(process.getInputStream()); - Thread t2 = IOHandler.handle(process.getErrorStream()); - - // wait for the debugge to be ready - synchronized(locker) { - locker.wait(); - } - - int exitCode = process.waitFor(); - try { - t1.join(); - t2.join(); - } catch ( InterruptedException e ) { - e.printStackTrace(); - throw new Exception("Debuggee failed InterruptedException"); - } - - if ( outputText.contains("capabilities") ) { - throw new Exception( - "Debuggee failed with ERROR about capabilities: " + outputText); - } - - if ( !outputText.contains("ERROR") ) { - throw new Exception( - "Debuggee does not have ERROR in the output: " + outputText); - } - - if ( exitCode == 0 ) { - throw new Exception( - "Debuggee should have failed with an non-zero exit code"); - } + OutputAnalyzer output = ProcessTools.executeTestJvm("-classpath", + TEST_CLASSES, + jdwpOption, // Notice jdwpOption specified twice + jdwpOption, + "Exit0"); + output.shouldContain("Cannot load this JVM TI agent twice"); + output.shouldHaveExitValue(1); } } diff --git a/jdk/test/com/sun/net/httpserver/SelCacheTest.java b/jdk/test/com/sun/net/httpserver/SelCacheTest.java index 5c574814fde..8c644bccfa5 100644 --- a/jdk/test/com/sun/net/httpserver/SelCacheTest.java +++ b/jdk/test/com/sun/net/httpserver/SelCacheTest.java @@ -24,11 +24,14 @@ /** * @test * @bug 6270015 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext * @run main/othervm -Dsun.net.httpserver.selCacheTimeout=2 SelCacheTest * @summary Light weight HTTP server */ import com.sun.net.httpserver.*; +import jdk.testlibrary.SimpleSSLContext; import java.util.*; import java.util.concurrent.*; @@ -65,7 +68,7 @@ public class SelCacheTest extends Test { executor = Executors.newCachedThreadPool(); s1.setExecutor (executor); s2.setExecutor (executor); - ctx = new SimpleSSLContext(System.getProperty("test.src")).get(); + ctx = new SimpleSSLContext().get(); s2.setHttpsConfigurator(new HttpsConfigurator (ctx)); s1.start(); s2.start(); diff --git a/jdk/test/com/sun/net/httpserver/Test1.java b/jdk/test/com/sun/net/httpserver/Test1.java index aa1c3969a2d..55d278fe1ae 100644 --- a/jdk/test/com/sun/net/httpserver/Test1.java +++ b/jdk/test/com/sun/net/httpserver/Test1.java @@ -24,6 +24,8 @@ /** * @test * @bug 6270015 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext * @run main/othervm Test1 * @run main/othervm -Dsun.net.httpserver.maxReqTime=10 Test1 * @run main/othervm -Dsun.net.httpserver.nodelay=true Test1 @@ -36,6 +38,7 @@ import java.util.concurrent.*; import java.io.*; import java.net.*; import javax.net.ssl.*; +import jdk.testlibrary.SimpleSSLContext; /* basic http/s connectivity test * Tests: @@ -72,7 +75,7 @@ public class Test1 extends Test { executor = Executors.newCachedThreadPool(); s1.setExecutor (executor); s2.setExecutor (executor); - ctx = new SimpleSSLContext(System.getProperty("test.src")).get(); + ctx = new SimpleSSLContext().get(); s2.setHttpsConfigurator(new HttpsConfigurator (ctx)); s1.start(); s2.start(); diff --git a/jdk/test/com/sun/net/httpserver/Test12.java b/jdk/test/com/sun/net/httpserver/Test12.java index 950103af6bc..910ec385a9c 100644 --- a/jdk/test/com/sun/net/httpserver/Test12.java +++ b/jdk/test/com/sun/net/httpserver/Test12.java @@ -24,6 +24,8 @@ /** * @test * @bug 6270015 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext * @run main/othervm Test12 * @summary Light weight HTTP server */ @@ -34,6 +36,7 @@ import java.util.concurrent.*; import java.io.*; import java.net.*; import javax.net.ssl.*; +import jdk.testlibrary.SimpleSSLContext; /* basic http/s connectivity test * Tests: @@ -62,7 +65,7 @@ public class Test12 extends Test { executor = Executors.newCachedThreadPool(); s1.setExecutor (executor); s2.setExecutor (executor); - ctx = new SimpleSSLContext(System.getProperty("test.src")).get(); + ctx = new SimpleSSLContext().get(); s2.setHttpsConfigurator(new HttpsConfigurator (ctx)); s1.start(); s2.start(); diff --git a/jdk/test/com/sun/net/httpserver/Test13.java b/jdk/test/com/sun/net/httpserver/Test13.java index c0181a778f4..0436f8b0643 100644 --- a/jdk/test/com/sun/net/httpserver/Test13.java +++ b/jdk/test/com/sun/net/httpserver/Test13.java @@ -24,6 +24,8 @@ /** * @test * @bug 6270015 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext * @run main/othervm Test13 * @summary Light weight HTTP server */ @@ -34,8 +36,8 @@ import java.util.concurrent.*; import java.util.logging.*; import java.io.*; import java.net.*; - import javax.net.ssl.*; +import jdk.testlibrary.SimpleSSLContext; /* basic http/s connectivity test * Tests: @@ -71,7 +73,7 @@ public class Test13 extends Test { executor = Executors.newCachedThreadPool(); s1.setExecutor (executor); s2.setExecutor (executor); - ctx = new SimpleSSLContext(System.getProperty("test.src")).get(); + ctx = new SimpleSSLContext().get(); s2.setHttpsConfigurator(new HttpsConfigurator (ctx)); s1.start(); s2.start(); diff --git a/jdk/test/com/sun/net/httpserver/Test6a.java b/jdk/test/com/sun/net/httpserver/Test6a.java index 1fb7a8c0a33..fd5a48ee730 100644 --- a/jdk/test/com/sun/net/httpserver/Test6a.java +++ b/jdk/test/com/sun/net/httpserver/Test6a.java @@ -24,6 +24,8 @@ /** * @test * @bug 6270015 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext * @run main/othervm Test6a * @summary Light weight HTTP server */ @@ -34,6 +36,7 @@ import java.util.concurrent.*; import java.io.*; import java.net.*; import javax.net.ssl.*; +import jdk.testlibrary.SimpleSSLContext; /** * Test https POST large file via chunked encoding (unusually small chunks) @@ -47,7 +50,7 @@ public class Test6a extends Test { HttpsServer server = HttpsServer.create (addr, 0); HttpContext ctx = server.createContext ("/test", handler); ExecutorService executor = Executors.newCachedThreadPool(); - SSLContext ssl = new SimpleSSLContext(System.getProperty("test.src")).get(); + SSLContext ssl = new SimpleSSLContext().get(); server.setExecutor (executor); server.setHttpsConfigurator(new HttpsConfigurator (ssl)); server.start (); diff --git a/jdk/test/com/sun/net/httpserver/Test7a.java b/jdk/test/com/sun/net/httpserver/Test7a.java index 2fca431f3a4..3599edf2030 100644 --- a/jdk/test/com/sun/net/httpserver/Test7a.java +++ b/jdk/test/com/sun/net/httpserver/Test7a.java @@ -24,6 +24,8 @@ /** * @test * @bug 6270015 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext * @run main/othervm Test7a * @summary Light weight HTTP server */ @@ -34,6 +36,7 @@ import java.util.concurrent.*; import java.io.*; import java.net.*; import javax.net.ssl.*; +import jdk.testlibrary.SimpleSSLContext; /** * Test POST large file via chunked encoding (large chunks) @@ -52,7 +55,7 @@ public class Test7a extends Test { HttpsServer server = HttpsServer.create (addr, 0); HttpContext ctx = server.createContext ("/test", handler); ExecutorService executor = Executors.newCachedThreadPool(); - SSLContext ssl = new SimpleSSLContext(System.getProperty("test.src")).get(); + SSLContext ssl = new SimpleSSLContext().get(); server.setHttpsConfigurator(new HttpsConfigurator (ssl)); server.setExecutor (executor); server.start (); diff --git a/jdk/test/com/sun/net/httpserver/Test8a.java b/jdk/test/com/sun/net/httpserver/Test8a.java index e2ef8ee9534..ac11931cacd 100644 --- a/jdk/test/com/sun/net/httpserver/Test8a.java +++ b/jdk/test/com/sun/net/httpserver/Test8a.java @@ -24,6 +24,8 @@ /** * @test * @bug 6270015 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext * @run main/othervm Test8a * @summary Light weight HTTP server */ @@ -34,6 +36,7 @@ import java.util.concurrent.*; import java.io.*; import java.net.*; import javax.net.ssl.*; +import jdk.testlibrary.SimpleSSLContext; /** * Test POST large file via fixed len encoding @@ -55,7 +58,7 @@ public class Test8a extends Test { server = HttpsServer.create (addr, 0); HttpContext ctx = server.createContext ("/test", handler); executor = Executors.newCachedThreadPool(); - SSLContext ssl = new SimpleSSLContext(System.getProperty("test.src")).get(); + SSLContext ssl = new SimpleSSLContext().get(); server.setHttpsConfigurator(new HttpsConfigurator (ssl)); server.setExecutor (executor); server.start (); diff --git a/jdk/test/com/sun/net/httpserver/Test9.java b/jdk/test/com/sun/net/httpserver/Test9.java index a2b74f2bcdd..581b9e54c9f 100644 --- a/jdk/test/com/sun/net/httpserver/Test9.java +++ b/jdk/test/com/sun/net/httpserver/Test9.java @@ -24,6 +24,8 @@ /** * @test * @bug 6270015 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext * @run main/othervm Test9 * @summary Light weight HTTP server */ @@ -34,6 +36,7 @@ import java.util.concurrent.*; import java.io.*; import java.net.*; import javax.net.ssl.*; +import jdk.testlibrary.SimpleSSLContext; /* Same as Test1 but requests run in parallel. */ @@ -59,7 +62,7 @@ public class Test9 extends Test { executor = Executors.newCachedThreadPool(); s1.setExecutor (executor); s2.setExecutor (executor); - ctx = new SimpleSSLContext(System.getProperty("test.src")).get(); + ctx = new SimpleSSLContext().get(); s2.setHttpsConfigurator(new HttpsConfigurator (ctx)); s1.start(); s2.start(); diff --git a/jdk/test/com/sun/net/httpserver/Test9a.java b/jdk/test/com/sun/net/httpserver/Test9a.java index d7460704dcf..6fd3f16562a 100644 --- a/jdk/test/com/sun/net/httpserver/Test9a.java +++ b/jdk/test/com/sun/net/httpserver/Test9a.java @@ -24,6 +24,8 @@ /** * @test * @bug 6270015 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext * @run main/othervm Test9a * @summary Light weight HTTP server */ @@ -34,6 +36,7 @@ import java.util.concurrent.*; import java.io.*; import java.net.*; import javax.net.ssl.*; +import jdk.testlibrary.SimpleSSLContext; /* Same as Test1 but requests run in parallel. */ @@ -56,8 +59,8 @@ public class Test9a extends Test { HttpContext c1 = server.createContext ("/test1", h); executor = Executors.newCachedThreadPool(); server.setExecutor (executor); - serverCtx = new SimpleSSLContext(System.getProperty("test.src")).get(); - clientCtx = new SimpleSSLContext(System.getProperty("test.src")).get(); + serverCtx = new SimpleSSLContext().get(); + clientCtx = new SimpleSSLContext().get(); server.setHttpsConfigurator(new HttpsConfigurator (serverCtx)); server.start(); diff --git a/jdk/test/java/io/ByteArrayOutputStream/MaxCapacity.java b/jdk/test/java/io/ByteArrayOutputStream/MaxCapacity.java new file mode 100644 index 00000000000..e46786cca27 --- /dev/null +++ b/jdk/test/java/io/ByteArrayOutputStream/MaxCapacity.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014 Google Inc. 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 + * @ignore This test has huge memory requirements + * @run main/timeout=1800/othervm -Xmx8g MaxCapacity + * @bug 8055949 + * @summary Check that we can write (almost) Integer.MAX_VALUE bytes + * to a ByteArrayOutputStream. + * @author Martin Buchholz + */ +import java.io.ByteArrayOutputStream; + +public class MaxCapacity { + public static void main(String[] args) { + long maxHeap = Runtime.getRuntime().maxMemory(); + if (maxHeap < 3L * Integer.MAX_VALUE) { + System.out.printf("Skipping test; max memory %sM too small%n", + maxHeap/(1024*1024)); + return; + } + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + for (long n = 0; ; n++) { + try { + baos.write((byte)'x'); + } catch (Throwable t) { + // check data integrity while we're here + byte[] bytes = baos.toByteArray(); + if (bytes.length != n) + throw new AssertionError("wrong length"); + if (bytes[0] != 'x' || + bytes[bytes.length - 1] != 'x') + throw new AssertionError("wrong contents"); + + long gap = Integer.MAX_VALUE - n; + System.out.printf("gap=%dM %d%n", gap/(1024*1024), gap); + if (gap > 1024) + throw t; + // t.printStackTrace(); + break; + } + } + } +} diff --git a/jdk/test/java/lang/Double/BitwiseConversion.java b/jdk/test/java/lang/Double/BitwiseConversion.java index 1491b0b966e..381a7e9aed6 100644 --- a/jdk/test/java/lang/Double/BitwiseConversion.java +++ b/jdk/test/java/lang/Double/BitwiseConversion.java @@ -25,21 +25,23 @@ * @test * @bug 5037596 * @summary Verify bitwise conversion works for non-canonical NaN values + * @library ../Math + * @build DoubleConsts + * @run main BitwiseConversion * @author Joseph D. Darcy */ import static java.lang.Double.*; -import static sun.misc.DoubleConsts.*; public class BitwiseConversion { static int testNanCase(long x) { int errors = 0; // Strip out sign and exponent bits - long y = x & SIGNIF_BIT_MASK; + long y = x & DoubleConsts.SIGNIF_BIT_MASK; double values[] = { - longBitsToDouble(EXP_BIT_MASK | y), - longBitsToDouble(SIGN_BIT_MASK | EXP_BIT_MASK | y) + longBitsToDouble(DoubleConsts.EXP_BIT_MASK | y), + longBitsToDouble(DoubleConsts.SIGN_BIT_MASK | DoubleConsts.EXP_BIT_MASK | y) }; for(double value: values) { @@ -60,7 +62,7 @@ public class BitwiseConversion { public static void main(String... argv) { int errors = 0; - for (int i = 0; i < SIGNIFICAND_WIDTH-1; i++) { + for (int i = 0; i < DoubleConsts.SIGNIFICAND_WIDTH-1; i++) { errors += testNanCase(1L< 710, expm1(x) should be infinity - for(int i = 10; i <= DoubleConsts.MAX_EXPONENT; i++) { + for(int i = 10; i <= Double.MAX_EXPONENT; i++) { double d = Math.scalb(2, i); failures += testExpm1Case(d, infinityD); } @@ -116,7 +114,7 @@ public class Expm1Tests { reachedLimit); } - for(int i = 7; i <= DoubleConsts.MAX_EXPONENT; i++) { + for(int i = 7; i <= Double.MAX_EXPONENT; i++) { double d = -Math.scalb(2, i); failures += testExpm1CaseWithUlpDiff(d, -1.0, 1, reachedLimit); } diff --git a/jdk/test/java/lang/Math/FloatConsts.java b/jdk/test/java/lang/Math/FloatConsts.java new file mode 100644 index 00000000000..626b19c9c4b --- /dev/null +++ b/jdk/test/java/lang/Math/FloatConsts.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, 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. + */ + +/** + * Common library for additional constants of the {@code float} type. + */ +public final class FloatConsts { + /** + * Don't let anyone instantiate this class. + */ + private FloatConsts() {} + + /** + * Bias used in representing a {@code float} exponent. + */ + public static final int EXP_BIAS = 127; + + /** + * Bit mask to isolate the exponent field of a {@code float}. + */ + public static final int EXP_BIT_MASK = 0x7F800000; + + /** + * Bit mask to isolate the sign bit of a {@code float}. + */ + public static final int SIGN_BIT_MASK = 0x80000000; + + /** + * Bit mask to isolate the significand field of a {@code float}. + */ + public static final int SIGNIF_BIT_MASK = 0x007FFFFF; + + /** + * The number of logical bits in the significand of a + * {@code float} number, including the implicit bit. + */ + public static final int SIGNIFICAND_WIDTH = 24; + + /** + * The exponent the smallest positive {@code float} subnormal + * value would have if it could be normalized. + */ + public static final int MIN_SUB_EXPONENT = Float.MIN_EXPONENT - + (SIGNIFICAND_WIDTH - 1); + + static { + // verify bit masks cover all bit positions and that the bit + // masks are non-overlapping + assert(((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK) == ~0) && + (((SIGN_BIT_MASK & EXP_BIT_MASK) == 0) && + ((SIGN_BIT_MASK & SIGNIF_BIT_MASK) == 0) && + ((EXP_BIT_MASK & SIGNIF_BIT_MASK) == 0))); + } +} diff --git a/jdk/test/java/lang/Math/HyperbolicTests.java b/jdk/test/java/lang/Math/HyperbolicTests.java index 8ff15ac151c..0df493698fe 100644 --- a/jdk/test/java/lang/Math/HyperbolicTests.java +++ b/jdk/test/java/lang/Math/HyperbolicTests.java @@ -28,8 +28,6 @@ * @author Joseph D. Darcy */ -import sun.misc.DoubleConsts; - public class HyperbolicTests { private HyperbolicTests(){} @@ -342,7 +340,7 @@ public class HyperbolicTests { // sinh(x) overflows for values greater than 710; in // particular, it overflows for all 2^i, i > 10. - for(int i = 10; i <= DoubleConsts.MAX_EXPONENT; i++) { + for(int i = 10; i <= Double.MAX_EXPONENT; i++) { double d = Math.scalb(2.0, i); // Result and expected are the same. @@ -701,7 +699,7 @@ public class HyperbolicTests { // cosh(x) overflows for values greater than 710; in // particular, it overflows for all 2^i, i > 10. - for(int i = 10; i <= DoubleConsts.MAX_EXPONENT; i++) { + for(int i = 10; i <= Double.MAX_EXPONENT; i++) { double d = Math.scalb(2.0, i); // Result and expected are the same. @@ -996,7 +994,7 @@ public class HyperbolicTests { failures += testTanhCaseWithUlpDiff(i, 1.0, 2.5); } - for(int i = 5; i <= DoubleConsts.MAX_EXPONENT; i++) { + for(int i = 5; i <= Double.MAX_EXPONENT; i++) { double d = Math.scalb(2.0, i); failures += testTanhCaseWithUlpDiff(d, 1.0, 2.5); diff --git a/jdk/test/java/lang/Math/HypotTests.java b/jdk/test/java/lang/Math/HypotTests.java index 9582c83daf8..1c1ff8c4d5d 100644 --- a/jdk/test/java/lang/Math/HypotTests.java +++ b/jdk/test/java/lang/Math/HypotTests.java @@ -28,8 +28,6 @@ * @author Joseph D. Darcy */ -import sun.misc.DoubleConsts; - public class HypotTests { private HypotTests(){} @@ -87,7 +85,7 @@ public class HypotTests { // Verify hypot(x, 0.0) is close to x over the entire exponent // range. for(int i = DoubleConsts.MIN_SUB_EXPONENT; - i <= DoubleConsts.MAX_EXPONENT; + i <= Double.MAX_EXPONENT; i++) { double input = Math.scalb(2, i); failures += testHypotCase(input, 0.0, input); @@ -125,7 +123,7 @@ public class HypotTests { for(int i = 0; i < 1000; i++) { double d = rand.nextDouble(); // Scale d to have an exponent equal to MAX_EXPONENT -15 - d = Math.scalb(d, DoubleConsts.MAX_EXPONENT + d = Math.scalb(d, Double.MAX_EXPONENT -15 - Tests.ilogb(d)); for(int j = 0; j <= 13; j += 1) { failures += testHypotCase(3*d, 4*d, 5*d, 2.5); diff --git a/jdk/test/java/lang/Math/IeeeRecommendedTests.java b/jdk/test/java/lang/Math/IeeeRecommendedTests.java index ce4c6595b4b..d1d28245850 100644 --- a/jdk/test/java/lang/Math/IeeeRecommendedTests.java +++ b/jdk/test/java/lang/Math/IeeeRecommendedTests.java @@ -28,9 +28,6 @@ * @author Joseph D. Darcy */ -import sun.misc.DoubleConsts; -import sun.misc.FloatConsts; - public class IeeeRecommendedTests { private IeeeRecommendedTests(){} @@ -54,7 +51,7 @@ public class IeeeRecommendedTests { * Returns a floating-point power of two in the normal range. */ static double powerOfTwoD(int n) { - return Double.longBitsToDouble((((long)n + (long)DoubleConsts.MAX_EXPONENT) << + return Double.longBitsToDouble((((long)n + (long)Double.MAX_EXPONENT) << (DoubleConsts.SIGNIFICAND_WIDTH-1)) & DoubleConsts.EXP_BIT_MASK); } @@ -63,7 +60,7 @@ public class IeeeRecommendedTests { * Returns a floating-point power of two in the normal range. */ static float powerOfTwoF(int n) { - return Float.intBitsToFloat(((n + FloatConsts.MAX_EXPONENT) << + return Float.intBitsToFloat(((n + Float.MAX_EXPONENT) << (FloatConsts.SIGNIFICAND_WIDTH-1)) & FloatConsts.EXP_BIT_MASK); } @@ -129,7 +126,7 @@ public class IeeeRecommendedTests { +16.0f, +Float.MIN_VALUE, +Float_MAX_SUBNORMAL, - +FloatConsts.MIN_NORMAL, + +Float.MIN_NORMAL, +Float.MAX_VALUE }; @@ -139,10 +136,10 @@ public class IeeeRecommendedTests { 0, 1, 4, - FloatConsts.MIN_EXPONENT - 1, - -FloatConsts.MAX_EXPONENT, - FloatConsts.MIN_EXPONENT, - FloatConsts.MAX_EXPONENT + Float.MIN_EXPONENT - 1, + -Float.MAX_EXPONENT, + Float.MIN_EXPONENT, + Float.MAX_EXPONENT }; // Special value tests @@ -152,7 +149,7 @@ public class IeeeRecommendedTests { // Normal exponent tests - for(int i = FloatConsts.MIN_EXPONENT; i <= FloatConsts.MAX_EXPONENT; i++) { + for(int i = Float.MIN_EXPONENT; i <= Float.MAX_EXPONENT; i++) { int result; // Create power of two @@ -175,7 +172,7 @@ public class IeeeRecommendedTests { failures += testGetExponentCase(randFloat, i); } - if (i > FloatConsts.MIN_EXPONENT) { + if (i > Float.MIN_EXPONENT) { float po2minus = Math.nextAfter(po2, Float.NEGATIVE_INFINITY); failures += testGetExponentCase(po2minus, i-1); @@ -199,13 +196,13 @@ public class IeeeRecommendedTests { i++, top *= 2.0f) { failures += testGetExponentCase(top, - FloatConsts.MIN_EXPONENT - 1); + Float.MIN_EXPONENT - 1); // Test largest value in next smaller binade if (i >= 3) {// (i == 1) would test 0.0; // (i == 2) would just retest MIN_VALUE testGetExponentCase(Math.nextAfter(top, 0.0f), - FloatConsts.MIN_EXPONENT - 1); + Float.MIN_EXPONENT - 1); if( i >= 10) { // create a bit mask with (i-1) 1's in the low order @@ -217,7 +214,7 @@ public class IeeeRecommendedTests { (rand.nextInt() & mask ) ) ; failures += testGetExponentCase(randFloat, - FloatConsts.MIN_EXPONENT - 1); + Float.MIN_EXPONENT - 1); } } } @@ -236,7 +233,7 @@ public class IeeeRecommendedTests { +16.0, +Double.MIN_VALUE, +Double_MAX_SUBNORMAL, - +DoubleConsts.MIN_NORMAL, + +Double.MIN_NORMAL, +Double.MAX_VALUE }; @@ -246,10 +243,10 @@ public class IeeeRecommendedTests { 0, 1, 4, - DoubleConsts.MIN_EXPONENT - 1, - -DoubleConsts.MAX_EXPONENT, - DoubleConsts.MIN_EXPONENT, - DoubleConsts.MAX_EXPONENT + Double.MIN_EXPONENT - 1, + -Double.MAX_EXPONENT, + Double.MIN_EXPONENT, + Double.MAX_EXPONENT }; // Special value tests @@ -259,7 +256,7 @@ public class IeeeRecommendedTests { // Normal exponent tests - for(int i = DoubleConsts.MIN_EXPONENT; i <= DoubleConsts.MAX_EXPONENT; i++) { + for(int i = Double.MIN_EXPONENT; i <= Double.MAX_EXPONENT; i++) { int result; // Create power of two @@ -282,7 +279,7 @@ public class IeeeRecommendedTests { failures += testGetExponentCase(randFloat, i); } - if (i > DoubleConsts.MIN_EXPONENT) { + if (i > Double.MIN_EXPONENT) { double po2minus = Math.nextAfter(po2, Double.NEGATIVE_INFINITY); failures += testGetExponentCase(po2minus, i-1); @@ -306,13 +303,13 @@ public class IeeeRecommendedTests { i++, top *= 2.0f) { failures += testGetExponentCase(top, - DoubleConsts.MIN_EXPONENT - 1); + Double.MIN_EXPONENT - 1); // Test largest value in next smaller binade if (i >= 3) {// (i == 1) would test 0.0; // (i == 2) would just retest MIN_VALUE testGetExponentCase(Math.nextAfter(top, 0.0), - DoubleConsts.MIN_EXPONENT - 1); + Double.MIN_EXPONENT - 1); if( i >= 10) { // create a bit mask with (i-1) 1's in the low order @@ -324,7 +321,7 @@ public class IeeeRecommendedTests { (rand.nextLong() & mask ) ) ; failures += testGetExponentCase(randFloat, - DoubleConsts.MIN_EXPONENT - 1); + Double.MIN_EXPONENT - 1); } } } @@ -400,15 +397,15 @@ public class IeeeRecommendedTests { {Float_MAX_VALUEmm, infinityF, Float.MAX_VALUE}, {Float_MAX_VALUEmm, Float_MAX_VALUEmm, Float_MAX_VALUEmm}, - {FloatConsts.MIN_NORMAL, infinityF, FloatConsts.MIN_NORMAL+ + {Float.MIN_NORMAL, infinityF, Float.MIN_NORMAL+ Float.MIN_VALUE}, - {FloatConsts.MIN_NORMAL, -infinityF, Float_MAX_SUBNORMAL}, - {FloatConsts.MIN_NORMAL, 1.0f, FloatConsts.MIN_NORMAL+ + {Float.MIN_NORMAL, -infinityF, Float_MAX_SUBNORMAL}, + {Float.MIN_NORMAL, 1.0f, Float.MIN_NORMAL+ Float.MIN_VALUE}, - {FloatConsts.MIN_NORMAL, -1.0f, Float_MAX_SUBNORMAL}, - {FloatConsts.MIN_NORMAL, FloatConsts.MIN_NORMAL, FloatConsts.MIN_NORMAL}, + {Float.MIN_NORMAL, -1.0f, Float_MAX_SUBNORMAL}, + {Float.MIN_NORMAL, Float.MIN_NORMAL, Float.MIN_NORMAL}, - {Float_MAX_SUBNORMAL, FloatConsts.MIN_NORMAL, FloatConsts.MIN_NORMAL}, + {Float_MAX_SUBNORMAL, Float.MIN_NORMAL, Float.MIN_NORMAL}, {Float_MAX_SUBNORMAL, Float_MAX_SUBNORMAL, Float_MAX_SUBNORMAL}, {Float_MAX_SUBNORMAL, 0.0f, Float_MAX_SUBNORMALmm}, @@ -472,15 +469,15 @@ public class IeeeRecommendedTests { {Double_MAX_VALUEmm, infinityD, Double.MAX_VALUE}, {Double_MAX_VALUEmm, Double_MAX_VALUEmm, Double_MAX_VALUEmm}, - {DoubleConsts.MIN_NORMAL, infinityD, DoubleConsts.MIN_NORMAL+ + {Double.MIN_NORMAL, infinityD, Double.MIN_NORMAL+ Double.MIN_VALUE}, - {DoubleConsts.MIN_NORMAL, -infinityD, Double_MAX_SUBNORMAL}, - {DoubleConsts.MIN_NORMAL, 1.0f, DoubleConsts.MIN_NORMAL+ + {Double.MIN_NORMAL, -infinityD, Double_MAX_SUBNORMAL}, + {Double.MIN_NORMAL, 1.0f, Double.MIN_NORMAL+ Double.MIN_VALUE}, - {DoubleConsts.MIN_NORMAL, -1.0f, Double_MAX_SUBNORMAL}, - {DoubleConsts.MIN_NORMAL, DoubleConsts.MIN_NORMAL,DoubleConsts.MIN_NORMAL}, + {Double.MIN_NORMAL, -1.0f, Double_MAX_SUBNORMAL}, + {Double.MIN_NORMAL, Double.MIN_NORMAL, Double.MIN_NORMAL}, - {Double_MAX_SUBNORMAL, DoubleConsts.MIN_NORMAL,DoubleConsts.MIN_NORMAL}, + {Double_MAX_SUBNORMAL, Double.MIN_NORMAL, Double.MIN_NORMAL}, {Double_MAX_SUBNORMAL, Double_MAX_SUBNORMAL, Double_MAX_SUBNORMAL}, {Double_MAX_SUBNORMAL, 0.0d, Double_MAX_SUBNORMALmm}, @@ -529,15 +526,15 @@ public class IeeeRecommendedTests { {NaNf, NaNf}, {-infinityF, -Float.MAX_VALUE}, {-Float.MAX_VALUE, -Float_MAX_VALUEmm}, - {-FloatConsts.MIN_NORMAL, -Float_MAX_SUBNORMAL}, + {-Float.MIN_NORMAL, -Float_MAX_SUBNORMAL}, {-Float_MAX_SUBNORMAL, -Float_MAX_SUBNORMALmm}, {-Float.MIN_VALUE, -0.0f}, {-0.0f, Float.MIN_VALUE}, {+0.0f, Float.MIN_VALUE}, {Float.MIN_VALUE, Float.MIN_VALUE*2}, {Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMAL}, - {Float_MAX_SUBNORMAL, FloatConsts.MIN_NORMAL}, - {FloatConsts.MIN_NORMAL, FloatConsts.MIN_NORMAL+Float.MIN_VALUE}, + {Float_MAX_SUBNORMAL, Float.MIN_NORMAL}, + {Float.MIN_NORMAL, Float.MIN_NORMAL+Float.MIN_VALUE}, {Float_MAX_VALUEmm, Float.MAX_VALUE}, {Float.MAX_VALUE, infinityF}, {infinityF, infinityF} @@ -567,15 +564,15 @@ public class IeeeRecommendedTests { {NaNd, NaNd}, {-infinityD, -Double.MAX_VALUE}, {-Double.MAX_VALUE, -Double_MAX_VALUEmm}, - {-DoubleConsts.MIN_NORMAL, -Double_MAX_SUBNORMAL}, + {-Double.MIN_NORMAL, -Double_MAX_SUBNORMAL}, {-Double_MAX_SUBNORMAL, -Double_MAX_SUBNORMALmm}, {-Double.MIN_VALUE, -0.0d}, {-0.0d, Double.MIN_VALUE}, {+0.0d, Double.MIN_VALUE}, {Double.MIN_VALUE, Double.MIN_VALUE*2}, {Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMAL}, - {Double_MAX_SUBNORMAL, DoubleConsts.MIN_NORMAL}, - {DoubleConsts.MIN_NORMAL, DoubleConsts.MIN_NORMAL+Double.MIN_VALUE}, + {Double_MAX_SUBNORMAL, Double.MIN_NORMAL}, + {Double.MIN_NORMAL, Double.MIN_NORMAL+Double.MIN_VALUE}, {Double_MAX_VALUEmm, Double.MAX_VALUE}, {Double.MAX_VALUE, infinityD}, {infinityD, infinityD} @@ -607,16 +604,16 @@ public class IeeeRecommendedTests { {-infinityF, -infinityF}, {-Float.MAX_VALUE, -infinityF}, {-Float_MAX_VALUEmm, -Float.MAX_VALUE}, - {-Float_MAX_SUBNORMAL, -FloatConsts.MIN_NORMAL}, + {-Float_MAX_SUBNORMAL, -Float.MIN_NORMAL}, {-Float_MAX_SUBNORMALmm, -Float_MAX_SUBNORMAL}, {-0.0f, -Float.MIN_VALUE}, {+0.0f, -Float.MIN_VALUE}, {Float.MIN_VALUE, 0.0f}, {Float.MIN_VALUE*2, Float.MIN_VALUE}, {Float_MAX_SUBNORMAL, Float_MAX_SUBNORMALmm}, - {FloatConsts.MIN_NORMAL, Float_MAX_SUBNORMAL}, - {FloatConsts.MIN_NORMAL+ - Float.MIN_VALUE, FloatConsts.MIN_NORMAL}, + {Float.MIN_NORMAL, Float_MAX_SUBNORMAL}, + {Float.MIN_NORMAL+ + Float.MIN_VALUE, Float.MIN_NORMAL}, {Float.MAX_VALUE, Float_MAX_VALUEmm}, {infinityF, Float.MAX_VALUE}, }; @@ -646,16 +643,16 @@ public class IeeeRecommendedTests { {-infinityD, -infinityD}, {-Double.MAX_VALUE, -infinityD}, {-Double_MAX_VALUEmm, -Double.MAX_VALUE}, - {-Double_MAX_SUBNORMAL, -DoubleConsts.MIN_NORMAL}, + {-Double_MAX_SUBNORMAL, -Double.MIN_NORMAL}, {-Double_MAX_SUBNORMALmm, -Double_MAX_SUBNORMAL}, {-0.0d, -Double.MIN_VALUE}, {+0.0d, -Double.MIN_VALUE}, {Double.MIN_VALUE, 0.0d}, {Double.MIN_VALUE*2, Double.MIN_VALUE}, {Double_MAX_SUBNORMAL, Double_MAX_SUBNORMALmm}, - {DoubleConsts.MIN_NORMAL, Double_MAX_SUBNORMAL}, - {DoubleConsts.MIN_NORMAL+ - Double.MIN_VALUE, DoubleConsts.MIN_NORMAL}, + {Double.MIN_NORMAL, Double_MAX_SUBNORMAL}, + {Double.MIN_NORMAL+ + Double.MIN_VALUE, Double.MIN_NORMAL}, {Double.MAX_VALUE, Double_MAX_VALUEmm}, {infinityD, Double.MAX_VALUE}, }; @@ -689,7 +686,7 @@ public class IeeeRecommendedTests { -Float.MAX_VALUE, -3.0f, -1.0f, - -FloatConsts.MIN_NORMAL, + -Float.MIN_NORMAL, -Float_MAX_SUBNORMALmm, -Float_MAX_SUBNORMAL, -Float.MIN_VALUE, @@ -698,7 +695,7 @@ public class IeeeRecommendedTests { Float.MIN_VALUE, Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMAL, - FloatConsts.MIN_NORMAL, + Float.MIN_NORMAL, 1.0f, 3.0f, Float_MAX_VALUEmm, @@ -739,7 +736,7 @@ public class IeeeRecommendedTests { -Double.MAX_VALUE, -3.0d, -1.0d, - -DoubleConsts.MIN_NORMAL, + -Double.MIN_NORMAL, -Double_MAX_SUBNORMALmm, -Double_MAX_SUBNORMAL, -Double.MIN_VALUE, @@ -748,7 +745,7 @@ public class IeeeRecommendedTests { Double.MIN_VALUE, Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMAL, - DoubleConsts.MIN_NORMAL, + Double.MIN_NORMAL, 1.0d, 3.0d, Double_MAX_VALUEmm, @@ -790,7 +787,7 @@ public class IeeeRecommendedTests { Float.MIN_VALUE, Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMAL, - FloatConsts.MIN_NORMAL, + Float.MIN_NORMAL, 1.0f, 3.0f, Float_MAX_VALUEmm, @@ -801,7 +798,7 @@ public class IeeeRecommendedTests { -Float.MAX_VALUE, -3.0f, -1.0f, - -FloatConsts.MIN_NORMAL, + -Float.MIN_NORMAL, -Float_MAX_SUBNORMALmm, -Float_MAX_SUBNORMAL, -Float.MIN_VALUE, @@ -864,7 +861,7 @@ public class IeeeRecommendedTests { Double.MIN_VALUE, Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMAL, - DoubleConsts.MIN_NORMAL, + Double.MIN_NORMAL, 1.0d, 3.0d, Double_MAX_VALUEmm, @@ -875,7 +872,7 @@ public class IeeeRecommendedTests { -Double.MAX_VALUE, -3.0d, -1.0d, - -DoubleConsts.MIN_NORMAL, + -Double.MIN_NORMAL, -Double_MAX_SUBNORMALmm, -Double_MAX_SUBNORMAL, -Double.MIN_VALUE, @@ -964,7 +961,7 @@ public class IeeeRecommendedTests { public static int testFloatScalb() { int failures=0; - int MAX_SCALE = FloatConsts.MAX_EXPONENT + -FloatConsts.MIN_EXPONENT + + int MAX_SCALE = Float.MAX_EXPONENT + -Float.MIN_EXPONENT + FloatConsts.SIGNIFICAND_WIDTH + 1; @@ -988,7 +985,7 @@ public class IeeeRecommendedTests { 3.0f*Float.MIN_VALUE, Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMAL, - FloatConsts.MIN_NORMAL, + Float.MIN_NORMAL, 1.0f, 2.0f, 3.0f, @@ -998,8 +995,8 @@ public class IeeeRecommendedTests { }; int [] oneMultiplyScalingFactors = { - FloatConsts.MIN_EXPONENT, - FloatConsts.MIN_EXPONENT+1, + Float.MIN_EXPONENT, + Float.MIN_EXPONENT+1, -3, -2, -1, @@ -1007,8 +1004,8 @@ public class IeeeRecommendedTests { 1, 2, 3, - FloatConsts.MAX_EXPONENT-1, - FloatConsts.MAX_EXPONENT + Float.MAX_EXPONENT-1, + Float.MAX_EXPONENT }; int [] manyScalingFactors = { @@ -1018,14 +1015,14 @@ public class IeeeRecommendedTests { -MAX_SCALE, -MAX_SCALE+1, - 2*FloatConsts.MIN_EXPONENT-1, // -253 - 2*FloatConsts.MIN_EXPONENT, // -252 - 2*FloatConsts.MIN_EXPONENT+1, // -251 + 2*Float.MIN_EXPONENT-1, // -253 + 2*Float.MIN_EXPONENT, // -252 + 2*Float.MIN_EXPONENT+1, // -251 - FloatConsts.MIN_EXPONENT - FloatConsts.SIGNIFICAND_WIDTH, + Float.MIN_EXPONENT - FloatConsts.SIGNIFICAND_WIDTH, FloatConsts.MIN_SUB_EXPONENT, - -FloatConsts.MAX_EXPONENT, // -127 - FloatConsts.MIN_EXPONENT, // -126 + -Float.MAX_EXPONENT, // -127 + Float.MIN_EXPONENT, // -126 -2, -1, @@ -1033,13 +1030,13 @@ public class IeeeRecommendedTests { 1, 2, - FloatConsts.MAX_EXPONENT-1, // 126 - FloatConsts.MAX_EXPONENT, // 127 - FloatConsts.MAX_EXPONENT+1, // 128 + Float.MAX_EXPONENT-1, // 126 + Float.MAX_EXPONENT, // 127 + Float.MAX_EXPONENT+1, // 128 - 2*FloatConsts.MAX_EXPONENT-1, // 253 - 2*FloatConsts.MAX_EXPONENT, // 254 - 2*FloatConsts.MAX_EXPONENT+1, // 255 + 2*Float.MAX_EXPONENT-1, // 253 + 2*Float.MAX_EXPONENT, // 254 + 2*Float.MAX_EXPONENT+1, // 255 MAX_SCALE-1, MAX_SCALE, @@ -1086,7 +1083,7 @@ public class IeeeRecommendedTests { // Create 2^MAX_EXPONENT float twoToTheMaxExp = 1.0f; // 2^0 - for(int i = 0; i < FloatConsts.MAX_EXPONENT; i++) + for(int i = 0; i < Float.MAX_EXPONENT; i++) twoToTheMaxExp *=2.0f; // Scale-up subnormal values until they all overflow @@ -1094,12 +1091,12 @@ public class IeeeRecommendedTests { float scale = 1.0f; // 2^j float value = subnormalTestCases[i]; - for(int j=FloatConsts.MAX_EXPONENT*2; j < MAX_SCALE; j++) { // MAX_SCALE -1 should cause overflow + for(int j=Float.MAX_EXPONENT*2; j < MAX_SCALE; j++) { // MAX_SCALE -1 should cause overflow int scaleFactor = j; failures+=testScalbCase(value, scaleFactor, - (Tests.ilogb(value) +j > FloatConsts.MAX_EXPONENT ) ? + (Tests.ilogb(value) +j > Float.MAX_EXPONENT ) ? Math.copySign(infinityF, value) : // overflow // calculate right answer twoToTheMaxExp*(twoToTheMaxExp*(scale*value)) ); @@ -1172,7 +1169,7 @@ public class IeeeRecommendedTests { public static int testDoubleScalb() { int failures=0; - int MAX_SCALE = DoubleConsts.MAX_EXPONENT + -DoubleConsts.MIN_EXPONENT + + int MAX_SCALE = Double.MAX_EXPONENT + -Double.MIN_EXPONENT + DoubleConsts.SIGNIFICAND_WIDTH + 1; @@ -1195,7 +1192,7 @@ public class IeeeRecommendedTests { 3.0d*Double.MIN_VALUE, Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMAL, - DoubleConsts.MIN_NORMAL, + Double.MIN_NORMAL, 1.0d, 2.0d, 3.0d, @@ -1205,8 +1202,8 @@ public class IeeeRecommendedTests { }; int [] oneMultiplyScalingFactors = { - DoubleConsts.MIN_EXPONENT, - DoubleConsts.MIN_EXPONENT+1, + Double.MIN_EXPONENT, + Double.MIN_EXPONENT+1, -3, -2, -1, @@ -1214,8 +1211,8 @@ public class IeeeRecommendedTests { 1, 2, 3, - DoubleConsts.MAX_EXPONENT-1, - DoubleConsts.MAX_EXPONENT + Double.MAX_EXPONENT-1, + Double.MAX_EXPONENT }; int [] manyScalingFactors = { @@ -1225,15 +1222,15 @@ public class IeeeRecommendedTests { -MAX_SCALE, -MAX_SCALE+1, - 2*DoubleConsts.MIN_EXPONENT-1, // -2045 - 2*DoubleConsts.MIN_EXPONENT, // -2044 - 2*DoubleConsts.MIN_EXPONENT+1, // -2043 + 2*Double.MIN_EXPONENT-1, // -2045 + 2*Double.MIN_EXPONENT, // -2044 + 2*Double.MIN_EXPONENT+1, // -2043 - DoubleConsts.MIN_EXPONENT, // -1022 - DoubleConsts.MIN_EXPONENT - DoubleConsts.SIGNIFICAND_WIDTH, + Double.MIN_EXPONENT, // -1022 + Double.MIN_EXPONENT - DoubleConsts.SIGNIFICAND_WIDTH, DoubleConsts.MIN_SUB_EXPONENT, - -DoubleConsts.MAX_EXPONENT, // -1023 - DoubleConsts.MIN_EXPONENT, // -1022 + -Double.MAX_EXPONENT, // -1023 + Double.MIN_EXPONENT, // -1022 -2, -1, @@ -1241,13 +1238,13 @@ public class IeeeRecommendedTests { 1, 2, - DoubleConsts.MAX_EXPONENT-1, // 1022 - DoubleConsts.MAX_EXPONENT, // 1023 - DoubleConsts.MAX_EXPONENT+1, // 1024 + Double.MAX_EXPONENT-1, // 1022 + Double.MAX_EXPONENT, // 1023 + Double.MAX_EXPONENT+1, // 1024 - 2*DoubleConsts.MAX_EXPONENT-1, // 2045 - 2*DoubleConsts.MAX_EXPONENT, // 2046 - 2*DoubleConsts.MAX_EXPONENT+1, // 2047 + 2*Double.MAX_EXPONENT-1, // 2045 + 2*Double.MAX_EXPONENT, // 2046 + 2*Double.MAX_EXPONENT+1, // 2047 MAX_SCALE-1, MAX_SCALE, @@ -1294,7 +1291,7 @@ public class IeeeRecommendedTests { // Create 2^MAX_EXPONENT double twoToTheMaxExp = 1.0; // 2^0 - for(int i = 0; i < DoubleConsts.MAX_EXPONENT; i++) + for(int i = 0; i < Double.MAX_EXPONENT; i++) twoToTheMaxExp *=2.0; // Scale-up subnormal values until they all overflow @@ -1302,12 +1299,12 @@ public class IeeeRecommendedTests { double scale = 1.0; // 2^j double value = subnormalTestCases[i]; - for(int j=DoubleConsts.MAX_EXPONENT*2; j < MAX_SCALE; j++) { // MAX_SCALE -1 should cause overflow + for(int j=Double.MAX_EXPONENT*2; j < MAX_SCALE; j++) { // MAX_SCALE -1 should cause overflow int scaleFactor = j; failures+=testScalbCase(value, scaleFactor, - (Tests.ilogb(value) +j > DoubleConsts.MAX_EXPONENT ) ? + (Tests.ilogb(value) +j > Double.MAX_EXPONENT ) ? Math.copySign(infinityD, value) : // overflow // calculate right answer twoToTheMaxExp*(twoToTheMaxExp*(scale*value)) ); @@ -1345,7 +1342,7 @@ public class IeeeRecommendedTests { double value = 0x1.000000000000bP-1; expected = 0x0.2000000000001P-1022; - for(int i = 0; i < DoubleConsts.MAX_EXPONENT+2; i++) { + for(int i = 0; i < Double.MAX_EXPONENT+2; i++) { failures+=testScalbCase(value, -1024-i, expected); @@ -1401,7 +1398,7 @@ public class IeeeRecommendedTests { +16.0f, +Float.MIN_VALUE, +Float_MAX_SUBNORMAL, - +FloatConsts.MIN_NORMAL, + +Float.MIN_NORMAL, +Float.MAX_VALUE }; @@ -1424,7 +1421,7 @@ public class IeeeRecommendedTests { // Normal exponent tests - for(int i = FloatConsts.MIN_EXPONENT; i <= FloatConsts.MAX_EXPONENT; i++) { + for(int i = Float.MIN_EXPONENT; i <= Float.MAX_EXPONENT; i++) { float expected; // Create power of two @@ -1448,7 +1445,7 @@ public class IeeeRecommendedTests { failures += testUlpCase(randFloat, expected); } - if (i > FloatConsts.MIN_EXPONENT) { + if (i > Float.MIN_EXPONENT) { float po2minus = Math.nextAfter(po2, Float.NEGATIVE_INFINITY); failures += testUlpCase(po2minus, expected/2.0f); @@ -1506,7 +1503,7 @@ public class IeeeRecommendedTests { +16.0d, +Double.MIN_VALUE, +Double_MAX_SUBNORMAL, - +DoubleConsts.MIN_NORMAL, + +Double.MIN_NORMAL, +Double.MAX_VALUE }; @@ -1529,7 +1526,7 @@ public class IeeeRecommendedTests { // Normal exponent tests - for(int i = DoubleConsts.MIN_EXPONENT; i <= DoubleConsts.MAX_EXPONENT; i++) { + for(int i = Double.MIN_EXPONENT; i <= Double.MAX_EXPONENT; i++) { double expected; // Create power of two @@ -1553,7 +1550,7 @@ public class IeeeRecommendedTests { failures += testUlpCase(randDouble, expected); } - if (i > DoubleConsts.MIN_EXPONENT) { + if (i > Double.MIN_EXPONENT) { double po2minus = Math.nextAfter(po2, Double.NEGATIVE_INFINITY); failures += testUlpCase(po2minus, expected/2.0f); @@ -1607,7 +1604,7 @@ public class IeeeRecommendedTests { {NaNf, NaNf}, {-infinityF, -1.0f}, {-Float.MAX_VALUE, -1.0f}, - {-FloatConsts.MIN_NORMAL, -1.0f}, + {-Float.MIN_NORMAL, -1.0f}, {-1.0f, -1.0f}, {-2.0f, -1.0f}, {-Float_MAX_SUBNORMAL, -1.0f}, @@ -1617,7 +1614,7 @@ public class IeeeRecommendedTests { {Float.MIN_VALUE, 1.0f}, {Float_MAX_SUBNORMALmm, 1.0f}, {Float_MAX_SUBNORMAL, 1.0f}, - {FloatConsts.MIN_NORMAL, 1.0f}, + {Float.MIN_NORMAL, 1.0f}, {1.0f, 1.0f}, {2.0f, 1.0f}, {Float_MAX_VALUEmm, 1.0f}, @@ -1641,7 +1638,7 @@ public class IeeeRecommendedTests { {NaNd, NaNd}, {-infinityD, -1.0}, {-Double.MAX_VALUE, -1.0}, - {-DoubleConsts.MIN_NORMAL, -1.0}, + {-Double.MIN_NORMAL, -1.0}, {-1.0, -1.0}, {-2.0, -1.0}, {-Double_MAX_SUBNORMAL, -1.0}, @@ -1651,7 +1648,7 @@ public class IeeeRecommendedTests { {Double.MIN_VALUE, 1.0}, {Double_MAX_SUBNORMALmm, 1.0}, {Double_MAX_SUBNORMAL, 1.0}, - {DoubleConsts.MIN_NORMAL, 1.0}, + {Double.MIN_NORMAL, 1.0}, {1.0, 1.0}, {2.0, 1.0}, {Double_MAX_VALUEmm, 1.0}, diff --git a/jdk/test/java/lang/Math/Log10Tests.java b/jdk/test/java/lang/Math/Log10Tests.java index e5484d11d90..7bc75644f2b 100644 --- a/jdk/test/java/lang/Math/Log10Tests.java +++ b/jdk/test/java/lang/Math/Log10Tests.java @@ -28,8 +28,6 @@ * @author Joseph D. Darcy */ -import sun.misc.DoubleConsts; - public class Log10Tests { private Log10Tests(){} @@ -70,7 +68,7 @@ public class Log10Tests { {Double.NEGATIVE_INFINITY, NaNd}, {-8.0, NaNd}, {-1.0, NaNd}, - {-DoubleConsts.MIN_NORMAL, NaNd}, + {-Double.MIN_NORMAL, NaNd}, {-Double.MIN_VALUE, NaNd}, {-0.0, -infinityD}, {+0.0, -infinityD}, diff --git a/jdk/test/java/lang/Math/Log1pTests.java b/jdk/test/java/lang/Math/Log1pTests.java index 5fe373edc78..eb4e8800224 100644 --- a/jdk/test/java/lang/Math/Log1pTests.java +++ b/jdk/test/java/lang/Math/Log1pTests.java @@ -28,8 +28,6 @@ * @author Joseph D. Darcy */ -import sun.misc.DoubleConsts; - public class Log1pTests { private Log1pTests(){} @@ -93,7 +91,7 @@ public class Log1pTests { } // For x > 2^53 log1p(x) ~= log(x) - for(int i = 53; i <= DoubleConsts.MAX_EXPONENT; i++) { + for(int i = 53; i <= Double.MAX_EXPONENT; i++) { double d = Math.scalb(2, i); failures += testLog1pCaseWithUlpDiff(d, StrictMath.log(d), 2.001); } diff --git a/jdk/test/java/lang/Math/Rint.java b/jdk/test/java/lang/Math/Rint.java index c362c4f9016..53e4d26b131 100644 --- a/jdk/test/java/lang/Math/Rint.java +++ b/jdk/test/java/lang/Math/Rint.java @@ -27,8 +27,6 @@ * @summary Check for correct implementation of Math.rint(double) */ -import sun.misc.DoubleConsts; - public class Rint { static int testRintCase(double input, double expected) { @@ -51,8 +49,8 @@ public class Rint { double [][] testCases = { {0.0, 0.0}, {Double.MIN_VALUE, 0.0}, - {Math.nextDown(DoubleConsts.MIN_NORMAL), 0.0}, - {DoubleConsts.MIN_NORMAL, 0.0}, + {Math.nextDown(Double.MIN_NORMAL), 0.0}, + {Double.MIN_NORMAL, 0.0}, {0.2, 0.0}, diff --git a/jdk/test/java/lang/Math/Tests.java b/jdk/test/java/lang/Math/Tests.java index 6148467bea5..b74086b9f5b 100644 --- a/jdk/test/java/lang/Math/Tests.java +++ b/jdk/test/java/lang/Math/Tests.java @@ -30,9 +30,6 @@ * and finally the expected result. */ -import sun.misc.FloatConsts; -import sun.misc.DoubleConsts; - public class Tests { private Tests(){}; // do not instantiate @@ -81,13 +78,13 @@ public class Tests { int exponent = Math.getExponent(d); switch (exponent) { - case DoubleConsts.MAX_EXPONENT+1: // NaN or infinity + case Double.MAX_EXPONENT+1: // NaN or infinity if( Double.isNaN(d) ) return (1<<30); // 2^30 else // infinite value return (1<<28); // 2^28 - case DoubleConsts.MIN_EXPONENT-1: // zero or subnormal + case Double.MIN_EXPONENT-1: // zero or subnormal if(d == 0.0) { return -(1<<28); // -(2^28) } @@ -117,14 +114,14 @@ public class Tests { } exponent++; assert( exponent >= - DoubleConsts.MIN_EXPONENT - (DoubleConsts.SIGNIFICAND_WIDTH-1) && - exponent < DoubleConsts.MIN_EXPONENT); + Double.MIN_EXPONENT - (DoubleConsts.SIGNIFICAND_WIDTH-1) && + exponent < Double.MIN_EXPONENT); return exponent; } default: - assert( exponent >= DoubleConsts.MIN_EXPONENT && - exponent <= DoubleConsts.MAX_EXPONENT); + assert( exponent >= Double.MIN_EXPONENT && + exponent <= Double.MAX_EXPONENT); return exponent; } } @@ -150,13 +147,13 @@ public class Tests { int exponent = Math.getExponent(f); switch (exponent) { - case FloatConsts.MAX_EXPONENT+1: // NaN or infinity + case Float.MAX_EXPONENT+1: // NaN or infinity if( Float.isNaN(f) ) return (1<<30); // 2^30 else // infinite value return (1<<28); // 2^28 - case FloatConsts.MIN_EXPONENT-1: // zero or subnormal + case Float.MIN_EXPONENT-1: // zero or subnormal if(f == 0.0f) { return -(1<<28); // -(2^28) } @@ -186,14 +183,14 @@ public class Tests { } exponent++; assert( exponent >= - FloatConsts.MIN_EXPONENT - (FloatConsts.SIGNIFICAND_WIDTH-1) && - exponent < FloatConsts.MIN_EXPONENT); + Float.MIN_EXPONENT - (FloatConsts.SIGNIFICAND_WIDTH-1) && + exponent < Float.MIN_EXPONENT); return exponent; } default: - assert( exponent >= FloatConsts.MIN_EXPONENT && - exponent <= FloatConsts.MAX_EXPONENT); + assert( exponent >= Float.MIN_EXPONENT && + exponent <= Float.MAX_EXPONENT); return exponent; } } diff --git a/jdk/test/java/lang/ProcessBuilder/InheritIO/InheritIO.sh b/jdk/test/java/lang/ProcessBuilder/InheritIO/InheritIO.sh index 2b33a037296..a8cfa51f3dd 100644 --- a/jdk/test/java/lang/ProcessBuilder/InheritIO/InheritIO.sh +++ b/jdk/test/java/lang/ProcessBuilder/InheritIO/InheritIO.sh @@ -36,9 +36,12 @@ if [ "x${TESTJAVA}" = "x" ]; then exit 1 fi +if [ "x${COMPILEJAVA}" = "x" ]; then + COMPILEJAVA="${TESTJAVA}" +fi JAVA="${TESTJAVA}/bin/java" -JAVAC="${TESTJAVA}/bin/javac" +JAVAC="${COMPILEJAVA}/bin/javac" cp -f ${TESTSRC}/InheritIO.java . diff --git a/jdk/test/java/lang/instrument/MakeJAR2.sh b/jdk/test/java/lang/instrument/MakeJAR2.sh index 062abe41444..596a0d47ed1 100644 --- a/jdk/test/java/lang/instrument/MakeJAR2.sh +++ b/jdk/test/java/lang/instrument/MakeJAR2.sh @@ -75,9 +75,9 @@ JAR="${COMPILEJAVA}/bin/jar" cp ${TESTSRC}/${AGENT}.java . cp ${TESTSRC}/${APP}.java . -rm -rf ilib -mkdir ilib -cp ${TESTSRC}/ilib/*.java ilib +rm -rf asmlib +mkdir asmlib +cp ${TESTSRC}/asmlib/*.java asmlib rm -rf bootpath mkdir -p bootpath/bootreporter cp ${TESTSRC}/bootreporter/*.java bootpath/bootreporter @@ -86,7 +86,7 @@ cd bootpath ${JAVAC} ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} bootreporter/*.java cd .. -${JAVAC} ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${AGENT}.java ilib/*.java +${JAVAC} ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -XDignore.symbol.file ${AGENT}.java asmlib/*.java ${JAVAC} ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -classpath .${PATHSEP}bootpath ${APP}.java echo "Manifest-Version: 1.0" > ${AGENT}.mf @@ -98,6 +98,6 @@ while [ $# != 0 ] ; do shift done -${JAR} ${TESTTOOLVMOPTS} cvfm ${AGENT}.jar ${AGENT}.mf ${AGENT}*.class ilib/*.class +${JAR} ${TESTTOOLVMOPTS} cvfm ${AGENT}.jar ${AGENT}.mf ${AGENT}*.class asmlib/*.class -# rm -rf ${AGENT}.java ilib ${AGENT}.mf ${AGENT}*.class +# rm -rf ${AGENT}.java asmlib ${AGENT}.mf ${AGENT}*.class diff --git a/jdk/test/java/lang/instrument/NMTHelper.java b/jdk/test/java/lang/instrument/NMTHelper.java index c5843f8f49b..ee5d1e1b882 100644 --- a/jdk/test/java/lang/instrument/NMTHelper.java +++ b/jdk/test/java/lang/instrument/NMTHelper.java @@ -21,8 +21,12 @@ * questions. */ +import java.io.File; +import java.io.FileWriter; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.Arrays; +import java.util.stream.Collectors; import sun.management.ManagementFactoryHelper; import com.sun.management.DiagnosticCommandMBean; @@ -53,14 +57,14 @@ public class NMTHelper Object[] dcmdArgs = {args}; String[] signature = {String[].class.getName()}; - try { - System.out.print("> " + cmd + " "); - for (String s : args) { - System.out.print(s + " "); - } - System.out.println(":"); + String cmdString = cmd + " " + + Arrays.stream(args).collect(Collectors.joining(" ")); + File f = new File("dcmdoutput-" + cmd + "-" + System.currentTimeMillis() + ".txt"); + System.out.println("Output from Dcmd '" + cmdString + "' is being written to file " + f); + try (FileWriter fw = new FileWriter(f)) { + fw.write("> " + cmdString + ":"); String result = (String) dcmd.invoke(cmd, dcmdArgs, signature); - System.out.println(result); + fw.write(result); return result; } catch(Exception ex) { ex.printStackTrace(); diff --git a/jdk/test/java/lang/instrument/NativeMethodPrefixAgent.java b/jdk/test/java/lang/instrument/NativeMethodPrefixAgent.java index 5bc34e46c15..1a51a8b4953 100644 --- a/jdk/test/java/lang/instrument/NativeMethodPrefixAgent.java +++ b/jdk/test/java/lang/instrument/NativeMethodPrefixAgent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, 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 @@ -35,7 +35,7 @@ import java.lang.instrument.*; import java.security.ProtectionDomain; import java.io.*; -import ilib.*; +import asmlib.*; class NativeMethodPrefixAgent { @@ -62,14 +62,25 @@ class NativeMethodPrefixAgent { System.out.println(trname + ": " + (redef? "Retransforming " : "Loading ") + className); if (className != null) { - Options opt = new Options(); - opt.shouldInstrumentNativeMethods = true; - opt.trackerClassName = "bootreporter/StringIdCallbackReporter"; - opt.wrappedTrackerMethodName = "tracker"; - opt.fixedIndex = transformId; - opt.wrappedPrefix = "wrapped_" + trname + "_"; try { - byte[] newcf = Inject.instrumentation(opt, loader, className, classfileBuffer); + byte[] newcf = Instrumentor.instrFor(classfileBuffer) + .addNativeMethodTrackingInjection( + "wrapped_" + trname + "_", + (h)->{ + h.push(h.getName()); + h.push(transformId); + h.invokeStatic("bootreporter/StringIdCallbackReporter", "tracker", "(Ljava/lang/String;I)V", false); + }) + .apply(); + /*** debugging ... + if (newcf != null) { + String fname = trname + (redef?"_redef" : "") + "/" + className; + System.err.println("dumping to: " + fname); + write_buffer(fname + "_before.class", classfileBuffer); + write_buffer(fname + "_instr.class", newcf); + } + ***/ + return redef? null : newcf; } catch (Throwable ex) { System.err.println("ERROR: Injection failure: " + ex); @@ -86,10 +97,14 @@ class NativeMethodPrefixAgent { // for debugging static void write_buffer(String fname, byte[]buffer) { try { - FileOutputStream outStream = new FileOutputStream(fname); - outStream.write(buffer, 0, buffer.length); - outStream.close(); - } catch (Exception ex) { + File f = new File(fname); + if (!f.getParentFile().exists()) { + f.getParentFile().mkdirs(); + } + try (FileOutputStream outStream = new FileOutputStream(f)) { + outStream.write(buffer, 0, buffer.length); + } + } catch (IOException ex) { System.err.println("EXCEPTION in write_buffer: " + ex); } } diff --git a/jdk/test/java/lang/instrument/RedefineBigClass.sh b/jdk/test/java/lang/instrument/RedefineBigClass.sh index 82cfd4c9f18..e5c84e7353a 100644 --- a/jdk/test/java/lang/instrument/RedefineBigClass.sh +++ b/jdk/test/java/lang/instrument/RedefineBigClass.sh @@ -27,7 +27,7 @@ # @author Daniel D. Daugherty # # @run shell MakeJAR3.sh RedefineBigClassAgent 'Can-Redefine-Classes: true' -# @run build BigClass RedefineBigClassApp +# @run build BigClass RedefineBigClassApp NMTHelper # @run shell/timeout=600 RedefineBigClass.sh # diff --git a/jdk/test/java/lang/instrument/RetransformAgent.java b/jdk/test/java/lang/instrument/RetransformAgent.java index 34b301b16c8..99d2bc089ed 100644 --- a/jdk/test/java/lang/instrument/RetransformAgent.java +++ b/jdk/test/java/lang/instrument/RetransformAgent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, 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 @@ -34,8 +34,7 @@ import java.lang.instrument.*; import java.security.ProtectionDomain; import java.io.*; - -import ilib.*; +import asmlib.*; class RetransformAgent { @@ -75,20 +74,25 @@ class RetransformAgent { // System.err.println("hook " + trname + ": " + className + // (redef? " REDEF" : " LOAD")); if ((redef? onRedef : onLoad) && className != null && className.equals(cname)) { - Options opt = new Options(); - opt.shouldInstrumentIndexed = true; - opt.shouldInstrumentCall = true; - opt.targetMethod = nname; - opt.fixedIndex = redef? redefIndex : loadIndex; - opt.trackerClassName = "RetransformAgent"; + int fixedIndex = redef ? redefIndex : loadIndex; try { - byte[] newcf = Inject.instrumentation(opt, loader, className, classfileBuffer); + byte[] newcf = Instrumentor.instrFor(classfileBuffer) + .addMethodEntryInjection( + nname, + (h)->{ + h.push(fixedIndex); + h.invokeStatic("RetransformAgent", "callTracker", "(I)V", false); + }) + .apply(); /*** debugging ... - String fname = trname + (redef?"_redef" : ""); - write_buffer(fname + "_before.class", classfileBuffer); - write_buffer(fname + "_instr.class", newcf); + if (newcf != null) { + String fname = trname + (redef?"_redef" : "") + "/" + className; + System.err.println("dumping to: " + fname); + write_buffer(fname + "_before.class", classfileBuffer); + write_buffer(fname + "_instr.class", newcf); + } ***/ - System.err.println(trname + ": " + className + " index: " + opt.fixedIndex + + System.err.println(trname + ": " + className + " index: " + fixedIndex + (redef? " REDEF" : " LOAD") + " len before: " + classfileBuffer.length + " after: " + newcf.length); @@ -104,10 +108,14 @@ class RetransformAgent { static void write_buffer(String fname, byte[]buffer) { try { - FileOutputStream outStream = new FileOutputStream(fname); - outStream.write(buffer, 0, buffer.length); - outStream.close(); - } catch (Exception ex) { + File f = new File(fname); + if (!f.getParentFile().exists()) { + f.getParentFile().mkdirs(); + } + try (FileOutputStream outStream = new FileOutputStream(f)) { + outStream.write(buffer, 0, buffer.length); + } + } catch (IOException ex) { System.err.println("EXCEPTION in write_buffer: " + ex); } } diff --git a/jdk/test/java/lang/instrument/RetransformBigClass.sh b/jdk/test/java/lang/instrument/RetransformBigClass.sh index 22065b6d369..332dd3269b7 100644 --- a/jdk/test/java/lang/instrument/RetransformBigClass.sh +++ b/jdk/test/java/lang/instrument/RetransformBigClass.sh @@ -27,7 +27,7 @@ # @author Daniel D. Daugherty # # @run shell MakeJAR4.sh RetransformBigClassAgent SimpleIdentityTransformer 'Can-Retransform-Classes: true' -# @run build BigClass RetransformBigClassApp +# @run build BigClass RetransformBigClassApp NMTHelper # @run shell/timeout=600 RetransformBigClass.sh # diff --git a/jdk/test/java/lang/instrument/asmlib/Instrumentor.java b/jdk/test/java/lang/instrument/asmlib/Instrumentor.java new file mode 100644 index 00000000000..333cd27873f --- /dev/null +++ b/jdk/test/java/lang/instrument/asmlib/Instrumentor.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2014, 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. + */ + +package asmlib; + +import java.io.PrintStream; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import jdk.internal.org.objectweb.asm.ClassReader; +import jdk.internal.org.objectweb.asm.ClassVisitor; +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; + +import java.util.function.Consumer; +import jdk.internal.org.objectweb.asm.Type; + +public class Instrumentor { + public static class InstrHelper { + private final MethodVisitor mv; + private final String name; + + InstrHelper(MethodVisitor mv, String name) { + this.mv = mv; + this.name = name; + } + + public String getName() { + return this.name; + } + + public void invokeStatic(String owner, String name, String desc, boolean itf) { + mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, itf); + } + + public void invokeSpecial(String owner, String name, String desc) { + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, false); + } + + public void invokeVirtual(String owner, String name, String desc) { + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, false); + } + + public void push(int val) { + if (val >= -1 && val <= 5) { + mv.visitInsn(Opcodes.ICONST_0 + val); + } else if (val >= Byte.MIN_VALUE && val <= Byte.MAX_VALUE) { + mv.visitIntInsn(Opcodes.BIPUSH, val); + } else if (val >= Short.MIN_VALUE && val <= Short.MAX_VALUE) { + mv.visitIntInsn(Opcodes.SIPUSH, val); + } else { + mv.visitLdcInsn(val); + } + } + + public void push(Object val) { + mv.visitLdcInsn(val); + } + + public void println(String s) { + mv.visitFieldInsn(Opcodes.GETSTATIC, Type.getInternalName(System.class), "out", Type.getDescriptor(PrintStream.class)); + mv.visitLdcInsn(s); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(PrintStream.class), "println", Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(String.class)), false); + } + } + + public static Instrumentor instrFor(byte[] classData) { + return new Instrumentor(classData); + } + + + private final ClassReader cr; + private final ClassWriter output; + private ClassVisitor instrumentingVisitor = null; + private final AtomicInteger matches = new AtomicInteger(0); + + private Instrumentor(byte[] classData) { + cr = new ClassReader(classData); + output = new ClassWriter(ClassWriter.COMPUTE_MAXS); + instrumentingVisitor = output; + } + + public synchronized Instrumentor addMethodEntryInjection(String methodName, Consumer injector) { + instrumentingVisitor = new ClassVisitor(Opcodes.ASM5, instrumentingVisitor) { + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); + + if (name.equals(methodName)) { + matches.getAndIncrement(); + + mv = new MethodVisitor(Opcodes.ASM5, mv) { + @Override + public void visitCode() { + injector.accept(new InstrHelper(mv, name)); + } + }; + } + return mv; + } + }; + return this; + } + + public synchronized Instrumentor addNativeMethodTrackingInjection(String prefix, Consumer injector) { + instrumentingVisitor = new ClassVisitor(Opcodes.ASM5, instrumentingVisitor) { + private final Set> wmGenerators = new HashSet<>(); + private String className; + + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + this.className = name; + super.visit(version, access, name, signature, superName, interfaces); + } + + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + if ((access & Opcodes.ACC_NATIVE) != 0) { + matches.getAndIncrement(); + + String newName = prefix + name; + wmGenerators.add((v)->{ + MethodVisitor mv = v.visitMethod(access & ~Opcodes.ACC_NATIVE, name, desc, signature, exceptions); + mv.visitCode(); + injector.accept(new InstrHelper(mv, name)); + Type[] argTypes = Type.getArgumentTypes(desc); + Type retType = Type.getReturnType(desc); + + boolean isStatic = (access & Opcodes.ACC_STATIC) != 0; + if (!isStatic) { + mv.visitIntInsn(Opcodes.ALOAD, 0); // load "this" + } + + // load the method parameters + if (argTypes.length > 0) { + int ptr = isStatic ? 0 : 1; + for(Type argType : argTypes) { + mv.visitIntInsn(argType.getOpcode(Opcodes.ILOAD), ptr); + ptr += argType.getSize(); + } + } + + mv.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : Opcodes.INVOKESPECIAL, className, newName, desc, false); + mv.visitInsn(retType.getOpcode(Opcodes.IRETURN)); + + mv.visitMaxs(1, 1); // dummy call; let ClassWriter to deal with this + mv.visitEnd(); + }); + return super.visitMethod(access, newName, desc, signature, exceptions); + } + return super.visitMethod(access, name, desc, signature, exceptions); + } + + @Override + public void visitEnd() { + wmGenerators.stream().forEach((e) -> { + e.accept(cv); + }); + super.visitEnd(); + } + }; + + return this; + } + + public synchronized byte[] apply() { + cr.accept(instrumentingVisitor, ClassReader.SKIP_DEBUG + ClassReader.EXPAND_FRAMES); + + return matches.get() == 0 ? null : output.toByteArray(); + } +} diff --git a/jdk/test/java/lang/instrument/ilib/ClassDump.java b/jdk/test/java/lang/instrument/ilib/ClassDump.java deleted file mode 100644 index 4dd1908f286..00000000000 --- a/jdk/test/java/lang/instrument/ilib/ClassDump.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (c) 2005, 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. - */ - -package ilib; - -import java.io.IOException; -import java.io.File; -import java.io.FileOutputStream; -import java.io.DataOutputStream; -import java.io.PrintStream; -import java.io.PrintWriter; -import java.io.CharArrayWriter; -import java.util.List; -import java.util.Iterator; -import java.util.ArrayList; - -public class ClassDump implements RuntimeConstants { - - public static void dump(Options opt, - ClassLoader loader, - String className, - byte[] classfileBuffer) { - ClassReaderWriter c = new ClassReaderWriter(classfileBuffer); - (new ClassDump(className, c)).doit(); - } - - static boolean verbose = true; - - final String className; - final ClassReaderWriter c; - private final PrintStream output; - - int constantPoolCount; - int methodsCount; - - ClassDump(String className, ClassReaderWriter c) { - this.className = className; - this.c = c; - this.output = System.err; - } - - void doit() { - int i; - c.copy(4 + 2 + 2); // magic min/maj version - constantPoolCount = c.copyU2(); - // copy old constant pool - c.copyConstantPool(constantPoolCount); - - traceln("ConstantPool size: " + constantPoolCount); - - c.copy(2 + 2 + 2); // access, this, super - int interfaceCount = c.copyU2(); - traceln("interfaceCount: " + interfaceCount); - c.copy(interfaceCount * 2); - copyFields(); // fields - copyMethods(); // methods - int attrCount = c.copyU2(); - traceln("class attrCount: " + attrCount); - // copy the class attributes - copyAttrs(attrCount); - } - - - void copyFields() { - int count = c.copyU2(); - if (verbose) { - System.out.println("fields count: " + count); - } - for (int i = 0; i < count; ++i) { - c.copy(6); // access, name, descriptor - int attrCount = c.copyU2(); - if (verbose) { - System.out.println("field attr count: " + attrCount); - } - copyAttrs(attrCount); - } - } - - void copyMethods() { - methodsCount = c.copyU2(); - if (verbose) { - System.out.println("methods count: " + methodsCount); - } - for (int i = 0; i < methodsCount; ++i) { - copyMethod(); - } - } - - void copyMethod() { - int accessFlags = c.copyU2();// access flags - int nameIndex = c.copyU2(); // name - checkIndex(nameIndex, "Method name"); - String methodName = c.constantPoolString(nameIndex); - traceln("method: " + methodName); - int descriptorIndex = c.copyU2(); // descriptor - checkIndex(descriptorIndex, "Method descriptor"); - int attrCount = c.copyU2(); // attribute count - if (verbose) { - System.out.println("method attr count: " + attrCount); - } - for (int i = 0; i < attrCount; ++i) { - copyAttrForMethod(methodName, accessFlags); - } - } - - void copyAttrs(int attrCount) { - for (int i = 0; i < attrCount; ++i) { - copyAttr(); - } - } - - void copyAttr() { - c.copy(2); // name - int len = c.copyU4(); // attr len - if (verbose) { - System.out.println("attr len: " + len); - } - c.copy(len); // attribute info - } - - void copyAttrForMethod(String methodName, int accessFlags) { - int nameIndex = c.copyU2(); // name - // check for Code attr - checkIndex(nameIndex, "Method attr name"); - if (nameIndex == c.codeAttributeIndex) { - try { - copyCodeAttr(methodName); - } catch (IOException exc) { - System.err.println("Code Exception - " + exc); - System.exit(1); - } - } else { - int len = c.copyU4(); // attr len - traceln("method attr len: " + len); - c.copy(len); // attribute info - } - } - - void copyAttrForCode() throws IOException { - int nameIndex = c.copyU2(); // name - - checkIndex(nameIndex, "Code attr name"); - int len = c.copyU4(); // attr len - traceln("code attr len: " + len); - c.copy(len); // attribute info - } - - void copyCodeAttr(String methodName) throws IOException { - traceln("Code attr found"); - int attrLength = c.copyU4(); // attr len - checkLength(attrLength, "Code attr length"); - int maxStack = c.readU2(); // max stack - c.copyU2(); // max locals - int codeLength = c.copyU4(); // code length - checkLength(codeLength, "Code length"); - - copyExceptionTable(); - - int attrCount = c.copyU2(); - checkLength(attrCount, "Code attr count"); - for (int i = 0; i < attrCount; ++i) { - copyAttrForCode(); - } - } - - /** - * Copy the exception table for this method code - */ - void copyExceptionTable() throws IOException { - int tableLength = c.copyU2(); // exception table len - checkLength(tableLength, "Exception Table length"); - if (tableLength > 0) { - traceln(); - traceln("Exception table:"); - traceln(" from:old/new to:old/new target:old/new type"); - for (int tcnt = tableLength; tcnt > 0; --tcnt) { - int startPC = c.readU2(); - int endPC = c.readU2(); - int handlerPC = c.readU2(); - int catchType = c.copyU2(); - if (verbose) { - traceFixedWidthInt(startPC, 6); - traceFixedWidthInt(endPC, 6); - traceFixedWidthInt(handlerPC, 6); - trace(" "); - if (catchType == 0) - traceln("any"); - else { - traceln("" + catchType); - } - } - } - } - } - - private void checkIndex(int index, String comment) { - if (index > constantPoolCount) { - output.println("ERROR BAD INDEX " + comment + " : " + index); - } else { - traceln(comment + " : " + index); - } - } - - private void checkLength(int length, String comment) { - if (length > c.inputBytes().length) { - output.println("ERROR BAD LENGTH " + comment + " : " + length); - } else { - traceln(comment + " : " + length); - } - } - - private void trace(String str) { - if (verbose) { - output.print(str); - } - } - - private void traceln(String str) { - if (verbose) { - output.println(str); - } - } - - private void traceln() { - if (verbose) { - output.println(); - } - } - - private void trace(int i) { - if (verbose) { - output.print(i); - } - } - - /** - * Print an integer so that it takes 'length' characters in - * the output. Temporary until formatting code is stable. - */ - private void traceFixedWidthInt(int x, int length) { - if (verbose) { - CharArrayWriter baStream = new CharArrayWriter(); - PrintWriter pStream = new PrintWriter(baStream); - pStream.print(x); - String str = baStream.toString(); - for (int cnt = length - str.length(); cnt > 0; --cnt) - trace(" "); - trace(str); - } - } - - -} diff --git a/jdk/test/java/lang/instrument/ilib/ClassReaderWriter.java b/jdk/test/java/lang/instrument/ilib/ClassReaderWriter.java deleted file mode 100644 index 6d9ed4d507a..00000000000 --- a/jdk/test/java/lang/instrument/ilib/ClassReaderWriter.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (c) 2005, 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. - */ - -package ilib; - -class ClassReaderWriter implements RuntimeConstants { - - int codeAttributeIndex; - int lineNumberAttributeIndex; - int localVarAttributeIndex; - - private final byte[] orig; - private final byte[] gen; - private final int sectionLength; - - private static final int GROWTH_FACTOR = 2; - private static final int SECTIONS = 2; - private static final String codeAttributeName = "Code"; - private static final String lineNumberAttributeName = "LineNumberTable"; - private static final String localVarAttributeName = "LocalVariableTable"; - - private int[] genSectionPos = new int[SECTIONS]; - - private int inputPos = 0; - private int genPos = 0; - private int markPos = 0; - private int currentSection = 0; - - private String[] constantPool; - - ClassReaderWriter(byte[] orig) { - this.orig = orig; - sectionLength = orig.length * GROWTH_FACTOR; - gen = new byte[sectionLength * SECTIONS]; - for (int section = 0; section < SECTIONS; ++section) { - genSectionPos[section] = section * sectionLength; - } - } - - int setSection(int section) { - int prevSection = currentSection; - genSectionPos[prevSection] = genPos; - genPos = genSectionPos[section]; - currentSection = section; - return prevSection; - } - - byte[] result() { - int section; - int totalLength = 0; - - setSection(0); // save current section - - for (section = 0; section < SECTIONS; ++section) { - int sectionStart = section * sectionLength; - int sectionGenLength = genSectionPos[section] - sectionStart; - totalLength += sectionGenLength; - } - - byte[] newcf = new byte[totalLength]; - int written = 0; - for (section = 0; section < SECTIONS; ++section) { - int sectionStart = section * sectionLength; - int sectionGenLength = genSectionPos[section] - sectionStart; - System.arraycopy(gen, sectionStart, newcf, written, sectionGenLength); - written += sectionGenLength; - } - - return newcf; - } - - int readU1() { - return ((int)orig[inputPos++]) & 0xFF; - } - - int readU2() { - int res = readU1(); - return (res << 8) + readU1(); - } - - short readS2() { - int res = readU1(); - return (short)((res << 8) + readU1()); - } - - int readU4() { - int res = readU2(); - return (res << 16) + readU2(); - } - - void writeU1(int val) { - gen[genPos++] = (byte)val; - } - - void writeU2(int val) { - writeU1(val >> 8); - writeU1(val & 0xFF); - } - - void writeU4(int val) { - writeU2(val >> 16); - writeU2(val & 0xFFFF); - } - - int copyU1() { - int value = readU1(); - writeU1(value); - return value; - } - - int copyU2() { - int value = readU2(); - writeU2(value); - return value; - } - - int copyU4() { - int value = readU4(); - writeU4(value); - return value; - } - - void copy(int count) { - for (int i = 0; i < count; ++i) { - gen[genPos++] = orig[inputPos++]; - } - } - - void skip(int count) { - inputPos += count; - } - - byte[] readBytes(int count) { - byte[] bytes = new byte[count]; - for (int i = 0; i < count; ++i) { - bytes[i] = orig[inputPos++]; - } - return bytes; - } - - void writeBytes(byte[] bytes) { - for (int i = 0; i < bytes.length; ++i) { - gen[genPos++] = bytes[i]; - } - } - - byte[] inputBytes() { - return orig; - } - - int inputPosition() { - return inputPos; - } - - void setInputPosition(int pos) { - inputPos = pos; - } - - void markLocalPositionStart() { - markPos = inputPos; - } - - int localPosition() { - return inputPos - markPos; - } - - void rewind() { - setInputPosition(markPos); - } - - int generatedPosition() { - return genPos; - } - - void randomAccessWriteU2(int pos, int val) { - int savePos = genPos; - genPos = pos; - writeU2(val); - genPos = savePos; - } - - void randomAccessWriteU4(int pos, int val) { - int savePos = genPos; - genPos = pos; - writeU4(val); - genPos = savePos; - } - - String constantPoolString(int index) { - return constantPool[index]; - } - - void copyConstantPool(int constantPoolCount){ - // copy const pool - constantPool = new String[constantPoolCount]; - // index zero not in class file - for (int i = 1; i < constantPoolCount; ++i) { - int tag = readU1(); - writeU1(tag); - switch (tag) { - case CONSTANT_CLASS: - case CONSTANT_STRING: - copy(2); - break; - case CONSTANT_FIELD: - case CONSTANT_METHOD: - case CONSTANT_INTERFACEMETHOD: - case CONSTANT_INTEGER: - case CONSTANT_FLOAT: - case CONSTANT_NAMEANDTYPE: - copy(4); - break; - case CONSTANT_LONG: - case CONSTANT_DOUBLE: - copy(8); - ++i; // these take two CP entries - duh! - break; - case CONSTANT_UTF8: - int len = copyU2(); - byte[] utf8 = readBytes(len); - String str = null; // null to shut the compiler up - try { - str = new String(utf8, "UTF-8"); - } catch (Exception exc) { - throw new Error("CP exception: " + exc); - } - constantPool[i] = str; - if (str.equals(codeAttributeName)) { - codeAttributeIndex = i; - } else if (str.equals(lineNumberAttributeName)) { - lineNumberAttributeIndex = i; - } else if (str.equals(localVarAttributeName)) { - localVarAttributeIndex = i; - } - writeBytes(utf8); - break; - default: - throw new Error(i + " unexpected CP tag: " + tag); - } - } - } - -} diff --git a/jdk/test/java/lang/instrument/ilib/Inject.java b/jdk/test/java/lang/instrument/ilib/Inject.java deleted file mode 100644 index 22acbc9324b..00000000000 --- a/jdk/test/java/lang/instrument/ilib/Inject.java +++ /dev/null @@ -1,746 +0,0 @@ -/* - * Copyright (c) 2005, 2011, 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. - */ - -package ilib; - -import java.io.IOException; -import java.io.File; -import java.io.FileOutputStream; -import java.io.DataOutputStream; -import java.util.List; -import java.util.Iterator; -import java.util.ArrayList; - -public class Inject implements RuntimeConstants { - - public static byte[] instrumentation(Options opt, - ClassLoader loader, - String className, - byte[] classfileBuffer) { - ClassReaderWriter c = new ClassReaderWriter(classfileBuffer); - (new Inject(className, c, loader == null, opt)).doit(); - return c.result(); - } - - static boolean verbose = false; - - final String className; - final ClassReaderWriter c; - final boolean isSystem; - final Options options; - - int constantPoolCount; - int methodsCount; - int methodsCountPos; - int profiler; - int wrappedTrackerIndex = 0; - int thisClassIndex = 0; - - TrackerInjector callInjector; - TrackerInjector allocInjector; - TrackerInjector defaultInjector; - - static interface TrackerInjector extends Injector { - void reinit(int tracker); - int stackSize(int currentSize); - } - - static class SimpleInjector implements TrackerInjector { - byte[] injection; - - public int stackSize(int currentSize) { - return currentSize; - } - - public void reinit(int tracker) { - injection = new byte[3]; - injection[0] = (byte)opc_invokestatic; - injection[1] = (byte)(tracker >> 8); - injection[2] = (byte)tracker; - } - - public byte[] bytecodes(String className, String methodName, int location) { - return injection; - } - } - - static class ObjectInjector implements TrackerInjector { - byte[] injection; - - public int stackSize(int currentSize) { - return currentSize + 1; - } - - public void reinit(int tracker) { - injection = new byte[4]; - injection[0] = (byte)opc_dup; - injection[1] = (byte)opc_invokestatic; - injection[2] = (byte)(tracker >> 8); - injection[3] = (byte)tracker; - } - - public byte[] bytecodes(String className, String methodName, int location) { - return injection; - } - } - - class IndexedInjector implements TrackerInjector { - int counter = 0; - int tracker; - List infoList = new ArrayList<>(); - - public int stackSize(int currentSize) { - return currentSize + 1; - } - - public void reinit(int tracker) { - this.tracker = tracker; - } - - void dump(File outDir, String filename) throws IOException { - try (FileOutputStream fileOut = - new FileOutputStream(new File(outDir, filename)); - DataOutputStream dataOut = new DataOutputStream(fileOut)) - { - String currentClassName = null; - - dataOut.writeInt(infoList.size()); - for (Iterator it = infoList.iterator(); it.hasNext(); ) { - Info info = it.next(); - if (!info.className.equals(currentClassName)) { - dataOut.writeInt(123456); // class name marker - currentClassName = info.className; - dataOut.writeUTF(currentClassName); - } - dataOut.writeInt(info.location); - dataOut.writeUTF(info.methodName); - } - } - } - - public byte[] bytecodes(String className, String methodName, int location) { - byte[] injection = new byte[6]; - int injectedIndex = options.fixedIndex != 0? options.fixedIndex : ++counter; - infoList.add(new Info(counter, className, methodName, location)); - injection[0] = (byte)opc_sipush; - injection[1] = (byte)(injectedIndex >> 8); - injection[2] = (byte)injectedIndex; - injection[3] = (byte)opc_invokestatic; - injection[4] = (byte)(tracker >> 8); - injection[5] = (byte)tracker; - return injection; - } - } - - Inject(String className, ClassReaderWriter c, boolean isSystem, Options options) { - this.className = className; - this.c = c; - this.isSystem = isSystem; - this.options = options; - } - - void doit() { - int i; - c.copy(4 + 2 + 2); // magic min/maj version - int constantPoolCountPos = c.generatedPosition(); - constantPoolCount = c.copyU2(); - // copy old constant pool - c.copyConstantPool(constantPoolCount); - - if (verbose) { - System.out.println("ConstantPool expanded from: " + - constantPoolCount); - } - - profiler = addClassToConstantPool(options.trackerClassName); - if (options.shouldInstrumentNew || options.shouldInstrumentObjectInit) { - if (options.shouldInstrumentIndexed) { - if (allocInjector == null) { - // first time - create it - allocInjector = new IndexedInjector(); - } - int allocTracker = addMethodToConstantPool(profiler, - options.allocTrackerMethodName, - "(I)V"); - allocInjector.reinit(allocTracker); - } else if (options.shouldInstrumentObject) { - if (allocInjector == null) { - // first time - create it - allocInjector = new ObjectInjector(); - } - int allocTracker = addMethodToConstantPool(profiler, - options.allocTrackerMethodName, - "(Ljava/lang/Object;)V"); - allocInjector.reinit(allocTracker); - } else { - if (allocInjector == null) { - // first time - create it - allocInjector = new SimpleInjector(); - } - int allocTracker = addMethodToConstantPool(profiler, - options.allocTrackerMethodName, - "()V"); - allocInjector.reinit(allocTracker); - } - defaultInjector = allocInjector; - } - if (options.shouldInstrumentCall) { - if (options.shouldInstrumentIndexed) { - if (callInjector == null) { - // first time - create it - callInjector = new IndexedInjector(); - } - int callTracker = addMethodToConstantPool(profiler, - options.callTrackerMethodName, - "(I)V"); - callInjector.reinit(callTracker); - } else { - if (callInjector == null) { - // first time - create it - callInjector = new SimpleInjector(); - } - int callTracker = addMethodToConstantPool(profiler, - options.callTrackerMethodName, - "()V"); - callInjector.reinit(callTracker); - } - defaultInjector = callInjector; - } - - if (verbose) { - System.out.println("To: " + constantPoolCount); - } - - c.setSection(1); - - c.copy(2 + 2 + 2); // access, this, super - int interfaceCount = c.copyU2(); - if (verbose) { - System.out.println("interfaceCount: " + interfaceCount); - } - c.copy(interfaceCount * 2); - copyFields(); // fields - copyMethods(); // methods - int attrCountPos = c.generatedPosition(); - int attrCount = c.copyU2(); - if (verbose) { - System.out.println("class attrCount: " + attrCount); - } - // copy the class attributes - copyAttrs(attrCount); - - c.randomAccessWriteU2(constantPoolCountPos, constantPoolCount); - } - - - void copyFields() { - int count = c.copyU2(); - if (verbose) { - System.out.println("fields count: " + count); - } - for (int i = 0; i < count; ++i) { - c.copy(6); // access, name, descriptor - int attrCount = c.copyU2(); - if (verbose) { - System.out.println("field attr count: " + attrCount); - } - copyAttrs(attrCount); - } - } - - void copyMethods() { - methodsCountPos = c.generatedPosition(); - methodsCount = c.copyU2(); - int initialMethodsCount = methodsCount; - if (verbose) { - System.out.println("methods count: " + methodsCount); - } - for (int i = 0; i < initialMethodsCount; ++i) { - copyMethod(); - } - } - - void copyMethod() { - int accessFlags = c.copyU2();// access flags - if (options.shouldInstrumentNativeMethods && (accessFlags & ACC_NATIVE) != 0) { - wrapNativeMethod(accessFlags); - return; - } - int nameIndex = c.copyU2(); // name - String methodName = c.constantPoolString(nameIndex); - c.copyU2(); // descriptor - int attrCount = c.copyU2(); // attribute count - if (verbose) { - System.out.println("methods attr count: " + attrCount); - } - for (int i = 0; i < attrCount; ++i) { - copyAttrForMethod(methodName, accessFlags); - } - } - - void wrapNativeMethod(int accessFlags) { - // first, copy the native method with the name changed - // accessFlags have already been copied - int nameIndex = c.readU2(); // name - String methodName = c.constantPoolString(nameIndex); - String wrappedMethodName = options.wrappedPrefix + methodName; - int wrappedNameIndex = writeCPEntryUtf8(wrappedMethodName); - c.writeU2(wrappedNameIndex); // change to the wrapped name - - int descriptorIndex = c.copyU2(); // descriptor index - - int attrCount = c.copyU2(); // attribute count - // need to replicate these attributes (esp Exceptions) in wrapper - // so mark this location so we can rewind - c.markLocalPositionStart(); - for (int i = 0; i < attrCount; ++i) { - copyAttrForMethod(methodName, accessFlags); - } - if (true) { - System.err.println(" wrapped: " + methodName); - } - - // now write the wrapper method - c.writeU2(accessFlags & ~ACC_NATIVE); - c.writeU2(nameIndex); // original unwrapped name - c.writeU2(descriptorIndex); // descriptor is the same - - c.writeU2(attrCount + 1); // wrapped plus a code attribute - // rewind to wrapped attributes - c.rewind(); - for (int i = 0; i < attrCount; ++i) { - copyAttrForMethod(methodName, accessFlags); - } - - // generate a Code attribute for the wrapper method - int wrappedIndex = addMethodToConstantPool(getThisClassIndex(), - wrappedNameIndex, - descriptorIndex); - String descriptor = c.constantPoolString(descriptorIndex); - createWrapperCodeAttr(nameIndex, accessFlags, descriptor, wrappedIndex); - - // increment method count - c.randomAccessWriteU2(methodsCountPos, ++methodsCount); - } - - void copyAttrs(int attrCount) { - for (int i = 0; i < attrCount; ++i) { - copyAttr(); - } - } - - void copyAttr() { - c.copy(2); // name - int len = c.copyU4(); // attr len - if (verbose) { - System.out.println("attr len: " + len); - } - c.copy(len); // attribute info - } - - void copyAttrForMethod(String methodName, int accessFlags) { - int nameIndex = c.copyU2(); // name - // check for Code attr - if (nameIndex == c.codeAttributeIndex) { - try { - copyCodeAttr(methodName); - } catch (IOException exc) { - System.err.println("Code Exception - " + exc); - System.exit(1); - } - } else { - int len = c.copyU4(); // attr len - if (verbose) { - System.out.println("method attr len: " + len); - } - c.copy(len); // attribute info - } - } - - void copyAttrForCode(InjectBytecodes ib) throws IOException { - int nameIndex = c.copyU2(); // name - - // check for Code attr - if (nameIndex == c.lineNumberAttributeIndex) { - ib.copyLineNumberAttr(); - } else if (nameIndex == c.localVarAttributeIndex) { - ib.copyLocalVarAttr(); - } else { - int len = c.copyU4(); // attr len - if (verbose) { - System.out.println("code attr len: " + len); - } - c.copy(len); // attribute info - } - } - - void copyCodeAttr(String methodName) throws IOException { - if (verbose) { - System.out.println("Code attr found"); - } - int attrLengthPos = c.generatedPosition(); - int attrLength = c.copyU4(); // attr len - int maxStack = c.readU2(); // max stack - c.writeU2(defaultInjector == null? maxStack : - defaultInjector.stackSize(maxStack)); // big enough for injected code - c.copyU2(); // max locals - int codeLengthPos = c.generatedPosition(); - int codeLength = c.copyU4(); // code length - if (options.targetMethod != null && !options.targetMethod.equals(methodName)) { - c.copy(attrLength - 8); // copy remainder minus already copied - return; - } - if (isSystem) { - if (codeLength == 1 && methodName.equals("finalize")) { - if (verbose) { - System.out.println("empty system finalizer not instrumented"); - } - c.copy(attrLength - 8); // copy remainder minus already copied - return; - } - if (codeLength == 1 && methodName.equals("")) { - if (verbose) { - System.out.println("empty system constructor not instrumented"); - } - if (!options.shouldInstrumentObjectInit) { - c.copy(attrLength - 8); // copy remainder minus already copied - return; - } - } - if (methodName.equals("")) { - if (verbose) { - System.out.println("system class initializer not instrumented"); - } - c.copy(attrLength - 8); // copy remainder minus already copied - return; - } - } - if (options.shouldInstrumentObjectInit - && (!className.equals("java/lang/Object") - || !methodName.equals(""))) { - c.copy(attrLength - 8); // copy remainder minus already copied - return; - } - - InjectBytecodes ib = new InjectBytecodes(c, codeLength, className, methodName); - - if (options.shouldInstrumentNew) { - ib.injectAfter(opc_new, allocInjector); - ib.injectAfter(opc_newarray, allocInjector); - ib.injectAfter(opc_anewarray, allocInjector); - ib.injectAfter(opc_multianewarray, allocInjector); - } - if (options.shouldInstrumentCall) { - ib.inject(0, callInjector.bytecodes(className, methodName, 0)); - } - if (options.shouldInstrumentObjectInit) { - ib.inject(0, allocInjector.bytecodes(className, methodName, 0)); - } - - ib.adjustOffsets(); - - // fix up code length - int newCodeLength = c.generatedPosition() - (codeLengthPos + 4); - c.randomAccessWriteU4(codeLengthPos, newCodeLength); - if (verbose) { - System.out.println("code length old: " + codeLength + - ", new: " + newCodeLength); - } - - ib.copyExceptionTable(); - - int attrCount = c.copyU2(); - for (int i = 0; i < attrCount; ++i) { - copyAttrForCode(ib); - } - - // fix up attr length - int newAttrLength = c.generatedPosition() - (attrLengthPos + 4); - c.randomAccessWriteU4(attrLengthPos, newAttrLength); - if (verbose) { - System.out.println("attr length old: " + attrLength + - ", new: " + newAttrLength); - } - } - - int nextDescriptorIndex(String descriptor, int index) { - switch (descriptor.charAt(index)) { - case 'B': // byte - case 'C': // char - case 'I': // int - case 'S': // short - case 'Z': // boolean - case 'F': // float - case 'D': // double - case 'J': // long - return index + 1; - case 'L': // object - int i = index + 1; - while (descriptor.charAt(i) != ';') { - ++i; - } - return i + 1; - case '[': // array - return nextDescriptorIndex(descriptor, index + 1); - } - throw new InternalError("should not reach here"); - } - - int getWrappedTrackerIndex() { - if (wrappedTrackerIndex == 0) { - wrappedTrackerIndex = addMethodToConstantPool(profiler, - options.wrappedTrackerMethodName, - "(Ljava/lang/String;I)V"); - } - return wrappedTrackerIndex; - } - - int getThisClassIndex() { - if (thisClassIndex == 0) { - thisClassIndex = addClassToConstantPool(className); - } - return thisClassIndex; - } - - int computeMaxLocals(String descriptor, int accessFlags) { - int index = 1; - int slot = 0; - - if ((accessFlags & ACC_STATIC) == 0) { - ++slot; - } - char type; - while ((type = descriptor.charAt(index)) != ')') { - switch (type) { - case 'B': // byte - case 'C': // char - case 'I': // int - case 'S': // short - case 'Z': // boolean - case 'F': // float - case 'L': // object - case '[': // array - ++slot; - break; - case 'D': // double - case 'J': // long - slot += 2; - break; - } - index = nextDescriptorIndex(descriptor, index); - } - - return slot; - } - - - void createWrapperCodeAttr(int methodNameIndex, int accessFlags, - String descriptor, int wrappedIndex) { - int maxLocals = computeMaxLocals(descriptor, accessFlags); - - c.writeU2(c.codeAttributeIndex); // - int attrLengthPos = c.generatedPosition(); - c.writeU4(0); // attr len -- fix up below - c.writeU2(maxLocals + 4); // max stack - c.writeU2(maxLocals); // max locals - int codeLengthPos = c.generatedPosition(); - c.writeU4(0); // code length -- fix up below - - int methodStringIndex = writeCPEntryString(methodNameIndex); - - c.writeU1(opc_ldc_w); - c.writeU2(methodStringIndex); // send the method name - c.writeU1(opc_sipush); - c.writeU2(options.fixedIndex); - c.writeU1(opc_invokestatic); - c.writeU2(getWrappedTrackerIndex()); - - // set-up args - int index = 1; - int slot = 0; - if ((accessFlags & ACC_STATIC) == 0) { - c.writeU1(opc_aload_0); // this - ++slot; - } - char type; - while ((type = descriptor.charAt(index)) != ')') { - switch (type) { - case 'B': // byte - case 'C': // char - case 'I': // int - case 'S': // short - case 'Z': // boolean - c.writeU1(opc_iload); - c.writeU1(slot); - ++slot; - break; - case 'F': // float - c.writeU1(opc_fload); - c.writeU1(slot); - ++slot; - break; - case 'D': // double - c.writeU1(opc_dload); - c.writeU1(slot); - slot += 2; - break; - case 'J': // long - c.writeU1(opc_lload); - c.writeU1(slot); - slot += 2; - break; - case 'L': // object - case '[': // array - c.writeU1(opc_aload); - c.writeU1(slot); - ++slot; - break; - } - index = nextDescriptorIndex(descriptor, index); - } - - // call the wrapped version - if ((accessFlags & ACC_STATIC) == 0) { - c.writeU1(opc_invokevirtual); - } else { - c.writeU1(opc_invokestatic); - } - c.writeU2(wrappedIndex); - - // return correct type - switch (descriptor.charAt(index+1)) { - case 'B': // byte - case 'C': // char - case 'I': // int - case 'S': // short - case 'Z': // boolean - c.writeU1(opc_ireturn); - break; - case 'F': // float - c.writeU1(opc_freturn); - break; - case 'D': // double - c.writeU1(opc_dreturn); - break; - case 'J': // long - c.writeU1(opc_lreturn); - break; - case 'L': // object - case '[': // array - c.writeU1(opc_areturn); - break; - case 'V': // void - c.writeU1(opc_return); - break; - } - - // end of code - - // fix up code length - int newCodeLength = c.generatedPosition() - (codeLengthPos + 4); - c.randomAccessWriteU4(codeLengthPos, newCodeLength); - - c.writeU2(0); // exception table length - c.writeU2(0); // attribute count - - // fix up attr length - int newAttrLength = c.generatedPosition() - (attrLengthPos + 4); - c.randomAccessWriteU4(attrLengthPos, newAttrLength); - } - - - int addClassToConstantPool(String className) { - int prevSection = c.setSection(0); - int classNameIndex = writeCPEntryUtf8(className); - int classIndex = writeCPEntryClass(classNameIndex); - c.setSection(prevSection); - return classIndex; - } - - int addMethodToConstantPool(int classIndex, - String methodName, - String descr) { - int prevSection = c.setSection(0); - int methodNameIndex = writeCPEntryUtf8(methodName); - int descrIndex = writeCPEntryUtf8(descr); - c.setSection(prevSection); - return addMethodToConstantPool(classIndex, methodNameIndex, descrIndex); - } - - int addMethodToConstantPool(int classIndex, - int methodNameIndex, - int descrIndex) { - int prevSection = c.setSection(0); - int nameAndTypeIndex = writeCPEntryNameAndType(methodNameIndex, - descrIndex); - int methodIndex = writeCPEntryMethodRef(classIndex, nameAndTypeIndex); - c.setSection(prevSection); - return methodIndex; - } - - int writeCPEntryUtf8(String str) { - int prevSection = c.setSection(0); - int len = str.length(); - c.writeU1(CONSTANT_UTF8); // Utf8 tag - c.writeU2(len); - for (int i = 0; i < len; ++i) { - c.writeU1(str.charAt(i)); - } - c.setSection(prevSection); - return constantPoolCount++; - } - - int writeCPEntryString(int utf8Index) { - int prevSection = c.setSection(0); - c.writeU1(CONSTANT_STRING); - c.writeU2(utf8Index); - c.setSection(prevSection); - return constantPoolCount++; - } - - int writeCPEntryClass(int classNameIndex) { - int prevSection = c.setSection(0); - c.writeU1(CONSTANT_CLASS); - c.writeU2(classNameIndex); - c.setSection(prevSection); - return constantPoolCount++; - } - - int writeCPEntryNameAndType(int nameIndex, int descrIndex) { - int prevSection = c.setSection(0); - c.writeU1(CONSTANT_NAMEANDTYPE); - c.writeU2(nameIndex); - c.writeU2(descrIndex); - c.setSection(prevSection); - return constantPoolCount++; - } - - int writeCPEntryMethodRef(int classIndex, int nameAndTypeIndex) { - int prevSection = c.setSection(0); - c.writeU1(CONSTANT_METHOD); - c.writeU2(classIndex); - c.writeU2(nameAndTypeIndex); - c.setSection(prevSection); - return constantPoolCount++; - } -} diff --git a/jdk/test/java/lang/instrument/ilib/InjectBytecodes.java b/jdk/test/java/lang/instrument/ilib/InjectBytecodes.java deleted file mode 100644 index 53e6a2feaea..00000000000 --- a/jdk/test/java/lang/instrument/ilib/InjectBytecodes.java +++ /dev/null @@ -1,769 +0,0 @@ -/* - * Copyright (c) 2005, 2010, 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. - */ - -/* - * An extension of BinaryCode that allows code to be printed. - * Includes printing of disassembled byte codes, exception info, - * local variable and line number info. - * - */ - -package ilib; - -import java.io.ByteArrayInputStream; -import java.io.CharArrayWriter; -import java.io.DataInputStream; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.PrintStream; -import java.util.Map; -import java.util.HashMap; - -class InjectBytecodes implements RuntimeConstants { - - private final ClassReaderWriter c; - private final PrintStream output; - private final int length; - private final int[] map; - private final byte[] widening; - private final Injector[] before = new Injector[256]; - private final Injector[] after = new Injector[256]; - private final String className; - private final String methodName; - private final Map snippets = new HashMap<>(); - - private int pos; - private int newPos; - - private class Span { - final int delta; - final int target; - final int newDelta; - final int newTarget; - - Span(int delta) { - this.delta = delta; - this.target = pos + delta; - this.newTarget = map[target]; - this.newDelta = newTarget - newPos; - } - } - - /** - * Constructor - */ - InjectBytecodes(ClassReaderWriter c, int length, - String className, String methodName) { - this.c = c; - this.output = System.out; - this.length = length; - this.map = new int[length + 1]; - this.widening = new byte[length + 1]; - this.className = className; - this.methodName = methodName; - c.markLocalPositionStart(); - for (int i = 0; i <= length; ++i) { - map[i] = i; - } - } - - public void inject(int at, byte[] newCode) { - snippets.put(new Integer(at), newCode); - trace("external "); - inject(at, newCode.length); - } - - private void inject(int at, int len) { - if (Inject.verbose) { - traceln("Injecting " + len + " at " + at); - } - for (int i = at; i <= length; ++i) { - map[i] += len; - } - } - - private void widen(int at, int len) { - int delta = len - widening[at]; - if (Inject.verbose) { - traceln(); - traceln("Widening to " + len + " at " + at); - } - inject(c.localPosition(), delta); // inject at end of instruction - widening[at] = (byte)len; // mark at beginning of instruction - } - - public void injectBefore(int code, Injector inj) { - before[code] = inj; - } - - public void injectAfter(int code, Injector inj) { - after[code] = inj; - } - - private void trace(String str) { - if (Inject.verbose) { - output.print(str); - } - } - - private void traceln(String str) { - if (Inject.verbose) { - output.println(str); - } - } - - private void traceln() { - if (Inject.verbose) { - output.println(); - } - } - - private void trace(int i) { - if (Inject.verbose) { - output.print(i); - } - } - - /** - * Print an integer so that it takes 'length' characters in - * the output. Temporary until formatting code is stable. - */ - private void traceFixedWidthInt(int x, int length) { - if (Inject.verbose) { - CharArrayWriter baStream = new CharArrayWriter(); - PrintWriter pStream = new PrintWriter(baStream); - pStream.print(x); - String str = baStream.toString(); - for (int cnt = length - str.length(); cnt > 0; --cnt) - trace(" "); - trace(str); - } - } - - void adjustOffsets() throws IOException { - if (Inject.verbose) { - traceln(); - traceln("Method " + methodName); - traceln(); - } - c.rewind(); - while (c.localPosition() < length) { - insertAtInstruction(); - } - trace("Searching for adjustments..."); - c.rewind(); - while (c.localPosition() < length) { - if (!adjustInstruction()) { - c.rewind(); - traceln(); - traceln("Restarting adjustments after change..."); - } - } - // write the new bytecodes - traceln(); - traceln(); - trace("Writing new code..."); - c.rewind(); - while (c.localPosition() < length) { - writeInstruction(); - } - if (!snippets.isEmpty()) { - throw new Error("not all snippets written"); - } - } - - /** - * Walk one instruction inserting instrumentation at specified instructions - */ - private void insertAtInstruction() throws IOException { - pos = c.localPosition(); - int opcode = c.readU1(); - if (opcode == opc_wide) { - // no support for instrumenting wide instructions - int wopcode = c.readU1(); - int lvIndex = c.readU2(); - switch (wopcode) { - case opc_aload: case opc_astore: - case opc_fload: case opc_fstore: - case opc_iload: case opc_istore: - case opc_lload: case opc_lstore: - case opc_dload: case opc_dstore: - case opc_ret: - break; - - case opc_iinc: - c.readS2(); - break; - default: - throw new Error("Invalid wide opcode: " + wopcode); - } - } else { - Injector inj; - - inj = before[opcode]; - if (inj != null) { - inject(pos, inj.bytecodes(className, methodName, pos)); - } - - switch (opcode) { - case opc_tableswitch:{ - int header = (pos+1+3) & (~3); // 4byte boundry - c.skip(header - (pos+1)); // skip old padding - - c.readU4(); - int low = c.readU4(); - int high = c.readU4(); - c.skip((high+1-low) * 4); - break; - } - - case opc_lookupswitch:{ - int header = (pos+1+3) & (~3); // 4byte boundry - c.skip(header - (pos+1)); // skip padding - - c.readU4(); - int npairs = c.readU4(); - c.skip(npairs * 8); - break; - } - - default: { - int instrLen = opcLengths[opcode]; - c.skip(instrLen-1); - } - } - inj = after[opcode]; - if (inj != null) { - pos = c.localPosition(); - inject(pos, inj.bytecodes(className, methodName, pos)); - } - } - } - - /** - * Walk one instruction adjusting for insertions - */ - private boolean adjustInstruction() throws IOException { - pos = c.localPosition(); - newPos = map[pos]; - int opcode = c.readU1(); - if (Inject.verbose) { - traceln(); - traceFixedWidthInt(pos, 4); - traceFixedWidthInt(newPos, 4); - trace(" "); - } - if (opcode == opc_wide) { - int wopcode = c.readU1(); - int lvIndex = c.readU2(); - if (Inject.verbose) { - trace(opcNames[wopcode] + "_w "); - } - switch (wopcode) { - case opc_aload: case opc_astore: - case opc_fload: case opc_fstore: - case opc_iload: case opc_istore: - case opc_lload: case opc_lstore: - case opc_dload: case opc_dstore: - case opc_ret: - trace(lvIndex); - break; - - case opc_iinc: - int constVal = c.readS2(); - if (Inject.verbose) { - trace(lvIndex + " " + constVal); - } - break; - default: - throw new Error("Invalid wide opcode: " + wopcode); - } - } else { - if (Inject.verbose) { - trace(opcNames[opcode]); - } - switch (opcode) { - - case opc_tableswitch:{ - int widened = widening[pos]; - int header = (pos+1+3) & (~3); // 4byte boundry - int newHeader = (newPos+1+3) & (~3); // 4byte boundry - - c.skip(header - (pos+1)); // skip old padding - - Span defaultSkip = new Span(c.readU4()); - int low = c.readU4(); - int high = c.readU4(); - if (Inject.verbose) { - trace(" " + low + " to " + high); - trace(": default= [was] " + defaultSkip.target); - trace(" [now] " + defaultSkip.newTarget); - for (int i = low; i <= high; ++i) { - Span jump = new Span(c.readU4()); - traceln(""); - trace('\t'); - traceFixedWidthInt(i, 5); - trace(": " + jump.newTarget); - } - } else { - c.skip((high+1-low) * 4); - } - int newPadding = newHeader - newPos; - int oldPadding = header - pos; - int deltaPadding = newPadding - oldPadding; - if (widened != deltaPadding) { - widen(pos, deltaPadding); - return false; // cause restart - } - break; - } - - case opc_lookupswitch:{ - int widened = widening[pos]; - int header = (pos+1+3) & (~3); // 4byte boundry - int newHeader = (newPos+1+3) & (~3); // 4byte boundry - - c.skip(header - (pos+1)); // skip old padding - - Span defaultSkip = new Span(c.readU4()); - int npairs = c.readU4(); - if (Inject.verbose) { - trace(" npairs: " + npairs); - trace(": default= [was] " + defaultSkip.target); - trace(" [now] " + defaultSkip.newTarget); - for (int i = 0; i< npairs; ++i) { - int match = c.readU4(); - Span jump = new Span(c.readU4()); - traceln(""); - trace('\t'); - traceFixedWidthInt(match, 5); - trace(": " + jump.newTarget); - } - } else { - c.skip(npairs * 8); - } - int newPadding = newHeader - newPos; - int oldPadding = header - pos; - int deltaPadding = newPadding - oldPadding; - if (widened != deltaPadding) { - widen(pos, deltaPadding); - return false; // cause restart - } - break; - } - - case opc_jsr: case opc_goto: - case opc_ifeq: case opc_ifge: case opc_ifgt: - case opc_ifle: case opc_iflt: case opc_ifne: - case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpge: - case opc_if_icmpgt: case opc_if_icmple: case opc_if_icmplt: - case opc_if_acmpeq: case opc_if_acmpne: - case opc_ifnull: case opc_ifnonnull: { - int widened = widening[pos]; - Span jump = new Span(c.readS2()); - if (widened == 0) { // not yet widened - int newDelta = jump.newDelta; - if ((newDelta < -32768) || (newDelta > 32767)) { - switch (opcode) { - case opc_jsr: case opc_goto: - widen(pos, 2); // will convert to wide - break; - default: - widen(pos, 5); // will inject goto_w - break; - } - return false; // cause restart - } - } - if (Inject.verbose) { - trace(" [was] " + jump.target + " ==> " + - " [now] " + jump.newTarget); - } - break; - } - - case opc_jsr_w: - case opc_goto_w: { - Span jump = new Span(c.readU4()); - if (Inject.verbose) { - trace(" [was] " + jump.target + - " [now] " + jump.newTarget); - } - break; - } - - default: { - int instrLen = opcLengths[opcode]; - c.skip(instrLen-1); - break; - } - } - } - return true; // successful return - } - - - /** - * Walk one instruction writing the transformed instruction. - */ - private void writeInstruction() throws IOException { - pos = c.localPosition(); - newPos = map[pos]; - byte[] newCode = snippets.remove(new Integer(pos)); - if (newCode != null) { - traceln(); - traceFixedWidthInt(pos, 4); - trace(" ... -- Inserting new code"); - c.writeBytes(newCode); - } - int opcode = c.readU1(); - if (Inject.verbose) { - traceln(); - traceFixedWidthInt(pos, 4); - traceFixedWidthInt(newPos, 4); - trace(" "); - } - if (opcode == opc_wide) { - int wopcode = c.readU1(); - int lvIndex = c.readU2(); - if (Inject.verbose) { - trace(opcNames[wopcode] + "_w "); - } - c.writeU1(opcode); - c.writeU1(wopcode); - c.writeU2(lvIndex); - switch (wopcode) { - case opc_aload: case opc_astore: - case opc_fload: case opc_fstore: - case opc_iload: case opc_istore: - case opc_lload: case opc_lstore: - case opc_dload: case opc_dstore: - case opc_ret: - trace(lvIndex); - break; - - case opc_iinc: - int constVal = c.readS2(); - c.writeU2(constVal); // ??? U vs S - if (Inject.verbose) { - trace(lvIndex + " " + constVal); - } - break; - default: - throw new Error("Invalid wide opcode: " + wopcode); - } - } else { - if (Inject.verbose) { - trace(opcNames[opcode]); - } - switch (opcode) { - - case opc_tableswitch:{ - int header = (pos+1+3) & (~3); // 4byte boundry - int newHeader = (newPos+1+3) & (~3); // 4byte boundry - - c.skip(header - (pos+1)); // skip old padding - - Span defaultSkip = new Span(c.readU4()); - int low = c.readU4(); - int high = c.readU4(); - - c.writeU1(opcode); // copy instruction - for (int i = newPos+1; i < newHeader; ++i) { - c.writeU1(0); // write new padding - } - c.writeU4(defaultSkip.newDelta); - c.writeU4(low); - c.writeU4(high); - - if (Inject.verbose) { - trace(" " + low + " to " + high); - trace(": default= [was] " + defaultSkip.target); - trace(" [now] " + defaultSkip.newTarget); - } - for (int i = low; i <= high; ++i) { - Span jump = new Span(c.readU4()); - c.writeU4(jump.newDelta); - if (Inject.verbose) { - traceln(""); - trace('\t'); - traceFixedWidthInt(i, 5); - trace(": " + jump.newTarget); - } - } - break; - } - - case opc_lookupswitch:{ - int header = (pos+1+3) & (~3); // 4byte boundry - int newHeader = (newPos+1+3) & (~3); // 4byte boundry - - c.skip(header - (pos+1)); // skip old padding - - Span defaultSkip = new Span(c.readU4()); - int npairs = c.readU4(); - if (Inject.verbose) { - trace(" npairs: " + npairs); - trace(": default= [was] " + defaultSkip.target); - trace(" [now] " + defaultSkip.newTarget); - } - c.writeU1(opcode); // copy instruction - for (int i = newPos+1; i < newHeader; ++i) { - c.writeU1(0); // write new padding - } - c.writeU4(defaultSkip.newDelta); - c.writeU4(npairs); - for (int i = 0; i< npairs; ++i) { - int match = c.readU4(); - Span jump = new Span(c.readU4()); - c.writeU4(match); - c.writeU4(jump.newDelta); - if (Inject.verbose) { - traceln(""); - trace('\t'); - traceFixedWidthInt(match, 5); - trace(": " + jump.newTarget); - } - } - break; - } - - case opc_jsr: case opc_goto: - case opc_ifeq: case opc_ifge: case opc_ifgt: - case opc_ifle: case opc_iflt: case opc_ifne: - case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpge: - case opc_if_icmpgt: case opc_if_icmple: case opc_if_icmplt: - case opc_if_acmpeq: case opc_if_acmpne: - case opc_ifnull: case opc_ifnonnull: { - int widened = widening[pos]; - Span jump = new Span(c.readS2()); - int newOpcode = opcode; // default to unchanged - if (widened == 0) { // not widened - c.writeU1(opcode); // rewrite instruction - c.writeU2(jump.newDelta); - } else if (widened == 2) { // wide form - switch (opcode) { - case opc_jsr: - newOpcode = opc_jsr_w; - break; - case opc_goto: - newOpcode = opc_jsr_w; - break; - default: - throw new Error("unexpected opcode: " + - opcode); - } - c.writeU1(newOpcode); // write wide instruction - c.writeU4(jump.newDelta); // write new and wide delta - } else if (widened == 5) { // insert goto_w - switch (opcode) { - case opc_ifeq: - newOpcode = opc_ifne; - break; - case opc_ifge: - newOpcode = opc_iflt; - break; - case opc_ifgt: - newOpcode = opc_ifle; - break; - case opc_ifle: - newOpcode = opc_ifgt; - break; - case opc_iflt: - newOpcode = opc_ifge; - break; - case opc_ifne: - newOpcode = opc_ifeq; - break; - case opc_if_icmpeq: - newOpcode = opc_if_icmpne; - break; - case opc_if_icmpne: - newOpcode = opc_if_icmpeq; - break; - case opc_if_icmpge: - newOpcode = opc_if_icmplt; - break; - case opc_if_icmpgt: - newOpcode = opc_if_icmple; - break; - case opc_if_icmple: - newOpcode = opc_if_icmpgt; - break; - case opc_if_icmplt: - newOpcode = opc_if_icmpge; - break; - case opc_if_acmpeq: - newOpcode = opc_if_acmpne; - break; - case opc_if_acmpne: - newOpcode = opc_if_acmpeq; - break; - case opc_ifnull: - newOpcode = opc_ifnonnull; - break; - case opc_ifnonnull: - newOpcode = opc_ifnull; - break; - default: - throw new Error("unexpected opcode: " + - opcode); - } - c.writeU1(newOpcode); // write inverse branch - c.writeU2(3 + 5); // beyond if and goto_w - c.writeU1(opc_goto_w);// add a goto_w - c.writeU4(jump.newDelta); // write new and wide delta - } else { - throw new Error("unexpected widening"); - } - - if (Inject.verbose) { - trace(" [was] " + jump.target + " ==> " + - opcNames[newOpcode] + - " [now] " + jump.newTarget); - } - break; - } - - case opc_jsr_w: - case opc_goto_w: { - Span jump = new Span(c.readU4()); - c.writeU1(opcode); // instruction itself - c.writeU4(jump.newDelta); - if (Inject.verbose) { - trace(" [was] " + jump.target + - " [now] " + jump.newTarget); - } - break; - } - - default: { - int instrLen = opcLengths[opcode]; - c.writeU1(opcode); // instruction itself - c.copy(instrLen-1); - } - } - } - } - - /** - * Copy the exception table for this method code - */ - void copyExceptionTable() throws IOException { - int tableLength = c.copyU2(); // exception table len - if (tableLength > 0) { - traceln(); - traceln("Exception table:"); - traceln(" from:old/new to:old/new target:old/new type"); - for (int tcnt = tableLength; tcnt > 0; --tcnt) { - int startPC = c.readU2(); - int newStartPC = map[startPC]; - c.writeU2(newStartPC); - int endPC = c.readU2(); - int newEndPC = map[endPC]; - c.writeU2(newEndPC); - int handlerPC = c.readU2(); - int newHandlerPC = map[handlerPC]; - c.writeU2(newHandlerPC); - int catchType = c.copyU2(); - if (Inject.verbose) { - traceFixedWidthInt(startPC, 6); - traceFixedWidthInt(newStartPC, 6); - traceFixedWidthInt(endPC, 6); - traceFixedWidthInt(newEndPC, 6); - traceFixedWidthInt(handlerPC, 6); - traceFixedWidthInt(newHandlerPC, 6); - trace(" "); - if (catchType == 0) - traceln("any"); - else { - traceln("" + catchType); - } - } - } - } - } - - /** - * Copy the line number table for this method code - */ - void copyLineNumberAttr() throws IOException { - // name index already read - c.copy(4); // attr len - int tableLength = c.copyU2(); // line table len - if (tableLength > 0) { - if (Inject.verbose) { - traceln(); - traceln("Line numbers for method " + methodName); - } - for (int tcnt = tableLength; tcnt > 0; --tcnt) { - int startPC = c.readU2(); - int newStartPC = map[startPC]; - c.writeU2(newStartPC); - int lineNumber = c.copyU2(); - if (Inject.verbose) { - traceln(" line " + lineNumber + - ": [was] " + startPC + - " [now] " + newStartPC); - } - } - } - } - - /** - * Copy the local variable table for this method code - */ - void copyLocalVarAttr() throws IOException { - // name index already read - c.copy(4); // attr len - int tableLength = c.copyU2(); // local var table len - if (tableLength > 0) { - if (Inject.verbose) { - traceln(); - traceln("Local variables for method " + methodName); - } - for (int tcnt = tableLength; tcnt > 0; --tcnt) { - int startPC = c.readU2(); - int newStartPC = map[startPC]; - c.writeU2(newStartPC); - int length = c.readU2(); - int endPC = startPC + length; - int newEndPC = map[endPC]; - int newLength = newEndPC - newStartPC; - c.writeU2(newLength); - int nameIndex = c.copyU2(); - int descriptorIndex = c.copyU2(); - int index = c.copyU2(); - if (Inject.verbose) { - trace(" "); - trace(descriptorIndex); - trace(" "); - trace(nameIndex); - traceln(" pc= [was] " + startPC + " [now] " + newStartPC + - ", length= [was] " + length + " [now] " + newLength + - ", slot=" + index); - } - } - } - } -} diff --git a/jdk/test/java/lang/instrument/ilib/RuntimeConstants.java b/jdk/test/java/lang/instrument/ilib/RuntimeConstants.java deleted file mode 100644 index 01a746ec5ff..00000000000 --- a/jdk/test/java/lang/instrument/ilib/RuntimeConstants.java +++ /dev/null @@ -1,732 +0,0 @@ -/* - * Copyright (c) 2005, 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. - */ - -package ilib; - -public interface RuntimeConstants { - - /* Signature Characters */ - char SIGC_VOID = 'V'; - String SIG_VOID = "V"; - char SIGC_BOOLEAN = 'Z'; - String SIG_BOOLEAN = "Z"; - char SIGC_BYTE = 'B'; - String SIG_BYTE = "B"; - char SIGC_CHAR = 'C'; - String SIG_CHAR = "C"; - char SIGC_SHORT = 'S'; - String SIG_SHORT = "S"; - char SIGC_INT = 'I'; - String SIG_INT = "I"; - char SIGC_LONG = 'J'; - String SIG_LONG = "J"; - char SIGC_FLOAT = 'F'; - String SIG_FLOAT = "F"; - char SIGC_DOUBLE = 'D'; - String SIG_DOUBLE = "D"; - char SIGC_ARRAY = '['; - String SIG_ARRAY = "["; - char SIGC_CLASS = 'L'; - String SIG_CLASS = "L"; - char SIGC_METHOD = '('; - String SIG_METHOD = "("; - char SIGC_ENDCLASS = ';'; - String SIG_ENDCLASS = ";"; - char SIGC_ENDMETHOD = ')'; - String SIG_ENDMETHOD = ")"; - char SIGC_PACKAGE = '/'; - String SIG_PACKAGE = "/"; - - /* Class File Constants */ - int JAVA_MAGIC = 0xcafebabe; - int JAVA_MIN_SUPPORTED_VERSION = 45; - int JAVA_MAX_SUPPORTED_VERSION = 48; - int JAVA_MAX_SUPPORTED_MINOR_VERSION = 0; - - /* Generate class file version for 1.1 by default */ - int JAVA_DEFAULT_VERSION = 45; - int JAVA_DEFAULT_MINOR_VERSION = 3; - - /* Constant table */ - int CONSTANT_UTF8 = 1; - int CONSTANT_UNICODE = 2; - int CONSTANT_INTEGER = 3; - int CONSTANT_FLOAT = 4; - int CONSTANT_LONG = 5; - int CONSTANT_DOUBLE = 6; - int CONSTANT_CLASS = 7; - int CONSTANT_STRING = 8; - int CONSTANT_FIELD = 9; - int CONSTANT_METHOD = 10; - int CONSTANT_INTERFACEMETHOD = 11; - int CONSTANT_NAMEANDTYPE = 12; - - /* Access and modifier flags */ - int ACC_PUBLIC = 0x00000001; - int ACC_PRIVATE = 0x00000002; - int ACC_PROTECTED = 0x00000004; - int ACC_STATIC = 0x00000008; - int ACC_FINAL = 0x00000010; - int ACC_SYNCHRONIZED = 0x00000020; - int ACC_VOLATILE = 0x00000040; - int ACC_TRANSIENT = 0x00000080; - int ACC_NATIVE = 0x00000100; - int ACC_INTERFACE = 0x00000200; - int ACC_ABSTRACT = 0x00000400; - int ACC_SUPER = 0x00000020; - int ACC_STRICT = 0x00000800; - - /* Type codes */ - int T_CLASS = 0x00000002; - int T_BOOLEAN = 0x00000004; - int T_CHAR = 0x00000005; - int T_FLOAT = 0x00000006; - int T_DOUBLE = 0x00000007; - int T_BYTE = 0x00000008; - int T_SHORT = 0x00000009; - int T_INT = 0x0000000a; - int T_LONG = 0x0000000b; - - /* Opcodes */ - int opc_try = -3; - int opc_dead = -2; - int opc_label = -1; - int opc_nop = 0; - int opc_aconst_null = 1; - int opc_iconst_m1 = 2; - int opc_iconst_0 = 3; - int opc_iconst_1 = 4; - int opc_iconst_2 = 5; - int opc_iconst_3 = 6; - int opc_iconst_4 = 7; - int opc_iconst_5 = 8; - int opc_lconst_0 = 9; - int opc_lconst_1 = 10; - int opc_fconst_0 = 11; - int opc_fconst_1 = 12; - int opc_fconst_2 = 13; - int opc_dconst_0 = 14; - int opc_dconst_1 = 15; - int opc_bipush = 16; - int opc_sipush = 17; - int opc_ldc = 18; - int opc_ldc_w = 19; - int opc_ldc2_w = 20; - int opc_iload = 21; - int opc_lload = 22; - int opc_fload = 23; - int opc_dload = 24; - int opc_aload = 25; - int opc_iload_0 = 26; - int opc_iload_1 = 27; - int opc_iload_2 = 28; - int opc_iload_3 = 29; - int opc_lload_0 = 30; - int opc_lload_1 = 31; - int opc_lload_2 = 32; - int opc_lload_3 = 33; - int opc_fload_0 = 34; - int opc_fload_1 = 35; - int opc_fload_2 = 36; - int opc_fload_3 = 37; - int opc_dload_0 = 38; - int opc_dload_1 = 39; - int opc_dload_2 = 40; - int opc_dload_3 = 41; - int opc_aload_0 = 42; - int opc_aload_1 = 43; - int opc_aload_2 = 44; - int opc_aload_3 = 45; - int opc_iaload = 46; - int opc_laload = 47; - int opc_faload = 48; - int opc_daload = 49; - int opc_aaload = 50; - int opc_baload = 51; - int opc_caload = 52; - int opc_saload = 53; - int opc_istore = 54; - int opc_lstore = 55; - int opc_fstore = 56; - int opc_dstore = 57; - int opc_astore = 58; - int opc_istore_0 = 59; - int opc_istore_1 = 60; - int opc_istore_2 = 61; - int opc_istore_3 = 62; - int opc_lstore_0 = 63; - int opc_lstore_1 = 64; - int opc_lstore_2 = 65; - int opc_lstore_3 = 66; - int opc_fstore_0 = 67; - int opc_fstore_1 = 68; - int opc_fstore_2 = 69; - int opc_fstore_3 = 70; - int opc_dstore_0 = 71; - int opc_dstore_1 = 72; - int opc_dstore_2 = 73; - int opc_dstore_3 = 74; - int opc_astore_0 = 75; - int opc_astore_1 = 76; - int opc_astore_2 = 77; - int opc_astore_3 = 78; - int opc_iastore = 79; - int opc_lastore = 80; - int opc_fastore = 81; - int opc_dastore = 82; - int opc_aastore = 83; - int opc_bastore = 84; - int opc_castore = 85; - int opc_sastore = 86; - int opc_pop = 87; - int opc_pop2 = 88; - int opc_dup = 89; - int opc_dup_x1 = 90; - int opc_dup_x2 = 91; - int opc_dup2 = 92; - int opc_dup2_x1 = 93; - int opc_dup2_x2 = 94; - int opc_swap = 95; - int opc_iadd = 96; - int opc_ladd = 97; - int opc_fadd = 98; - int opc_dadd = 99; - int opc_isub = 100; - int opc_lsub = 101; - int opc_fsub = 102; - int opc_dsub = 103; - int opc_imul = 104; - int opc_lmul = 105; - int opc_fmul = 106; - int opc_dmul = 107; - int opc_idiv = 108; - int opc_ldiv = 109; - int opc_fdiv = 110; - int opc_ddiv = 111; - int opc_irem = 112; - int opc_lrem = 113; - int opc_frem = 114; - int opc_drem = 115; - int opc_ineg = 116; - int opc_lneg = 117; - int opc_fneg = 118; - int opc_dneg = 119; - int opc_ishl = 120; - int opc_lshl = 121; - int opc_ishr = 122; - int opc_lshr = 123; - int opc_iushr = 124; - int opc_lushr = 125; - int opc_iand = 126; - int opc_land = 127; - int opc_ior = 128; - int opc_lor = 129; - int opc_ixor = 130; - int opc_lxor = 131; - int opc_iinc = 132; - int opc_i2l = 133; - int opc_i2f = 134; - int opc_i2d = 135; - int opc_l2i = 136; - int opc_l2f = 137; - int opc_l2d = 138; - int opc_f2i = 139; - int opc_f2l = 140; - int opc_f2d = 141; - int opc_d2i = 142; - int opc_d2l = 143; - int opc_d2f = 144; - int opc_i2b = 145; - int opc_i2c = 146; - int opc_i2s = 147; - int opc_lcmp = 148; - int opc_fcmpl = 149; - int opc_fcmpg = 150; - int opc_dcmpl = 151; - int opc_dcmpg = 152; - int opc_ifeq = 153; - int opc_ifne = 154; - int opc_iflt = 155; - int opc_ifge = 156; - int opc_ifgt = 157; - int opc_ifle = 158; - int opc_if_icmpeq = 159; - int opc_if_icmpne = 160; - int opc_if_icmplt = 161; - int opc_if_icmpge = 162; - int opc_if_icmpgt = 163; - int opc_if_icmple = 164; - int opc_if_acmpeq = 165; - int opc_if_acmpne = 166; - int opc_goto = 167; - int opc_jsr = 168; - int opc_ret = 169; - int opc_tableswitch = 170; - int opc_lookupswitch = 171; - int opc_ireturn = 172; - int opc_lreturn = 173; - int opc_freturn = 174; - int opc_dreturn = 175; - int opc_areturn = 176; - int opc_return = 177; - int opc_getstatic = 178; - int opc_putstatic = 179; - int opc_getfield = 180; - int opc_putfield = 181; - int opc_invokevirtual = 182; - int opc_invokespecial = 183; - int opc_invokestatic = 184; - int opc_invokeinterface = 185; - int opc_xxxunusedxxx = 186; - int opc_new = 187; - int opc_newarray = 188; - int opc_anewarray = 189; - int opc_arraylength = 190; - int opc_athrow = 191; - int opc_checkcast = 192; - int opc_instanceof = 193; - int opc_monitorenter = 194; - int opc_monitorexit = 195; - int opc_wide = 196; - int opc_multianewarray = 197; - int opc_ifnull = 198; - int opc_ifnonnull = 199; - int opc_goto_w = 200; - int opc_jsr_w = 201; - int opc_breakpoint = 202; - - /* Opcode Names */ - String opcNames[] = { - "nop", - "aconst_null", - "iconst_m1", - "iconst_0", - "iconst_1", - "iconst_2", - "iconst_3", - "iconst_4", - "iconst_5", - "lconst_0", - "lconst_1", - "fconst_0", - "fconst_1", - "fconst_2", - "dconst_0", - "dconst_1", - "bipush", - "sipush", - "ldc", - "ldc_w", - "ldc2_w", - "iload", - "lload", - "fload", - "dload", - "aload", - "iload_0", - "iload_1", - "iload_2", - "iload_3", - "lload_0", - "lload_1", - "lload_2", - "lload_3", - "fload_0", - "fload_1", - "fload_2", - "fload_3", - "dload_0", - "dload_1", - "dload_2", - "dload_3", - "aload_0", - "aload_1", - "aload_2", - "aload_3", - "iaload", - "laload", - "faload", - "daload", - "aaload", - "baload", - "caload", - "saload", - "istore", - "lstore", - "fstore", - "dstore", - "astore", - "istore_0", - "istore_1", - "istore_2", - "istore_3", - "lstore_0", - "lstore_1", - "lstore_2", - "lstore_3", - "fstore_0", - "fstore_1", - "fstore_2", - "fstore_3", - "dstore_0", - "dstore_1", - "dstore_2", - "dstore_3", - "astore_0", - "astore_1", - "astore_2", - "astore_3", - "iastore", - "lastore", - "fastore", - "dastore", - "aastore", - "bastore", - "castore", - "sastore", - "pop", - "pop2", - "dup", - "dup_x1", - "dup_x2", - "dup2", - "dup2_x1", - "dup2_x2", - "swap", - "iadd", - "ladd", - "fadd", - "dadd", - "isub", - "lsub", - "fsub", - "dsub", - "imul", - "lmul", - "fmul", - "dmul", - "idiv", - "ldiv", - "fdiv", - "ddiv", - "irem", - "lrem", - "frem", - "drem", - "ineg", - "lneg", - "fneg", - "dneg", - "ishl", - "lshl", - "ishr", - "lshr", - "iushr", - "lushr", - "iand", - "land", - "ior", - "lor", - "ixor", - "lxor", - "iinc", - "i2l", - "i2f", - "i2d", - "l2i", - "l2f", - "l2d", - "f2i", - "f2l", - "f2d", - "d2i", - "d2l", - "d2f", - "i2b", - "i2c", - "i2s", - "lcmp", - "fcmpl", - "fcmpg", - "dcmpl", - "dcmpg", - "ifeq", - "ifne", - "iflt", - "ifge", - "ifgt", - "ifle", - "if_icmpeq", - "if_icmpne", - "if_icmplt", - "if_icmpge", - "if_icmpgt", - "if_icmple", - "if_acmpeq", - "if_acmpne", - "goto", - "jsr", - "ret", - "tableswitch", - "lookupswitch", - "ireturn", - "lreturn", - "freturn", - "dreturn", - "areturn", - "return", - "getstatic", - "putstatic", - "getfield", - "putfield", - "invokevirtual", - "invokespecial", - "invokestatic", - "invokeinterface", - "xxxunusedxxx", - "new", - "newarray", - "anewarray", - "arraylength", - "athrow", - "checkcast", - "instanceof", - "monitorenter", - "monitorexit", - "wide", - "multianewarray", - "ifnull", - "ifnonnull", - "goto_w", - "jsr_w", - "breakpoint" - }; - - /* Opcode Lengths */ - int opcLengths[] = { - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 3, - 2, - 3, - 3, - 2, - 2, - 2, - 2, - 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 2, - 99, - 99, - 1, - 1, - 1, - 1, - 1, - 1, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 5, - 0, - 3, - 2, - 3, - 1, - 1, - 3, - 3, - 1, - 1, - 0, - 4, - 3, - 3, - 5, - 5, - 1 - }; - -} diff --git a/jdk/test/java/net/URLPermission/URLTest.java b/jdk/test/java/net/URLPermission/URLTest.java index 8318c019ce8..ceb0d2c8aeb 100644 --- a/jdk/test/java/net/URLPermission/URLTest.java +++ b/jdk/test/java/net/URLPermission/URLTest.java @@ -27,7 +27,8 @@ import java.net.URLPermission; * * @test * @bug 8010464 - * @compile ../../../com/sun/net/httpserver/SimpleSSLContext.java + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext * @run main/othervm/policy=policy.1 URLTest one * @run main/othervm URLTest one * @run main/othervm/policy=policy.2 URLTest two @@ -43,6 +44,7 @@ import java.util.concurrent.*; import java.util.logging.*; import com.sun.net.httpserver.*; import javax.net.ssl.*; +import jdk.testlibrary.SimpleSSLContext; public class URLTest { static boolean failed = false; @@ -209,10 +211,7 @@ public class URLTest { httpServer.setExecutor (e); httpsServer.setExecutor (es); - // take the keystore from elsewhere in test hierarchy - String keysdir = System.getProperty("test.src") - + "/../../../com/sun/net/httpserver/"; - ctx = new SimpleSSLContext(keysdir).get(); + ctx = new SimpleSSLContext().get(); httpsServer.setHttpsConfigurator(new HttpsConfigurator (ctx)); httpServer.start(); diff --git a/jdk/test/java/net/URLPermission/policy.1 b/jdk/test/java/net/URLPermission/policy.1 index a7468719165..93439790658 100644 --- a/jdk/test/java/net/URLPermission/policy.1 +++ b/jdk/test/java/net/URLPermission/policy.1 @@ -28,12 +28,13 @@ grant { // needed for HttpServer permission "java.net.SocketPermission" "localhost:1024-", "listen,resolve,accept"; permission "java.util.PropertyPermission" "test.src", "read"; - permission java.io.FilePermission "${test.src}/../../../com/sun/net/httpserver/testkeys", "read"; + permission java.io.FilePermission "${test.src}/../../../lib/testlibrary/jdk/testlibrary/testkeys", "read"; //permission "java.util.logging.LoggingPermission" "control"; //permission "java.io.FilePermission" "/tmp/-", "read,write"; permission "java.lang.RuntimePermission" "modifyThread"; permission "java.lang.RuntimePermission" "setFactory"; + permission "java.util.PropertyPermission" "test.src.path", "read"; }; // Normal permissions that aren't granted when run under jtreg diff --git a/jdk/test/java/net/URLPermission/policy.2 b/jdk/test/java/net/URLPermission/policy.2 index b71126a9ab9..43ee0f204a8 100644 --- a/jdk/test/java/net/URLPermission/policy.2 +++ b/jdk/test/java/net/URLPermission/policy.2 @@ -28,12 +28,13 @@ grant { // needed for HttpServer permission "java.net.SocketPermission" "localhost:1024-", "listen,resolve,accept"; permission "java.util.PropertyPermission" "test.src", "read"; - permission java.io.FilePermission "${test.src}/../../../com/sun/net/httpserver/testkeys", "read"; + permission java.io.FilePermission "${test.src}/../../../lib/testlibrary/jdk/testlibrary/testkeys", "read"; //permission "java.util.logging.LoggingPermission" "control"; //permission "java.io.FilePermission" "/tmp/-", "read,write"; permission "java.lang.RuntimePermission" "modifyThread"; permission "java.lang.RuntimePermission" "setFactory"; + permission "java.util.PropertyPermission" "test.src.path", "read"; }; // Normal permissions that aren't granted when run under jtreg diff --git a/jdk/test/java/net/URLPermission/policy.3 b/jdk/test/java/net/URLPermission/policy.3 index 9c29ce37096..54ddb2a591c 100644 --- a/jdk/test/java/net/URLPermission/policy.3 +++ b/jdk/test/java/net/URLPermission/policy.3 @@ -28,12 +28,13 @@ grant { // needed for HttpServer permission "java.net.SocketPermission" "localhost:1024-", "listen,resolve,accept"; permission "java.util.PropertyPermission" "test.src", "read"; - permission java.io.FilePermission "${test.src}/../../../com/sun/net/httpserver/testkeys", "read"; + permission java.io.FilePermission "${test.src}/../../../lib/testlibrary/jdk/testlibrary/testkeys", "read"; //permission "java.util.logging.LoggingPermission" "control"; //permission "java.io.FilePermission" "/tmp/-", "read,write"; permission "java.lang.RuntimePermission" "modifyThread"; permission "java.lang.RuntimePermission" "setFactory"; + permission "java.util.PropertyPermission" "test.src.path", "read"; }; // Normal permissions that aren't granted when run under jtreg diff --git a/jdk/test/java/security/KeyStore/PKCS12/ReadP12Test.java b/jdk/test/java/security/KeyStore/PKCS12/ReadP12Test.java new file mode 100644 index 00000000000..429a49857e5 --- /dev/null +++ b/jdk/test/java/security/KeyStore/PKCS12/ReadP12Test.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2003,2014, 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 static java.lang.System.out; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.Key; +import java.security.KeyStore; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.Base64; +import java.util.Enumeration; + +/* + * @test + * @bug 8048617 + * @author Bill Situ + * @summary Read different types p12 key store to Check the read related APIs. + * including following test cases: + * ReadP12_IE_Chain: Read p12 key store (contains private key and associated + * certificate chain) from IE. + * ReadP12_IE_Self: Read p12 key store (contains only private key and + * self-signed certificate) from IE. + * ReadP12_JDK_Chain: Read p12 key store (contains private key and associated + * certificate chain) from JDK + * ReadP12_JDK_Self: Read p12 key store (contains only private key and + * self-signed certificate) from JDK. + * ReadP12_Mozilla_Self: Read p12 key store (contains only private key and + * self-signed certificate) from Mozilla. + * ReadP12_Mozilla_Chain: Read p12 key store (contains private key and + * associated certificate chain) from Mozilla. + * ReadP12_Mozilla_TwoEntries: Read p12 key store (contains 2 entries) from + * Mozilla. + * ReadP12_Netscape_Chain: Read p12 key store (contains private key and + * associated certificate chain) from Netscape. + * ReadP12_Netscape_Self: Read p12 key store (contains only private key and + * self-signed certificate) from Netscape. + * ReadP12_Netscape_TwoEntries: Read p12 key store (contains 2 entries) from + * Netscape. + * ReadP12_OpenSSL: Read p12 key store from OpenSSL. + */ + +public class ReadP12Test { + + private final static String IN_KETYSTORE_TYPE = "pkcs12"; + private final static String IN_KEYSTORE_PRV = "SunJSSE"; + private final static String IN_STORE_PASS = "pass"; + + public static void main(String args[]) throws Exception { + + ReadP12Test jstest = new ReadP12Test(); + String testCase = ""; + try { + testCase = "ReadP12_IE_Chain"; + jstest.readTest("ie_chain.pfx.data"); + + testCase = "ReadP12_IE_Self"; + jstest.readTest("ie_self.pfx.data"); + + testCase = "ReadP12_JDK_Chain"; + jstest.readTest("jdk_chain.p12.data"); + + testCase = "ReadP12_JDK_Self"; + jstest.readTest("jdk_self.p12.data"); + + testCase = "ReadP12_Mozilla_Chain"; + jstest.readTest("mozilla_chain.p12.data"); + + testCase = "ReadP12_Mozilla_Self"; + jstest.readTest("mozilla_self.p12.data"); + + testCase = "ReadP12_Mozilla_TwoEntries"; + jstest.readTest("mozilla_twoentries.p12.data"); + + testCase = "ReadP12_Netscape_Chain"; + jstest.readTest("netscape_chain.p12.data"); + + testCase = "ReadP12_Netscape_Self"; + jstest.readTest("netscape_self.p12.data"); + + testCase = "ReadP12_Netscape_TwoEntries"; + jstest.readTest("netscape_twoentries.p12.data"); + + testCase = "ReadP12_openssl"; + jstest.readTest("openssl.p12.data"); + + } catch (Exception e) { + System.err.println(testCase + ": failed with execption: " + + e.getMessage()); + throw e; + + } + out.println(testCase + ": Pass!!"); + } + + private void readTest(String inKeyStore) throws Exception { + + KeyStore inputKeyStore; + + // Initialize KeyStore + String dir = System.getProperty("test.src", "."); + String keystorePath = dir + File.separator + "certs" + File.separator + + "readP12"; + inputKeyStore = KeyStore + .getInstance(IN_KETYSTORE_TYPE, IN_KEYSTORE_PRV); + // KeyStore have encoded by Base64.getMimeEncoder().encode(),need decode + // first. + byte[] input = Files.readAllBytes(Paths.get(keystorePath, inKeyStore)); + ByteArrayInputStream arrayIn = new ByteArrayInputStream(Base64 + .getMimeDecoder().decode(input)); + inputKeyStore.load(arrayIn, IN_STORE_PASS.toCharArray()); + out.println("Initialize KeyStore : " + inKeyStore + " success"); + + out.println("getProvider : " + inputKeyStore.getProvider()); + out.println("getType : " + inputKeyStore.getType()); + out.println("getDefaultType : " + KeyStore.getDefaultType()); + + int idx = 0; + Enumeration e = inputKeyStore.aliases(); + String alias; + while (e.hasMoreElements()) { + alias = e.nextElement(); + out.println("Alias " + idx + " : " + alias); + if (inputKeyStore.containsAlias(alias) == false) { + throw new RuntimeException("Alias not found"); + } + + out.println("getCreationDate : " + + inputKeyStore.getCreationDate(alias)); + + X509Certificate cert = (X509Certificate) inputKeyStore + .getCertificate(alias); + out.println("getCertificate : " + cert.getSubjectDN()); + String retAlias = inputKeyStore.getCertificateAlias(cert); + if (!retAlias.equals(alias)) { + throw new RuntimeException("Alias mismatch"); + } + out.println("getCertificateAlias : " + retAlias); + + Certificate[] certs = inputKeyStore.getCertificateChain(alias); + for (int i = 0; i < certs.length; i++) { + out.println("getCertificateChain " + i + " : " + + ((X509Certificate) certs[i]).getSubjectDN()); + } + + boolean isCertEntry = inputKeyStore.isCertificateEntry(alias); + // test KeyStore only contain key pair entries. + if (isCertEntry == true) { + throw new RuntimeException( + "inputKeystore should not be certEntry because test keystore only contain key pair entries."); + } + + boolean isKeyEntry = inputKeyStore.isKeyEntry(alias); + if (isKeyEntry) { + Key key = inputKeyStore.getKey(alias, + IN_STORE_PASS.toCharArray()); + out.println("Key : " + key.toString()); + } else { + throw new RuntimeException("Entry type unknown\n"); + } + idx++; + } + + int size = inputKeyStore.size(); + if (idx != size) { + throw new RuntimeException("Size not match"); + } + + } +} diff --git a/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/ie_chain.pfx.data b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/ie_chain.pfx.data new file mode 100644 index 00000000000..3dbe7e4fcb3 --- /dev/null +++ b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/ie_chain.pfx.data @@ -0,0 +1,61 @@ +MIINXgIBAzCCDRoGCSqGSIb3DQEHAaCCDQsEgg0HMIINAzCCA7wGCSqGSIb3DQEHAaCCA60EggOp +MIIDpTCCA6EGCyqGSIb3DQEMCgECoIICtjCCArIwHAYKKoZIhvcNAQwBAzAOBAipOP0AVsizDgIC +B9AEggKQIP/YI9/C2WYbIWxKuqXMD8WPCvqj1fhHmZJ0epCzgEdOR7GT/h2Fy4/wxrthPkj4JqkS +akQog3pjOFtj9D8QtkOw/b761qsyj17TYlQS9C6qVhcddMA+Ca2NcDhKlYofQMNTuYPXkXlpCh5R +CNFgQ+PLVZwNZjqoitjv0RLQqBudhTmJSvfDlW2w+CpbziEeRNzn0pX0/Ts7KxykDscOmUCGHKic +b6FqHoioElcmBp7ae3zdXuvI1x/1Y435qju2yODPpMXEZbdsD5iL07RZyL2vm6lfQbLc37TszDBx +ZZJ7ja5F4V/j/6/AVLkcqfZxFOnXz5Ki9rQblYJbkkTpJAyiNqi8Gx+zgPGtLWvV6KRD0zmxo6q/ +OmdjKz4v9aG7MDSXenoy6tPAOvAQcQYaksvFZs1FjorJJpFzasfTUfy94JzrHUzRSPzNRDANHG/6 +TgxC1FMNw+iQUY9L8j4xrWsr2JN5tAgYcWz1qZrp4cx0he9cbQeqYcjv7ZvIQbIe2zxdvxh7WByy +r8hNMe3RkMOM2yuP85JuWipq+9jt4/CrimKljN1ULPw+V9FZzY8kKcEiSPD+KXdJNkrMr77/lUJz +PGNYpFBFb4natmi31ZBH2VomTeKPpeanN/ghWojft1mGd1s1nD4NelrWATMVquH2Cq6nhKLRHi4c +KbQsMo+ftLvkDHHtpYenjGHbwEFfowkwn9slsZqmPEATV6caHNITCBbhQmvvhqPDPPViV+u1M1c7 +vwf/ol7IjBlubwzBJAg6f5GW0tMNHxfg5E7O27AyREyvexk0IVakzIwUuP2anPTjPW0vyeePLtiG +TXNoUe+5UIzpshnLmSlerhVGoB+HBM1yoaaJHay7sdyQbVUxgdcwEwYJKoZIhvcNAQkVMQYEBAEA +AAAwWwYJKoZIhvcNAQkUMU4eTAB7ADcAMQA5AEIAQgA4ADkANAAtADMANQA2ADEALQA0AEMAMAA0 +AC0AOQBCADIAMAAtADMAOQBCAEMARAAzADQANwAzADUAMQAwAH0wYwYJKwYBBAGCNxEBMVYeVABN +AGkAYwByAG8AcwBvAGYAdAAgAEIAYQBzAGUAIABDAHIAeQBwAHQAbwBnAHIAYQBwAGgAaQBjACAA +UAByAG8AdgBpAGQAZQByACAAdgAxAC4AMDCCCT8GCSqGSIb3DQEHBqCCCTAwggksAgEAMIIJJQYJ +KoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIEmpyonjQeMACAgfQgIII+Pr+GLKaSN1U1soCnWsw +4kRoDxPPLNbzv/K+lsbGVk9vXjv5aBTi55FMCXvA5kGvdnQYrQ1KfIZmFVh3PnFQn/J6LVrpLbHC +/D27wvnOMausJA7uJi6wgkUCkQmXn7kesWhr+bBI9Ci7uyOUxdY53Yg43OQtZbWvQjGe6GiVRqWm +8NANuZ3c1IT2TmJw5xfvvE4tcHK0d75ApvTa43CkKmUY5A4SyNY4SUVdl9Cx50LEHcqGwV+uVGzy +kdO0+bgXI66FPKriuqPfayeTmL8T9PimwhOfY38OqtTKHwJ7E817i/B8ULpkRO67uYYJpeK4cIz1 +0rDW/JPG8BqN47Rej8rCpmY1F4hOuFzYA3PAh50YlI2wD2vSSqVPMUe/AtsL+u2Nxl/EidWp/8EL +l8rBgYJjSl+YjSRV22C/ZwDu/8oV3LeCuwL2SaO1r1tww3WuRAFcCctsemP84YI27Q8Z54P6wM8c +kjYH9F3oT9bHUAfJUm2d6d3wd+iGbrrxdkLrD5tEQB16K8RAbhPPfrM5rcRlh+Zvn068H/Kc9rEa +sfJD7ygUBZJ5MSsr4zP4koMZ0xjxAaXRUsURsF13772XL3zfTCVd5fV3wIpJsoXugZTOQ6hjAmeN +yGMZDn14GyxvwLbGFB0Yx8GAIRDxBvDXkYOqEMocmNwZo+uxPew1H4PMkWMm/yh4Y4V/H9Jmyd3v +aD2BWVyx7PIJ4cet3RdydHrKSNVBzwrO+y5HKZc7V7aRM0kZgdAJh9eDTlYk6B+ZHd1EawYRlIfl +f4JydqRkRaya7FOfQ3mLgrz6bdde720XZVWqe9bbsBucbYAJsYvklYYYutnsx1Ri9UYYAbRDy920 +Z6iO1EGF5wcUc0nifXObYJ2x0ldlQskUdThPjZBl2Mk4F9oxS6W5j2llm1hS/vGnFtykQ5NMaxzi +Jkhi1Mjm/KZJUo2xJai1gtHwBOnlocXZYqJQECabBayA7rLH3pFUhU/Wqkycz4m8dUVXLNHiMIEd +3sc0QASMF56kqXtzph2zbXBbCD8afyt8WjMzZvO4lEGNM8xi/7C6h45QsdGZgqkHrYBJbSHfrU05 +ZvNpV8YcfhkzX6gNtZU5XDDBPgkYn41sEt3aVRHvRAqc+uhczQ8svVhPUsriWnKk2bfw8iAn1xex +5huB52uVPRfuL7wJxyV1Rk8WhK10xCzFDnJtRUAJ6UtuezrMOh28NPULQnLIx1kF00+uflY5vAHM +rAf92+NqORZUflKVidqHYmF7bdeNGw3qshaK/0+3grs6rQeQAvxiTdmG+sBP9poBIeeHo2OzcACB +wTuerZiYlzL7mAUegdiPD+wOa2yfGF+WG2vM9npO+a1ZWsoWceAxpLOyubBVfLyc7lfCo7ma70Vd +Kl/o7VevEqLIz5ZkaCoupWk7nDKDMG73vGXqJwaYjd8teOw66aELd2WI4cAoFTvPayxMKHD8hf4n +78riWe2XomUzafZLoMhj5vfYsiwwL3F5O/KUtTOXNNDDVuAwByiCfN65LIjU/Dhn8t6Izkox/Tnl +9kPqNxqJAxFtARCFo9Xpgba761dTBmUF9J+Krg6B53NEv+0qvJY3w1H8Fnop9S+eEs6/4qUMmgO4 +wrm3aEaLY4XWGejuxUEQ9+3/cxK1YTJIpBeK8Q1/yPgj2mq62RRGcyDPEMbcbFcsI4MKlGggcpHV +H8hv1XPLbrMi56lax3dB/EkJzJ+5IEnYd0NkXclyQm4d7KUy6LG5I2Quwt0J50dxbqmfR0gWwGsY +nsT4Kk71NiUyU9AWl46EOZIzONN4Vnm0qq3oNJ5e8VpKTb2g80m5ouw+tPiDA/IA3Vu3VKLT589j +5IQrNYhrizZnEApqPAQwBiN6D+0BLgsNeQDUn56emMj1ETDgfjukqAQjlGUvAr/VV/+eFHvkqwJU +Hy6Xzd36Cq4/sYKYVU7OFzh6Ts9gCvblZxbFI1yNimEvwZ/bINKAemQLoji3s1UIs5X+BYqKZpI5 +nZsjbIHLafNjfPoMKUlpQa27jFc4s4GQ9WLBDRnVIuzqpdmdslxc2Q+dwzbT+zFoAAe5VzA+ABxv +cjPYCBVpys4hYH1p3uwUq/hKkR7QgPE2c25qIHl+6VVS9dgaQ4XnHtVZjFzDk8u5YNenHx8E3lx4 +Ebe3mNjsM51X16ERkGC7X+w4Ko89wvb7jnnOheC0W5ICZQgphdasjff259yEJuhfk62r6bhZH2Um +2IkUACGxKaEzh55Z5P2rcaSjAwIeWnLHDCPSOJ819/4XQEtPfbZs9eymDwNOg13kZhadSQF8+zht +0Tko/9k41bNaT2ZqogskrIF9oltpofddqOa5IcE2d13T2IuDkV8/whV87P8Dg6fmFYpFCHN7zsks +X+IHrRIt7gILXPwecu2LfUZxdH/Cr5WbfMzTnsWWSB7/Z9MLrlEISHM4zC7DlkbRSD7LyXyI4weh +HNelf0uLtYRhXku5BkJUyysIYDpSHHxsMJ04Th+RZ7s8seoLBeAn7gbsj3B/JUOxIaEx8+W3bjb1 +wq6cc+KqLnvcO2BDvH30PfeQo7YjTNr4wcEoUFZXwhTL5owVc4GKtlfl/YxBXs2E6r6l43svlay6 +vCq58xTvWzzRtzvb6oh6qnoMP2xc8YTdpKma64TBmnFOVE/eGXZxVyk19TXwrokqUliutqhM6acv +x87+Yru+uXTbUpMA0MuW0Ch6uvcwxmM1hq5vHDVBTAfGuXsdQMapKoqseFUfza7N2eSgU8oaJCGQ +rmhvDn+MNzh2VyLOnPBwJ+sUnHM7XOnz/rCD99uRhhssEwZ5Xij+FG3EeTYyntGp6Z7ODIazLHM8 +81QtQDrJg2EDJ5RZHHrPbyUQDCkGpLZNOOoJkAD7I0VZRC3jJb8lTMXdKQjCd39F842+FXTSvOv9 +lmEOFH4AEyI6CokzFQCD0TXhTaG9wtzaE2q41eEKF45J5vyQxrNabZXeovNIVZryK+N8ep28M084 +vXp7uJm0bg5NunK6vTIqsxenQZWvXay8EwYLbAm8crDxK5sbW4tZtNeVxPE6ekCbifdxdgm0671w +rt4wOzAfMAcGBSsOAwIaBBT1C0A3jyKtjUTFASRSO852mKBZQQQUqy721AxhZ26s5Tsue4OHTjEB +CxwCAgfQ \ No newline at end of file diff --git a/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/ie_self.pfx.data b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/ie_self.pfx.data new file mode 100644 index 00000000000..acde65c2ebe --- /dev/null +++ b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/ie_self.pfx.data @@ -0,0 +1,47 @@ +MIIKRgIBAzCCCgIGCSqGSIb3DQEHAaCCCfMEggnvMIIJ6zCCBgwGCSqGSIb3DQEHAaCCBf0EggX5 +MIIF9TCCBfEGCyqGSIb3DQEMCgECoIIE/jCCBPowHAYKKoZIhvcNAQwBAzAOBAjnValj/qxAxQIC +B9AEggTYZZfhDgMBhoV+P+A4KJf/gnrbkgp4ZDWzXl8gOttjRXofhACETGpX5IHsE7UnXbRc4T70 +ByZGlcGTDuT9VgiFnFN4VTs1tRIz2W4cs4EmogLX2sX4KP3U6lZiXugEJ36wPSSN8A1prsZsrTid +ff6bsi+sIO+OI6X8Y0degOU44huDhZe7Fmjed13aW6jLhr8SKRSoufDR/sjVnJK476qkYZc4/Dlr +sMmYftHdgxjfm1KdOVycWm+1ItRzniZemiYYYB+vkUBYPO/rMKCp717SWOQhs7SNQcG4KjdLs8vv +skiRPgRzfbt6vaEC4yKy27FDFqzx4unLRzGJ+ekbLzzZAu4TMS7j5g7Ngo0d7GS4+ZGHamOvDuXQ +x8/Itv1/0qzGMwLXyu1x4K1hTgFKD5NQoEk89qZMDVXi4ylGTWXE0x5azKCXP06LxP9/Pit/ufG9 +CwUAIeDrZ4A6F0hyT4p7WMgaUqry54/YrjQBd632I7FacKnYojgcW+xQeRufxiYJ5x/6QIZ4dDmj +4rX7W4/0UOVlyFltmmoSq1HJRMaw95iUE+ft3q6vK/bvy6FZSd1CAbr0tut6HBmcW6BOdXFGmXGS +JnbwaK1IFU4c6KOVAwP16poGhOxaJqRaa4zMBaPcYg84rQ3aI00UHGKQvRb6UWYVGVayc13WYcGQ +Mm8GEjlmh4URRXaRL1qTKCjjYjG1mvTG+TOYUwGZUOGD+6fkGFKMkNXxLmaDyyT0cSoBeMl4whQx +obafWD8sMxCJb/E0eil/fbu114rmFfrrqP2evPEIuQoacNr+OUnfr+T6vbBpT79emxkgsKuG7eEt +4okYQTCp6aEpk7ZKppiZVOBvrN1lZfOH9s9qqtbx5Y+9uj5aGADHkhr6c4pYoIaa1BuUKgBiglE7 +QdRFm98TFlC328BbUvBFXEAnshXeYHRPgevcapDBIqFz8ZBnJNMgY3KZ+mug0wg09vsFE8TkH86p +WwvgUzLlZDNt64OHh9E5Ql1MtnMlp0nunpLQyYcmCn8AJIcxSnaicjSlp+Z04hSWXAesbWie41H2 +OA1CqsQdc9EePijdjX3QxDK9mBNhXY2ngWrvwkmlYatHdSFzXB4uzCsT5NKK0nKI/AmUN5vVVv01 +CFCPHgyBBxF1wom2mA/QFv+7WX6c5Oj0WgOLe/3VySQ9xPoI53Cc1Jl7uOm6kXIMzMxCOiDDcScJ +i0LwyDtmVZlOqhiGCiguoptQnTT3zzp2uaDLVvyMy7bZP8T7G7ka7CSpWQNr0USldgpT8HOXJWgI +4il9iQlaajYO9ntwtYAlMTjsYy4NNoW0uYajdnjT1wO+0w1A0SKP7UrRnyaonf/G4z/VeNSh+yEn +7RkFErPhhvHQRFMG3Gkgw4ER+zo7Q7x2m5R7FOeCp4x0/wiI0e/SzyYxBqXSQfEWxQjb7IJVfd6a +gFT/heXJDvEGbLzUR9jhDptGggE2NlFyA4G+ol6XRRZKlBA0XUYJPHY+fyvcHikiJeMM/YRkrhCE +LOqfCNOafSSSLcQNzJjevq/cDpgybQZV+BrN3yPtQlZgZAy9jOZlULVQSak7K2dF355mEtPNQUIH +4U+GdMXitRVknz/dv7SF8tVzR/GYJEX51i0Qou+rzOFhmurxHyomRHnB5WTG8D/SbzGB3zATBgkq +hkiG9w0BCRUxBgQEAQAAADBbBgkqhkiG9w0BCRQxTh5MAHsAMwA4ADkARgA0AEMAMQA3AC0AMABC +ADQARgAtADQAOABFADYALQA5ADAARAA1AC0AMwAwAEMAMgA5AEYANAA4ADUAMAAwADUAfTBrBgkr +BgEEAYI3EQExXh5cAE0AaQBjAHIAbwBzAG8AZgB0ACAARQBuAGgAYQBuAGMAZQBkACAAQwByAHkA +cAB0AG8AZwByAGEAcABoAGkAYwAgAFAAcgBvAHYAaQBkAGUAcgAgAHYAMQAuADAwggPXBgkqhkiG +9w0BBwagggPIMIIDxAIBADCCA70GCSqGSIb3DQEHATAcBgoqhkiG9w0BDAEGMA4ECBHBi0p8N2Vx +AgIH0ICCA5A7JaVFBqZTQbSEJhtjKPmwteV230BLhKvw4qfM9vxcBNj8kBZGDJaWYZK5BatuKMu8 +xd60lqzoKgUOHrN9etjMCe2h/z/RyyeVpBuEILJUQaj+SuSTSUUTpGKokKVnSQvCAD1UgJGFt/ac +elBlaIw9pRDnDZgFhzZ3AWO09vBz+GcowUlA77W173d6fHf26khicTalsdXbimnMt48/mdtKH9ep +pjgxJwhshPhgKKt5M87nEyaaGSEFfsrPgcIj79poWwj8WE6sAg+bVw3OfX9rvbpP2vWF/e6Vc2x/ +QJPChQZs8LqJAUy2lI55gZgv+hTKkkBXoHG0c4248KdyvBT5DCiFufaj/dp1Eja02Qxo+BqZLJS7 +EYE1YxB7Ty9CUxWvAt6aRLQ0ZLbrK28mwgCePctczxQa+tcCMCfL/JJvcZtiu5CaHObLzF7Ymbh7 +/Q6u1+5u3/Im7aBdY5AksTz2Zn4JjzSAXKTdEgcadjGsxTd/lj4dUOreXN9rUgNyQzjQHpljnhxF +6ZAAbNC8FJwFIAm+ipmV7keCWT8s6MQeoQ5qr5RDhVhGUVM2CWoKRjhbKzWbnKetfmjAUnvn0+ZO +vSKmOShMG8QgyG8trDIH734jTG6u6yoe3Afjw52DtfOo1OVi0ZDsj5GviFDZYQX5Z/86N4Tx7Tol +e/Wz5918nziNoU3+07ZySsRRESuLj6p11sUmFFPj64W/CZ1YQB/H4+R+94uYyWiovHudC/69KnBg +Rfj0XpdSg0l+HKgTez7OuJrEu9/+5QF0M1unJSGxpdojVkACf+bxu2+4czzh80sL/3Yzcenvg/nt +AQGm+sX/K2oF2E0h/22RD4U2txDxORVGcF+wfNUHkl2m+rBkgsUMhECeWGwoI/y5ZBHWWcQP2ByZ +78fa8a9L1RWGvn51yLOe/cPZ0pmYBDZ9aiP1KucGBNMTzHefZiRXscXjB28u7/YxUb7fFPY3RjjO +p2Rm17rrFrvR9/oChO9ZVJrm8p2lQfKufz/t1USs8+gZPS+kLfE3wxZefo1nFmbkTWQT6hW+z4zh +0QoBNwGJVFYxPuGvyOmQ4ksEHe7G8fc7ihkiZ+A9fJROqOjVA/ThnWIuiLKbDFlW1rQbdlihQy7Z +oKbzbA9eOMUCaXMEti5CG/97pOCiElARHDactfiy0J7ykjCGLCkw1/3j5Qdr3feN4GWqOBTfn0cK +eq8RT0pBkT0wOzAfMAcGBSsOAwIaBBRW5H12kY01oB2hnm0lkT0yUbjP4wQUF7tfAlojMdSZIdKB +/FfU1hlVl8YCAgfQ \ No newline at end of file diff --git a/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/jdk_chain.p12.data b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/jdk_chain.p12.data new file mode 100644 index 00000000000..f379d2ba380 --- /dev/null +++ b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/jdk_chain.p12.data @@ -0,0 +1,62 @@ +MIINqAIBAzCCDWIGCSqGSIb3DQEHAaCCDVMEgg1PMIINSzCCAzgGCSqGSIb3DQEHAaCCAykEggMl +MIIDITCCAx0GCyqGSIb3DQEMCgECoIICsjCCAq4wKAYKKoZIhvcNAQwBAzAaBBQj8/7sNqA6OGwS +O3nBO2jejhMCdgICBAAEggKA+SmvxFl8NlTv9TZf9YTiFOoUfLGNNxX+KaW9Qy+vBtAqU9rIqLeU +Wc7K5ovqYIcOHUYqjMECgfGWKEcT5XQljB9uPXh+L55glggXpJ6ZtgNjwOCGfXak+x2nV5ynIRD8 +196Txb3tyGJrEEVvmm5UFMRnFbUiXmwRvV1nBAgAXFCpdv+cowKsY0SS9NIyYujzhObByV70Bd0Y +rOTV6Wvg/Pw/p9FpOskiLSgwxY0Eb+ryAUjMs+DXsH7okVQj5xriWKz2jyRSMvRlxj7qL+SvgTcQ +J+2dB1QO9y34AAP0eTypJhZ2aEZl7PiDJ2QigP7ahm2YCTpGLyR8drrRD4UNWZ6WVt+wp0giTkmd +QHYm/4XVqUDcYbXjOPapfQPDgWEDZdduGS/Lt+ELfeItRP+aPQxBaZoRjfXbUmv96WSbNl4YSEJE +hq3Ri+3xClzXDK08AB1g4ro9kQSMJb/zt5We+X9XLaDl2w4H23/MaMcuBbXb42eLIoSELcBYAlc+ +ffoZ/5rXzRfAjVO0Po3qnB6DAa68DTa1goXvQy5C2j/Qf8G4BRKumB9pXm/CxqvQOJ/1tXZR9mMe +D5HALMI8G9Wm1wyf01FNDjNQR+BhDHM6tNNyjvc+ibt91ihtUWjGEPLyaenZbTwu7IwX/NXbGge6 +xFhzG/NK1t8IdDCpOz/1u5OrCRuD+wUORDezg0XoU5AOSmXZoj8R/2nps8+u3jglyYWknwlid7B/ +z/P3l0mScSHkWhm377flKwd4i2xq8epLmOdzjc3Hv6BJnj/SuLf1Zihlt9fPp17R48D6Diklwoci +pOJb6ktXjhcP9NYryYKC0jJkxONPImhStpS945brpjFYMDMGCSqGSIb3DQEJFDEmHiQAcABrAGMA +cwAxADIAdABlAHMAdABlAG4AZAB1AHMAZQByADEwIQYJKoZIhvcNAQkVMRQEElRpbWUgMTA2NTI4 +ODkxODE4MTCCCgsGCSqGSIb3DQEHBqCCCfwwggn4AgEAMIIJ8QYJKoZIhvcNAQcBMCgGCiqGSIb3 +DQEMAQYwGgQUQ/DkvP0s9CqcMXsf460GeDOK4AkCAgQAgIIJuHO3HSQsW9lR/QojhuvENOWLWOvW +RPdJsxTnWwAzpEBH3BRiv8zc1tkNs7N+U9CbIZJS6O4qDe5Is3PEQAkbxZeG+4IAAMUqataDtX3J +uZkFMbQEhpWYRfbwVAsM/boTMM2gd49VRj2FvtrplzZqZtkixhg+DqJDqtqeuWonWKjTuRP60CXe +Xj4v3ot9+tuRzSk61Iq3UcmiIH+0fvqdk1s5bVWAIrwfpRqptG6HVcob7gTrYUvL+AuVm68jUtFO +KjRbHL5OcJlnkNUU+dOkjH6eJWQKDPCTzJU/c4lwOJPjd/EuYVKhMfEC/4HoR2hmxeJn6GIosDGx +/R87K80NVQm+IQjXeDdQ/XJKwV+2CjSfJpN/Y6VcCq/74BYODl0OixG7TdsG0igvn2QtVEQyRyeW +f6A9+ZQphhyiZ1ZIGyfEdmgAgSgc1MX5m1xkeSZhKKBm7NMcBu3Ilrx/35drqNb+1mcFCqV6f5su +xnlzTKx96gy/Ug0E/4WbttwD7cCfXbpz58/8hOFDIeTGRbuvCpx+kkXRI0Dm7ifFkwNuV97G72n+ +VxzlsYElAF5Ek7bQFbVYTqO0RhpxGkjhCC6qZLfd7pq432sD7j5+VcI1EG0SWu+4GzO2j4wUkACZ +u7k2Kt5dAUAQjH7rk4c6Y+Sv4aCBDraLnyi2fOHPlrhpPI3pGQ2YeV7949Kwz6RElf8cRFN0dQ+y +LamJu4ymgfvcQH/0ui6QKU03knPJJ/VK1DKOMUx75rjCQyNe3fENyo52Q/Q/2KgIHgzDR4OP0j1l +/xmSeeAsWRhFOFm3MPghykgMXe91VgdxgpXKP9MksxC+2B1UjQAXD36E6dn12fpjmRXGuD/CkTGb +trpNX7fIIauYfaXsISrXJQui5cTNSjWdjxZI7k/78IAtTCvhClPMaZ1Ru4sep2x7UylnvMSDO1+L +j1gfAyoCmm0uJyQAHU+9OBiDWZpdMChnol2fmF3JroUOAy/7FF/aOjTpWMKxB6lynS65d7uaclls +2rqzb3ENmHpuYjAe/dCLyn5Jv3WT43+hReMcFOszw0YdkBBOK04/6BlHAm9JV6yoxysORCRrih0n +ut7/p5pU8lSSTkszcmKbw3priHKlHa/A5mxkwHxIsVdQv7NMjR2iGrH/IHXHF4vo3lO3xMbuUl+C +7StCpA61Qgcy1+reuuYp9z+uA4+KGrPDjZbkqIa8UR7PdqIvGh3Wb48OySYWtenW2RF+Wq3rXj8P +98g6XZlB5SUdMNBQry1oaHGKGNorPP4uJkaOy7FiyujaMFPd+WOTBgfcMTishPTZrnA8eF41jAae +rA5qJA383RKxE1iopq255oJwdxt1bDv+ad9cnyY2nh9t26ASuoJ3SyAZrGTqTwaWq1jrx0Z6LnSn +k8Cas4Ig/J/Coqi8A+EibADDPxxJNXixyNwepFlplKsSBlsFFBMvij4dOu56yH21B6lwAmjxeYcD +sFcEuHu9Yjl9XhELiur0WuVUM8FpuPfD/I2KlsG6RjY7vXXuQ6nk19l5ylxFDNV5VweV+DnsfZI/ +trQ/o31fLg7Y+KF7OHnNIclxpMiz7t8c4UXwHc2xV1vHDqJ70rHANt+1M3iydQDx+LS69iCbnFG8 +kJRQgBR+prhs7dSA98vVdHLYa4/RRwGdzj8jeQ/YVEOOMfayL8EZ9uKbXPsN2ijLsieJHhDHDSmw +6GfikIxh8Q6pPjxmZWEwLh2gaSRX3VEYjFqg2FxAKrnCB21csVXc7bZSmuDOU07AiALfEQSj273F +LVZKa0HBjKzI4DlBMOhGYr3NusZvwk4/AK9Rti1kQl0DLOZ1VoNtBysefs3AyyT6Y2qZCsG3cFWI +TRy9xOrX7bjIjabmDWWWrcWmgu1UyN/5o5Jm0dhXR/6RIqbOWC56ahrHeGAxZfGfEal292nXM66v +/ptu26ap4mixi+hrHkt8gGUO/LkmVqINSDpwfiWiQpbGVYDoKZCKF2cNgK6d3I9EfsOEXmejTROR +86nVj3Uz1otQ50sxVu8zRaH5Kkys9EwVOQPHsqjWY4fkkUAbLFc2Xk+D3pnyZFyBijRjE05Xa2QL +tiOr+PH9tIBMgkn1AIddmg3f/zZIfLHxw0Gj9r8rqqyO+xwdokdzF3n5vq+uDZB+bMqY0UG/aDfa +0amrPqNOM4EKz3xhlpmN/wrVIdpSYshPMwgyWbX1fuHipBgm0Sff3lVq8ejO+VXnqNJ5Pi5NowxQ +4gVyE2OMtU7Ya73Sm1leWSRigI0MpLeVCccu8SxGriUTI0G5w1JSq1sqr6q16aL06/nlU486sQ54 +LtU1EGpk6BW5GXvVjEqE+Dee4wEpoKf2UcftZ8TO4ya3BmEWYMBiDLIxWvxV/Ppm3pIBhyH0OfLY +RN1JPAe8CJn4mZ+TIWBVNMWfcSYKKu5Sk2s2sulU7aVRQp+xvuGC4s6EopbDY1XwKdc6cRyVUccA +/KD95goSlXcxux6xA5LnxI81QKCiNmnQk1gwGY1Y6P5igW5s1HVbdbthVc7yI9r60vLth+TQr4ec +AdnLOh6FTYHI+GWzcBDae/TiAU/24PJJfZDMEoZjvqfWni9x7Y50knH8qjnFb84IdLjb0E93+yj9 +4nyrKtMp0egVsYA4bblyHL8O54J4aOGtg1CjuT1q/TkcTjd3Hheyu+kYbvFpdbltKjZ/m+Vob63G +fwoB0/JPIZseKLjSMMITogNVezAiHsJV4kYyMOmnbRBLA1OyIiV0gnAnX7KpUXg0DXsDO4H9uxGv +DVm9QyD832m7HbDe7vzJv5nrq0yxSJfxPiinq+5GmQUVwYFYsLwfvkUINF4CTeWvFGumOBTU5YNP +4G2NVbAgkNpBwJhljABNXChChAeesBvQ4fTK5L3WwDcCO4uDEIHlIQvd4QJQa+QWQ39voKIOnjz4 +/jGwqFcssy+aXnlI6Ub9UpMkc4vcE3rVB0qanitlSVBszL97PSorJaoddKs+wMBwBiY5RlvRBaFT +EtWbiWfLEeAC4cNkEmDToMZNwE1fS+0ZqSoOYqEjAw2M4HXvmZqqS6bP9zEs9n4qCKaT2dYG6rQB +wpHy0WH9myqcgdY1JILfRpQK6PehDXLUMT8a44Fk9vxULare2dQ3uTTyBqfE+B+ainFQ/QBxP7t+ +vsjPxPxxD22eWUT1v4xhT7mzurM83N+AJAaAU2QJ6vYwTGS2NNTDjmm8pMyoLjey0KJKud8isbAC +mqsZHEC0tqOkdVdikLEmcjq5yMl5qZpDYYHrWbth8/5bdRus+UWj7jXOMBW6h43eyKvs4/HEhWEd +KRyvXX7ylBPr+Ow1JYKcg9IwPTAhMAkGBSsOAwIaBQAEFEkDUNCE10mwzwFgzaDBuOaQNXMqBBQA +IsNed5PjTXd1/rQmWIcCDOy9lgICBAA= \ No newline at end of file diff --git a/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/jdk_self.p12.data b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/jdk_self.p12.data new file mode 100644 index 00000000000..b643ba4f20a --- /dev/null +++ b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/jdk_self.p12.data @@ -0,0 +1,45 @@ +MIIJzgIBAzCCCYgGCSqGSIb3DQEHAaCCCXkEggl1MIIJcTCCA/MGCSqGSIb3DQEHBqCCA+QwggPg +AgEAMIID2QYJKoZIhvcNAQcBMCgGCiqGSIb3DQEMAQYwGgQUAz+z63B0n0UriCxfGp3W/qYiuN4C +AgQAgIIDoH9ARpsBx2g6u9l+FNrXZa7dQZ+z2f2XhmM60HBm4m1eeZtQr2E/Yl4Yck33qT4L6cIp +6cR3cS+pHe1/jlgfP7QaWSDODj6QVU2PUZfL95/9fScYvp2DOWH9PD0qVBJVIZAh7zJb2/CXUXxF +NSSFbTMo3jaTqYHg3I4BIo5CgyN/Nj2bwrcLMBwhk6Le328bT2jApkIMUSfkWb8xTBom3PW72pLc +h7Vwgf5hrxSF29BIwGtzEnbVJMw45oDlsieQM+SICmXUh/uMNn94Z+17S0DDHZNwg//dRevbY7iF +IPSiNphFeiD3qEX+4GvZO8g3esbxUmbN7yssJ3WftOlfcAgMZClEYjXbtEnGtvFEOTIWCUuCIs5B +UgOO0ySzoXdwZx7tHfYqmkSK6APvzvUUro0ynwz4TlEL4M/+O4e/JaOKuv/O7g43wVZohS0GDu9a +S98ri5aEKm3+evPbnxclbsrGzoym7tOWCaq2RIKfbJB/ARJuIWUGWVr5LHw/ovANgGIFs0+Sla0g +sJMR06OoS+PFvvPBUoW2bEUXOf9ugposQuHIDuw8V3EP1yGuOYGTM7IZSf5cbKZ/2NAQe/oc8hkI +VqcJeYFCRwcFqacPJDa2IUaX0ZhR6WwGorzXPn3i9YDgTo55+WqOjujGlVnRW2aP6E3JbwJh3q0x +hHIlvg6rVa6MgqKFl8/mNEQPvUMiNojmo1GT1xQ6KhsIzJQee7ZyLFBg6pJU7aN5hxh6J32Y3SBd +VAauKllwSZ05jR0U+WYFF3NfTR3UgqSvtyKfLEWo4GFhEKpp5NwCTtTPHBs7Qt/CTr3QyNZ8ciRW +LpmXRIDe8UGschK30QNr1wh9DrK4LU0Rsl7oYhFUDEGE3dxIqgUifb0X5IpX4kjpK7NODmO3iUr3 +IT77Mukk8LJk2pfCyerPh9NdXS4fN1r1coTWcNwXt+FF5pzC8Jw0goV8TWCk4izmpmroi64UKfam +h/4/dt+fZLRpP8joBMxXmyvPRECtTF2Osz6WxOenRnqT8CdqxOITwsuypk1ZZqIc1zbQc53ddmOQ +IWZp3EopTM6NUem4J70yiZS24Eve4UsyrkzINvKTiuGGWbiAAgJlegi7YDmkbH8nsNvDtMRgvst3 +uYXazCGii7CJSNFrOSKebi1LPxISJmYWzuqiS3b/VO5VkRp0w21n+Yh4gOTsn8tTkZoWV9kOuZzt +odHgt47FwoprVX0bwJ5jk29fWsw2z9UwggV2BgkqhkiG9w0BBwGgggVnBIIFYzCCBV8wggVbBgsq +hkiG9w0BDAoBAqCCBPowggT2MCgGCiqGSIb3DQEMAQMwGgQUEyyUrMkExJyP55CaARyqFL7stccC +AgQABIIEyFyuDycIN0LU8HtRhDr3dbX0+fkXmgPAHX4CyJTS8YzV5U4r6knRH2EFx/EbJq2/ql82 +OfXFg2BBvnlDdf9H1XVq6e3yr6exxRyOc6xSQiKWU1RpF8AsYIpiYfYd3MErRK/Qp2OnPAU++5S3 +wog/Qda0a5tRSrxs/1M6Ts5aBDaO4YiQIu/J9VaU+FMWx8F0UmeEfm21DNUgrTQxzdB6m0dHGcXE +XHiba7VT4t4f0qPuBBji8tHziipvCer4m6KQJxPN0UhheJvhsqO9AQHSrUXeKkHBzhqojP5gPc5f +HJMGhi5zIVUgBtA9PRB/IEUZ02TFOLoMu5pTRGrVSoSjvJTDhjrutV9w1v6ILyJiqAUA1Acza9Lg +stVAA/sALJhHDXn6HcQqyT9vIG+GhswOvRWnxnDHHxTbK9dy2RyhpBgGkBA07pqmB1pOyPvoJHfj +Ix9fi2g7K1bdgERYehSfWoDPt9joYnWfg2TtpYduDD5hnJA3bqb3+pARFKe8G/4Y7WCILQKCFvQB +p48a5sq+Dd5dWlyhUNr5fxZPsVpaMa5nA/iFog/ILocBsGmCkOA/fXeO5uzTX/ze+BohE+d2Y5rp +//LZyvfxSIM90odzUNRvKowbRHKx1tKReOKXLE9UkwFCraMOXqX4DhFbuiXvLYjqs45mbfZodQ96 +J+lJvPvS0w1xl7okRhvD8E5sUATgIeIAapU7sSZLfsYXoSFndNBgUfZ+7bm574sM6y2tC3Fd2Ytt +jw3/avfk3V0L4ddAfpYMCK1vJSgNiGdAwPOe8ieihn/kg3pY6glQXkXKHZHVIwg4MlGHfw7KBqry +W2rnh9TwdxUC8Z8CzEaT/8fKxYkF9ZJa8bCP5l4vyKOYdy+m4WZMb5hwZ9GxHodcuDzagRvQ5RZd +VwC1SQwXO6ad34eSizBZmHVeYJCA6JrixBRbtXfA6frk8nmKvqSO8WxM0ma+2MBS40wLvWWAPs7y +P2xKKOJJpUuNlDeRTtSbogUnB40KO5IYLqzad9LlU9V5dfluZ3GgI4fWBNZa2ykK2Q77jVTda2a5 +kgiK+/OQYZuLo3gO+3Y5zAxEZ91gqibI9yRv4/XiyxGSiOBY+EUmJLTw8R9j9BJLrMckf22BUYNm +wpcHZVILWmBi7L45loni7DGvsxzibLNMn1NHL6zWZHYHEayI/HqfrRRhadPnizvTwkZOF9XYOrlv +BdVcQuhyigPbOlpplLzJQ5DPmnet216FSVk4nn82CvWZr02RlRP426elooMhABVnKgFhGWH1VtuW +ewja9X+/wznDyP0yzmPldwKn7w1UXkCwI3AdBhzDlkwOAMU1QqunDXnchDvwg0BGR8M23obINGiH +6JwQ/iWl6nUG7EVSqJcZvWnz1jQO0tCgr30YBl31jZ584bW743vANF3tFFo4bacdJlOqGkb7rNdj +KxoGE2XLyVd2rzjdLrcnr4ViwrJRZl+1XB62DVH7cr5+86lF1V7/2UJR3XzjdLV5SfSoBzexLxiA +1gPov8RE8UnVbqhZbqeaR+tQkoeuZy8vyP545+brD1BkV+b2QGJaGMP2DDJC74CpVITyiVm4C08u +2ay6G+tblKuBOVM70xBmbiwq8inFiBd3vl7aObMyj1AgPjFOMCcGCSqGSIb3DQEJFDEaHhgAcABr +AGMAcwAxADIAdABlAHMAdABjAGEwIwYJKoZIhvcNAQkVMRYEFAxeTobq6DehjSbiylxISkcqQqH6 +MD0wITAJBgUrDgMCGgUABBR8ZwGkxtDxkXoUy1JndD2dkf+Q5wQUlDj7Q1RzRmooVNZ+0cEv+M/q +I6oCAgQA \ No newline at end of file diff --git a/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/mozilla_chain.p12.data b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/mozilla_chain.p12.data new file mode 100644 index 00000000000..623d470c86b --- /dev/null +++ b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/mozilla_chain.p12.data @@ -0,0 +1,73 @@ +MIACAQMwgAYJKoZIhvcNAQcBoIAkgAQBMAQBgAQBMAQBgAQBBgQBCQQJKoZIhvcNAQcBBAGgBAGA +BAEkBAGABAEEBAEBBAEwBAEEBAEDBAOCAx4EAQQEAQEEATAEAQQEAQMEA4IDGgQBBAQBAQQBBgQB +BAQBAQQBCwQBBAQBCwQLKoZIhvcNAQwKAQIEAQQEAQEEAaAEAQQEAQMEA4ICrQQBBAQBAQQBMAQB +BAQBAwQDggKpBAEEBAEBBAEwBAEEBAEBBAEjBAEEBAEBBAEGBAEEBAEBBAEKBAEEBAEKBAoqhkiG +9w0BDAEDBAEEBAEXBBcwFQQQKJ0s1k6Yhc9YUlHulAdsYwIBAQQBBAQBAQQBBAQBBAQBAwQDggKA +BAEEBAOCAoAEggKALk0hQJ9bgp0taVmPt+8aOIluzqPyDTizShw1vBVIYUZR632m2wd8hZGg7Apd +y7+P/wZQUhAAiqxWMpz7KdMnt2q8oV+7ghH4+2skdMBIAsK3Z5JH+RH5ABwyGdPmO5Xxjtw12eu7 +D82h+CCkf4VpDBlALqkiLLpT1ktyZuabMtLwmBbKiunFue0NWcXD6hPYuKbyAKW206Vj6Dr9XT4J +0KSEeBTKRlDUjZaN1LgNzhbv7D8G42NBTVRtBVcGuxqwckBf5gd0SqJpKnSt8HOw+tv1VqcGnzDK +hWi8szZq674aIlJhhmbqgMD1hAi+Yv+nFuFDbVnvnFAWBXyYGbZhl3sbZTMoMCGVcNgX+O+C083h +9RsWGvszvqPmTxhFoCRHbEl+RxyN1cJzB4HlNhe3/FHWficDvoWH+CaVOvIZER3hZ3q3q+6hK1j1 +sDRzBaHhjs/fwPrgcEyrzDCg9q5Uhk2s0lSFftGCr6IasFuC9fwk27DQNr1gTnT3bfDveOBs3/6N +2JOSV6GDbWlDPfQTbdmN7QF2OaYzGYMiHdSj73SDr1VIwdqB4PFKPsxqNqtNf97d7i9TIQLS8Lz9 +4/cC13ZyNC4QpdIqr16/VBGBLShltCV/pttORcbeTV1RuKkIfL+FFfFAO5OuzojK8Qb9xFfF24ES +3CmVUbSsVquQ42d9p6Zm+z44YFdJjyLaxXbGNx42iXQFLu6H4AVpRjpuNgKEGYyw+4oL/TGCAzTc +cZC3hPQH5YvaWCwhU/9GWf/+XINthMCH2gtfDfNfHRpy0lxAIUVqXhkgjzxL1UALB12Gmis6ekCU +/HYVRvcDBLM7RRzB89DeSOGDcB4/rq1zzwQBBAQBAQQBMQQBBAQBAQQBWgQBBAQBAQQBMAQBBAQB +AQQBMwQBBAQBAQQBBgQBBAQBAQQBCQQBBAQBCQQJKoZIhvcNAQkUBAEEBAEBBAExBAEEBAEBBAEm +BAEEBAEBBAEeBAEEBAEBBAEkBAEEBAEkBCQAcABrAGMAcwAxADIAdABlAHMAdABlAG4AZAB1AHMA +ZQByADEEAQQEAQEEATAEAQQEAQEEASMEAQQEAQEEAQYEAQQEAQEEAQkEAQQEAQkECSqGSIb3DQEJ +FQQBBAQBAQQBMQQBBAQBAQQBFgQBBAQBAQQBBAQBBAQBAQQBFAQBBAQBFAQU7jX+kJ7Tz1lx5EIV +lvrhCfHfOV0EAgAABAIAAAQCAAAEATAEAYAEAQYEAQkECSqGSIb3DQEHBgQBoAQBgAQBMAQBgAQB +AgQBAQQBAAQBMAQBgAQBBgQBCQQJKoZIhvcNAQcBBAEwBAEjBAEGBAEKBAoqhkiG9w0BDAEGBBcw +FQQQ0Lfb4OSnwCcfXsGpoWUudwIBAQQBoAQBgAQBBAQBCAQIkdzo0OWZ66QEAQQEAQgECMeWQTc+ +8BQIBAEEBAEIBAjJ3QSSmEnGJAQBBAQBEAQQypjzZ3c7ndwAJYyEmysAHgQBBAQBCAQI/7tHMiOF +5qwEAQQEA4ICwASCAsCvI0f870z8Pvc5Ten63g72yigziid2hFhZv2u6zYP/afxQNGhxtJqg6WBR +8unA+UwSgXHXDwUuWThfzEDC170R5o/Bb8LrBF3ART+zZfJEi8/B6laSCCRA2N3RrvYAL/WLi468 +0qIsfqcUkBUWuy30S9EwrbXH0f0DKPEwXO+0njNBqZQkiwoNOlZPqRvzrffMMs/uE3YR9REhvD+P +rtMWYuqLOvcIMuWSwnTNVkzQWMwVkymW9fmpN+C4opsIACGwK0xLhFCKb/KSbdGezPEX/SRqePg5 +qZOtRntB0TbUob9s1qJSoFoG7yKq8qaYc19oIrr2uXvxa9/58UhwAF1TlcKp+G8Gp4SaWfiIsC+b +ghbBXvc7RnPs4dRmBSoM1GhgXCZygbrM2xWUYFwezT0CnCB+1jOhNw2wUKou/MGQ3o7BFKL+wby0 +FaP2bwVb/W1nXElW9DJaMX4L6jxFJD0NFSoCrHyd5FmorIziga4a+U3sLTR2gxW1Acs9NCKm6uNX +DHlql28qPmwDolLwlxvBd/k3lQutN2ApRtTmatLoLS/6/YrWwUg+/B/21gtwZ0LjZZevjheUGwd/ +ggPPPPnqwvh2Lj3vtX55QIRGRhaoMO00xj5+Nv14GADrf0SuHlCmtDH0IPW6kBs+3vqTFfnCf5Mh +kvaizLo0NmYTBwCe8cCFDNgAfIp7rOL8x+FV7GmC7qvt2Agol4dmbx0g5npirtKm93sG1XDX3Voe +odVwAFmM5AQkRovQVil68O9YecCsNDe7UVpqAQy649vKNNs7pjl+0LThzMSX0J4pZe55SJLDOCG1 +0yzlduDDddEDt+6qwNcoDl4/Wyak8HxE4SoQz4gjmeaCMr4m1EREYR8dunTia0101zIrjjrX0PkV +n5Jo2K6TPHQ6t2xL7BdEQyasDY9oJtNjCVQEeVDI5F/yhAQBBAQBCAQICv6r6pOG07MEAQQEAQgE +CM+NkassAbK6BAEEBAEIBAgh8E2D5WRKMwQBBAQBMAQw64ddVJKgPyBhXdFashI1c/2ZfYsDgPSW +leQU5xRNMovja3cNo9PU6rbj5TXO1eT2BAEEBAEIBAgKwj6DMTSk5QQBBAQBCAQIVH7Ksgbu26UE +AQQEAQgECNSHaoEajS8cBAEEBAEIBAhNWS52nNBMswQBBAQBCAQICPU3PkpTkKQEAQQEAQgECFTh +uyiBaQDoBAEEBAOCAxgEggMYyMvmypM9bOpLKi1wzYBWPz9O1UoG6yiP6SFUg5nZDnN5vW5Fl5v4 +hsqz264ZCIIig9Q/krRhPfYi1Fei9UA34FwJiTqwWhS1jtPz64Z4zPp22TcrJ8u/Z66hbRwpY9Zq +/IiK6YtpV51OJWH6vSEX2aeApCTySCWNj0G+MsCh47QUGOccs+fGv1aJFZAFlHay69f57DNnnePN +kpQJ9HtfNXz4zrN31qBqYrjkBqUmNFU93M7AlPJ+UbxZrmJwp1g28GrJDjO6KVhmcGfzqGwDhgpk +JuC+KWFx6lJlFNNBGk82M/UcEBEwdmIhfES4Ed/pfGMs+ilrzO9iB1yjIqh20Cn7TcSFOg0fiUIj +3dcfEA56WunD/TvYS7po2WOhPnEBqXIVjU4ZZD72m85OSkoie6XswFEDI8gLk3PrZfgc8wv3qJF7 +hoWdpsP5XzPeH5gdt6C+ebeUKh/lGi+7sQsUzpYn9LrjcLbB0i0F+Z5DAZmOCPbEztSa8jyp+mx7 +Jrtizp+s3emaYBCE9a1Ri0k+J4BkhMyEBZk+vYOm2GhxH/LY+Gma4sJkp8O18VmDJ9hJerhrqCpJ +CMoajGwzof4S1/jEewDTVySh51kA4pNy5Mh73a0Bzf388x1lzd4UJ8Euvcp0CKWoOPObiJKb2dW+ +bQQ6xqjgOG/SZYCFykndAXsI2ZFLV2V0o0/2daKy61PLexmG0SuYvksXHU3AwGJ+h+LvQUWAK+d1 +3fpZ9XVe0o++8hav40P4mAhntuOjLz41urIqtkyxQOX5tsRSUWOwx0Y/Rc/j61pQafShNe9MQVEq +Oo0vFGyFwsbAZy70Htp2AGktQjCtqHcEUd5+MZFi1OOSllZFIZiNF+ebVu96veURG0xn6soozxzY +Qoe5P7/hpzSjqkudr3XzgJYHGJFcdQcjkKmKs2H5Pk9PFBiBShDxY2FK/BC+wWWVNpX1LWf6Iu9h +9vUmfeHfAXAWrfrRIMbbvcUHAx/ahTy8w+S6pMH07jXuEin65tQmGZXvOZQ0gImrW40SoG2LYeA1 +malP4DauCLGS6flLBAEEBAEIBAillTh0sMOXcwQBBAQBCAQIGN//fAKJ1JsEAQQEAQgECM3dVE5V +yoVmBAEEBAEYBBgdyoE9k9xPE25zrGlKKhDIGb6e2hVWVgYEAQQEARAEEOwrKqIVaGehAzFTPOye +QmYEAQQEAQgECDWCMuxFGr2CBAEEBAEIBAjCuLKgQZkYzwQBBAQBCAQIqJlhaKBT8HkEAQQEA4IC +QASCAkAyQKm+d7+EvEBPudDfFKNaftw5NC140bbcuD1kIZqw/qSLpTusYBcRso7ySTszmYAqNG5w +uXXIy/TFTVG9cdPCS+qoI4chxYscJrRI9eex5rtdoRfsX6slq1XMy6S+k/UVJuHBeswWfZwLDo0C +2XFtwd/UL4cYrkYK+pojd5sedtvtFH8WuezcjcOJ/iAjB0v5unK7EkLHHSkp/U++FGBmGtbZRuDS +ZX9Ge3sH1YPaQO+SVl8RyPDjF32rvvGBNIf9p64TF5PFRp6M7V2cUgfAPFGNR91wouTK6jbE84Wh +mFwkIf2YXAWTmWImaiYkKiSeaAOf+2AqY55iVX8By4Xb9If/Es5rCFF+xfW4v9EM5Wbuk2s/ktNa +26K2MrXbdKNgEmwICrq8NVjqpMqu3LLlVIDqzxO0PxVIyUfaRgmAwGG6iFVTGh0gtHh/JEmuH60x +ZCY8WgBS7nBMKuF2CgxDjMrQ0mer6FonXwPbHiYkUpc7J+KaliyDWmbxwJjBriSj+rThEJ7jg8TA +4Ro1IRF6yzJyAvsXRYXHko7XePizZOsRffXLgSgnzcwh+45AHq9jxMJ7EmWwoawmgvB2WwsD8Xah +f8s7zM07dyhzEifUtAKqgGznqqkY5sBsuG9avY7oNvqdRo146LM8ZI3LVkPG4fyQsyKDkivgqrPp +T44uuddd9aCSin1Lot8V5UO+qF+PWJE8VbbObRRP8QUARktQQKNqUsAfry0FLdJ8Yv7Ib4FLtjxn +lD6Sq+WMMpXGnxcEAQQEAQgECMONWxXYfPfhBAEEBAEIBAhh+55FHbAwzgQBBAQBIAQguWZEyrFt +n9z/zuxAuHPdrjF/M8dpcOcSrrU2W6SkiAIEAQQEAQgECCOncp8X/0YIBAEEBAEIBAg9EPBdfPjB +MQQBBAQBCAQIjBJWUnE0AUYEAQQEARAEEDtzVkwblT0wH2JtjnlN3xwEAQQEAQgECKN9mrkoW0bd +BAIAAAQCAAAEAgAABAIAAAQCAAAEAgAAAAAAAAAAMDUwITAJBgUrDgMCGgUABBQi1DByHr7xEEbI +o8rv5OcUCY4LCgQQBJk3S8mxlQnP+3lHAlg/5gAA \ No newline at end of file diff --git a/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/mozilla_self.p12.data b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/mozilla_self.p12.data new file mode 100644 index 00000000000..c36f26b516b --- /dev/null +++ b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/mozilla_self.p12.data @@ -0,0 +1,54 @@ +MIACAQMwgAYJKoZIhvcNAQcBoIAkgAQBMAQBgAQBMAQBgAQBBgQBCQQJKoZIhvcNAQcBBAGgBAGA +BAEkBAGABAEEBAEBBAEwBAEEBAEDBAOCBVoEAQQEAQEEATAEAQQEAQMEA4IFVgQBBAQBAQQBBgQB +BAQBAQQBCwQBBAQBCwQLKoZIhvcNAQwKAQIEAQQEAQEEAaAEAQQEAQMEA4IE9QQBBAQBAQQBMAQB +BAQBAwQDggTxBAEEBAEBBAEwBAEEBAEBBAEjBAEEBAEBBAEGBAEEBAEBBAEKBAEEBAEKBAoqhkiG +9w0BDAEDBAEEBAEXBBcwFQQQ6zZGbbQFxSQTlsEh5FOilQIBAQQBBAQBAQQBBAQBBAQBAwQDggTI +BAEEBAOCBMgEggTI1ytsmvJlGYHISOsItbY1TnvnTK5ROYkbJOhb/lVbo4/vWNuvI9QtX7FgC17K +PuftyQpE+uIZQpW6oxLMxVV3OlPVcf1NnN/tEIcZJ1oq/Uobjm/hAEKCYhBfWHi7HTa5Nm35/rJm +zC2mdTVUR7ig/Hh1zzASp1N9VLK42ulfOciyxu7Rfw7laLcPixktDB+tC1o8ID6qvu9Et+5Z3kBt +NTL/g1N6mfMw7FxPPbDPTGpRh/FqT+kaUTADCZ4t8ILzVCWLMrhoqPaq4P9fjDxFInjsDil6ufVW +4m8luB3BJzXNqOb86mTYO3FYsbgwntko/psjwyYQeVXCkzcDWELoNPvE/UHKTdRZTM0t5kDoE+JQ +Qh5eEYA8TmitbFn4nGpnHyTjzvGdCjfZvnjDvSWTILuB2oh4xi78LSLnVEnxYf1TZ6taXCjTyMEU +Ki40eyc2mzHYpR+DAXlX4TiDRbek3vEZvEnm0EpQY4EEPNVMWsMlVVzkeImxq85pEaTgoYgpISoY +wRw1UBJt74iuZUFXIoW+qiJcYc/4a+/wBj1rGBAoSulujf16bU8DQlzqiVhhZjmr+HRDOi2O7Fxt +gFN0Wh8nW5DpdxyoUpkAmek4F6un6TpBQidSCiBgm/oqmYWpJxWguV3JeciF9mlZOxEXsfh2yqs0 +FUWv2iBW7RvqA9mdufCDy9iThJ3zzDykU0R2kxtr7nFvDmn8GM3ScGg2qTJwLWgba93+EvieYR4y +aQPZv0veeZ63twfzroL+Y6tc2+LT4zrdI1WTXxlH8RBzcT7CWBC3cT9rndpcVVQAvAp6MuOARPyy +gfAPsMcaQnEH0maoJDW7tqyvJoGY0qpeN2IvMQV10xA7kndjNH4SIjmrFCXbohI//g2apReDQ22n +Y2BXxhheNeNyC5e5WZuhDP6ambpcuUT8O3pvC/oMNUSYSzlS8MLjaOdOTVWaCodsuOYLx0b++5VU +4ZvvUDkzdv13280bVEwbIgdAmf9NG+EzSzfC9QbP2SNjrdvWIdtit8QMctJcQzs1DNQdf3L+3OBr +kTKsheL6vK320hZAVNg0i85tkk7Y3/i1Z5UGXIu/dY6DLWYibDpXSe3A39Z2TCdDgVsiznzk64XX +JffMOyF+b9zc21ig432hS5GuGRr7+BnAaPSlPdZ6pRTaafAmxRiuHCPlmsMj3p94jdzQIZgOzkrc +DE+MBhZZLsCBtfIY36ObHZUXYldjbleLTnGyRxxgJaC4POxhORD9lyVyCzlcMLXkJyrqG166+/D2 +L5bKXtRdZ1vohu1DQWnrTt8BjyulH076aIMHYRZQCkxDC3d1CU196+vaGr0fNZzJ7SMEu/4ITjez +gWF95vWmg182WzWCC+EH1WCLsuwL0Lk/6hKENYpUzAxyIhbc6UrP6ZriWBUbRzIhP9LnJcTjLOtZ +o3YOE1xOGisdIkzhNCQBuHPaJmY/bWuMa1705n/AMN+Bgqj/0qVw0L+pqBRSbfQk0MlAkVDTE/HF +B9EOVwew9pqgNPPSmZNSX0pzYJoyuDhruuJKt//PLWxfj0Nk8MVxNBC0m+0PH/PYY5JR2BLIcQ+v +feTp5qAUaZPROQjfkdTRP0vMvZiCTgW6hg4hv45qEXy+3zmDG6EyBAEEBAEBBAExBAEEBAEBBAFO +BAEEBAEBBAEwBAEEBAEBBAEnBAEEBAEBBAEGBAEEBAEBBAEJBAEEBAEJBAkqhkiG9w0BCRQEAQQE +AQEEATEEAQQEAQEEARoEAQQEAQEEAR4EAQQEAQEEARgEAQQEARgEGABwAGsAYwBzADEAMgB0AGUA +cwB0AGMAYQQBBAQBAQQBMAQBBAQBAQQBIwQBBAQBAQQBBgQBBAQBAQQBCQQBBAQBCQQJKoZIhvcN +AQkVBAEEBAEBBAExBAEEBAEBBAEWBAEEBAEBBAEEBAEEBAEBBAEUBAEEBAEUBBQMXk6G6ug3oY0m +4spcSEpHKkKh+gQCAAAEAgAABAIAAAQBMAQBgAQBBgQBCQQJKoZIhvcNAQcGBAGgBAGABAEwBAGA +BAECBAEBBAEABAEwBAGABAEGBAEJBAkqhkiG9w0BBwEEATAEASMEAQYEAQoECiqGSIb3DQEMAQYE +FzAVBBAr95PVK3vr+5UJmECRsFqzAgEBBAGgBAGABAEEBAEIBAiif28iXfCoFwQBBAQBCAQIIJQU +kCqHwT4EAQQEAQgECCqSwJeWqg16BAEEBAEQBBBfOYWwNlna5Nj3uiiSIXFLBAEEBAEIBAj5OiZ6 +Yz8bpwQBBAQDggMYBIIDGDmuJQskAtlahFW5Z1tGUOB8pTHKkmRJZdWN/2mHZBtBPUSE1J7Y+CnW +TC1jD3PPW1TiAn+7PtTGjEV+Ib9FvLOUKGj603P2mi526WMmO/KN9VrPo8UFTI7y5D3Jjv4RDrWz +K7IAR+i+usDLYLFRNhN+YF8tonRdB18/ZzyPNbkmoYbIngMMlXY6w92RC6VemrkRlY5T2mdv5aEo +IwDCaOgMeG6VTU2OvfGq5XoA0xCULMARlN0YtP6Mi1vjqD8FpXW2WGgiBdTIOKzMj6cO5Pxfmi68 +573Nr3+Obls5C5pxNtD9vb0JFmgSBDdIuCrDS6u7AQDObH6cisJD8GYMPF74sSL3w+X5lvWy8p2D +YaROmMzcSu8l4oCOqa+17wHtjFjBPj77FEUSB69NmnQXudI5qMWeQ4LjytOcMrzsIN7ul/dm6ifR +gQjYkcSPQGbY0dA3scmfb/XKcUkvI0L+Hi1o95NKkU4aoEz9GhGQ+oA0UGSmiLDKCmiNkVKuFBd+ +x+vhze02D2h05x1HnbhZ4I5W8dPqtP8dLlIB3qOzP1sdDEBKAsCbrYXbDAKqPUeEZyMBBzSQBuKM +16zBsz1JO/B2DVdxEA+nGf0RxSHpHFlHQbcPZqa7PIwL8qi3OXM9Pr66Zn+VKmzeSEWKUtv2AzVc +qUhZxOljaixnTC1vWs79NnNwy3PAuiAaAbBsWSVIaNHvdp4HMwsawN/KKlAjsG6PNMQRvpHyJOL6 +QQtQHtShyaBIGqHisG5C7nbebTYZg42px6fvviNfzcQcIWEM/8Nx/jjQbf2ibRLiqJIjohKQzmfR +RQQ4PPsOD04S9APPixiCgkwj+SrxCFu7u64QzRY92hpDtl78gB1qcUZOCNQuf3kv5B4x5ALZyZU7 +Ckr9yu3yjNbgpnJ8gfFE006iAHqpLU2rn6i/xJXHb8cKv8VMHxO0EMR1SOtC7lLNI/iOIpN99/Pm +3U9j6XwcIWoU/4Be9BITKqIw423XThI9qNa9dGj+Oa73xJP6J7dP7gWk2ZmSJclXMA6W72rNqBVe +nO38KaAW72ua7AQBBAQBCAQIeWKILNPVXOMEAQQEAQgECPpwizh9y4WnBAEEBAEYBBi3tGsk9rHI +yZSUfNtMIDrErllTfg2GN3oEAQQEAQgECLz46GLmSgG2BAEEBAEIBAgrwI+J9uoOrgQBBAQBCAQI +1rx18cjRHAwEAQQEARAEEOxoG0/8z95+B8v/zQLWEx4EAQQEAQgECHjhPmEWa8hSBAIAAAQCAAAE +AgAABAIAAAQCAAAEAgAAAAAAAAAAMDUwITAJBgUrDgMCGgUABBTZql8WIANfobuVIA3JOsmBS/sC +0AQQxrOtDDKIzjpW4+rATcwNPAAA \ No newline at end of file diff --git a/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/mozilla_twoentries.p12.data b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/mozilla_twoentries.p12.data new file mode 100644 index 00000000000..d0c451b24c3 --- /dev/null +++ b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/mozilla_twoentries.p12.data @@ -0,0 +1,125 @@ +MIACAQMwgAYJKoZIhvcNAQcBoIAkgAQBMAQBgAQBMAQBgAQBBgQBCQQJKoZIhvcNAQcBBAGgBAGA +BAEkBAGABAEEBAEBBAEwBAEEBAEDBAOCBVoEAQQEAQEEATAEAQQEAQMEA4IFVgQBBAQBAQQBBgQB +BAQBAQQBCwQBBAQBCwQLKoZIhvcNAQwKAQIEAQQEAQEEAaAEAQQEAQMEA4IE9QQBBAQBAQQBMAQB +BAQBAwQDggTxBAEEBAEBBAEwBAEEBAEBBAEjBAEEBAEBBAEGBAEEBAEBBAEKBAEEBAEKBAoqhkiG +9w0BDAEDBAEEBAEXBBcwFQQQ6T2lKjQK0wo/cjrjNyb0CwIBAQQBBAQBAQQBBAQBBAQBAwQDggTI +BAEEBAOCBMgEggTIiZ+WxZhkj+CjQo4+eTTGf/tSoJMtp85VFwcFUy2+Bz2+WIOf7abQ3yVRmkSc +MUeb/1vQDS+NXMimZDLoIIN9M1ql3Mq5Qtr++kURQeZAVh9q2ZJNDAmw2rvAWGJxdbqPrMA2WgQc +oGZVLiN2eIdWXxJkjLdNzjMWtpsh+6Yw52lwq8ZEIKgu7v23my8+HCemGCL87wf7qU0nQjq+I5jf +QZujYJL5iDNvosZLFLzBuOZKG7voDY2gJtbl+yiOUMOPBQYdDE8qiF+eHqu8WZ/JwlA/3EtnuIDz +i/9f9mIHMINC5vpvPXuo9TE0nF9PvxtL8mGmRcxG0vVro0sPEzu1f13OsN4qwDUVWJ6Xr154zkU8 +9wMi8SAY+gbETvbZZQpxgHWsaEjG9r7fCjiLE/x+5VZCaPeNK8zB+cb0Z2wPGPlojV6Ggcqt/7dI +pZtRMyeSNpSCTncgZlBwh6JLKRCLFSEjZhGzKIsCjT9TpU+IzoD9Niue1cWo2ciZIuTMaSwnqYhO +KzJ/Wivqx9tjhEVI9cCuLf/JPpmFvsmrdMurjD6s4WQPMc7prK8aMJy5W3vcN32wuEQyR6KcqhDn +QxsX7KPavuIi3dTe8I4pNaMJlZ3Ubif4qvt5qJe6I3rxuie2Q1ux7clXk99W5ZvU06tCYTv/3GP4 +M3TjupaWAtmgWZRLsjbTW2NBnxVP40o0AthzYCElyrqhlQPTRU/p1y3RPXyVyssZXwCtvQJe4cxb +V38+kjVSrYL+WGjVkuCQAs4KSdmsH97ShclgAAsrqhDi4+DNhaVIuoFMhkwp4DngxiWMNHWYMjAC +DdzmmPbc0xdOFKJcCzygTsqYWwV3nfg2pGD0Lj9Cpplu0QGy86UA3pfKK+t9lLCng6XN72A1fr8u +QhPgj/hhLjZkeMUp1A9mhqSiST93SX2LTsrDsEgcZaXux+aOHEFVZ87jUPz+y/lGNOC/K4yKEsxx +0pj8lcOjnbZgt9LtQ/DAFDL0FClNEG1AJmMfDElJh4Vryeh3vUIEIpAbf7481XdNcxfKtWGTVSZl +BgNWjDCkYWv0t3dKmRJIp4yeCHTra60Y8pEteZmRJuzCLUMl4gRVDBR5GR2KqoqQ65qgGAp6dqMK +fSqKT7f+4bsuCg7KLGQr2tIYD2g+2xN3y1bDNi/n6wzQaGq26IytLBEwVpC5d4Lk+geE7u8XUE29 +9gPM9QbHKtN+C5DuDIBYzvID0pbEChFj+yGtceA0HA+nv0IHaXYHa7R+o53pEWcZcS+4lXsJPa3Z +hiZXCM3qEljZ9xqzH56aj33I2donq4HLhn17+PC5Nk3O/xGhRpYd2Dmfq89qXRiu+NKGYUR/4rQl +CTCCLWK19oTTScTsOoT96eiXGHkqm9Y3Zly9dbUp3GS7VsPTorLK9mXWPao0u0b7JjEArKo2Bpj1 +YqYk6ihJDSx356kZBXKHrJKh6iNlDjLTj1PZo+u399J8XxjwP0KO0RJW16iaA35i+laXYkW+7HKn +FEbacDK8FigDt8yy75odzmhawtiJ4uRUWjHG9Fp5NTgowOLSUFctVmeJhX7Urzs3ticoZ318uqCH +XYlwiOrNoby05RPi85dcC9O9kw7RovcyURRPPu2PFPA8vMOOOdyCBAEEBAEBBAExBAEEBAEBBAFO +BAEEBAEBBAEwBAEEBAEBBAEnBAEEBAEBBAEGBAEEBAEBBAEJBAEEBAEJBAkqhkiG9w0BCRQEAQQE +AQEEATEEAQQEAQEEARoEAQQEAQEEAR4EAQQEAQEEARgEAQQEARgEGABwAGsAYwBzADEAMgB0AGUA +cwB0AGMAYQQBBAQBAQQBMAQBBAQBAQQBIwQBBAQBAQQBBgQBBAQBAQQBCQQBBAQBCQQJKoZIhvcN +AQkVBAEEBAEBBAExBAEEBAEBBAEWBAEEBAEBBAEEBAEEBAEBBAEUBAEEBAEUBBQMXk6G6ug3oY0m +4spcSEpHKkKh+gQCAAAEAgAABAIAAAQBMAQBgAQBBgQBCQQJKoZIhvcNAQcGBAGgBAGABAEwBAGA +BAECBAEBBAEABAEwBAGABAEGBAEJBAkqhkiG9w0BBwEEATAEASMEAQYEAQoECiqGSIb3DQEMAQYE +FzAVBBAU8Fi506qx5fheZUPRwPSMAgEBBAGgBAGABAEEBAEIBAgYZXC5Ln5QcQQBBAQBCAQI/DEM +s0UWr18EAQQEAQgECApF6YITXI7EBAEEBAEQBBD+dQAdQdEx1Iy0Lsd8jTz8BAEEBAEIBAgqnbOf +NtYHBwQBBAQDggMYBIIDGJZ3MppS8l/nmlZefysfNYtDl5h/cXcCq4j4PzLflFjjc6nIfu+XV9GJ +5ObCNIeYCxCZeKFnv1IbQQSptBtx1PBrAmOVtTyFtMwNjIPo4exkJ2xAR1UBC6O0Q5lhvQfh8Pny +4YITW7CDcP4fMVwH77EUuJ+DGZ8kd/SJsrs4P0chapTe4RoiJIGCczhL5B2enAqEl9eqnPusy6I/ +V2CQo7ESsa72yC5GSdswPKcLH5Uot2ao6dfDGXawm6oyg6/OFIaWnqtJtIG8vNN92w4sVkowZpCb +esqhET8ipoy+dyeFRoUbe39u1kG4sPEKi2PPL4T1K4QbJr3qJ7lFx46SZlc2Tt/mViix1xick4ll +vVmzZLi3duQn7zFFAiMDSInn7Si8eQlz3fSp9GE+CERFBYOtHmyPvU0niB+iLunAt18+sdPSH+JN +cJH2bk2MMkALweekRdj+hh/r134tjnHwfv5PnuQg0TpMvGXNvXGKVpwqK8rKHWFxP0YmYDTZktAT +Uyx673OK06Bkkl3Gg//BSWtT8znqmRFyM2sA3PsWMof91MyY1HNoA2hoWV6ZfomEybv2UeOUIZDE +nitw9Me5npDXy7oO1X6Q5RzS6r8yU5QjgJxH2U0/Slxv5n6HDdxYGewSjvUkoskX4V34iUhaWfuz +PGTt3POc+Hzs2AnYNGiZoxx12GW/o+UkcMW9hgdQnBthU7xp0T/GS4YZm0ycYu6Ew2MkjeVlWAG3 +nWijENXnMKzrdpEydokMwHe8DbO4xm3jtyxBRlXkMJFDMGilwuXjTz5wVrJWhn4tr5kfu3rNI5tQ +U8ucLqtbKUjq4VHRnS9UGKdcAX/b0yzKMWXJIKoW0Gdwknr+Vby1YfuaNdPCNXTB8Cn7RszbtdZ2 +RTndT88dH6WzcMYT/QVApX4qMhsoLAnqjLRBo5RDIDTuz0Zci+zNt5nNB5qHDH3NOnGRSPc7N5eV +s/7cakskv4/j4bub6YqZmF+SpXbpdF14IpDanOdG+17+24XMICXtv5w5xmsc/ZiC7QHfjLU05PsY ++RBuf+4p9pAnsgQBBAQBCAQIJh2bKJsjE+QEAQQEAQgECNd6y4UnkxF1BAEEBAEYBBjlG9loooSJ +A+sn8OI4j3QUrGyhJ99WeqQEAQQEAQgECOkSEQ32eQhPBAEEBAEIBAjslAKvxfPSDwQBBAQBCAQI +wjXD/rGyjI4EAQQEARAEENHxbBXR5NECyr/gysP2Gb8EAQQEAQgECERKzrBGnYbCBAIAAAQCAAAE +AgAABAIAAAQCAAAEATAEAYAEAQYEAQkECSqGSIb3DQEHAQQBoAQBgAQBJAQBgAQBBAQBAQQBMAQB +BAQBAwQDggMeBAEEBAEBBAEwBAEEBAEDBAOCAxoEAQQEAQEEAQYEAQQEAQEEAQsEAQQEAQsECyqG +SIb3DQEMCgECBAEEBAEBBAGgBAEEBAEDBAOCAq0EAQQEAQEEATAEAQQEAQMEA4ICqQQBBAQBAQQB +MAQBBAQBAQQBIwQBBAQBAQQBBgQBBAQBAQQBCgQBBAQBCgQKKoZIhvcNAQwBAwQBBAQBFwQXMBUE +ENVX3NCs1FIcnm4Mx2B7UJMCAQEEAQQEAQEEAQQEAQQEAQMEA4ICgAQBBAQDggKABIICgGoxGhVA +sDhVFHmJzzJ5mpjnKl6HSe3pwWsByzBnIMr2DTdfL4dZSziwc2L8CRYhM//94XxByZ/DGnd0ACMu +9v0DK+/KK6Ua7tdWPmLHlSdmq9sLJujjFBMk9AFKz6WCay/gdpLtvOxHzZMWIlBoyKP/k5jsV9NM +JFhwJRzse5Xo55z1qbC3rFUPmgjN33oCBW1hOuzmKnt8hvYZ2QdyZaVOk9bweywgxHUKGr3Ux/iG +RTQMCVuM9KUZNp1xKmApfpjLmK9OnXrEMTx01vK4iKSzdqpANUGCrWXhs20hnuJEOou2qA9qw1G2 +pQVAk3wLaTUWA8VqidRgwfYNDLVUtb21X8vKdN+aHTBHtCwt2WJu0RRCdELRyr5FMa7Tj+iLWVAo +4PHe+rSWUfsWbiMNUoUbvASiZEDWHRzYva3f05QSabW4azIwrRq30exi0BHq+a3oOnNySAG5nfRU +6gaT3m80hRc5M60xf3xZK/voTt0sJi08j1ftl2D8BLEpbpIiN8YF87/Jmjx+ae6sQlRYu180bpMM +haAoygUQPpbVILhXgfDK4OliJKrDDA8qSGgcWtKMYa6UeCiW9yH92BXkV+P40e2JL+/E/tGdH8Rv +X1NJQfA40c35xt2a1NUrS92Ta+ez3OMGavlUszQI2JaqitkUVJzXSIKBdCv6WuqS8cqqzCgsMBTk +A56rFxQsEYFuoo6RS7AFtawXwyRL7z8Q/tcaCoS/MtljC90Dh/7l7lnhjqF1FyG0mo5/12qbuHY2 +A5Th0vhkkN1L40Pr2anLak1wkZfuu6ecs4eYu0kmGuT1grZM121oOPuNNOUtisbhf06++mUmBC6W +EENZKM2oS/kEAQQEAQEEATEEAQQEAQEEAVoEAQQEAQEEATAEAQQEAQEEATMEAQQEAQEEAQYEAQQE +AQEEAQkEAQQEAQkECSqGSIb3DQEJFAQBBAQBAQQBMQQBBAQBAQQBJgQBBAQBAQQBHgQBBAQBAQQB +JAQBBAQBJAQkAHAAawBjAHMAMQAyAHQAZQBzAHQAZQBuAGQAdQBzAGUAcgAxBAEEBAEBBAEwBAEE +BAEBBAEjBAEEBAEBBAEGBAEEBAEBBAEJBAEEBAEJBAkqhkiG9w0BCRUEAQQEAQEEATEEAQQEAQEE +ARYEAQQEAQEEAQQEAQQEAQEEARQEAQQEARQEFO41/pCe089ZceRCFZb64Qnx3zldBAIAAAQCAAAE +AgAABAEwBAGABAEGBAEJBAkqhkiG9w0BBwYEAaAEAYAEATAEAYAEAQIEAQEEAQAEATAEAYAEAQYE +AQkECSqGSIb3DQEHAQQBMAQBIwQBBgQBCgQKKoZIhvcNAQwBBgQXMBUEEFqPD8ay4cZWE+g9XDco +B6oCAQEEAaAEAYAEAQQEAQgECE5Myc8ub0ZCBAEEBAEIBAiqeJVcfzY2WQQBBAQBCAQI8/3T4HIK +xi4EAQQEARAEEFkiuh/ypU02LdlwFCkQfQsEAQQEAQgECFS+AsdubK0PBAEEBAOCAsAEggLAZKnl +mLO9inxv7mcN8CnC7Sh1KNzSGbVyN8BSLwaXtKC8Vq5II7Mfkpi3BTpFdlayen7eawq5ztN2SAMa +mRBdWoZhiBGUxGebkcVNQ5sWr6pbzM/kvHX0dwDYw3p9gW9YcpYR8F8Bj02rVj74u6gthixuj9d1 +DvWBzilRPAFLugxw/4AvDQOlcIQCLAuxnx+LQ7CePLjmuQ/MZn7YN2YtYY8bVD5u5zWIafSfOORB +oWLRGynw3E4KCo7N/3zhcffwHx0EQd5hMKWCaHQZHKywt4YzlKabpSfqwAS5mNTD0xC5l4QIN9ZD +6Sp+ZmlKrYIjbYqJGWtblGzclRFXUOVTrTDnFote+68+/Rx6vjq03+fFvJEApsKEYH2AMySqg/SG +qKHCYLh3wGMe2JAbVKdUXJQX3yIaQtqiYd/m6mZjIeBmf94zHEzfHeyILgHYUYnsdbWTzqRRCIWu +OQm36KrHvbw1dlxKUYZymHH4MAD1fvn3nAykWyPZ9nOVqLJyg/BT6mpiZWdLWiroYRUHSKKOE1iB +3iYsZjmh8BIqpc7mRioekQrX3AchLWBli9vnPJld6QDxVqf6na+qQNnmREVpOctKuDEbHSx9EWdJ +soYKN9fn4iivJD7D0VdBrNBTeirsf27a0Ry76fzMu855SFd+Wl+hfTw6n1qQ08xJMPRl1anX+0XV +CTAfeZwezoh+8awf0TTi39A7bJDoy0ndcDmN4Ed19DRg4wdavbfQ7gh86zHjR0K73PlPmTEoZvmR +5fYkpKI54GlaOkefjDTD8f9dtmg3AmoQ8U4rWwYt+96l3ULcBE9zGXVg84MjWXTeJ11xsdFBI7+m +OqWW7tPXjYJfkV/O/bEF1q7RZq48rhDCwH0sWb3jR+yWEZfwFGxkAajJr/fFZGs7tcvuJ3CYv41+ +j5U4ZdFRoT/ts1ZDpS9POZMEAQQEAQgECKvgM6Yn7BfwBAEEBAEIBAjmlTrxP0FAoQQBBAQBCAQI +zQ9MR6upWWEEAQQEATAEMKbONdOzZ+9I4lykvTpfnlfEEvsnK8dfL74zOQRLFISuaeTHzOWz3UIr +J/IglAO85gQBBAQBCAQIgaeDUW9TMPsEAQQEAQgECEbwJPWlSffoBAEEBAEIBAhszMP/NwtPUQQB +BAQBCAQIC8dq4IDCDY4EAQQEAQgECGnjPeosA97aBAEEBAEIBAgh4oHQUNUzYAQBBAQDggMYBIID +GJgadAXt5gG94sH8dq9fXADsXJsysvo0HWsRARYzS6aaq2j30pZR5+LoYylTlcvhj2CDKnORtO3N +WocFBhkDDJmylTq26A6rSVoZ91os9+fSdQGuYd+Cl3qmlZ692FYSxa8HTAsmMnUMvMtvfx1Z9FwW +85Pte9R7mP/mWqCCLkmYKSeXdrv9bMdjrVmVM4lOXmwYe4LhzrtzJFS8cDiJWtJEU2U0nR+w4fG8 +xsgcaztCXqwpD/LVcHWIHjhFGzkfOFk69B6pBi5ZMtpQ4j2G8+KRP84m6Ofttc5An7gcYknSWBe2 +h30IivneAh04tNdc7vxxWpK/acL07QwL8bVHVPyJdp7n5IGt0AD7AoV0AklQWd4HoJcuF4rruKeU +uaQxiSX3HtjP0pDUjCnczYZiJHCke8O5RAGQey1El+MbjG33g7cjGsWLXSrMSvkRz4v9QjWP9SaN +0c//j9lD8zqQSfNkfo5Y4/I5VzZTCRt2f4aLo3bEnIV88TJX9g33Bv2WoACdAqsP7TeoQt3NNJyY +rTZxnMG911YynAkEdk1EE9Yf/72g9eN4qv15xnZsJjSAwUS7B+Nwqy5ZRTk4ntCDk/ijFXIwZ/F8 +usfBl6OI8MEsPp5Jgl5oAxRvWCKRWVfkeP/xCRIhteRFFnx8ponOs95JoQyacxDCNLhyhWi9XT/g +8heWoxIZBCPRPQw8ZuiAL4vqAF+CMlffevJhsTmXvq9vVIwobgFNvUCNbkxAe60v0yyflzGU9SQp +uqntI8wLNJHGyfttta0Z/2NKOzj6CACi+O9l3mv23YhPHs8FwkEEhe5HeWAqzmRtPCxcRcNqPdvU +FdmPS/5jfNWtVpNz7EG3H4GgWFbd8i7IEjweNTmz4PT2awNLi0JBfpW4QLB6LDGcU0B3XgdWiERN +P4wDrq8h4JexXXPWjiPPHa+9Frh4pkptQvP6H/99JIXUcrh0ZT8T00yGF7oXEpRp1nSjrfyFpAWa +wQPA1mLUNqOpWtXeBBBOzAe7qajOtC1ZKXs3gF2LSzqXCvuCaCsu9REl5p1zEtCGfSK2jAQBBAQB +CAQIi/x2VsxkPxYEAQQEAQgECKI1oX89gMNzBAEEBAEIBAiz4/LsQRiCwgQBBAQBGAQYGtfk/zsU +hUbVJZnaIA0MR3Cl5ESL5hLbBAEEBAEQBBAPgNDapK8WgYzH8iXDoKIVBAEEBAEIBAjvLHhVCj8/ +AgQBBAQBCAQI5oyRUtC68GEEAQQEAQgECItjgvI+46JVBAEEBAOCAkAEggJAdB0AyWAaJ4y400q9 +3KgK8mPTmzdRvkJIcyhu/XOjGnNmjOdWC4BmpG5YYKdTjXmADJG/x3+VbK0+axQx/8mZFe0kzNh6 +vazKXwkKRBbAxfBlNSIo4XYAWtPBUvcGNSmi/mYOnjVbE7omojdNdp4DPNQJxxu4x7Y/qbIVdUUh +Yub2COY6Yny+5YDgfC7euIU8eJmfKFculAexhSF4e8xHbb4F80ihwk76csR8H6QSml/pA9up8XWV +pvtA84FcY47q1Dp7xYfjyyokPItxuGepiKRewMGgtYnvK446NlvAJrOJ05X/HZiIaMqZOx5zsScQ +VMHdBWyOQSMdaiaobfbNsbyM8jp8QjGsfUQB5KSx05iAjL0WdIcORfxPWkYysl1afhUnkIkqYraw +gsO/3ekAMrtiPagaGwJ6sCgMfbniapIFYbv6StYfaFJlgNphS/DIobXbVbyZj5Uxt7FkJ5T4YYKk +mharN+bIxYB4CnLMmq0tWTtu5I0AQ8x4eU+4KIgz80nG+AoqkCiHqCx2/c8jjO+QyJ0gdrUgHStB +acbDEmAGOIPw1I6UbZcbYr+Dw+Jlgu4e32WuT+reIghLt7KCWw90hxWJOYmNIKJJT8Ewz+Df7Wo5 +2Uka3dKxtQHIDC1LgKmEeXTB1Hopcdpz/c6Kq8Ggh0T1kcZXTJSM2MeRvhBIGhOX6k6QMrUtb4eE +KS9TY9rHSncue7f67JqPs5M9O9iOwG+uC7KhVDeiXyVnevcJx1LQoBW+lY7PyBxfz/mLBAEEBAEI +BAgGsHMj+U49xQQBBAQBCAQIYEhNq/vbNkEEAQQEASAEIHVkTzJskJH7dTPVu3L70TP3a9O3UCPP +1XNL8it1xwrUBAEEBAEIBAhv1CJBZZXkRwQBBAQBCAQIjpPAXu2cCDUEAQQEAQgECPzpQ2fbKHER +BAEEBAEQBBBnyGy02G8nSEv/AjOfesi7BAEEBAEIBAjp6fhwciDeoAQCAAAEAgAABAIAAAQCAAAE +AgAABAIAAAAAAAAAADA1MCEwCQYFKw4DAhoFAAQUF710Y0xSt781mbg0wkOomTUoFNYEEG6xrJYt +AoiyQ6u3imI281gAAA== \ No newline at end of file diff --git a/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/netscape_chain.p12.data b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/netscape_chain.p12.data new file mode 100644 index 00000000000..af0557ab30d --- /dev/null +++ b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/netscape_chain.p12.data @@ -0,0 +1,73 @@ +MIACAQMwgAYJKoZIhvcNAQcBoIAkgAQBMAQBgAQBMAQBgAQBBgQBCQQJKoZIhvcNAQcBBAGgBAGA +BAEkBAGABAEEBAEBBAEwBAEEBAEDBAOCAx4EAQQEAQEEATAEAQQEAQMEA4IDGgQBBAQBAQQBBgQB +BAQBAQQBCwQBBAQBCwQLKoZIhvcNAQwKAQIEAQQEAQEEAaAEAQQEAQMEA4ICrQQBBAQBAQQBMAQB +BAQBAwQDggKpBAEEBAEBBAEwBAEEBAEBBAEjBAEEBAEBBAEGBAEEBAEBBAEKBAEEBAEKBAoqhkiG +9w0BDAEDBAEEBAEXBBcwFQQQA11Re9+yWMD2hxCOcjeWNwIBAQQBBAQBAQQBBAQBBAQBAwQDggKA +BAEEBAOCAoAEggKAYxWd7bKL33PkLthLUJah6/MDI8HwYX7Tw+zvykaINhfW0KaR+kIKHYdE5s5n +W0mbHmvS9wK6ZrZNX0Hnx8cBvdwY8YqTw4r4YBSLO3pNq8mpy8g4fZCGTIObaVmnbUWGjtDKOiQi +a+js653i4g08pvBmk4V2sXbLl/BR6R6Q6oL1WTUzWYOAG3VsbKKsE/y67TF2tCC1MBU5VFdjDoZn +N4WcifhJz8H9MjUYUgx3BdKCeQeRPvP2h/2/VeMV6zcXPOLnrT1xzqbPxL/uvBKmGZ3OmDwaezhA +DK4czV5HhUMutH7HkFKkKeQKrD97Vd/XnN7npgj9Xjde6autEXit4d2r/0RSlBuDuCCUxKoz3UeY +8JSDC8xJ+bZRb0cKDneTGQ8S7UcGz7yP9swQJPiZQVoiWRqkpZzqYELSVAulXCnaivx63jxjohLc +v//wl6hqkJu/JStaluxc8DDTPMOR6QwkCMDM9OevSm7/sOTS5j6hfeOQcPHdzFrfqSAo0yo0bFML +xyiQbjcCrT2yqqcz1ioHyw7zDx5lkAUO9EZ0/ObP5l/GweR6fSQBzKwtbt54aXwEcykPQps6hxhg +co98zWxYSy/ZeMvFevxEXIkE+dl+/CcXxZ3wjCIyrByozMBttalgu6H7T3+VetNpkcCQV5tZP7lx +qrao0QKKfn2guQ89PjkhqbDYjD2/kH02bN7UQVEDYKaw0lVCS8fRo5DQX1yCcFXr5TgaUG+RHPZ7 +K5ptuJeIYCJGJ+GxFvild7/sxvOKz+mGA2QlunmPM1Sn4cqbxKkq52pcVo1tnXvD7CmCJhyb89yG +jboPnbvgnILFqnAdGm8dFjZEbiYZV0+s9AQBBAQBAQQBMQQBBAQBAQQBWgQBBAQBAQQBMAQBBAQB +AQQBMwQBBAQBAQQBBgQBBAQBAQQBCQQBBAQBCQQJKoZIhvcNAQkUBAEEBAEBBAExBAEEBAEBBAEm +BAEEBAEBBAEeBAEEBAEBBAEkBAEEBAEkBCQAcABrAGMAcwAxADIAdABlAHMAdABlAG4AZAB1AHMA +ZQByADEEAQQEAQEEATAEAQQEAQEEASMEAQQEAQEEAQYEAQQEAQEEAQkEAQQEAQkECSqGSIb3DQEJ +FQQBBAQBAQQBMQQBBAQBAQQBFgQBBAQBAQQBBAQBBAQBAQQBFAQBBAQBFAQU7jX+kJ7Tz1lx5EIV +lvrhCfHfOV0EAgAABAIAAAQCAAAEATAEAYAEAQYEAQkECSqGSIb3DQEHBgQBoAQBgAQBMAQBgAQB +AgQBAQQBAAQBMAQBgAQBBgQBCQQJKoZIhvcNAQcBBAEwBAEjBAEGBAEKBAoqhkiG9w0BDAEGBBcw +FQQQT2p7Fmlz1FMb7rnQCrviJAIBAQQBoAQBgAQBBAQBCAQIk4Tqy3E2P9cEAQQEAQgECBAya759 +PYRpBAEEBAEIBAhOiT6KDnBdTQQBBAQBEAQQnWLSdhTgeFycLqr7uaxi4gQBBAQBCAQIba+k0cJO +azoEAQQEA4ICwASCAsB00Q8uf2YWhODVusZrhYoBYjOXenCKFfXt8foqtIi4beToKqRHthCRgnEu +ix4yTiz/MV2YxpRhlMHHQV5AkgvLdfhY3NfOzRgvR6fW4IiEdkFnjpzTxOPVxf1wAgUcAQe7NEEc +HWqhVDXp11Pz8s5UCsXrS0QJ2uyxncdI/pq3M3hnEAAcfeMcyAmr6dmDbg3DPGe88AiZPcmI0IyT +/TKCI01dmDF2uVawXyGNW3430+BH08IekB7dyWAhrVlFge0uZeJrmF6GOAJrUZIu+zbiwBmsSWpe +WSCrts3nvohDP00iuCr/JPY6TVXO022L/n4m5huBEYai3TKTkcqMXVLLCDIeUU6ryX4vHorrSh1U +lCTEKfPl2Cci0vQK3+8Cn6tsXFrO6Vr5sRGxvCqVUXySHOU931KcjCtmT8uqqtrLCLq0yflIf48f +GfBJPvlITdqiPd3v2i0tYrCYBz/rMKxrDnURV9yL5ylGYdwW47i0cCnIUMRIg5b1BYaDUQeQOK9v +9aBEcnk2/Q3JCBR2q/Crp5fokw4ZK6S1cDWvX0EF24LYWJOPoOjnxBwfVPdYfGxTYTjnFSKSfN/k +DlX52yUobs5kEz/ZxaW3rEb4o/r639BK7goGzIbDCOJC7ETuBRUSI/ieLocgXwOxA6AqSk5zClrU +1pW5/nG/AYC2VSnLxVBdRzp3jmbIWRIlOe2MAzh2r+EGpGUd0slKeAl2WgRxnLJ7hkDf578xbxkY +hnNVDew8WywGQBfFJAA5HvlCdSDWqkvVuWsedGTbnsGaqZnle08pc2H5p2uoKc18fhirmgLK6/TG +4ut4jXVu+gZtoBvyUTt/DfYlXRIB7cu46zwRlpDKrwu9/dWUVdLHLxyJ+teNQTE5dP/XRLi4nAur +IOnRgwehWn9WTywUsuZ/WbTBxg28etWEqPMe6D864qchtwQBBAQBCAQIetwqQ9kqoiIEAQQEAQgE +CO3n0pqFaSdYBAEEBAEIBAgkOWr+YomkDwQBBAQBMAQwABJQwhZeCFYXdTWHVFSUjVKzCljg2cK9 +I8XZfT/GdTke0SDfF9kX/dwk0uA1ugTLBAEEBAEIBAjQf5PnCZCy5AQBBAQBCAQIhU67ubFpQT0E +AQQEAQgECB5MCpPjRsmhBAEEBAEIBAjhVpLf3tjQDAQBBAQBCAQIr75qW6ii1fQEAQQEAQgECPYv +UA5L/xBsBAEEBAOCAxgEggMYUsJH05lKmCEGvIEJx71d+HshL21eca5r3MGoWR4JTVbJRfs4/K4c +Fw22gSr3dcSnff0C2y5sJwRk6hM6TgFYhGB6b6fa41gXEFc9u6kxAG/rVya8D3HjIO6qzdp/NewV +yWsacatXRP6fEUV3r8z85LIj6r1YoCpaO9VkmnY/Ow6BLTXr5RCLgk+MDfqQoLb6MDDv0ny4ujUe +jjIZ6nJlm8R0ZqFG7WHFOC+WbmOv5S7wds3MNU6YGxEvJKYvtTsIOBxaR7AT5bcxEhm90VNFKfmG +U/lyJuq6ihhbExcwGFsqMOpb/vd+wrjH+wghljByrBNNEpZ9D0F+mdCP5+mNfKm3VzKfvF8PoSIa +uDJwK5vd+pHJZVoNaax9nBKA+x2ZilUEQdHo8tR6B6mnyUmkRvGsMvnALnsFyszdmhwSWFVNoPK7 +QD/5Kt/q+A5GsXMolDSQ+v89QjuaK97L5pY1tP69b+2P/fGXLpbl6L3R1m7/npE8uAQHNKn2ynHO +shAkwB0Z2pIYIzQbcogpS0eghgQMdOq4KRO96V91Cfq8I91ptjCkxELN+60bA8ClexAvi+spFKMf +AaIWckH/qUQym86C+6AddAA0DYCZHS1Tbyz+TficWnEG3wa3VutP66gvCthCz+rTNDcdqSKUejL0 +Va1RY4k+ZCjoJyyhi9eWl6Xpfw2Ww70gIag5S0GjDEZk3ejBM9KD0AbQAjsUO1m0uM7x9tswWerv +gVNpPTSPc+JQLC5n9/mfN/G8hRNccw5FzFXXgF2ji1qq/M6zatNZqZ7sm4L3dYK2TyTZDSSwumHu +pw6FQZgyOAHhrZhLkk2zgzOQi0/ajIEhIXMI7ZX13vXhr9zd6uxJ6KGcvDQAUTTPgDXiuRMIEJVe +OdV/DTwtPdr0dr1tlE1GNYyRLDcqMmIVucOluNENLN3suzMqhGrNMLM39DFUGQ94UGvB+Y9XC8N+ +Qjyn4VmKB0X8GEIdLljElJvf/wF1JLOmDowgWBKC9sE5qk7ysvMq/L/8KL7kuiKfXQKMdQiPCrZ8 +6h5rYDNgTAxhPdvCBAEEBAEIBAgEayXwySMP2QQBBAQBCAQI/qwkSXsKBNwEAQQEAQgECA5BSRJQ +on35BAEEBAEYBBg2hIeNvtC0m6vUIpESLQO5pXYlcrmE/PUEAQQEARAEEO2duY7cZk2cCjQLnl1v +Y+UEAQQEAQgECIPg1hybd+oTBAEEBAEIBAgZ2wdgxzKRTQQBBAQBCAQIVCA2yFmyrQcEAQQEA4IC +QASCAkB+3zeUIgdXzkTMWod2MVW+8Jb/vs36Q8Cp5Pcd1ZHUw+PHtdH3+u4gVttctx+gabNIUiJe +PuZXfzviNpUtbCoZjsYeS+RZyzRN8gpBnaZEoMSITf0taZVxyv74e/LvELha7PUVbRMwMEgkNsiR +YddIVRuIB0ATi18kWXEybmAl0ddEyE0V7ZMJMCdrNbZ2vu8MKmgHkBj3iuOuhWyZjuzCiSU8cx2f +hJwgYx5jU72SYlMv1YTu+Bykcb4BYG4VL4FEo+8rFa3ypwi7xOAPpO6sSsgf6F2U0yDYr+HcRDGA +HE1MgUPlpNDniYM05axjpnWVCy3vYW04iscDd062R46BD6maGiMPl+yVTGfn26Obr3khMG9IFVwk +F1BAFM+ecU8r9tsAJiM+fSwGVYdfLCX6sFcC27DmAoVn0MXBdSQqi8eO1fqDYS/mKkKkuzwJaI6S +20kbUEPGLo2toK/QXUlPERMWUsNLHPsvQgVpFSugE6hN+shWQ6tZ4sVnNN63DEWAvPHmvgwU/oTx +dvtuoBmpmpbh23xHdkawVXDZ3WAyplb5ZISRhxeBGlcVhHn7fKhuA4Odd+S1rHofnY6kQWli19Op +ma/1JRgcIzQvOWQRwACRVXjaYxnn/7iuLgGKN9gJ+eCsJ+QdoToqUQeJGXOlR5YLA+BuIMl6h2sB +zW21eD8K6RBP87WokMBzEvePRCmnjSDcrqB+4/gH9JjYygLm20SLE0ZZvRdL3ThpIsTLKD/50l/I +h4amQE2F8HgFJt8EAQQEAQgECAia/dA2XXppBAEEBAEIBAjhWSasbQIBvwQBBAQBIAQgIO/8xCiO +kItRKbD3muPYWYL2hriNl5JmJX7TF1lrYKUEAQQEAQgECEtxRSdf6NswBAEEBAEIBAh0MGFGrB4O +IgQBBAQBCAQIIs4UF0epM7IEAQQEARAEEN1lEFX/95lNnWOlh9t2N6AEAQQEAQgECO5ohSpEejWS +BAIAAAQCAAAEAgAABAIAAAQCAAAEAgAAAAAAAAAAMDUwITAJBgUrDgMCGgUABBSCL64+O9/0Dj3l +l3kjJ0+sn34/TgQQKK+gqvx7hiM6AgcLr375KAAA \ No newline at end of file diff --git a/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/netscape_self.p12.data b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/netscape_self.p12.data new file mode 100644 index 00000000000..bdc94837e17 --- /dev/null +++ b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/netscape_self.p12.data @@ -0,0 +1,54 @@ +MIACAQMwgAYJKoZIhvcNAQcBoIAkgAQBMAQBgAQBMAQBgAQBBgQBCQQJKoZIhvcNAQcBBAGgBAGA +BAEkBAGABAEEBAEBBAEwBAEEBAEDBAOCBVoEAQQEAQEEATAEAQQEAQMEA4IFVgQBBAQBAQQBBgQB +BAQBAQQBCwQBBAQBCwQLKoZIhvcNAQwKAQIEAQQEAQEEAaAEAQQEAQMEA4IE9QQBBAQBAQQBMAQB +BAQBAwQDggTxBAEEBAEBBAEwBAEEBAEBBAEjBAEEBAEBBAEGBAEEBAEBBAEKBAEEBAEKBAoqhkiG +9w0BDAEDBAEEBAEXBBcwFQQQ4eiSg5zfyUwdqG251zs8vwIBAQQBBAQBAQQBBAQBBAQBAwQDggTI +BAEEBAOCBMgEggTIJHLhX9tA330EoYs3J/1z+kyq7Hxnu2hon+xM1+CkmdEpqAh0SMRvyTvJ/chz +MS/RBG+JfioXwBD+Ax9lS64Fr4nuPY7tlIW13cEJ0jsjFl8W0Lpu+dZ2S80wImI88GCIdTPsglnI +Ir2aUy3iAvm0A7XqTp0UB6kluAsJ1ma8AC6LWKnFPW44WPVG1Y40owBF+Dkq00dhjqF+vxWuQIKu +7Hh4CboIA5ydprYp+SH9W1AjaTWuSDLyHr7BFUST/Ei3JzqA17J/+IuJAurIPCLcsB6gyIHRnxNg +/KT8X7X1o1jwa2jpzjj1wUo7yCxGk521gDkdC3IUKVelGYHo0JxepTRVQdl0n62tSwSeb6zk8jhA +n3H7vhlSXT4o6ATKvdDD8ztYBGc044gS7+TCKfHhoHtIcnDh9kqUxRDPGQ8CQYtv295eAkTgqZnZ +NZZAIeuwDJZd1h1TOG/GQbOOfHjFStPV8TBgDovlDpT5TfjSk1pA4txn8x3XfUWKVBDDiXsXYi9C +WBhUnpGTd04ZzX59xNvnzGnTWGoiXiYqFMGOfkktUBJIrTIieWTlhMHQ8i8yAkQb387DRTctyj2h +1LMAMtxcxuTJ47lLhk7xk6zXHrYPW+krk0+X1FnqoiOtUSFTpv7ZA58EtaI/i5u0ts+8WXZ5s3kv +CStXK2W8H9I8I4XVxWBcGEjp7jY0gvGizTtSYiVJ7jvSgMKL+IHUlyDzyXxod/8Led150raS53Ox +qPn9sMCAh1FPZrAQh2cXMFTJVNfylIKR8Ax/UwKvzM7Ix5SRqN4CHp48KFYfm9+lSgio+GikINJm +i+MNs13m0idRKxo4lnNfQyBBdLXkQN2QhJ8YgKqEIe7FTk7Jw5MoYfinuW6VXeYRxaJ6b/grSTrw +QeDKOC0/PJAvKFuCJSswCTAE0rU5AXrODPH10GmUCiAwenrQugbYsBVsqW4oBb2AOq+LZREk6l38 +S360XntRgNCj0C8YTc1bhuxpAT6ZSL+90RoCOULJP88HL+uUoBpaPxGVItmx77687GENu6zeS1qP +FfUF/rCbcD4T0s23wZzS3I93LOX3NzAjC2Vk/X49Ktlon4vXpHcQZ3WGo8xuo6o1WESA5NSV2U5i +o/l3hRmloKfhtLtI8e9XYf4SqaDVS7Y17iAEXybvvslSJHl5fHu3ARR15l44KEggUJbiUekaDRiB +RE+0lQRcrpDRNtjRHl/kAqmrCIHPJrTPKTk5zQbDoqjSwtWkLouHVVvv7ZqLlY5rBGuUmgftWAH2 +PxVrtQIwtsI/AeotD7gmICoyr0h/cKw44axad8iLdzUcMrqEK4A4xESkE3vB6OdYsUB8GkD06vrH +kcG28UfWhsuY80P7tPGrVRYQ2ou2gi0+DEVB8i22bVwTx4vHEX/9xRCUXP3HrtkJGvIr7VM48Tvv +Qu6GeXGlFiXPwNI3f3TP9dByCHPF3CIVyYZLckTN1NNWv6o4D8AXYZ9aIK5McAHypAWImakXEWob +NAt0TfZiKiU2Fu+wKXEdN7TQPya1drc9BMa4orcaFqF/VgAjBO+WDuFIX5+ufehQh/ATuT7EeTdk +BtFKq1EFVjwOEwHVsIPRwvfQGjya8W7JfDftZk8L1dRK6ZuKxtWeBAEEBAEBBAExBAEEBAEBBAFO +BAEEBAEBBAEwBAEEBAEBBAEnBAEEBAEBBAEGBAEEBAEBBAEJBAEEBAEJBAkqhkiG9w0BCRQEAQQE +AQEEATEEAQQEAQEEARoEAQQEAQEEAR4EAQQEAQEEARgEAQQEARgEGABwAGsAYwBzADEAMgB0AGUA +cwB0AGMAYQQBBAQBAQQBMAQBBAQBAQQBIwQBBAQBAQQBBgQBBAQBAQQBCQQBBAQBCQQJKoZIhvcN +AQkVBAEEBAEBBAExBAEEBAEBBAEWBAEEBAEBBAEEBAEEBAEBBAEUBAEEBAEUBBQMXk6G6ug3oY0m +4spcSEpHKkKh+gQCAAAEAgAABAIAAAQBMAQBgAQBBgQBCQQJKoZIhvcNAQcGBAGgBAGABAEwBAGA +BAECBAEBBAEABAEwBAGABAEGBAEJBAkqhkiG9w0BBwEEATAEASMEAQYEAQoECiqGSIb3DQEMAQYE +FzAVBBAPM1IaXWtgW3rSUYg+u9+DAgEBBAGgBAGABAEEBAEIBAj0vq5Po02WNQQBBAQBCAQIW1L2 +O6SwUhUEAQQEAQgECGggWt3Z2qnfBAEEBAEQBBCDQnikdk/V9LJ94oxAA8ZsBAEEBAEIBAiHonA3 +qIksGAQBBAQDggMYBIIDGEIX08ZeTewJwDVvonJ4io2WZJrkGnCZGE0MMqunPUYF2ySw8xGZix+H +6JIfFx5smwKThh/JL+1uku1/QlBuFhCMxeEsN1Kh4ywjUznShAQbmhDIkFJsFxtFLgkQ4Dn75Jdr +r1sK47Anzooc8mkWCnvA0/reiOdZ1Y1cWwllTvz7G09jMe/w9h05hZmazvgdIF3k77ow64o5kNpv +8S89y98vyEqH9MDOIBrJA64XlASodT3YiLc06QHBK+m1ooEbtfD+ZwgM2tEzFEc3K6lfCLs60fza +5BjloMfL1u4SfOVk+QDMgQZxfpHnJE2u7oUfSX+vT1J9TCSvjVfRpI33+7nznCNWASEpj0rTtVZE +yPHfnKeiIbeC03+ILtI/IhRaXg2fR/9+1i2M0O3n5YX6jEPzEgjqc2gB5ix4GW0J6wWwSsFCL5Li +h94yKMZmqpIq0TTOHNV7T7xTmqGlldXKOb8xZbxzbCKnlmJLst5tILRpkmsL5cjZNHuLnVo/KS9d +1qdUC9RF+CmptZtejShX2pQsPUKZgFMomjSjzB7s0TKYxqPMgb4lazNvgeW4B6EO0R041Ce0eldN +O23I9wSiPZrROx1K6Mn8d1LkVJ/KLC5T6fyysRRHV4tlfTUxJInQey1RluF2NO+6w63206fKJDn7 +lHOrQoJa1JDY4LgU7RilIRHpRZ2l930td7EIKljWmu/TZykZYmzobg2qigxv7mId04idSr0QT5t1 +HXUI+CL9ci8IjFAwwR41JEQwpZu65ESh6qSKR+sXhejX1g2UZbeLubnQB4rrNRwId05y8Jmh6Ii8 +etzbp1VsMcJJVhs/HMZZkE2Vqq8iFJEKzubHBw6EV1e6mfoi6BWUIwQ53eDmMtlMceKHuz9rD5rn +4UC4O0yLIxUj4XHauJTAEPTW87mV806vtnT9eOoOIf2le8kZCBk3v5zFQHSjtKe2WsqoHrY0+6bc +bExIHLs6DIxxtZR7SsaxrLRrEIshktI9xgmAqugoG33cp9nx7V3tfsfEAr1hkZ23r9JXGgDO1nH5 +Knrd9R/OWa2uSQQBBAQBCAQI440xkYbDTTcEAQQEAQgECFdAbOkOgrSWBAEEBAEYBBgK9/iE3qQz +1vMl1XtaszxfMe6PfarzItgEAQQEAQgECMaj6sWU4SMpBAEEBAEIBAhAztqxK0OlNQQBBAQBCAQI +oy+USUyraLEEAQQEARAEEFq8fjDoPdAyfJsi/bzSLK8EAQQEAQgECOruG87mWvaTBAIAAAQCAAAE +AgAABAIAAAQCAAAEAgAAAAAAAAAAMDUwITAJBgUrDgMCGgUABBQzMEgJJvPUMzhrw5LQm5iUbv/C +HwQQ6Vxq63yfCeamza5PZKytWQAA \ No newline at end of file diff --git a/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/netscape_twoentries.p12.data b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/netscape_twoentries.p12.data new file mode 100644 index 00000000000..cdc8438d0c0 --- /dev/null +++ b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/netscape_twoentries.p12.data @@ -0,0 +1,125 @@ +MIACAQMwgAYJKoZIhvcNAQcBoIAkgAQBMAQBgAQBMAQBgAQBBgQBCQQJKoZIhvcNAQcBBAGgBAGA +BAEkBAGABAEEBAEBBAEwBAEEBAEDBAOCBVoEAQQEAQEEATAEAQQEAQMEA4IFVgQBBAQBAQQBBgQB +BAQBAQQBCwQBBAQBCwQLKoZIhvcNAQwKAQIEAQQEAQEEAaAEAQQEAQMEA4IE9QQBBAQBAQQBMAQB +BAQBAwQDggTxBAEEBAEBBAEwBAEEBAEBBAEjBAEEBAEBBAEGBAEEBAEBBAEKBAEEBAEKBAoqhkiG +9w0BDAEDBAEEBAEXBBcwFQQQxXsQcQJrh4QpLLn7YLjghAIBAQQBBAQBAQQBBAQBBAQBAwQDggTI +BAEEBAOCBMgEggTIzyTPE6ABvJ4C4SQLGDsV8SH5rX772SpsrvSJ1pGISoOHvcgwp9rBkg9eBKfJ +uOh4miBCIssLSICJUyNvl8U/P471h4CN9DI0XWWkPY/B/0AxH9rpNED3mS99xznwpNyVDUUFH787 +WpfvkieOwsx8KUxxkU3IY0+1yqgY9NfEUSrIxEq5nBh0euEW1M88jFW6+i5cV3fuyWSROaCF5RIz +jHgXnFJi9uiLDohMBAStZWoiPMZ+Joc67Anoyok5ijjktEBrfyxTxP1AoeemPNq3sbCAPDLKGjxq +yZ4a9ZexL2MpX1AtvKJdAlgxBjon8TSxmNpziyT0gSpE5fN7Bso19uVbEJy07UUee4Bg1GmIJJD5 +VmMuG0hJjOJZ/nuDHRyK5VfAFMVIpJTtEJBl9zFTm30fhfZmKbyPvNcUGklPf+YxtCgeCcoxDSOT +ZLFagYnK6UerH++7Krlr8U4yW9hXrzz0Jak6FGBsh42hC/g8QeSnIf7t+ZxYiwDKx/a7GmAkDo5r +zS/7AIh2Im1G2lR6zBPh3IX8d+cF5taXf4NUIlb8y6osCtoJWslSeDg9BsLToF36BzYixYKdrd5Y +6o3XdEcagl0EKdzX8h9Vd1Drh1WAIkMnDUu5ye9iuDKBDxOX6rbWMDpDy8e9cpRlGthZlYRc4HRw +fM4i4LYLYzAvJiz9OXsoJkHydZ0dsZrbJ/7kSHgdKRHXQJA2ZFJBdyC9Ffc515wGaFCTwiSWcBG4 +C9VFh6TtUv2Rpp1nC3xsb1o4bnMHjeNs82wpUTJ1qMgJO83x64uvg8zEWDHgsj5KKshmOJaQ5iib +fTv7TvU5+W1bvKWckxH0uyC1rVkqZFBYG8pVxxr2K3e9MK3LZKKqJ25ZllNPch62DUTDINKhfnMn +1n9FhCuNQuExCy6/AkvCBYnaJeFbG6uOhCqTbwoAcnSNF74Oj/wo0/7D/EceJ06uEqzZihq46WwA +hjxRcizlJV96xuMZt0ReMOiUZBLZqSTwLWfNH7vw6/o2CcuYQIHwKOl2j35Q2EAPYI5Ov/1C+xtT +1TRYY4Zk5ZtbReXDL93kcMcCvf1S3gFsAXdbAW6+IIOhYiMWZ/OLq+eCYgoDsjDIFfdbK073U8RR +T3pzUk4hLl2LHg2j589Nzp01x55xSc4bSPk+s6lPL4vtWeKT0oxxMJHT1ty5kcYR1/u+e08g0B6z +JcIC6+pPlqu1rOERZqxBwxs3LzTok8gXVHekRTcmfFXInbfwq/IXt7o/e/kjqwVgLMh6swymb2qN +2H/RXmpEY4/SAydVMNzR/qYLgUvBUGr+xbb9huKTQZYHxyNCCj2p+jTme0KCfwUogoDXAjQLTXPX +fBvHxy+VgUaX6n8T28yZ44XEpeAWcn+Tz3V6TzD/jAYtzqaLbGq6FhDCvrg9fLFzcF8m6gPMc7QD +5QOCqnZsDWWpQzUFj+3oQwciu4kthE/m1Gkvh0UAJ/EL3xFjb7aSLfH0ydHcZ79Dl8nBzLqGBNnj +FNVNps53b88E2SI+OidU1S1Fb3OERZaxdk3yzM2MdEsu3+YiAeecmx8Oy0i/3uBSsX/WBiVD9Hvb +/rOOVjqAcWjtQF5D+8MLmdi9J78yQhM1f1k132tXaVevlcO8aLMzBAEEBAEBBAExBAEEBAEBBAFO +BAEEBAEBBAEwBAEEBAEBBAEnBAEEBAEBBAEGBAEEBAEBBAEJBAEEBAEJBAkqhkiG9w0BCRQEAQQE +AQEEATEEAQQEAQEEARoEAQQEAQEEAR4EAQQEAQEEARgEAQQEARgEGABwAGsAYwBzADEAMgB0AGUA +cwB0AGMAYQQBBAQBAQQBMAQBBAQBAQQBIwQBBAQBAQQBBgQBBAQBAQQBCQQBBAQBCQQJKoZIhvcN +AQkVBAEEBAEBBAExBAEEBAEBBAEWBAEEBAEBBAEEBAEEBAEBBAEUBAEEBAEUBBQMXk6G6ug3oY0m +4spcSEpHKkKh+gQCAAAEAgAABAIAAAQBMAQBgAQBBgQBCQQJKoZIhvcNAQcGBAGgBAGABAEwBAGA +BAECBAEBBAEABAEwBAGABAEGBAEJBAkqhkiG9w0BBwEEATAEASMEAQYEAQoECiqGSIb3DQEMAQYE +FzAVBBBbb1d6dKaOwrbqK8wsNTgHAgEBBAGgBAGABAEEBAEIBAht3DkcYQPHTwQBBAQBCAQIdMnk +ZWUXI5YEAQQEAQgECPsyfjep8dVqBAEEBAEQBBA9tlw4De3xZHxmmmfqFkCxBAEEBAEIBAinPOl+ +lQiHggQBBAQDggMYBIIDGFwp2SZkJ85+7/eyv09RlXdOZX6MXk18//+QYswYo/mIEmxXo9E7xYAg +l7fassIOBxgNrMo67MnV+71RMrdzJ7ESHGD+5Kcj9x+bhUR0kij+ia0f+GYoUdZFrz+nu7cqw/gC +Xb8O/JCNgIslKqRCwj8wYfpo1WZTV0brTT40bQ6ubYv13VsbR0APaYRN9AQeMiLkFpen3FBy4tgI +B+MKUN1sOYlDQ/DeCVHQXQ2s48WFfmLMARAeWOv0qePED6NGsY23ynphotf1iU2S4tPuG5QzqUOu +xyumZDE8fXY+YBwg2kdZLaM4F6oTowWusap0F7J1/U015vNs1TBDyvzeFpO/5jwyBOp/20UYL7dc +xgz2KsRaONh0F82OV+juGvPGRjvJoJ3xAN8MvSk3DdjCLJcuG9oQzuBFlEWAYW+pIzaHw0mRafTK +Qaj/OC/V0BglWhowUWrluagu9s8vB0yKJcifzzeFacFrOD4L1eVag9E45v7jhwj35lzbtcNMjNUN +Ve4gWwCcHTDBzPnS05ktLq4ItsCXt9dxWbVG8f2fNl6IkFIghfZCOl3QU5OSsg+FaqBjgPS2BV0B +c4iYlvb0ebiqCoF5Bgby0bllf2ZaKvvWYXD6/reed44/puKe43nx7cLi0qsPUAPlKP3baSXh/9+/ +k9SEB8IGKnB2r9VVc8UddAYWWjAgtmlE43GGLlO/67HgjBjyFyl9/XdRiR1/LG1svtZuagaXMe9U +fSp6F20XpNaebCscWsA8al5A78C4wHMcAOXJZupIv3fTXJ+kd2rhvVifB6GVoN2JqFTLvjS3QZ7J +xBFsfgwreBwmt3uofbNRerNDuTOYXdV5c5eO/Nf8IBntnR3e/4PO3mYaAyy9voBWQF26T1c4Lg8O +EXFSvcuQpWM7o6Mz5929oV3GjCnhAjciARUvbHbi383aC8nWMXqUiVj2WsYV2WpMePW7gvouF8K5 +JHlwGu2RmGbvsFj9pXvQj8UZt+F7ZsGQHx9rqfoLZ6BGo4Ob627sXG+NBW7TCkSgW2N1iwBlkG9L +TfnFfKWQrKhAlwQBBAQBCAQIpR9pjd7hM2oEAQQEAQgECGKfLCEe7E3EBAEEBAEYBBgnz1o5qrXz +1MuSiN2WFyWx+1u599V9hC0EAQQEAQgECO1UOPgG5+n8BAEEBAEIBAhYid2HguD+FQQBBAQBCAQI +4rHnPIaHbNMEAQQEARAEECAJvHwPTq4sTaEVN12j7j4EAQQEAQgECKNo7ZXm2xqlBAIAAAQCAAAE +AgAABAIAAAQCAAAEATAEAYAEAQYEAQkECSqGSIb3DQEHAQQBoAQBgAQBJAQBgAQBBAQBAQQBMAQB +BAQBAwQDggMeBAEEBAEBBAEwBAEEBAEDBAOCAxoEAQQEAQEEAQYEAQQEAQEEAQsEAQQEAQsECyqG +SIb3DQEMCgECBAEEBAEBBAGgBAEEBAEDBAOCAq0EAQQEAQEEATAEAQQEAQMEA4ICqQQBBAQBAQQB +MAQBBAQBAQQBIwQBBAQBAQQBBgQBBAQBAQQBCgQBBAQBCgQKKoZIhvcNAQwBAwQBBAQBFwQXMBUE +EP0YoeWJFNsFWsDsqs4pP9kCAQEEAQQEAQEEAQQEAQQEAQMEA4ICgAQBBAQDggKABIICgKDesb00 +a8prpIqx3Dwli/TX+Yq9o0aBb+d9cFetaGIV+OPwptdIyTxEOuIeQgQOqVbJ5dHEkSyDC2/o0Hp0 +G4lsuh22eCteq3RDPXSMZNWeZuMWc5mji3WIx6eOFJBVQaSstR6bg66G+3jTdupw//vajlP2Ywej +Z+E4AVsXG3d8pYOI51L52GmS+K00YZMz8nD9Mzq6DYNR8ZaxTaIMGouCtaPfWDpB/bTe992MgQVy +7W4NmxV4wZP0dx1J4w/v+enBwkpDsQmID3mzg3VDotwMk8EfQop2Ay5fsLbmMsteNYugDzg4h8J3 +vIt9gDGGn4IRkhdouoSz5cTctjIHEOdNg8KvW9NZrv9rks1kXDUGrBKJDLX70XLKH1ctfWehzS+R +hxEfWtO8loCBT573nqbv8Y+vI0GUqNdMO3J0YzkICpXM0j3Mrtjz1DLBxq7fg3zK+F2SZihnAsh+ +go4M7UsLWeBeLctCvv6YSQdeXIvOrwgmZXJJ1uLMWpSKRHIU2AnED1TEECYIAiMlQmoqH01xpl9U +qg4S8X/ayAGWiPHRRaE6Hmp8jgJ6+IXleBmI6qMb3U+Rw8p7NcNLPaBqighQkjTYMqYukZNc8Mf+ +blxV6ww3RFrxsQaT1pX/+g4ZcQ51TmxWDEWENmzWmTUX0xdpPKcVtHKvk5enyTP2Hp8yEljssPwX +KkKvkq/SgYKPV2n39JwJIpDldCvQ0mL15Rz1GMWNtejOWyx3Lb8t8icAQKD0KXDJE92lQGG10+RP +b0du9R+JWjdLZi7WKnsdjPfOCflwGVE+/S6YcpIk+8uwhMhsyg3fQfS8mDPWrsKidsq/LZE0KxYY +RMaoXc+ks3YEAQQEAQEEATEEAQQEAQEEAVoEAQQEAQEEATAEAQQEAQEEATMEAQQEAQEEAQYEAQQE +AQEEAQkEAQQEAQkECSqGSIb3DQEJFAQBBAQBAQQBMQQBBAQBAQQBJgQBBAQBAQQBHgQBBAQBAQQB +JAQBBAQBJAQkAHAAawBjAHMAMQAyAHQAZQBzAHQAZQBuAGQAdQBzAGUAcgAxBAEEBAEBBAEwBAEE +BAEBBAEjBAEEBAEBBAEGBAEEBAEBBAEJBAEEBAEJBAkqhkiG9w0BCRUEAQQEAQEEATEEAQQEAQEE +ARYEAQQEAQEEAQQEAQQEAQEEARQEAQQEARQEFO41/pCe089ZceRCFZb64Qnx3zldBAIAAAQCAAAE +AgAABAEwBAGABAEGBAEJBAkqhkiG9w0BBwYEAaAEAYAEATAEAYAEAQIEAQEEAQAEATAEAYAEAQYE +AQkECSqGSIb3DQEHAQQBMAQBIwQBBgQBCgQKKoZIhvcNAQwBBgQXMBUEEFcOsjCyR2JkhJT8EJux +EGQCAQEEAaAEAYAEAQQEAQgECKQXYXagNUODBAEEBAEIBAjsfIO7mv8y9wQBBAQBCAQInwyOeHoo +dy0EAQQEARAEENmxB/vR6dTtZw0HZh17bDUEAQQEAQgECNWbhuLMLYdnBAEEBAOCAsAEggLAnZMW +1RMrb5GmyTMpY48+rUrckBSutk6IrWEY856TPTYlPuT4GfwIkWj3fiXEF9bVorxMzR0rKldHBXLR +F98UXCDZwcb8uDp+vmxstN6wW7tUzHS1ob9GEypEs6rQjZH+wG/Z5qO0SPxgfbPgb34Zi2MMS68p +/v5sWZPCuzCR/Ob3ro6AcG9bUUfgXi+gmTabMOPxpHvys38WemfWOmKvydq4cPf7U1dinbm1uFDH +cS6J/aCG6+wVhfFw3wNch8Ho4y4K+3QhwP7pWy5KtsZec9Svu1XMnM9gjJKn5OYTvwjYvJjyllrP +uQ/brETr4bpwciOzmCd7gQwWf3vi/dSF9XVtPSqc6OIX1Mm+HNWP70b0Anb3kzEPgTA4f19+vfst +NnjeF93DWy74JbVRHO86vTmtP8niSReCFuYTYEJ2Jo245SCIcc/PpsSOTnk6fZliC3SaLw6l3r88 +tFNs6J2UaqO+BFEleMjPCyeLyoBcwpEIBZcl2nY0MAWQD3b4yWIZOfqka7JxXuHOe9CRv8N2odfk +klGh7ZraTWa39yFXfbrgDGAQAinOw3aUIbXhjJAArhsDSegrS9VxiWgaS18jgnSUjLfkiC3deCdR +J2cXCOXmV8dFDkgWiIOidVszYjGXLQaTih/bnEyqFO0XTCeDiDwr++ytaQd6EIz+1JS2lzOa+7rx +pSV+Y3Qmtl52DAnm6wucqOSLSk1rHUa05NmbqV9x1CMNT3AsqKiAA3CRAkJts8cB60CjyleeH92S +r/+2vUEbnJMagSrtXRBB6zc8JMoe9oCJXW+gOUcElqsWAPqecVTNjzf/KxYBUVLepD1jT93iXLU5 +e/Korn/E3u0tvF4Ewv5BfLRW8Ra6PZt/pG/FWw8Mk0zKPfk7sYOaMebdwNSrEmWGu0chORmHFb4P +ay808p3eLFcRuwq6FvraUfkEAQQEAQgECKqKT9ClzRHSBAEEBAEIBAjOJ0fCdWYMIQQBBAQBCAQI +H1JCDNSrTOQEAQQEATAEMOUntjYOx/prWmyejQLhdx6GcXJ7imksF3cqApUrHNpEFspBuoB2+X2D +dJsl9tysBgQBBAQBCAQIVBg81/TutYIEAQQEAQgECDp3/8CLnbJZBAEEBAEIBAguF+XeIDVIIgQB +BAQBCAQImXPDRXQeNUsEAQQEAQgECL7LjjJyPhbZBAEEBAEIBAhWiCzMQ0tXkgQBBAQDggMYBIID +GKVhuuT4QW/iBLdByN9KHLa8M85MCi7cngoBigWiTxk2EXOhq2P1ke2TB/kewDF7Aad2ABdXJNJS +xG36Mxjs0GPRt3d6/s1QrAecJjdBuOYwKsWZuHKxQ+YPaXL+IoxTcJTyDqaQ8iydEwohUy1XmHbp +oAoMtzBsytV5VkcMLJMytlaFl2R2lS5ddBJBvWVVz1+/VrSJZwcs+qv3YabeNsyExqxMCnLVPmeT +D/ahQ/kPutZ8ypaIMCpf6gg3teHdJeLXRvHsI7ufwPO8K92Zr5ljAxallSsdnyJjW63Za4zTsYAr +fxFSH+Gp8EliF8G+DaIMaR8LPt+OZX4f//QK3KTasHw6t1HeCG4IeyaMMT5S0/I2J0oSVcVGE8nM +VEND4DxnEdeBL6dobiYAwf0hOkoMZ7PBbnoCvB1AhqFtZrBeTeOGK8qE37JTainGB2+e6Yp7VDIp +LIeci+Ql0qP03FTog8v7RHdHD7Z3RLxDbk2uL41r1+muDd6FbHMn4mFJ9A8PLx6oXSH81T3np1S1 +HtJD1/vnwZhG4m35ty0e2dcTV0Dgsvny25KmgdIIY7V1SGTnNor/P1MDQrZiB63Ak5I677Y+UY1t +TWTo+XmXyS3dWeSNgW2lSckm2C4CFWfgSO0d8OfoHpphrr7gZ45Y2gl2422NUVQxQ+A6xIx64vm6 +EKldtLNsNPZbVcqk99yPrzgJO4jUBKU7teOhDRGV12Yp5ypuuod7vxkSsXQZsNZNSn5Bqh6EyFZI +iov1WVSPAQrl4x0mMsHGWt9P6ftWUsTyUbapGNiFm0HcJjq7DFwrn3aPZT2jZa4vKOwDtanpyGqf +oPzSHs2M5lea0syLOa5bOsKKVrHqLhzbZ8s0ILcm8fgEtXYavuLqGqgJjopFj7u1LPmISe37Vcud +XmCNQ/XkXLO50qyOnMhaPFsk/iEvCpzM1CxJ5Z4gJl98eOmYofNiyH29yGRYbWue5snmk55xurro +Ni3JpjqRWiaJPzPOQxVteDttn+bYrYDTe4YrTb1Q/2nRUZuV09Zid2qlcsqfQSOPsYwP1AQBBAQB +CAQIXWt7IOP7/JkEAQQEAQgECEQcar+PdoDwBAEEBAEIBAjoSg0WD9zdPQQBBAQBGAQYluNLxBFl +X8NS2G/kuxg+RHRDGakOLIvgBAEEBAEQBBAbVu84HLxC3OTsOXEewUaIBAEEBAEIBAi9LxmHqScs +owQBBAQBCAQIq2DiiNTRcloEAQQEAQgECF4a8S695bj4BAEEBAOCAkAEggJA2uditoxB2C6Y/E0i +6opGHRtWslvfSikuqQAcpxnSe+kJUHQisjWSwJMUIdB6cH+BYcLvcwWIr+WlAzJbZDIksiza6ghu +ZBrSGhyxMPsfv21KLO/LdL6BEhpkEVWkTvZbPR+f8ebKMaYYKYKOFSgGvaYOz0LwXs0Q9GS5Z8g4 +qTSoQdcmoZ06nuTDCTPJxT4lE9twKptcxvXqvrh79LX6qFw0Pq82oSj3erByazQHEc5WfDTqPJ5W +mTI7XOlrWKK4i+WroNXrexp/BzyK/6kP1190J6MZaub2arAF34rIlNJGGDlXsZ3+wFZ/jP5dEoox +p1Wd+OxhSNes6MDda+bCPKPb1HxhH5/SbfaDsx5rDEcm29VtUtHkLOml4zvQYFFlmvN2UDVLQGFI +A7llbqepIrhGGd4+3RDhWFCVi/wwr6n+TWai0s0Nk2XtQMZ8oh1o35amfhXwugUnaa5iUNeyFYqN ++UieLHMKyd4iBBHm90/S6Bzxm/miFDuBgA979KHo7X/XD6I+T0O8zPpi0z7EYMLiQg/Z9UIFYtJa +xUI8Lvud8PVbGUlWs3146gApWZBCtodggY8CSXGVH1Z1Ecjhj8UwxQA6qCQYrSPk0pdWygTeNDTH +T1SZC577la7wJyJdVTaLfWKgwyVTWjMmdoW96ppWHPYOUwWMA9pmd3Oi4WfsAQMtgnFba8sejKx4 +LoBv4ikaiZFRqPXrzFISKh+8eMetU/EH4CGdCHGOP8OcIFYqMpskhOUaIjSCT2fhZsNxBAEEBAEI +BAhpucWKjxDXJAQBBAQBCAQIJrnC/DfMCUUEAQQEASAEIPpod2Id3zMoqoWYmg4+1N4TEBXWWjY6 +xdqbQLnbavPQBAEEBAEIBAgQ1DQiYMlQvwQBBAQBCAQIfobT9m0NL6MEAQQEAQgECO88SOz8Mrm5 +BAEEBAEQBBAhKm3aTWchcpEqcmDZMslFBAEEBAEIBAilVOqmFlh1bAQCAAAEAgAABAIAAAQCAAAE +AgAABAIAAAAAAAAAADA1MCEwCQYFKw4DAhoFAAQU4mtN68ZA4iPtEOTXDVJm54QTLygEEApVeHi+ +LK2fdlxrCGzUHTgAAA== \ No newline at end of file diff --git a/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/openssl.p12.data b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/openssl.p12.data new file mode 100644 index 00000000000..101a03993c5 --- /dev/null +++ b/jdk/test/java/security/KeyStore/PKCS12/certs/readP12/openssl.p12.data @@ -0,0 +1,41 @@ +MIIJDAIBAzCCCNIGCSqGSIb3DQEHAaCCCMMEggi/MIIIuzCCBYcGCSqGSIb3DQEHBqCCBXgwggV0 +AgEAMIIFbQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIELQQ5giZFkcCAggAgIIFQBgoLahw +nwhVA6dtjxWdyiJlb6vIFa+jVvrftKwtzplcDb3nWS0MD9EJtA5D672Yng7z2szv28JbnA3V9B6g +ZcXStYo3Eb7UAp/ng3iAOIvqu6pLIn077nZVrgMzYeSOVgsXpZUM5IzROWmVsBonsXJyBJbJSg26 +lcOOF7Qoqg/0kRqAgVbOofSrKHHub27IQniVdcV0+5NCEzd+GfmfwGQCHDyhLl9WOsbPSuq+RDWX +tLT3T0jQBfoQuhCtYFuGmPx3RpvtoedJxFpgyfelRZpGgOfbH44V5o2O5hohy8Vq1FaGX4ZnwpX/ +BS3tjcHa6UNbv2+rTevC+ap7Blx8PBUasHDPpf8TcMLVR0dZ66gIp8cHslYT9VOVWWtGLRCyAhCB +6Jo+NotjXhR9Jsh0FJ6vYOzsZxIUvbWzQi3FjYwmyGK04SVk4qGpYHKZFNxdsJQyYhCmB0FD7UEG +DEFHnIZ2yc6HKRWzV6nYhYvBtTuzHJ6xslA5pgX5ThiKttY/Zzq779pj/DMYPUzbAsOHUeBs2GQi +xaVKulOUbCrzSQ6p63FrF84WxeQtcuZBcYIZsf6mTxguLffDottRI1P9DeLmngS3qPgLGZtUTTXt +OeEc8N4lfXCAZW35rtORrCbIWXwyoV0FXyZcHRDlUVPTYiKxTf+ykv8jSjThAGyOAiGskQiBDvFe +zUmoXRtTtStG9sh+iFFrEz5kyyK2kxnN65AZdRbo6O6VAe/Vyr6uIPFjdvpuF5uIIbE0yXhBU52+ +iIi6NPCKEXz/UNfsjqsYn7MDMvLJ1IDQ9Xl72Rl9TUEHPF30mK54W/MZdc2p42v/oDEMs8tI7TRE +gJmpPge9J8gr3bwPC3h+A/xzJ3NsgvRNj5+eB0MD7DM0ONVuomrFVigOjfiAyjBNt3nS/JAGnVqT +TtyYT6jQJz5yhyTL8WMsVZiysp8S2KWJQMmkHb7jKOh6rhK6PsNrc7mA3Np05/U2hPqvk/nDPqxl +6E5WdRLADkh9DE6Dimk8BvM9UfDkMNPmGEr8n9hUuSmHcZ/C+68oMd5tPwjZL0ZueJ4ME7rm4DAI +hc3p8tF4TynCko1Uu4mBhVXBuHpJjYeflhNbr8YJvpd+JvOYFK0vq3IRVuiOQSQIBRSMbvWoCiU6 +wIpsqC8nUgWkbOAolHQLVc4gLE78VFbsR+9AwSv4UYUXLsRhW7gblgvGALNHw1e5Rq0pMVWBgQGo +/3JIAl7GL/fmL6a2ezbN63oXU79dqS42r+CvoPZwOZgv/rBZzp4XAlay6tSPJVs9qYIkUQRPGtCn +zDNR0QbhFTuwQqZUPZoLvJPzOxN1J6a02KnB+TTKPzYSUviMD+XTsJSHD+Nfiw3UpL/8IWK3VOlY +MNLpA4c1Sulxy+SotpzGBywUJZD2uFrtmP97SipTfgJzV/peH/5LZ92TSMMo9GC18kAu/fIqIl+I +TiKgwyLZ5sEOsbzNSnfJ2+RYr1DUqikTsM7hQoBltGv//JJO0DSNmvZu/jXiNPmg8DQZh38ge6nB +JadT5ZBQBpuIaevxctdNf7nXtFUPeOmvCkJItFItYEaD1poujxqWJSczgDkn12veHuC1s682b/C2 +D1rvWuwgDBkGO+0p4PoU3P2RuYuOc8f/vRMVl+B+QHW+EPwCDeHwGNjSoUrC+Mg6eKtW8nRQz13j +TdxXqcw4T7Guo5lIbYmE7KKQg5VHmgRInk1Fks4GqxgGegnWBXIGt/da0/EuPSPNkblk8RjrHdvg +TF+ZNclfEPbTm1g7Hk2qUWigJCoPlpOFeZzpHDCCAywGCSqGSIb3DQEHAaCCAx0EggMZMIIDFTCC +AxEGCyqGSIb3DQEMCgECoIICpjCCAqIwHAYKKoZIhvcNAQwBAzAOBAhprJ2OEtZpfgICCAAEggKA +/EaWUBVKx1zLId1ifHBPyoR09GleBU0+jVXmuCxgcPb7Us4dEp60Tgg4tKGoOsiIukIQvnfK/vD4 +UwP1HYd1u89epsrpC7uDrClYOS+3Zq6GhwBtQ+thr0c0d6feIHYJ1sCJEUdKBORN03AOACdIiuwC +mLbnNEEDUkXzFRli0RdXBRNGHRp80GsAkfEBo+CwQa8eCWupb1lWcL2E4EldWNXlxLQIAsXV05CO +xSUbLaIu9oKoKsm9EJ6D4v1tyqVGgqWydVrWbDdle0cRJevSRnce0Qed87FCoS8LgoCr2crOWMvn +XWTy+julpj07QJWMD5Yl03D8lbWrW//p7DFflaQlWtEevl0ulbe/p7j7Bi3nbnP7CHOanViIZygi +QlSX3PrDESDrvFIQklL3osaSBa5NdOeXapn2+WWHgFeJ3JkdLAkSwmpBWV3/O91vNENE8wccwtCP +3aFBYjN+/WeWVmXGIkLt0SF1D6fjedAW/4REpy1BIqLC9et+AVaQ1mRs31hXnZcWwEzewJTyTDf/ +iCd0POF8zgkEFRPlaaYSAQCx4fwO6x/6vFgJOAnF52CNFfwBCHjg4mnQSrksaDRxQ8zHh2PFElvB +gujAaw0buUFj6+PmKImGDRWnLiaZ4bECyqnAHPW9txAiMFw4IhugHvUDZdkQJyjskboRZMCOv3Zb +cksgnRPW8emqi4b9dpatcakxFyqMaFWEyUNZ9pVJblBMcmWy1jhfmvHLqEMj6XSB0BoxLm/hlvvh +b0BoTeHE6Y4P6uLyVkgO0PDeK2zSilO76xxopwnaHewqSLFrFow6RigMMMuZ3gkRwffWPw7GZ/6w +OAMUkUy9Z4xoWOHxojFYMCMGCSqGSIb3DQEJFTEWBBQ+1XUMoIuapQz8y+wtVU4OS2/MVzAxBgkq +hkiG9w0BCRQxJB4iAHAAawBjAHMAMQAyAG8AcABlAG4AcwBzAGwAdABlAHMAdDAxMCEwCQYFKw4D +AhoFAAQU0eEVVRJLmHOENfblXST7WPskPuMECOPkUlL+BAAZAgIIAA== \ No newline at end of file diff --git a/jdk/test/java/security/MessageDigest/TestDigestIOStream.java b/jdk/test/java/security/MessageDigest/TestDigestIOStream.java new file mode 100644 index 00000000000..46028e85af8 --- /dev/null +++ b/jdk/test/java/security/MessageDigest/TestDigestIOStream.java @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2003, 2014, 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.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.security.DigestInputStream; +import java.security.DigestOutputStream; +import java.security.MessageDigest; +import java.util.Arrays; +import java.util.Random; +import static java.lang.System.out; + +/** + * @test + * @bug 8050370 + * @summary MessageDigest tests with DigestIOStream + * @author Kevin Liu + */ + +enum ReadModel { + READ, BUFFER_READ, MIX_READ +} + +public class TestDigestIOStream { + + private static final int[] DATA_LEN_ARRAY = { + 1, 50, 2500, 125000, 6250000 + }; + private static final String[] ALGORITHM_ARRAY = { + "MD2", "MD5", "SHA1", "SHA-224", "SHA-256", "SHA-384", "SHA-512" + }; + + private static byte[] data; + + private static MessageDigest md = null; + + public static void main(String argv[]) throws Exception { + TestDigestIOStream test = new TestDigestIOStream(); + test.run(); + } + + public void run() throws Exception { + for (String algorithm: ALGORITHM_ARRAY) { + + md = MessageDigest.getInstance(algorithm); + + for (int length: DATA_LEN_ARRAY) { + + Random rdm = new Random(); + data = new byte[length]; + rdm.nextBytes(data); + + if (!testMDChange(algorithm, length)) { + throw new RuntimeException("testMDChange failed at:" + + algorithm + "/" + length); + } + if (!testMDShare(algorithm, length)) { + throw new RuntimeException("testMDShare failed at:" + + algorithm + "/" + length); + } + for (ReadModel readModel: ReadModel.values()) { + // test Digest function when digest switch on + if (!testDigestOnOff(algorithm, readModel, true, length)) { + throw new RuntimeException("testDigestOn failed at:" + + algorithm + "/" + length + "/" + readModel); + } + // test Digest function when digest switch off + if (!testDigestOnOff(algorithm, readModel, false, length)) { + throw new RuntimeException("testDigestOff failed at:" + + algorithm + "/" + length + "/" + readModel); + } + } + } + } + int testNumber = ALGORITHM_ARRAY.length * ReadModel.values().length + * DATA_LEN_ARRAY.length * 2 + ALGORITHM_ARRAY.length + * DATA_LEN_ARRAY.length * 2; + out.println("All " + testNumber + " Tests Passed"); + } + + /** + * Test DigestInputStream and DigestOutputStream digest function when digest + * set on and off + * + * @param algo + * Message Digest algorithm + * @param readModel + * which read method used(READ, BUFFER_READ, MIX_READ) + * @param on + * digest switch(on and off) + * @param dataLength + * plain test data length. + * @exception Exception + * throw unexpected exception + */ + public boolean testDigestOnOff(String algo, ReadModel readModel, + boolean on, int dataLength) throws Exception { + + // Generate the DigestInputStream/DigestOutputStream object + try (ByteArrayInputStream bais = new ByteArrayInputStream(data); + DigestInputStream dis = new DigestInputStream(bais, + MessageDigest.getInstance(algo)); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DigestOutputStream dos = new DigestOutputStream(baos, + MessageDigest.getInstance(algo)); + ByteArrayOutputStream baOut = new ByteArrayOutputStream();) { + + // Perform the update using all available/possible update methods + int k = 0; + byte[] buffer = new byte[5]; + boolean enDigest = true; + // Make sure the digest function is on (default) + dis.on(enDigest); + dos.on(enDigest); + + switch (readModel) { + case READ: // use only read() + while ((k = dis.read()) != -1) { + if (on) { + dos.write(k); + } else { + dos.write(k); + if (enDigest) { + baOut.write(k); + } + enDigest = !enDigest; + dos.on(enDigest); + dis.on(enDigest); + } + } + break; + case BUFFER_READ: // use only read(byte[], int, int) + while ((k = dis.read(buffer, 0, buffer.length)) != -1) { + if (on) { + dos.write(buffer, 0, k); + } else { + dos.write(buffer, 0, k); + if (enDigest) { + baOut.write(buffer, 0, k); + } + enDigest = !enDigest; + dis.on(enDigest); + dos.on(enDigest); + } + } + break; + case MIX_READ: // use both read() and read(byte[], int, int) + while ((k = dis.read()) != -1) { + if (on) { + dos.write(k); + if ((k = dis.read(buffer, 0, buffer.length)) != -1) { + dos.write(buffer, 0, k); + } + } else { + dos.write(k); + if (enDigest) { + baOut.write(k); + } + enDigest = !enDigest; + dis.on(enDigest); + dos.on(enDigest); + if ((k = dis.read(buffer, 0, buffer.length)) != -1) { + dos.write(buffer, 0, k); + if (enDigest) { + baOut.write(buffer, 0, k); + } + enDigest = !enDigest; + dis.on(enDigest); + dos.on(enDigest); + } + } + } + break; + default: + out.println("ERROR: Invalid read/write combination choice!"); + return false; + } + + // Get the output and the "correct" digest values + byte[] output1 = dis.getMessageDigest().digest(); + byte[] output2 = dos.getMessageDigest().digest(); + byte[] standard; + if (on) { + standard = md.digest(data); + } else { + byte[] dataDigested = baOut.toByteArray(); + standard = md.digest(dataDigested); + } + + // Compare the output byte array value to the input data + if (!MessageDigest.isEqual(data, baos.toByteArray())) { + out.println("ERROR of " + readModel + + ": output and input data unexpectedly changed"); + return false; + } + // Compare generated digest values + if (!MessageDigest.isEqual(output1, standard) + || !MessageDigest.isEqual(output2, standard)) { + out.println("ERROR" + readModel + + ": generated digest data unexpectedly changed"); + return false; + } + + return true; + } catch (Exception ex) { + out.println("testDigestOnOff failed at:" + algo + "/" + readModel + + "/" + dataLength + " with unexpected exception"); + throw ex; + } + } + + /** + * Test DigestInputStream and DigestOutputStream digest function when Swap + * the message digest engines between DigestIn/OutputStream + * + * @param algo + * Message Digest algorithm + * @param dataLength + * plain test data length. + * @exception Exception + * throw unexpected exception + */ + public boolean testMDChange(String algo, int dataLength) throws Exception { + // Generate the DigestInputStream/DigestOutputStream object + MessageDigest mdIn = MessageDigest.getInstance(algo); + MessageDigest mdOut = MessageDigest.getInstance(algo); + try (ByteArrayInputStream bais = new ByteArrayInputStream(data); + DigestInputStream dis = new DigestInputStream(bais, mdIn); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DigestOutputStream dos = new DigestOutputStream(baos, mdOut);) { + + // Perform the update using all available/possible update methods + int k = 0; + byte[] buffer = new byte[10]; + + // use both read() and read(byte[], int, int) + while ((k = dis.read()) != -1) { + dos.write(k); + if ((k = dis.read(buffer, 0, buffer.length)) != -1) { + dos.write(buffer, 0, k); + } + + // Swap the message digest engines between + // DigestIn/OutputStream objects + dis.setMessageDigest(mdOut); + dos.setMessageDigest(mdIn); + mdIn = dis.getMessageDigest(); + mdOut = dos.getMessageDigest(); + } + + // Get the output and the "correct" digest values + byte[] output1 = mdIn.digest(); + byte[] output2 = mdOut.digest(); + byte[] standard = md.digest(data); + + // Compare generated digest values + return MessageDigest.isEqual(output1, standard) + && MessageDigest.isEqual(output2, standard); + } catch (Exception ex) { + out.println("testMDChange failed at:" + algo + "/" + dataLength + + " with unexpected exception"); + throw ex; + } + } + + /** + * Test DigestInputStream and DigestOutputStream digest function when use + * same message digest object. + * + * @param algo + * Message Digest algorithm + * @param dataLength + * plain test data length. + * @exception Exception + * throw unexpected exception + */ + public boolean testMDShare(String algo, int dataLength) throws Exception { + MessageDigest mdCommon = MessageDigest.getInstance(algo); + // Generate the DigestInputStream/DigestOutputStream object + try (ByteArrayInputStream bais = new ByteArrayInputStream(data); + DigestInputStream dis = new DigestInputStream(bais, mdCommon); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DigestOutputStream dos = new DigestOutputStream(baos, mdCommon);) { + + // Perform the update using all available/possible update methods + int k = 0; + byte[] buffer = new byte[10]; + + // use both read() and read(byte[], int, int) + while (k < data.length) { + int len = dis.read(buffer, 0, buffer.length); + if (len != -1) { + k += len; + if (k < data.length) { + dos.write(data[k]); + k++; + dis.skip(1); + } + } + } + + // Get the output and the "correct" digest values + byte[] output = mdCommon.digest(); + byte[] standard = md.digest(data); + + // Compare generated digest values + return MessageDigest.isEqual(output, standard); + } catch (Exception ex) { + out.println("TestMDShare failed at:" + algo + "/" + dataLength + + " with unexpected exception"); + throw ex; + } + } +} diff --git a/jdk/test/java/util/Currency/PropertiesTest.sh b/jdk/test/java/util/Currency/PropertiesTest.sh index cae14e6013c..82810bd2f6d 100644 --- a/jdk/test/java/util/Currency/PropertiesTest.sh +++ b/jdk/test/java/util/Currency/PropertiesTest.sh @@ -100,14 +100,14 @@ run PropertiesTest -c dump1 dump2 ${PROPS} # Make a private copy of the jdk so we can write to the properties file location # without disturbing other users, including concurrently executing tests. WRITABLEJDK=.${FS}testjava -cp -Hr $TESTJAVA $WRITABLEJDK +cp -H -R $TESTJAVA $WRITABLEJDK || exit 1 if [ -d ${TESTJAVA}${FS}jre ]; then PROPLOCATION=${WRITABLEJDK}${FS}jre${FS}lib else PROPLOCATION=${WRITABLEJDK}${FS}lib fi -chmod -R +w $WRITABLEJDK -cp ${PROPS} $PROPLOCATION +chmod -R +w $WRITABLEJDK || exit 1 +cp ${PROPS} $PROPLOCATION || exit 1 echo "Properties location: ${PROPLOCATION}" # run diff --git a/jdk/test/java/util/Formatter/BasicDouble.java b/jdk/test/java/util/Formatter/BasicDouble.java index 8c6b8e9bc58..4d3bcae836e 100644 --- a/jdk/test/java/util/Formatter/BasicDouble.java +++ b/jdk/test/java/util/Formatter/BasicDouble.java @@ -36,9 +36,6 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.DoubleConsts; - - import static java.util.Calendar.*; @@ -1313,12 +1310,12 @@ public class BasicDouble extends Basic { test("%.1a", "-0x1.0p0", -1.0); test("%.11a", "0x1.80000000000p1", 3.0); test("%.1a", "0x1.8p1", 3.0); - test("%.11a", "0x1.00000000000p-1022", DoubleConsts.MIN_NORMAL); - test("%.1a", "0x1.0p-1022", DoubleConsts.MIN_NORMAL); + test("%.11a", "0x1.00000000000p-1022", Double.MIN_NORMAL); + test("%.1a", "0x1.0p-1022", Double.MIN_NORMAL); test("%.11a", "0x1.00000000000p-1022", - Math.nextDown(DoubleConsts.MIN_NORMAL)); + Math.nextDown(Double.MIN_NORMAL)); test("%.1a", "0x1.0p-1022", - Math.nextDown(DoubleConsts.MIN_NORMAL)); + Math.nextDown(Double.MIN_NORMAL)); test("%.11a", "0x1.ffffffffffep-1023", 0x0.fffffffffffp-1022); test("%.1a", "0x1.0p-1022", 0x0.fffffffffffp-1022); test("%.30a", "0x0.000000000000100000000000000000p-1022", Double.MIN_VALUE); diff --git a/jdk/test/javax/management/remote/mandatory/notif/NotificationAccessControllerTest.java b/jdk/test/javax/management/remote/mandatory/notif/NotificationAccessControllerTest.java index 1dd7927b5e0..fca338f5628 100644 --- a/jdk/test/javax/management/remote/mandatory/notif/NotificationAccessControllerTest.java +++ b/jdk/test/javax/management/remote/mandatory/notif/NotificationAccessControllerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, 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 @@ -37,6 +37,8 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.Semaphore; import javax.management.MBeanServer; import javax.management.MBeanServerConnection; import javax.management.MBeanServerFactory; @@ -56,10 +58,12 @@ import javax.security.auth.Subject; public class NotificationAccessControllerTest { public class NAC implements NotificationAccessController { - private boolean throwException; + private final boolean throwException; public NAC(boolean throwException) { this.throwException = throwException; } + + @Override public void addNotificationListener( String connectionId, ObjectName name, @@ -72,10 +76,14 @@ public class NotificationAccessControllerTest { (subject == null ? null : subject.getPrincipals())); if (throwException) if (name.getCanonicalName().equals("domain:name=1,type=NB") + && + subject != null && subject.getPrincipals().contains(new JMXPrincipal("role"))) throw new SecurityException(); } + + @Override public void removeNotificationListener( String connectionId, ObjectName name, @@ -88,10 +96,14 @@ public class NotificationAccessControllerTest { (subject == null ? null : subject.getPrincipals())); if (throwException) if (name.getCanonicalName().equals("domain:name=2,type=NB") + && + subject != null && subject.getPrincipals().contains(new JMXPrincipal("role"))) throw new SecurityException(); } + + @Override public void fetchNotification( String connectionId, ObjectName name, @@ -105,13 +117,17 @@ public class NotificationAccessControllerTest { echo("\tsubject: " + (subject == null ? null : subject.getPrincipals())); if (!throwException) - if (name.getCanonicalName().equals("domain:name=2,type=NB") && + if (name.getCanonicalName().equals("domain:name=2,type=NB") + && + subject != null + && subject.getPrincipals().contains(new JMXPrincipal("role"))) throw new SecurityException(); } } public class CustomJMXAuthenticator implements JMXAuthenticator { + @Override public Subject authenticate(Object credentials) { String role = ((String[]) credentials)[0]; echo("\nCreate principal with name = " + role); @@ -129,6 +145,7 @@ public class NotificationAccessControllerTest { public static class NB extends NotificationBroadcasterSupport implements NBMBean { + @Override public void emitNotification(int seqnum, ObjectName name) { if (name == null) { sendNotification(new Notification("nb", this, seqnum)); @@ -139,13 +156,20 @@ public class NotificationAccessControllerTest { } public class Listener implements NotificationListener { - public List notifs = new ArrayList(); + public final List notifs = new CopyOnWriteArrayList<>(); + + private final Semaphore s; + public Listener(Semaphore s) { + this.s = s; + } + @Override public void handleNotification(Notification n, Object h) { echo("handleNotification:"); echo("\tNotification = " + n); echo("\tNotification.SeqNum = " + n.getSequenceNumber()); echo("\tHandback = " + h); notifs.add(n); + s.release(); } } @@ -192,6 +216,17 @@ public class NotificationAccessControllerTest { JMXConnectorServer server = null; JMXConnector client = null; + /* + * (!enableChecks) + * - List must contain three notifs from sources nb1, nb2 and nb3 + * (enableChecks && !throwException) + * - List must contain one notif from source nb1 + * (enableChecks && throwException) + * - List must contain two notifs from sources nb2 and nb3 + */ + final int expected_notifs = + (!enableChecks ? 3 : (throwException ? 2 : 1)); + // Create a new MBeanServer // final MBeanServer mbs = MBeanServerFactory.createMBeanServer(); @@ -199,7 +234,7 @@ public class NotificationAccessControllerTest { try { // Create server environment map // - final Map env = new HashMap(); + final Map env = new HashMap<>(); env.put("jmx.remote.authenticator", new CustomJMXAuthenticator()); if (enableChecks) { env.put("com.sun.jmx.remote.notification.access.controller", @@ -222,7 +257,7 @@ public class NotificationAccessControllerTest { // Create server environment map // - final Map cenv = new HashMap(); + final Map cenv = new HashMap<>(); String[] credentials = new String[] { "role" , "password" }; cenv.put("jmx.remote.credentials", credentials); @@ -246,7 +281,9 @@ public class NotificationAccessControllerTest { // Add notification listener // - Listener li = new Listener(); + Semaphore s = new Semaphore(0); + + Listener li = new Listener(s); try { mbsc.addNotificationListener(nb1, li, null, null); if (enableChecks && throwException) { @@ -263,6 +300,9 @@ public class NotificationAccessControllerTest { } mbsc.addNotificationListener(nb2, li, null, null); + System.out.println("\n+++ Expecting to receive " + expected_notifs + + " notification" + (expected_notifs > 1 ? "s" : "") + + " +++"); // Invoke the "sendNotification" method // mbsc.invoke(nb1, "emitNotification", @@ -277,7 +317,7 @@ public class NotificationAccessControllerTest { // Wait for notifications to be emitted // - Thread.sleep(2000); + s.acquire(expected_notifs); // Remove notification listener // @@ -303,21 +343,7 @@ public class NotificationAccessControllerTest { sources.add(nb1); sources.add(nb2); sources.add(nb3); - if (!enableChecks) { - // List must contain three notifs from sources nb1, nb2 and nb3 - // - result = checkNotifs(3, li.notifs, sources); - } - if (enableChecks && !throwException) { - // List must contain one notif from source nb1 - // - result = checkNotifs(1, li.notifs, sources); - } - if (enableChecks && throwException) { - // List must contain two notifs from sources nb2 and nb3 - // - result = checkNotifs(2, li.notifs, sources); - } + result = checkNotifs(expected_notifs, li.notifs, sources); if (result > 0) { return result; } diff --git a/jdk/test/javax/net/ssl/HttpsURLConnection/Equals.java b/jdk/test/javax/net/ssl/HttpsURLConnection/Equals.java new file mode 100644 index 00000000000..0a482f31b90 --- /dev/null +++ b/jdk/test/javax/net/ssl/HttpsURLConnection/Equals.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014, 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 + * @library /lib/testlibrary + * @build jdk.testlibrary.SimpleSSLContext + * @run main Equals + * @bug 8055299 + */ + +import com.sun.net.httpserver.*; + +import java.net.*; +import java.util.*; +import java.io.*; +import javax.net.ssl.*; +import java.util.concurrent.*; +import jdk.testlibrary.SimpleSSLContext; + +public class Equals { + + static SSLContext ctx; + + public static void main (String[] args) throws Exception { + HttpsServer s2 = null; + ExecutorService executor=null; + try { + InetSocketAddress addr = new InetSocketAddress (0); + s2 = HttpsServer.create (addr, 0); + HttpHandler h = new Handler (); + HttpContext c2 = s2.createContext ("/test1", h); + executor = Executors.newCachedThreadPool(); + s2.setExecutor (executor); + ctx = new SimpleSSLContext().get(); + s2.setHttpsConfigurator(new HttpsConfigurator (ctx)); + s2.start(); + + int httpsport = s2.getAddress().getPort(); + test(httpsport); + System.out.println ("OK"); + } finally { + if (s2 != null) + s2.stop(2); + if (executor != null) + executor.shutdown (); + } + } + + static class Handler implements HttpHandler { + int invocation = 1; + public void handle (HttpExchange t) + throws IOException + { + InputStream is = t.getRequestBody(); + while (is.read () != -1) { + } + is.close(); + t.sendResponseHeaders (200, 0); + t.close(); + } + } + + static void test (int port) throws Exception { + URL url = new URL ("https://localhost:"+port+"/test1/"); + HttpsURLConnection urlcs = (HttpsURLConnection) url.openConnection(); + urlcs.setHostnameVerifier (new HostnameVerifier () { + public boolean verify (String s, SSLSession s1) { + return true; + } + }); + urlcs.setSSLSocketFactory (ctx.getSocketFactory()); + + InputStream is = urlcs.getInputStream(); + while (is.read() != -1) { + } + is.close(); + if (!urlcs.equals(urlcs)) { + throw new RuntimeException("Test failed"); + } + } +} diff --git a/jdk/test/com/sun/net/httpserver/SimpleSSLContext.java b/jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java similarity index 55% rename from jdk/test/com/sun/net/httpserver/SimpleSSLContext.java rename to jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java index 5f1a4606142..57a74fcf794 100644 --- a/jdk/test/com/sun/net/httpserver/SimpleSSLContext.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java @@ -21,6 +21,8 @@ * questions. */ +package jdk.testlibrary; + import com.sun.net.httpserver.*; import java.util.*; @@ -31,16 +33,64 @@ import java.security.*; import java.security.cert.*; import javax.net.ssl.*; +/** + * Creates a simple usable SSLContext for SSLSocketFactory + * or a HttpsServer using either a given keystore or a default + * one in the test tree. + * + * Using this class with a security manager requires the following + * permissions to be granted: + * + * permission "java.util.PropertyPermission" "test.src.path", "read"; + * permission java.io.FilePermission + * "${test.src}/../../../lib/testlibrary/jdk/testlibrary/testkeys", "read"; + * The exact path above depends on the location of the test. + */ public class SimpleSSLContext { SSLContext ssl; - SimpleSSLContext (String dir) throws IOException { + /** + * loads default keystore from SimpleSSLContext + * source directory + */ + public SimpleSSLContext () throws IOException { + String paths = System.getProperty("test.src.path"); + StringTokenizer st = new StringTokenizer(paths,":"); + boolean securityExceptions = false; + while (st.hasMoreTokens()) { + String path = st.nextToken(); + try { + File f = new File(path, "jdk/testlibrary/testkeys"); + if (f.exists()) { + init (new FileInputStream(f)); + return; + } + } catch (SecurityException e) { + // catch and ignore because permission only required + // for one entry on path (at most) + securityExceptions = true; + } + } + if (securityExceptions) { + System.err.println("SecurityExceptions thrown on loading testkeys"); + } + } + + /** + * loads default keystore from given directory + */ + public SimpleSSLContext (String dir) throws IOException { + String file = dir+"/testkeys"; + FileInputStream fis = new FileInputStream(file); + init(fis); + } + + private void init (InputStream i) throws IOException { try { - String file = dir+"/testkeys"; char[] passphrase = "passphrase".toCharArray(); KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(new FileInputStream(file), passphrase); + ks.load(i, passphrase); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, passphrase); @@ -63,7 +113,7 @@ public class SimpleSSLContext { } } - SSLContext get () { + public SSLContext get () { return ssl; } } diff --git a/jdk/test/com/sun/net/httpserver/testkeys b/jdk/test/lib/testlibrary/jdk/testlibrary/testkeys similarity index 100% rename from jdk/test/com/sun/net/httpserver/testkeys rename to jdk/test/lib/testlibrary/jdk/testlibrary/testkeys diff --git a/jdk/test/sun/management/HotspotClassLoadingMBean/GetClassInitializationTime.java b/jdk/test/sun/management/HotspotClassLoadingMBean/GetClassInitializationTime.java index 2c9de426922..84b9a5de6e0 100644 --- a/jdk/test/sun/management/HotspotClassLoadingMBean/GetClassInitializationTime.java +++ b/jdk/test/sun/management/HotspotClassLoadingMBean/GetClassInitializationTime.java @@ -26,6 +26,7 @@ * @bug 4858522 * @summary Basic unit test of HotspotClassLoadingMBean.getClassInitializationTime() * @author Steve Bohne + * @run main/othervm -XX:+UsePerfData GetClassInitializationTime */ /* diff --git a/jdk/test/sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java b/jdk/test/sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java index b3de63042ab..903e6b76bb6 100644 --- a/jdk/test/sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java +++ b/jdk/test/sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java @@ -26,6 +26,7 @@ * @bug 4858522 * @summary Basic unit test of HotspotRuntimeMBean.getSafepointSyncTime() * @author Steve Bohne + * @run main/othervm -XX:+UsePerfData GetSafepointSyncTime */ /* diff --git a/jdk/test/sun/management/HotspotThreadMBean/GetInternalThreads.java b/jdk/test/sun/management/HotspotThreadMBean/GetInternalThreads.java index 08b0e4252db..99dda98ab44 100644 --- a/jdk/test/sun/management/HotspotThreadMBean/GetInternalThreads.java +++ b/jdk/test/sun/management/HotspotThreadMBean/GetInternalThreads.java @@ -27,6 +27,7 @@ * @summary Basic Test for HotspotThreadMBean.getInternalThreadCount() * and getInternalThreadCpuTime() * @author Mandy Chung + * @run main/othervm -XX:+UsePerfData GetInternalThreads */ import sun.management.*; diff --git a/jdk/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java b/jdk/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java index 558b2dabb04..1350eafb40a 100644 --- a/jdk/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java +++ b/jdk/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java @@ -29,10 +29,10 @@ * @author Luis-Miguel Alventosa * @run clean JvmstatCountersTest * @run build JvmstatCountersTest - * @run main/othervm/timeout=600 JvmstatCountersTest 1 - * @run main/othervm/timeout=600 -Dcom.sun.management.jmxremote JvmstatCountersTest 2 - * @run main/othervm/timeout=600 -Dcom.sun.management.jmxremote.port=0 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false JvmstatCountersTest 3 - * @run main/othervm/timeout=600 JvmstatCountersTest 4 + * @run main/othervm/timeout=600 -XX:+UsePerfData JvmstatCountersTest 1 + * @run main/othervm/timeout=600 -XX:+UsePerfData -Dcom.sun.management.jmxremote JvmstatCountersTest 2 + * @run main/othervm/timeout=600 -XX:+UsePerfData -Dcom.sun.management.jmxremote.port=0 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false JvmstatCountersTest 3 + * @run main/othervm/timeout=600 -XX:+UsePerfData JvmstatCountersTest 4 */ import java.io.*; diff --git a/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java b/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java index 046da3a46eb..f941e767b7f 100644 --- a/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java +++ b/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java @@ -53,7 +53,7 @@ import jdk.testlibrary.JDKToolLauncher; * @bug 7110104 * @library /lib/testlibrary * @build jdk.testlibrary.* JMXStartStopTest JMXStartStopDoSomething - * @run main/othervm/timeout=600 JMXStartStopTest + * @run main/othervm/timeout=600 -XX:+UsePerfData JMXStartStopTest * @summary Makes sure that enabling/disabling the management agent through * JCMD achieves the desired results */ diff --git a/jdk/test/sun/misc/FloatingDecimal/OldFloatingDecimalForTest.java b/jdk/test/sun/misc/FloatingDecimal/OldFloatingDecimalForTest.java index 253e9e9e568..63bbbf5eb14 100644 --- a/jdk/test/sun/misc/FloatingDecimal/OldFloatingDecimalForTest.java +++ b/jdk/test/sun/misc/FloatingDecimal/OldFloatingDecimalForTest.java @@ -23,8 +23,6 @@ //package sun.misc; -import sun.misc.DoubleConsts; -import sun.misc.FloatConsts; import java.util.regex.*; public class OldFloatingDecimalForTest{ @@ -2217,12 +2215,12 @@ public class OldFloatingDecimalForTest{ // Check for overflow and update exponent accordingly. - if (exponent > DoubleConsts.MAX_EXPONENT) { // Infinite result + if (exponent > Double.MAX_EXPONENT) { // Infinite result // overflow to properly signed infinity return new OldFloatingDecimalForTest(sign * Double.POSITIVE_INFINITY); } else { // Finite return value - if (exponent <= DoubleConsts.MAX_EXPONENT && // (Usually) normal result - exponent >= DoubleConsts.MIN_EXPONENT) { + if (exponent <= Double.MAX_EXPONENT && // (Usually) normal result + exponent >= Double.MIN_EXPONENT) { // The result returned in this block cannot be a // zero or subnormal; however after the @@ -2242,7 +2240,7 @@ public class OldFloatingDecimalForTest{ (DoubleConsts.SIGNIF_BIT_MASK & significand); } else { // Subnormal or zero - // (exponent < DoubleConsts.MIN_EXPONENT) + // (exponent < Double.MIN_EXPONENT) if (exponent < (DoubleConsts.MIN_SUB_EXPONENT -1 )) { // No way to round back to nonzero value @@ -2282,7 +2280,7 @@ public class OldFloatingDecimalForTest{ // Now, discard the bits significand = significand >> bitsDiscarded; - significand = (( ((long)(DoubleConsts.MIN_EXPONENT -1) + // subnorm exp. + significand = (( ((long)(Double.MIN_EXPONENT -1) + // subnorm exp. (long)DoubleConsts.EXP_BIAS) << (DoubleConsts.SIGNIFICAND_WIDTH-1)) & DoubleConsts.EXP_BIT_MASK) | @@ -2350,7 +2348,7 @@ public class OldFloatingDecimalForTest{ * information must be preserved (i.e. case 1). */ if ((exponent >= FloatConsts.MIN_SUB_EXPONENT-1) && - (exponent <= FloatConsts.MAX_EXPONENT ) ){ + (exponent <= Float.MAX_EXPONENT ) ){ // Outside above exponent range, the float value // will be zero or infinity. diff --git a/jdk/test/sun/misc/FloatingDecimal/TestFloatingDecimal.java b/jdk/test/sun/misc/FloatingDecimal/TestFloatingDecimal.java index 08fa34afceb..b04545a65f3 100644 --- a/jdk/test/sun/misc/FloatingDecimal/TestFloatingDecimal.java +++ b/jdk/test/sun/misc/FloatingDecimal/TestFloatingDecimal.java @@ -58,6 +58,9 @@ public class sun.misc.FloatingDecimal { * @test * @bug 7032154 * @summary unit tests of sun.misc.FloatingDecimal + * @library ../../../java/lang/Math + * @build DoubleConsts FloatConsts + * @run main TestFloatingDecimal * @author Brian Burkhalter */ public class TestFloatingDecimal { diff --git a/jdk/test/sun/net/www/protocol/http/RedirectOnPost.java b/jdk/test/sun/net/www/protocol/http/RedirectOnPost.java index ebbbadb27e3..6582a67744f 100644 --- a/jdk/test/sun/net/www/protocol/http/RedirectOnPost.java +++ b/jdk/test/sun/net/www/protocol/http/RedirectOnPost.java @@ -23,7 +23,9 @@ /** * @test - * @compile ../../../../../com/sun/net/httpserver/SimpleSSLContext.java RedirectOnPost.java + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext + * @compile RedirectOnPost.java * @run main/othervm RedirectOnPost * @bug 8029127 * @summary A redirect POST request does not work and illegalStateException on HttpURLConnection.getInputStream @@ -35,17 +37,16 @@ import java.util.*; import com.sun.net.httpserver.*; import java.util.concurrent.*; import javax.net.ssl.*; +import jdk.testlibrary.SimpleSSLContext; public class RedirectOnPost { public static void main(String[] args) throws Exception { - ExecutorService e= Executors.newFixedThreadPool(5); - String keysdir = System.getProperty("test.src") - + "/../../../../../com/sun/net/httpserver/"; - SSLContext ctx = new SimpleSSLContext(keysdir).get(); - HttpServer httpServer = getHttpServer(e); - HttpsServer httpsServer = getHttpsServer(e, ctx); + ExecutorService e= Executors.newFixedThreadPool(5); + SSLContext ctx = new SimpleSSLContext().get(); + HttpServer httpServer = getHttpServer(e); + HttpsServer httpsServer = getHttpsServer(e, ctx); try { // take the keystore from elsewhere in test hierarchy diff --git a/jdk/test/sun/security/smartcardio/TestDirect.java b/jdk/test/sun/security/smartcardio/TestDirect.java index 964cbfa2fd9..3dde7c3b63f 100644 --- a/jdk/test/sun/security/smartcardio/TestDirect.java +++ b/jdk/test/sun/security/smartcardio/TestDirect.java @@ -30,6 +30,7 @@ // This test requires special hardware. +import java.util.List; import javax.smartcardio.Card; import javax.smartcardio.CardTerminal; import javax.smartcardio.CardTerminals; @@ -38,8 +39,12 @@ import javax.smartcardio.TerminalFactory; public class TestDirect { public static void main(String[] args) throws Exception { TerminalFactory terminalFactory = TerminalFactory.getDefault(); - CardTerminals cardTerminals = terminalFactory.terminals(); - CardTerminal cardTerminal = cardTerminals.list().get(0); + List cardTerminals = terminalFactory.terminals().list(); + System.out.println("Terminals: " + cardTerminals); + if (cardTerminals.isEmpty()) { + throw new Exception("No card terminals available"); + } + CardTerminal cardTerminal = cardTerminals.get(0); Card card = cardTerminal.connect("DIRECT"); card.disconnect(true); diff --git a/jdk/make/ModulesXml.gmk b/make/CheckModules.gmk similarity index 63% rename from jdk/make/ModulesXml.gmk rename to make/CheckModules.gmk index 1399e46bace..1000400cf6e 100644 --- a/jdk/make/ModulesXml.gmk +++ b/make/CheckModules.gmk @@ -28,41 +28,18 @@ default: all include $(SPEC) include MakeBase.gmk -include Tools.gmk -# -# Generate modules.xml for jdeps to use -# It augments $(TOPDIR)/modules.xml to include module membership -# -JDEPS_MODULES_XML := $(JDK_OUTPUTDIR)/modules/jdk.dev/com/sun/tools/jdeps/resources/modules.xml - -METADATA := $(JDK_OUTPUTDIR)/btclasses/build/tools/module/modules.xml -$(METADATA): $(TOPDIR)/modules.xml - $(call install-file) - -METADATA_FILES := $(METADATA) - -ifndef OPENJDK - CLOSED_METADATA := $(JDK_OUTPUTDIR)/btclasses/build/tools/module/closed/modules.xml - $(CLOSED_METADATA): $(TOPDIR)/closed/modules.xml - $(call install-file) - - METADATA_FILES += $(CLOSED_METADATA) -endif - -$(JDEPS_MODULES_XML): $(BUILD_TOOLS_JDK) $(METADATA_FILES) - $(MKDIR) -p $(@D) - $(RM) $@ - $(TOOL_GENMODULESXML) $@ $(JDK_OUTPUTDIR)/modules +JDEPS_MODULES_XML := $(JDK_OUTPUTDIR)/modules/jdk.dev/com/sun/tools/jdeps/resources/jdeps-modules.xml # # Verify access across module boundaries # -checkdeps: $(JDEPS_MODULES_XML) +checkdeps: $(ECHO) "Checking dependencies across JDK modules" - $(FIXPATH) $(JDK_OUTPUTDIR)/bin/jdeps -verify:access -mp $(JDK_OUTPUTDIR)/modules - -gen-modules-xml: $(JDEPS_MODULES_XML) + $(JAVA) -Xbootclasspath/p:$(INTERIM_LANGTOOLS_JAR) \ + -Djdeps.modules.xml=$(JDEPS_MODULES_XML) \ + com.sun.tools.jdeps.Main \ + -verify:access -mp $(JDK_OUTPUTDIR)/modules all: checkdeps diff --git a/make/CompileJavaModules.gmk b/make/CompileJavaModules.gmk index ccf630cf4ca..e9dfb7d16dd 100644 --- a/make/CompileJavaModules.gmk +++ b/make/CompileJavaModules.gmk @@ -28,8 +28,9 @@ default: all include $(SPEC) include MakeBase.gmk +include Modules.gmk include JavaCompilation.gmk -include SetupJava.gmk +include SetupJavaCompilers.gmk # Hook to include the corresponding custom file, if present. $(eval $(call IncludeCustomExtension, , CompileJavaModules.gmk)) @@ -399,36 +400,6 @@ jdk.dev_COPY := .js oqlhelp.html .txt ################################################################################ -ifneq ($(OPENJDK_TARGET_OS), solaris) - jdk.attach_EXCLUDE_FILES += \ - sun/tools/attach/SolarisAttachProvider.java \ - sun/tools/attach/SolarisVirtualMachine.java \ - # -endif - -ifneq ($(OPENJDK_TARGET_OS), linux) - jdk.attach_EXCLUDE_FILES += \ - sun/tools/attach/LinuxAttachProvider.java \ - sun/tools/attach/LinuxVirtualMachine.java \ - # -endif - -ifneq ($(OPENJDK_TARGET_OS), macosx) - jdk.attach_EXCLUDE_FILES += \ - sun/tools/attach/BsdAttachProvider.java \ - sun/tools/attach/BsdVirtualMachine.java \ - # -endif - -ifneq ($(OPENJDK_TARGET_OS),aix) - jdk.attach_EXCLUDE_FILES += \ - sun/tools/attach/AixAttachProvider.java \ - sun/tools/attach/AixVirtualMachine.java \ - # -endif - -################################################################################ - jdk.jvmstat_COPY := aliasmap ################################################################################ diff --git a/make/Javadoc.gmk b/make/Javadoc.gmk index c283d0294c8..c7be3809b1c 100644 --- a/make/Javadoc.gmk +++ b/make/Javadoc.gmk @@ -52,7 +52,6 @@ HOTSPOT_DOCS_IMPORT_PATH=$(HOTSPOT_OUTPUTDIR)/docs BUILD_NUMBER=$(JDK_BUILD_NUMBER) JAVADOC_CMD = $(JAVA) \ - -Xmx1024m \ -Djava.awt.headless=true \ $(NEW_JAVADOC) \ -bootclasspath $(JDK_OUTPUTDIR)/classes diff --git a/make/Main.gmk b/make/Main.gmk index 4138043391a..f95a8bdfdaf 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -37,6 +37,7 @@ include $(SRC_ROOT)/make/MakeHelpers.gmk # Load the vital tools for all the makefiles. include $(SRC_ROOT)/make/common/MakeBase.gmk +include $(SRC_ROOT)/make/common/Modules.gmk # Load common profile names definitions include $(JDK_TOPDIR)/make/ProfileNames.gmk @@ -234,8 +235,7 @@ nashorn-jar: +($(CD) $(NASHORN_TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f BuildNashorn.gmk all) # Creates the jar files (rt.jar resources.jar etc) -# this depends on all modules built -main-jars: exploded-image +main-jars: +($(CD) $(JDK_TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f CreateJars.gmk) # Creates the images (j2sdk-image j2re-image etc) @@ -297,14 +297,10 @@ ALL_TARGETS += test test-make ################################################################################ # Verification targets -# generate modules.xml in the exploded image -modules-xml: - +($(CD) $(JDK_TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f ModulesXml.gmk gen-modules-xml) - verify-modules: - +($(CD) $(JDK_TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f ModulesXml.gmk checkdeps) + +($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f CheckModules.gmk) -ALL_TARGETS += modules-xml verify-modules +ALL_TARGETS += verify-modules ################################################################################ # Install targets @@ -355,6 +351,9 @@ else $(LAUNCHER_TARGETS): java.base-libs + # The demos are currently linking to libjvm and libjava, just like all other + # jdk libs, even though they don't need to. To avoid warnings, make sure they + # aren't built until after libjava and libjvm are available to link to. demos: $(JAVA_TARGETS) # Declare dependency from -java to -gensrc @@ -381,16 +380,18 @@ else # This dependency needs to be explicitly declared. jdk.jdi-gensrc generates a # header file used by jdk.jdwp libs. - jdk.jdwp-libs: jdk.jdi-gensrc + jdk.jdwp.agent-libs: jdk.jdi-gensrc # Explicitly add dependencies for special targets java.base-java: unpack-sec + jdk.dev-gendata: java rmic + security-jars: java nashorn-jar: jdk.scripting.nashorn-java - main-jars: java rmic security-jars nashorn-jar policy-jars import-hotspot + main-jars: java rmic security-jars nashorn-jar policy-jars import-hotspot gendata # On windows, the jars target needs to wait for jgss libs to be built. # Should ideally split out the sec-bin zip file generation to avoid @@ -418,9 +419,7 @@ else test: exploded-image - modules-xml: build-tools-jdk java - - verify-modules: exploded-image modules-xml + verify-modules: exploded-image endif @@ -457,7 +456,10 @@ $(foreach m, $(COPY_MODULES), $(eval $m: $m-copy)) ALL_MODULE_TARGETS := $(sort $(GENSRC_MODULES) $(JAVA_MODULES) \ $(GENDATA_MODULES) $(LIB_MODULES) $(LAUNCHER_MODULES) $(COPY_MODULES)) -exploded-image: $(ALL_MODULE_TARGETS) modules-xml +exploded-image: $(ALL_MODULE_TARGETS) +# The old 'jdk' target most closely matches the new exploded-image. Keep an +# alias for ease of use. +jdk: exploded-image jars: main-jars nashorn-jar security-jars policy-jars @@ -469,7 +471,7 @@ profiles: $(ALL_PROFILES) docs: docs-javadoc docs-jvmtidoc ALL_TARGETS += gensrc gendata copy java rmic libs launchers \ - $(ALL_MODULE_TARGETS) exploded-image jars \ + $(ALL_MODULE_TARGETS) exploded-image jdk jars \ $(ALL_PROFILES) profiles docs ################################################################################ @@ -489,6 +491,12 @@ ALL_TARGETS += default all # If running a clean target, disable parallel execution ifneq ($(findstring clean, $(MAKECMDGOALS)), ) .NOTPARALLEL: + # It's not recommended to run additional targets to clean on the same make + # command line. Try to detect this and issue a warning. + ifneq ($(filter-out clean%, $(MAKECMDGOALS)), ) + $(warning Mixing clean targets with normal build targets will not work well \ + and is not recommended.) + endif endif CLEAN_COMPONENTS += langtools corba hotspot jdk nashorn images \ diff --git a/make/MakeHelpers.gmk b/make/MakeHelpers.gmk index 19a4634d908..b8581e3f6eb 100644 --- a/make/MakeHelpers.gmk +++ b/make/MakeHelpers.gmk @@ -303,4 +303,32 @@ define CleanComponent @$(PRINTF) " done\n" endef +################################################################################ + +MAKE_DIR_LIST := $(JDK_TOPDIR)/make + +# Find all modules that has a makefile for a certain build phase +# Param 1: Make subdir to look in +# Param 2: File prefix to look for +FindModulesWithMakefileFor = $(sort $(foreach d, $(MAKE_DIR_LIST), \ + $(patsubst $d/$(strip $1)/$(strip $2)-%.gmk,%, \ + $(wildcard $d/$(strip $1)/$(strip $2)-*.gmk)))) + +# Declare a recipe for calling such a makefile +# Param 1: Module name +# Param 2: Suffix for rule +# Param 3: Make subdir +# Param 4: Makefile prefix +define DeclareRecipeForModuleMakefile + $$(strip $1)-$$(strip $2): + +($(CD) $$(dir $$(firstword $$(wildcard $$(addsuffix /$$(strip $3)/$$(strip $4)-$$(strip $1).gmk, \ + $(MAKE_DIR_LIST))))) \ + && $(MAKE) $(MAKE_ARGS) \ + -f $$(strip $4)-$$(strip $1).gmk \ + $$(addprefix -I, $$(wildcard $(MAKE_DIR_LIST) \ + $$(addsuffix /$$(strip $3), $(MAKE_DIR_LIST))))) +endef + +################################################################################ + endif # _MAKEHELPERS_GMK diff --git a/make/common/IdlCompilation.gmk b/make/common/IdlCompilation.gmk index 50df0df104d..d816f23e613 100644 --- a/make/common/IdlCompilation.gmk +++ b/make/common/IdlCompilation.gmk @@ -60,7 +60,7 @@ define add_idl_package $(RM) -rf $3/$$($4_TMPDIR) $(MKDIR) -p $(dir $5) $(ECHO) $(LOG_INFO) Compiling IDL $(patsubst $2/%,%,$4) - LC_ALL=C $8 -td $3/$$($4_TMPDIR) \ + $8 -td $3/$$($4_TMPDIR) \ -i $2/org/omg/CORBA \ -i $2/org/omg/PortableInterceptor \ -i $2/org/omg/PortableServer \ diff --git a/make/common/JavaCompilation.gmk b/make/common/JavaCompilation.gmk index 919317f91ba..32753d2e9cf 100644 --- a/make/common/JavaCompilation.gmk +++ b/make/common/JavaCompilation.gmk @@ -564,7 +564,7 @@ define SetupJavaCompilation endif # Using sjavac to compile. - $1_COMPILE_TARGETS := $$($1_BIN)/javac_state + $1_COMPILE_TARGETS := $$($1_BIN)/_the.$1_batch # Create SJAVAC variable form JAVAC variable. Expects $1_JAVAC to be # "bootclasspathprepend -cp .../javac.jar com.sun.tools.javac.Main" @@ -574,8 +574,12 @@ define SetupJavaCompilation # Set the $1_REMOTE to spawn a background javac server. $1_REMOTE:=--server:portfile=$$($1_SJAVAC_PORTFILE),id=$1,sjavac=$$(subst $$(SPACE),%20,$$(subst $$(COMMA),%2C,$$(strip $$($1_SERVER_JVM) $$($1_SJAVAC)))) - $$($1_BIN)/javac_state: $$($1_SRCS) $$($1_DEPENDS) + $$($1_BIN)/_the.$1_batch: $$($1_SRCS) $$($1_DEPENDS) $(MKDIR) -p $$(@D) + # As a workaround for sjavac not tracking api changed from the classpath, force full + # recompile if an external dependency, which is something other than a source + # change, triggered this compilation. + $$(if $$(filter-out $$($1_SRCS), $$?), $(FIND) $$(@D) -name "*.class" $(FIND_DELETE)) $$(call ListPathsSafely,$1_SRCS,\n, >> $$($1_BIN)/_the.$1_batch.tmp) $(ECHO) Compiling $1 ($$($1_JVM) $$($1_SJAVAC) \ @@ -590,8 +594,16 @@ define SetupJavaCompilation $$($1_HEADERS_ARG) \ -d $$($1_BIN) && \ $(MV) $$($1_BIN)/_the.$1_batch.tmp $$($1_BIN)/_the.$1_batch) - # sjavac doesn't touch this if nothing has changed - $(TOUCH) $$@ + # Create a pubapi file that only changes when the pubapi changes. Dependent + # compilations can use this file to only get recompiled when pubapi has changed. + # Grep returns 1 if no matching lines are found. Do not fail for this. + $(GREP) -e "^I" $$($1_BIN)/javac_state > $$($1_BIN)/_the.$1_pubapi.tmp \ + || test "$$$$?" = "1" + if [ ! -f $$($1_BIN)/_the.$1_pubapi ] \ + || [ "`$(DIFF) $$($1_BIN)/_the.$1_pubapi $$($1_BIN)/_the.$1_pubapi.tmp`" != "" ]; then \ + $(MV) $$($1_BIN)/_the.$1_pubapi.tmp $$($1_BIN)/_the.$1_pubapi; \ + fi + else # Using plain javac to batch compile everything. $1_COMPILE_TARGETS := $$($1_BIN)/_the.$1_batch @@ -681,7 +693,7 @@ endef # param 1 is for example BUILD_MYPACKAGE # param 2 is the output directory (BIN) define SetupJavaCompilationCompileTarget - $(if $(findsring yes, $(ENABLE_SJAVAC)), $(strip $2)/javac_state, \ + $(if $(findstring yes, $(ENABLE_SJAVAC)), $(strip $2)/_the.$(strip $1)_pubapi, \ $(strip $2)/_the.$(strip $1)_batch) endef endif diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk index 8c987609efa..cecb04ce6bc 100644 --- a/make/common/MakeBase.gmk +++ b/make/common/MakeBase.gmk @@ -25,7 +25,6 @@ ################################################################ # -# Check that GNU make and cygwin are recent enough. # Setup common utility functions. # ################################################################ @@ -532,71 +531,6 @@ define SetupCopyFiles endef -################################################################################ -# Module list macros - -ALL_TOP_SRC_DIRS := \ - $(JDK_TOPDIR)/src \ - $(LANGTOOLS_TOPDIR)/src \ - $(CORBA_TOPDIR)/src \ - $(JAXP_TOPDIR)/src \ - $(JAXWS_TOPDIR)/src \ - $(NASHORN_TOPDIR)/src \ - # - -# There are snmp classes in the open but they are not included in OpenJDK -JAVA_MODULES_FILTER := jdk.snmp - -# Find all modules with java sources by looking in the source dirs -define FindJavaModules - $(filter-out $(JAVA_MODULES_FILTER), $(sort $(notdir \ - $(patsubst %/,%, $(dir $(patsubst %/,%, $(dir $(patsubst %/,%, $(dir \ - $(wildcard $(patsubst %,%/*/share/classes/*, $(ALL_TOP_SRC_DIRS)) \ - $(patsubst %,%/*/$(OPENJDK_TARGET_OS_API_DIR)/classes/*, $(ALL_TOP_SRC_DIRS)) \ - $(patsubst %,%/*/$(OPENJDK_TARGET_OS)/classes/*, $(ALL_TOP_SRC_DIRS)))))))))))) -endef - -MODULES_LIST_FILE := $(SRC_ROOT)/make/common/modules.list - -# Param 1: Module to find deps for -define FindDepsForModule - $(if $(filter-out java.base, $1), java.base $(filter-out jdk.scripting.nashorn, $(filter-out java.base, $(wordlist 2, 100, $(shell $(GREP) '^$(strip $1):' $(MODULES_LIST_FILE)))))) -endef - -# Find all modules with source for the target platform. -define FindAllModules - $(sort $(filter-out closed demo sample, $(notdir $(patsubst %/,%, $(dir \ - $(wildcard $(patsubst %, %/*/share, $(ALL_TOP_SRC_DIRS)) \ - $(patsubst %, %/*/$(OPENJDK_TARGET_OS), $(ALL_TOP_SRC_DIRS)) \ - $(patsubst %, %/*/$(OPENJDK_TARGET_OS_API_DIR), $(ALL_TOP_SRC_DIRS)))))))) -endef - -################################################################################ - -MAKE_DIR_LIST := $(JDK_TOPDIR)/make - -# Find all modules that has a makefile for a certain build phase -# Param 1: Make subdir to look in -# Param 2: File prefix to look for -FindModulesWithMakefileFor = $(sort $(foreach d, $(MAKE_DIR_LIST), \ - $(patsubst $d/$(strip $1)/$(strip $2)-%.gmk,%, \ - $(wildcard $d/$(strip $1)/$(strip $2)-*.gmk)))) - -# Declare a recipe for calling such a makefile -# Param 1: Module name -# Param 2: Suffix for rule -# Param 3: Make subdir -# Param 4: Makefile prefix -define DeclareRecipeForModuleMakefile - $$(strip $1)-$$(strip $2): - +($(CD) $$(dir $$(firstword $$(wildcard $$(addsuffix /$$(strip $3)/$$(strip $4)-$$(strip $1).gmk, \ - $(MAKE_DIR_LIST))))) \ - && $(MAKE) $(MAKE_ARGS) \ - -f $$(strip $4)-$$(strip $1).gmk \ - $$(addprefix -I, $$(wildcard $(MAKE_DIR_LIST) \ - $$(addsuffix /$$(strip $3), $(MAKE_DIR_LIST))))) -endef - ################################################################################ # Hook to include the corresponding custom file, if present. diff --git a/make/common/Modules.gmk b/make/common/Modules.gmk new file mode 100644 index 00000000000..87b03f8b0ec --- /dev/null +++ b/make/common/Modules.gmk @@ -0,0 +1,79 @@ +# +# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +ifndef _MODULES_GMK +_MODULES_GMK := 1 + +################################################################################ +# Module list macros + +ALL_TOP_SRC_DIRS := \ + $(JDK_TOPDIR)/src \ + $(LANGTOOLS_TOPDIR)/src \ + $(CORBA_TOPDIR)/src \ + $(JAXP_TOPDIR)/src \ + $(JAXWS_TOPDIR)/src \ + $(NASHORN_TOPDIR)/src \ + # + +# There are snmp classes in the open but they are not included in OpenJDK +JAVA_MODULES_FILTER := jdk.snmp + +# Find all modules with java sources by looking in the source dirs +define FindJavaModules + $(filter-out $(JAVA_MODULES_FILTER), $(sort $(notdir \ + $(patsubst %/,%, $(dir $(patsubst %/,%, $(dir $(patsubst %/,%, $(dir \ + $(wildcard $(patsubst %,%/*/share/classes/*, $(ALL_TOP_SRC_DIRS)) \ + $(patsubst %,%/*/$(OPENJDK_TARGET_OS_API_DIR)/classes/*, $(ALL_TOP_SRC_DIRS)) \ + $(patsubst %,%/*/$(OPENJDK_TARGET_OS)/classes/*, $(ALL_TOP_SRC_DIRS)))))))))))) +endef + +MODULES_LIST_FILE := $(SRC_ROOT)/make/common/modules.list +MODULE_DEPS_MAKEFILE := $(OUTPUT_ROOT)/module-deps.gmk + +$(MODULE_DEPS_MAKEFILE): $(MODULES_LIST_FILE) + $(CAT) $^ | $(SED) -e 's/^\([^:]*\):/DEPS_\1 :=/g' > $@ + +-include $(MODULE_DEPS_MAKEFILE) + +# Param 1: Module to find deps for +define FindDepsForModule + $(DEPS_$(strip $1)) +endef + +# Find all modules with source for the target platform. +define FindAllModules + $(sort $(filter-out closed demo sample, $(notdir $(patsubst %/,%, $(dir \ + $(wildcard $(patsubst %, %/*/share, $(ALL_TOP_SRC_DIRS)) \ + $(patsubst %, %/*/$(OPENJDK_TARGET_OS), $(ALL_TOP_SRC_DIRS)) \ + $(patsubst %, %/*/$(OPENJDK_TARGET_OS_API_DIR), $(ALL_TOP_SRC_DIRS)))))))) +endef + +################################################################################ + +# Hook to include the corresponding custom file, if present. +$(eval $(call IncludeCustomExtension, , common/Modules.gmk)) + +endif # _MODULES_GMK diff --git a/make/common/SetupJava.gmk b/make/common/SetupJavaCompilers.gmk similarity index 100% rename from make/common/SetupJava.gmk rename to make/common/SetupJavaCompilers.gmk diff --git a/make/jprt.properties b/make/jprt.properties index 26d24c0171f..c81bbf0cb7f 100644 --- a/make/jprt.properties +++ b/make/jprt.properties @@ -466,15 +466,16 @@ my.make.rule.test.targets.hotspot.internalvmtests= \ windows_i586_6.1-fastdebug-c2-hotspot_internalvmtests, \ windows_x64_6.1-fastdebug-c2-hotspot_internalvmtests -my.make.rule.test.targets.hotspot.reg.group= \ - solaris_sparcv9_5.11-{product|fastdebug}-c2-GROUP, \ - solaris_x64_5.11-{product|fastdebug}-c2-GROUP, \ - linux_i586_2.6-{product|fastdebug}-c2-GROUP, \ - linux_x64_2.6-{product|fastdebug}-c2-GROUP, \ - windows_i586_6.1-{product|fastdebug}-c2-GROUP, \ - windows_x64_6.1-{product|fastdebug}-c2-GROUP, \ - linux_i586_2.6-{product|fastdebug}-c1-GROUP, \ - windows_i586_6.1-{product|fastdebug}-c1-GROUP +my.make.rule.test.targets.hotspot.reg.group= \ + solaris_sparcv9_5.11-fastdebug-c2-GROUP, \ + solaris_x64_5.11-fastdebug-c2-GROUP, \ + linux_i586_2.6-fastdebug-c2-GROUP, \ + linux_x64_2.6-fastdebug-c2-GROUP, \ + macosx_x64_10.7-fastdebug-c2-GROUP, \ + windows_i586_6.1-fastdebug-c2-GROUP, \ + windows_x64_6.1-fastdebug-c2-GROUP, \ + linux_i586_2.6-fastdebug-c1-GROUP, \ + windows_i586_6.1-fastdebug-c1-GROUP my.make.rule.test.targets.hotspot= \ ${my.make.rule.test.targets.hotspot.clienttests}, \ @@ -483,6 +484,7 @@ my.make.rule.test.targets.hotspot= \ ${my.make.rule.test.targets.hotspot.reg.group:GROUP=hotspot_wbapitest}, \ ${my.make.rule.test.targets.hotspot.reg.group:GROUP=hotspot_compiler}, \ ${my.make.rule.test.targets.hotspot.reg.group:GROUP=hotspot_gc}, \ - ${my.make.rule.test.targets.hotspot.reg.group:GROUP=hotspot_runtime}, \ + ${my.make.rule.test.targets.hotspot.reg.group:GROUP=hotspot_runtime}, \ + ${my.make.rule.test.targets.hotspot.reg.group:GROUP=hotspot_runtime_closed}, \ ${my.make.rule.test.targets.hotspot.reg.group:GROUP=hotspot_serviceability}, \ ${my.additional.make.rule.test.targets.hotspot} diff --git a/nashorn/.hgtags b/nashorn/.hgtags index beb365444ba..6e0ea8019c3 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -261,3 +261,4 @@ aa3fda2d2967847dbd264aa962d624c07fc6c29f jdk9-b23 b33633fc10c5bffd39d3492ed2602dadd8d44642 jdk9-b25 ed60a4e9dd35dcabb9b24e90434f5f615d988981 jdk9-b26 221a84ef44c00335b563d92f470efaf8162b471e jdk9-b27 +00c31e5eaf26f9b238165157b9d1c617b03abcb6 jdk9-b28 diff --git a/nashorn/make/build.xml b/nashorn/make/build.xml index ec959c8c0a6..4764c0d15d7 100644 --- a/nashorn/make/build.xml +++ b/nashorn/make/build.xml @@ -32,8 +32,12 @@ + + + + @@ -294,7 +298,7 @@ -grant codeBase "file:/${toString:nashorn.ext.path}/nashorn.jar" { +grant codeBase "file:/${toString:dist.path}/nashorn.jar" { permission java.security.AllPermission; }; diff --git a/nashorn/samples/find_nonfinals.js b/nashorn/samples/find_nonfinals.js index c1a4865d6c8..affb753efa9 100644 --- a/nashorn/samples/find_nonfinals.js +++ b/nashorn/samples/find_nonfinals.js @@ -45,7 +45,7 @@ var Modifier = Java.type("java.lang.reflect.Modifier"); // locate nashorn.jar from java.ext.dirs function findNashorn() { - var paths = System.getProperty("java.ext.dirs").split(':'); + var paths = System.getProperty("java.ext.dirs").split(File.pathSeparator); for each (var p in paths) { var nashorn = p + File.separator + "nashorn.jar"; if (new File(nashorn).exists()) { diff --git a/nashorn/samples/find_nonfinals2.js b/nashorn/samples/find_nonfinals2.js new file mode 100644 index 00000000000..75fde6246c9 --- /dev/null +++ b/nashorn/samples/find_nonfinals2.js @@ -0,0 +1,118 @@ +#// Usage: jjs find_nonfinals2.js -- + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// This example demonstrates Java subclassing by Java.extend +// and javac Compiler and Tree API. This example finds method +// parameters without "final" keyword and prints info on those. + +if (arguments.length == 0) { + print("Usage: jjs find_nonfinals2.js -- "); + exit(1); +} + +// Java types used +var File = Java.type("java.io.File"); +var Files = Java.type("java.nio.file.Files"); +var FileVisitOption = Java.type("java.nio.file.FileVisitOption"); +var StringArray = Java.type("java.lang.String[]"); +var ToolProvider = Java.type("javax.tools.ToolProvider"); +var Tree = Java.type("com.sun.source.tree.Tree"); +var TreeScanner = Java.type("com.sun.source.util.TreeScanner"); +var Modifier = Java.type("javax.lang.model.element.Modifier"); + +function checkNonFinalParams(p) { + // get the system compiler tool + var compiler = ToolProvider.systemJavaCompiler; + // get standard file manager + var fileMgr = compiler.getStandardFileManager(null, null, null); + // Using Java.to convert script array (arguments) to a Java String[] + var compUnits = fileMgr.getJavaFileObjects( + Java.to(arguments, StringArray)); + // create a new compilation task + var task = compiler.getTask(null, fileMgr, null, null, null, compUnits); + // subclass SimpleTreeVisitor - to find non-final method params + var NonFinalsFinder = Java.extend(TreeScanner); + + function printMethod(method) { + print(method.modifiers + " "+ method.returnType + " " + + method.name + "(" + method.parameters + ")"); + } + + var pkgName, clsName, compUnitName, lineMap; + var visitor = new NonFinalsFinder() { + visitCompilationUnit: function(compUnit, p) { + pkgName = compUnit.packageName; + compUnitName = compUnit.sourceFile.name; + lineMap = compUnit.lineMap; + return Java.super(visitor).visitCompilationUnit(compUnit, p); + }, + + visitClass: function(clazz, p) { + clsName = clazz.name; + return Java.super(visitor).visitClass(clazz, p); + }, + + visitMethod: function (method, p) { + var params = method.parameters; + for each (var p in params) { + var modifiers = p.modifiers; + if (! modifiers.flags.contains(Modifier.FINAL)) { + print(compUnitName); + print(pkgName + "." + clsName); + printMethod(method); + print("->", p, + " @ " + lineMap.getLineNumber(p.pos) + ":" + + lineMap.getColumnNumber(p.pos)); + } + } + } + } + + for each (var cu in task.parse()) { + cu.accept(visitor, null); + } +} + +// for each ".java" file in directory (recursively). +function main(dir) { + var totalCount = 0; + Files.walk(dir.toPath(), FileVisitOption.FOLLOW_LINKS). + forEach(function(p) { + var name = p.toFile().absolutePath; + if (name.endsWith(".java")) { + checkNonFinalParams(p); + } + }); +} + +main(new File(arguments[0])); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java index b261a1b629e..7f4ca755f51 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java @@ -164,7 +164,7 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin return Context.getContext(); } }, GET_CONTEXT_ACC_CTXT); - return wrap(context.eval(global, s, null, null, false), global); + return wrap(context.eval(global, s, sobj, null, false), global); } }); } diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/InputListener.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/AssertsEnabled.java similarity index 69% rename from jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/InputListener.java rename to nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/AssertsEnabled.java index 99a37c2e9f2..f067866439b 100644 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/InputListener.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/AssertsEnabled.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,17 +23,23 @@ * questions. */ -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. +package jdk.nashorn.internal; + +/** + * Class that exposes the current state of asserts. + * */ +public final class AssertsEnabled { + private static boolean assertsEnabled = false; + static { + assert assertsEnabled = true; // Intentional side effect + } - -package com.sun.tools.example.debug.bdi; - -public interface InputListener { - String getLine(); + /** + * Returns true if asserts are enabled + * @return true if asserts are enabled + */ + public static boolean assertsEnabled() { + return assertsEnabled; + } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ApplySpecialization.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ApplySpecialization.java index a5fbfdf9134..d1668894ab3 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ApplySpecialization.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ApplySpecialization.java @@ -35,6 +35,7 @@ import java.util.Deque; import java.util.HashSet; import java.util.List; import java.util.Set; + import jdk.nashorn.internal.ir.AccessNode; import jdk.nashorn.internal.ir.CallNode; import jdk.nashorn.internal.ir.Expression; @@ -127,6 +128,14 @@ public final class ApplySpecialization extends NodeVisitor imple */ private boolean argumentsEscape(final FunctionNode functionNode) { + @SuppressWarnings("serial") + final UnsupportedOperationException uoe = new UnsupportedOperationException() { + @Override + public Throwable fillInStackTrace() { + return null; + } + }; + final Deque> stack = new ArrayDeque<>(); //ensure that arguments is only passed as arg to apply try { @@ -151,7 +160,7 @@ public final class ApplySpecialization extends NodeVisitor imple @Override public Node leaveIdentNode(final IdentNode identNode) { if (isParam(identNode.getName()) || ARGUMENTS.equals(identNode.getName()) && !isCurrentArg(identNode)) { - throw new UnsupportedOperationException(); + throw uoe; //avoid filling in stack trace } return identNode; } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java index 91a022d9acc..a45a362ecbf 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java @@ -485,7 +485,7 @@ final class AssignSymbols extends NodeOperatorVisitor implements if (functionNode.isDeclared()) { final Iterator blocks = lc.getBlocks(); if (blocks.hasNext()) { - defineSymbol(blocks.next(), functionNode.getIdent().getName(), IS_VAR); + defineSymbol(blocks.next(), functionNode.getIdent().getName(), IS_VAR | (functionNode.isAnonymous()? IS_INTERNAL : 0)); } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java index 0266e5d1ae4..a5eb57c7e36 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java @@ -75,6 +75,7 @@ import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.function.Supplier; +import jdk.nashorn.internal.AssertsEnabled; import jdk.nashorn.internal.IntDeque; import jdk.nashorn.internal.codegen.ClassEmitter.Flag; import jdk.nashorn.internal.codegen.CompilerConstants.Call; @@ -237,11 +238,6 @@ final class CodeGenerator extends NodeOperatorVisitor emittedMethods = new HashSet<>(); // Function Id -> ContinuationInfo. Used by compilation of rest-of function only. @@ -4316,7 +4312,11 @@ final class CodeGenerator extends NodeOperatorVisitor(new LexicalContext()) { @Override public Node leaveFunctionNode(final FunctionNode fn) { @@ -618,7 +617,7 @@ enum CompilationPhase { assert pre != null; - if (!isApplicable(functionNode)) { + if (!functionNode.hasState(pre)) { final StringBuilder sb = new StringBuilder("Compilation phase "); sb.append(this). append(" is not applicable to "). @@ -631,7 +630,7 @@ enum CompilationPhase { throw new CompilationException(sb.toString()); } - startTime = System.currentTimeMillis(); + startTime = System.nanoTime(); return functionNode; } @@ -644,7 +643,7 @@ enum CompilationPhase { */ protected FunctionNode end(final Compiler compiler, final FunctionNode functionNode) { compiler.getLogger().unindent(); - endTime = System.currentTimeMillis(); + endTime = System.nanoTime(); compiler.getScriptEnvironment()._timing.accumulateTime(toString(), endTime - startTime); isFinished = true; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java index 07093e726ea..a1a95bc997c 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java @@ -33,6 +33,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.net.URL; +import java.nio.file.Files; import java.security.AccessController; import java.security.MessageDigest; import java.security.PrivilegedAction; @@ -54,6 +55,9 @@ import jdk.nashorn.internal.runtime.options.Options; * type info persistence altogether by specifying the {@code nashorn.typeInfo.disabled} system property. */ public final class OptimisticTypesPersistence { + // The name of the default subdirectory within the system cache directory where we store type info. + private static final String DEFAULT_CACHE_SUBDIR_NAME = "com.oracle.java.NashornTypeInfo"; + // The directory where we cache type info private static final File cacheDir = createCacheDir(); // In-process locks to make sure we don't have a cross-thread race condition manipulating any file. private static final Object[] locks = cacheDir == null ? null : createLockArray(); @@ -193,7 +197,11 @@ public final class OptimisticTypesPersistence { } else { // When no directory is explicitly specified, get an operating system specific cache directory, // and create "com.oracle.java.NashornTypeInfo" in it. - dir = new File(getCacheDirBase(), "com.oracle.java.NashornTypeInfo"); + final File systemCacheDir = getSystemCacheDir(); + dir = new File(systemCacheDir, DEFAULT_CACHE_SUBDIR_NAME); + if (isSymbolicLink(dir)) { + return null; + } } final String versionDirName; try { @@ -203,6 +211,9 @@ public final class OptimisticTypesPersistence { return null; } final File versionDir = new File(dir, versionDirName); + if (isSymbolicLink(versionDir)) { + return null; + } versionDir.mkdirs(); if(versionDir.isDirectory()) { getLogger().info("Optimistic type persistence directory is " + versionDir); @@ -218,7 +229,7 @@ public final class OptimisticTypesPersistence { * Returns an operating system specific root directory for cache files. * @return an operating system specific root directory for cache files. */ - private static File getCacheDirBase() { + private static File getSystemCacheDir() { final String os = System.getProperty("os.name", "generic"); if("Mac OS X".equals(os)) { // Mac OS X stores caches in ~/Library/Caches @@ -291,6 +302,19 @@ public final class OptimisticTypesPersistence { return currentMax; } + /** + * Returns true if the specified file is a symbolic link, and also logs a warning if it is. + * @param file the file + * @return true if file is a symbolic link, false otherwise. + */ + private static boolean isSymbolicLink(final File file) { + if (Files.isSymbolicLink(file.toPath())) { + getLogger().warning("Directory " + file + " is a symlink"); + return true; + } + return false; + } + private static Object[] createLockArray() { final Object[] lockArray = new Object[Runtime.getRuntime().availableProcessors() * 2]; for (int i = 0; i < lockArray.length; ++i) { diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java index dfb6804ff8b..a67ab816aec 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java @@ -39,6 +39,7 @@ import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.function.Function; +import jdk.nashorn.internal.AssertsEnabled; import jdk.nashorn.internal.codegen.CompileUnit; import jdk.nashorn.internal.codegen.Compiler; import jdk.nashorn.internal.codegen.CompilerConstants; @@ -57,7 +58,6 @@ import jdk.nashorn.internal.runtime.linker.LinkerCallSite; */ @Immutable public final class FunctionNode extends LexicalContextExpression implements Flags { - /** Type used for all FunctionNodes */ public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class); @@ -517,27 +517,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag * @return true of the node is in the given state */ public boolean hasState(final EnumSet state) { - //this.compilationState >= state, or we fail - for (final CompilationState cs : state) { - if (!hasState(cs)) { - return false; - } - } - return true; - } - - /** - * Check whether the state of this FunctionNode contains a given compilation - * state. - * - * A node can be in many states at once, e.g. both lowered and initialized. - * To check for an exact state, use {@link #hasState(EnumSet)} - * - * @param state state to check for - * @return true if state is present in the total compilation state of this FunctionNode - */ - public boolean hasState(final CompilationState state) { - return compilationState.contains(state); + return !AssertsEnabled.assertsEnabled() || compilationState.containsAll(state); } /** @@ -550,7 +530,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag * @return function node or a new one if state was changed */ public FunctionNode setState(final LexicalContext lc, final CompilationState state) { - if (this.compilationState.contains(state)) { + if (!AssertsEnabled.assertsEnabled() || this.compilationState.contains(state)) { return this; } final EnumSet newState = EnumSet.copyOf(this.compilationState); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java index 3d4d7348979..24501979bab 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java @@ -71,7 +71,7 @@ public final class IdentNode extends Expression implements PropertyKey, Function */ public IdentNode(final long token, final int finish, final String name) { super(token, finish); - this.name = name.intern(); + this.name = name; this.type = null; this.flags = 0; this.programPoint = INVALID_PROGRAM_POINT; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java index f58d2a6324c..37ec4b96a39 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java @@ -178,12 +178,15 @@ public abstract class Node implements Cloneable { @Override public final boolean equals(final Object other) { - return super.equals(other); + return this == other; } @Override public final int hashCode() { - return super.hashCode(); + // NOTE: we aren't delegating to Object.hashCode as it still requires trip to the VM for initializing, + // it touches the object header and/or stores the identity hashcode somewhere, etc. There's several + // places in the compiler pipeline that store nodes in maps, so this can get hot. + return Long.hashCode(token); } /** diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/AbstractParser.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/AbstractParser.java index 4d81340f134..5c61396cb2b 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/AbstractParser.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/AbstractParser.java @@ -31,6 +31,8 @@ import static jdk.nashorn.internal.parser.TokenType.EOF; import static jdk.nashorn.internal.parser.TokenType.EOL; import static jdk.nashorn.internal.parser.TokenType.IDENT; +import java.util.HashMap; +import java.util.Map; import jdk.nashorn.internal.ir.IdentNode; import jdk.nashorn.internal.ir.LiteralNode; import jdk.nashorn.internal.parser.Lexer.LexerToken; @@ -91,6 +93,8 @@ public abstract class AbstractParser { /** What should line numbers be counted from? */ protected final int lineOffset; + private final Map canonicalNames = new HashMap<>(); + /** * Construct a parser. * @@ -409,7 +413,7 @@ public abstract class AbstractParser { next(); // Create IDENT node. - return new IdentNode(identToken, finish, ident).setIsFutureStrictName(); + return createIdentNode(identToken, finish, ident).setIsFutureStrictName(); } // Get IDENT. @@ -418,7 +422,22 @@ public abstract class AbstractParser { return null; } // Create IDENT node. - return new IdentNode(identToken, finish, ident); + return createIdentNode(identToken, finish, ident); + } + + /** + * Creates a new {@link IdentNode} as if invoked with a {@link IdentNode#IdentNode(long, int, String) + * constructor} but making sure that the {@code name} is deduplicated within this parse job. + * @param identToken the token for the new {@code IdentNode} + * @param identFinish the finish for the new {@code IdentNode} + * @param name the name for the new {@code IdentNode}. It will be de-duplicated. + * @return a newly constructed {@code IdentNode} with the specified token, finish, and name; the name will + * be deduplicated. + */ + protected IdentNode createIdentNode(final long identToken, final int identFinish, final String name) { + final String existingName = canonicalNames.putIfAbsent(name, name); + final String canonicalName = existingName != null ? existingName : name; + return new IdentNode(identToken, identFinish, canonicalName); } /** @@ -453,7 +472,7 @@ public abstract class AbstractParser { final String ident = (String)getValue(identToken); next(); // Create IDENT node. - return new IdentNode(identToken, finish, ident); + return createIdentNode(identToken, finish, ident); } else { expect(IDENT); return null; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java index 3e0d1e632c6..74ab1e5a5d7 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java @@ -116,6 +116,7 @@ import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; import jdk.nashorn.internal.runtime.ScriptEnvironment; import jdk.nashorn.internal.runtime.ScriptingFunctions; import jdk.nashorn.internal.runtime.Source; +import jdk.nashorn.internal.runtime.Timing; import jdk.nashorn.internal.runtime.logging.DebugLogger; import jdk.nashorn.internal.runtime.logging.Loggable; import jdk.nashorn.internal.runtime.logging.Logger; @@ -222,7 +223,7 @@ public class Parser extends AbstractParser implements Loggable { * @param name the name for the first parsed function. */ public void setFunctionName(final String name) { - defaultNames.push(new IdentNode(0, 0, name)); + defaultNames.push(createIdentNode(0, 0, name)); } /** @@ -257,7 +258,7 @@ public class Parser extends AbstractParser implements Loggable { */ public FunctionNode parse(final String scriptName, final int startPos, final int len, final boolean allowPropertyFunction) { final boolean isTimingEnabled = env.isTimingEnabled(); - final long t0 = isTimingEnabled ? System.currentTimeMillis() : 0L; + final long t0 = isTimingEnabled ? System.nanoTime() : 0L; log.info(this, " begin for '", scriptName, "'"); try { @@ -278,8 +279,8 @@ public class Parser extends AbstractParser implements Loggable { } finally { final String end = this + " end '" + scriptName + "'"; if (isTimingEnabled) { - env._timing.accumulateTime(toString(), System.currentTimeMillis() - t0); - log.info(end, "' in ", System.currentTimeMillis() - t0, " ms"); + env._timing.accumulateTime(toString(), System.nanoTime() - t0); + log.info(end, "' in ", Timing.toMillisPrint(System.nanoTime() - t0), " ms"); } else { log.info(end); } @@ -2243,7 +2244,7 @@ loop: } } - propertyName = new IdentNode(propertyToken, finish, ident).setIsPropertyName(); + propertyName = createIdentNode(propertyToken, finish, ident).setIsPropertyName(); } else { propertyName = propertyName(); } @@ -2261,7 +2262,7 @@ loop: private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) { final PropertyKey getIdent = propertyName(); final String getterName = getIdent.getPropertyName(); - final IdentNode getNameNode = new IdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName)); + final IdentNode getNameNode = createIdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName)); expect(LPAREN); expect(RPAREN); final FunctionNode functionNode = functionBody(getSetToken, getNameNode, new ArrayList(), FunctionNode.Kind.GETTER, functionLine); @@ -2272,7 +2273,7 @@ loop: private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) { final PropertyKey setIdent = propertyName(); final String setterName = setIdent.getPropertyName(); - final IdentNode setNameNode = new IdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName)); + final IdentNode setNameNode = createIdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName)); expect(LPAREN); // be sloppy and allow missing setter parameter even though // spec does not permit it! diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java index d4355777b46..15d4ba4f0a2 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java @@ -163,39 +163,26 @@ public final class Context { @Override public void initialize(final Collection> classes, final Source source, final Object[] constants) { - // do these in parallel, this significantly reduces class installation overhead - // however - it still means that every thread needs a separate doPrivileged - final Global global = currentGlobal.get(); - classes.parallelStream().forEach( - new Consumer>() { + try { + AccessController.doPrivileged(new PrivilegedExceptionAction() { @Override - public void accept(final Class clazz) { - // Global threadlocal may be needed by StructureLoader during in field lookup. - currentGlobal.set(global); - try { - AccessController.doPrivileged(new PrivilegedExceptionAction() { - @Override - public Void run() { - try { - //use reflection to write source and constants table to installed classes - final Field sourceField = clazz.getDeclaredField(SOURCE.symbolName()); - sourceField.setAccessible(true); - sourceField.set(null, source); + public Void run() throws Exception { + for (final Class clazz : classes) { + //use reflection to write source and constants table to installed classes + final Field sourceField = clazz.getDeclaredField(SOURCE.symbolName()); + sourceField.setAccessible(true); + sourceField.set(null, source); - final Field constantsField = clazz.getDeclaredField(CONSTANTS.symbolName()); - constantsField.setAccessible(true); - constantsField.set(null, constants); - } catch (final IllegalAccessException | NoSuchFieldException e) { - throw new RuntimeException(e); - } - return null; - } - }); - } catch (final PrivilegedActionException e) { - throw new RuntimeException(e); + final Field constantsField = clazz.getDeclaredField(CONSTANTS.symbolName()); + constantsField.setAccessible(true); + constantsField.set(null, constants); } + return null; } }); + } catch (final PrivilegedActionException e) { + throw new RuntimeException(e); + } } @Override diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Source.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Source.java index 30157e14430..38d4b85a3ba 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Source.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Source.java @@ -711,11 +711,16 @@ public final class Source implements Loggable { } /** - * Get the content of this source as a char array - * @return content + * Get the content of this source as a char array. Note that the underlying array is returned instead of a + * clone; modifying the char array will cause modification to the source; this should not be done. While + * there is an apparent danger that we allow unfettered access to an underlying mutable array, the + * {@code Source} class is in a restricted {@code jdk.nashorn.internal.*} package and as such it is + * inaccessible by external actors in an environment with a security manager. Returning a clone would be + * detrimental to performance. + * @return content the content of this source as a char array */ public char[] getContent() { - return data().clone(); + return data(); } /** diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Timing.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Timing.java index f295fed03e0..ae61345a1dd 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Timing.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Timing.java @@ -31,6 +31,7 @@ import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; import java.util.function.Supplier; import jdk.nashorn.internal.runtime.logging.DebugLogger; import jdk.nashorn.internal.runtime.logging.Loggable; @@ -57,7 +58,7 @@ public final class Timing implements Loggable { */ public Timing(final boolean isEnabled) { this.isEnabled = isEnabled; - this.startTime = System.currentTimeMillis(); + this.startTime = System.nanoTime(); } /** @@ -91,12 +92,12 @@ public final class Timing implements Loggable { * or add to its accumulated time * * @param module module name - * @param duration duration to add to accumulated time for module + * @param durationNano duration to add to accumulated time for module, in nanoseconds. */ - public void accumulateTime(final String module, final long duration) { + public void accumulateTime(final String module, final long durationNano) { if (isEnabled()) { ensureInitialized(Context.getContextTrusted()); - timeSupplier.accumulateTime(module, duration); + timeSupplier.accumulateTime(module, durationNano); } } @@ -143,6 +144,15 @@ public final class Timing implements Loggable { return log; } + /** + * Takes a duration in nanoseconds, and returns a string representation of it rounded to milliseconds. + * @param durationNano duration in nanoseconds + * @return the string representing the duration in milliseconds. + */ + public static String toMillisPrint(final long durationNano) { + return Long.toString(TimeUnit.NANOSECONDS.toMillis(durationNano)); + } + final class TimeSupplier implements Supplier { private final Map timings; @@ -166,7 +176,7 @@ public final class Timing implements Loggable { @Override public String get() { - final long t = System.currentTimeMillis(); + final long t = System.nanoTime(); long knownTime = 0L; int maxKeyLength = 0; @@ -174,7 +184,7 @@ public final class Timing implements Loggable { for (final Map.Entry entry : timings.entrySet()) { maxKeyLength = Math.max(maxKeyLength, entry.getKey().length()); - maxValueLength = Math.max(maxValueLength, entry.getValue().toString().length()); + maxValueLength = Math.max(maxValueLength, toMillisPrint(entry.getValue()).length()); } maxKeyLength++; @@ -192,12 +202,13 @@ public final class Timing implements Loggable { } final Long duration = entry.getValue(); - len = duration.toString().length(); + final String strDuration = toMillisPrint(duration); + len = strDuration.length(); for (int i = 0; i < maxValueLength - len; i++) { sb.append(' '); } - sb.append(duration). + sb.append(strDuration). append(" ms\n"); knownTime += duration; @@ -206,9 +217,9 @@ public final class Timing implements Loggable { final long total = t - startTime; sb.append('\n'); sb.append("Total runtime: "). - append(total). + append(toMillisPrint(total)). append(" ms (Non-runtime: "). - append(knownTime). + append(toMillisPrint(knownTime)). append(" ms ["). append((int)(knownTime * 100.0 / total)). append("%])"); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java index de68120cda7..67dd88e2c49 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java @@ -88,14 +88,14 @@ public final class Bootstrap { static { final DynamicLinkerFactory factory = new DynamicLinkerFactory(); final NashornBeansLinker nashornBeansLinker = new NashornBeansLinker(); - final JSObjectLinker jsObjectLinker = new JSObjectLinker(nashornBeansLinker); factory.setPrioritizedLinkers( new NashornLinker(), new NashornPrimitiveLinker(), new NashornStaticClassLinker(), new BoundDynamicMethodLinker(), new JavaSuperAdapterLinker(), - jsObjectLinker, + new JSObjectLinker(nashornBeansLinker), + new BrowserJSObjectLinker(nashornBeansLinker), new ReflectionCheckLinker()); factory.setFallbackLinkers(nashornBeansLinker, new NashornBottomLinker()); factory.setSyncOnRelink(true); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java new file mode 100644 index 00000000000..e8cfa4edde6 --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.runtime.linker; + +import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.*; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import jdk.internal.dynalink.CallSiteDescriptor; +import jdk.internal.dynalink.linker.GuardedInvocation; +import jdk.internal.dynalink.linker.LinkRequest; +import jdk.internal.dynalink.linker.LinkerServices; +import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; +import jdk.internal.dynalink.support.CallSiteDescriptorFactory; +import jdk.nashorn.internal.lookup.MethodHandleFactory; +import jdk.nashorn.internal.lookup.MethodHandleFunctionality; +import jdk.nashorn.internal.runtime.JSType; + +/** + * A Dynalink linker to handle web browser built-in JS (DOM etc.) objects. + */ +final class BrowserJSObjectLinker implements TypeBasedGuardingDynamicLinker { + private static final ClassLoader myLoader = BrowserJSObjectLinker.class.getClassLoader(); + private static final String JSOBJECT_CLASS = "netscape.javascript.JSObject"; + // not final because this is lazily initialized + // when we hit a subclass for the first time. + private static volatile Class jsObjectClass; + private final NashornBeansLinker nashornBeansLinker; + + BrowserJSObjectLinker(final NashornBeansLinker nashornBeansLinker) { + this.nashornBeansLinker = nashornBeansLinker; + } + + @Override + public boolean canLinkType(final Class type) { + return canLinkTypeStatic(type); + } + + static boolean canLinkTypeStatic(final Class type) { + if (jsObjectClass != null && jsObjectClass.isAssignableFrom(type)) { + return true; + } + + // check if this class is a subclass of JSObject + Class clazz = type; + while (clazz != null) { + if (clazz.getClassLoader() == myLoader && + clazz.getName().equals(JSOBJECT_CLASS)) { + jsObjectClass = clazz; + return true; + } + clazz = clazz.getSuperclass(); + } + + return false; + } + + private static void checkJSObjectClass() { + assert jsObjectClass != null : JSOBJECT_CLASS + " not found!"; + } + + @Override + public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception { + final LinkRequest requestWithoutContext = request.withoutRuntimeContext(); // Nashorn has no runtime context + final Object self = requestWithoutContext.getReceiver(); + final CallSiteDescriptor desc = requestWithoutContext.getCallSiteDescriptor(); + checkJSObjectClass(); + + if (desc.getNameTokenCount() < 2 || !"dyn".equals(desc.getNameToken(CallSiteDescriptor.SCHEME))) { + // We only support standard "dyn:*[:*]" operations + return null; + } + + final GuardedInvocation inv; + if (jsObjectClass.isInstance(self)) { + inv = lookup(desc, request, linkerServices); + } else { + throw new AssertionError(); // Should never reach here. + } + + return Bootstrap.asTypeSafeReturn(inv, linkerServices, desc); + } + + private GuardedInvocation lookup(final CallSiteDescriptor desc, final LinkRequest request, final LinkerServices linkerServices) throws Exception { + final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0); + final int c = desc.getNameTokenCount(); + + switch (operator) { + case "getProp": + case "getElem": + case "getMethod": + if (c > 2) { + return findGetMethod(desc); + } else { + // For indexed get, we want GuardedInvocation from beans linker and pass it. + // BrowserJSObjectLinker.get uses this fallback getter for explicit signature method access. + final GuardedInvocation beanInv = nashornBeansLinker.getGuardedInvocation(request, linkerServices); + return findGetIndexMethod(beanInv); + } + case "setProp": + case "setElem": + return c > 2 ? findSetMethod(desc) : findSetIndexMethod(); + default: + return null; + } + } + + private static GuardedInvocation findGetMethod(final CallSiteDescriptor desc) { + final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); + final MethodHandle getter = MH.insertArguments(JSOBJECT_GETMEMBER, 1, name); + return new GuardedInvocation(getter, IS_JSOBJECT_GUARD); + } + + private static GuardedInvocation findGetIndexMethod(final GuardedInvocation inv) { + final MethodHandle getter = MH.insertArguments(JSOBJECTLINKER_GET, 0, inv.getInvocation()); + return inv.replaceMethods(getter, inv.getGuard()); + } + + private static GuardedInvocation findSetMethod(final CallSiteDescriptor desc) { + final MethodHandle getter = MH.insertArguments(JSOBJECT_SETMEMBER, 1, desc.getNameToken(2)); + return new GuardedInvocation(getter, IS_JSOBJECT_GUARD); + } + + private static GuardedInvocation findSetIndexMethod() { + return new GuardedInvocation(JSOBJECTLINKER_PUT, IS_JSOBJECT_GUARD); + } + + @SuppressWarnings("unused") + private static boolean isJSObject(final Object self) { + return jsObjectClass.isInstance(self); + } + + @SuppressWarnings("unused") + private static Object get(final MethodHandle fallback, final Object jsobj, final Object key) throws Throwable { + if (key instanceof Integer) { + return JSOBJECT_GETSLOT.invokeExact(jsobj, (int)key); + } else if (key instanceof Number) { + final int index = getIndex((Number)key); + if (index > -1) { + return JSOBJECT_GETSLOT.invokeExact(jsobj, index); + } + } else if (key instanceof String) { + final String name = (String)key; + if (name.indexOf('(') != -1) { + return fallback.invokeExact(jsobj, key); + } else { + return JSOBJECT_GETMEMBER.invokeExact(jsobj, (String)key); + } + } + return null; + } + + @SuppressWarnings("unused") + private static void put(final Object jsobj, final Object key, final Object value) throws Throwable { + if (key instanceof Integer) { + JSOBJECT_SETSLOT.invokeExact(jsobj, (int)key, value); + } else if (key instanceof Number) { + JSOBJECT_SETSLOT.invokeExact(jsobj, getIndex((Number)key), value); + } else if (key instanceof String) { + JSOBJECT_SETMEMBER.invokeExact(jsobj, (String)key, value); + } + } + + private static int getIndex(final Number n) { + final double value = n.doubleValue(); + return JSType.isRepresentableAsInt(value) ? (int)value : -1; + } + + private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality(); + // method handles of the current class + private static final MethodHandle IS_JSOBJECT_GUARD = findOwnMH_S("isJSObject", boolean.class, Object.class); + private static final MethodHandle JSOBJECTLINKER_GET = findOwnMH_S("get", Object.class, MethodHandle.class, Object.class, Object.class); + private static final MethodHandle JSOBJECTLINKER_PUT = findOwnMH_S("put", Void.TYPE, Object.class, Object.class, Object.class); + + private static MethodHandle findOwnMH_S(final String name, final Class rtype, final Class... types) { + return MH.findStatic(MethodHandles.lookup(), BrowserJSObjectLinker.class, name, MH.type(rtype, types)); + } + + // method handles of netscape.javascript.JSObject class + // These are in separate class as we lazily initialize these + // method handles when we hit a subclass of JSObject first time. + static class JSObjectHandles { + // method handles of JSObject class + static final MethodHandle JSOBJECT_GETMEMBER = findJSObjectMH_V("getMember", Object.class, String.class).asType(MH.type(Object.class, Object.class, String.class)); + static final MethodHandle JSOBJECT_GETSLOT = findJSObjectMH_V("getSlot", Object.class, int.class).asType(MH.type(Object.class, Object.class, int.class)); + static final MethodHandle JSOBJECT_SETMEMBER = findJSObjectMH_V("setMember", Void.TYPE, String.class, Object.class).asType(MH.type(Void.TYPE, Object.class, String.class, Object.class)); + static final MethodHandle JSOBJECT_SETSLOT = findJSObjectMH_V("setSlot", Void.TYPE, int.class, Object.class).asType(MH.type(Void.TYPE, Object.class, int.class, Object.class)); + + private static MethodHandle findJSObjectMH_V(final String name, final Class rtype, final Class... types) { + checkJSObjectClass(); + return MH.findVirtual(MethodHandles.publicLookup(), jsObjectClass, name, MH.type(rtype, types)); + } + } +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java index 13e78bf242f..67c8e4bb066 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java @@ -81,7 +81,7 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTy final GuardedInvocation inv; if (self instanceof JSObject) { - inv = lookup(desc); + inv = lookup(desc, request, linkerServices); } else if (self instanceof Map || self instanceof Bindings) { // guard to make sure the Map or Bindings does not turn into JSObject later! final GuardedInvocation beanInv = nashornBeansLinker.getGuardedInvocation(request, linkerServices); @@ -110,7 +110,7 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTy } - private static GuardedInvocation lookup(final CallSiteDescriptor desc) { + private GuardedInvocation lookup(final CallSiteDescriptor desc, final LinkRequest request, final LinkerServices linkerServices) throws Exception { final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0); final int c = desc.getNameTokenCount(); @@ -118,7 +118,14 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTy case "getProp": case "getElem": case "getMethod": - return c > 2 ? findGetMethod(desc) : findGetIndexMethod(); + if (c > 2) { + return findGetMethod(desc); + } else { + // For indexed get, we want get GuardedInvocation beans linker and pass it. + // JSObjectLinker.get uses this fallback getter for explicit signature method access. + final GuardedInvocation beanInv = nashornBeansLinker.getGuardedInvocation(request, linkerServices); + return findGetIndexMethod(beanInv); + } case "setProp": case "setElem": return c > 2 ? findSetMethod(desc) : findSetIndexMethod(); @@ -137,8 +144,9 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTy return new GuardedInvocation(getter, IS_JSOBJECT_GUARD); } - private static GuardedInvocation findGetIndexMethod() { - return new GuardedInvocation(JSOBJECTLINKER_GET, IS_JSOBJECT_GUARD); + private static GuardedInvocation findGetIndexMethod(final GuardedInvocation inv) { + final MethodHandle getter = MH.insertArguments(JSOBJECTLINKER_GET, 0, inv.getInvocation()); + return inv.replaceMethods(getter, inv.getGuard()); } private static GuardedInvocation findSetMethod(final CallSiteDescriptor desc) { @@ -170,7 +178,8 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTy } @SuppressWarnings("unused") - private static Object get(final Object jsobj, final Object key) { + private static Object get(final MethodHandle fallback, final Object jsobj, final Object key) + throws Throwable { if (key instanceof Integer) { return ((JSObject)jsobj).getSlot((Integer)key); } else if (key instanceof Number) { @@ -179,7 +188,13 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTy return ((JSObject)jsobj).getSlot(index); } } else if (key instanceof String) { - return ((JSObject)jsobj).getMember((String)key); + final String name = (String)key; + // get with method name and signature. delegate it to beans linker! + if (name.indexOf('(') != -1) { + return fallback.invokeExact(jsobj, key); + } else { + return ((JSObject)jsobj).getMember(name); + } } return null; } @@ -238,7 +253,7 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTy // method handles of the current class private static final MethodHandle IS_JSOBJECT_GUARD = findOwnMH_S("isJSObject", boolean.class, Object.class); - private static final MethodHandle JSOBJECTLINKER_GET = findOwnMH_S("get", Object.class, Object.class, Object.class); + private static final MethodHandle JSOBJECTLINKER_GET = findOwnMH_S("get", Object.class, MethodHandle.class, Object.class, Object.class); private static final MethodHandle JSOBJECTLINKER_PUT = findOwnMH_S("put", Void.TYPE, Object.class, Object.class, Object.class); // method handles of JSObject class diff --git a/nashorn/test/script/basic/JDK-8015969.js b/nashorn/test/script/basic/JDK-8015969.js index c8f8ca6817a..57c6e1fcfce 100644 --- a/nashorn/test/script/basic/JDK-8015969.js +++ b/nashorn/test/script/basic/JDK-8015969.js @@ -32,43 +32,26 @@ var m = new javax.script.ScriptEngineManager(); var e = m.getEngineByName("nashorn"); +e.put("fail", fail); e.eval(< at line number 1 +java.lang.NullPointerException +java.lang.ClassNotFoundException: java.lang.NullPointerException +java.lang.NullPointerException: library can't be null +java.lang.NullPointerException: library can't be null diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/NoSessionException.java b/nashorn/test/script/trusted/classfilter_mozilla_compat.js similarity index 50% rename from jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/NoSessionException.java rename to nashorn/test/script/trusted/classfilter_mozilla_compat.js index 3e92e2eb167..cb05a3d7c40 100644 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/NoSessionException.java +++ b/nashorn/test/script/trusted/classfilter_mozilla_compat.js @@ -1,12 +1,10 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. + * 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 @@ -23,18 +21,32 @@ * questions. */ -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. +/** + * @test + * @bug 8036987 + * @run */ +var factory = Java.type('jdk.nashorn.api.scripting.NashornScriptEngineFactory') +var engine = new factory().getScriptEngine(function(str){ + return str.indexOf('java.util') != -1; +}) -package com.sun.tools.example.debug.bdi; +load("nashorn:mozilla_compat.js"); +engine.eval("load('nashorn:mozilla_compat.js');") -public class NoSessionException extends Exception { - - private static final long serialVersionUID = -7324357828115128603L; +function tryEval (str) { + try { + print(eval(str)) + print(engine.eval(str)) + } catch (exc) { + print(exc.message) + } } + +tryEval("new JavaAdapter(javax.script.ScriptContext){}.class") +tryEval("new JavaAdapter(java.util.ArrayList){}.class") +tryEval("importClass(java.lang.Integer); Integer") +tryEval("importClass(java.util.HashSet); HashSet") +tryEval("importPackage(java.lang); Integer") +tryEval("importPackage(java.util); HashMap") diff --git a/nashorn/test/script/trusted/classfilter_mozilla_compat.js.EXPECTED b/nashorn/test/script/trusted/classfilter_mozilla_compat.js.EXPECTED new file mode 100644 index 00000000000..9481e98e182 --- /dev/null +++ b/nashorn/test/script/trusted/classfilter_mozilla_compat.js.EXPECTED @@ -0,0 +1,12 @@ +class javax.script.ScriptContext$$NashornJavaAdapter +TypeError: Java.extend needs at least one type argument. in nashorn:mozilla_compat.js at line number 39 +class jdk.nashorn.javaadapters.java.util.ArrayList +class jdk.nashorn.javaadapters.java.util.ArrayList +[JavaClass java.lang.Integer] +TypeError: [object JavaPackage] is not a Java class in nashorn:mozilla_compat.js at line number 373 at column number 16 +[JavaClass java.util.HashSet] +[JavaClass java.util.HashSet] +[JavaClass java.lang.Integer] +ReferenceError: "Integer" is not defined in nashorn:mozilla_compat.js at line number 67 +[JavaClass java.util.HashMap] +[JavaClass java.util.HashMap] diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java index e6df0490644..09199a52703 100644 --- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java +++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java @@ -271,6 +271,11 @@ public class ScriptEngineSecurityTest { @Test public static void proxyStaticAccessCheckTest() throws ScriptException { + if (System.getSecurityManager() == null) { + // pass vacuously + return; + } + final ScriptEngineManager m = new ScriptEngineManager(); final ScriptEngine e = m.getEngineByName("nashorn"); final Runnable r = (Runnable)Proxy.newProxyInstance( @@ -297,4 +302,43 @@ public class ScriptEngineSecurityTest { } } } + + + @Test + public void nashornConfigSecurityTest() { + if (System.getSecurityManager() == null) { + // pass vacuously + return; + } + + final NashornScriptEngineFactory fac = new NashornScriptEngineFactory(); + try { + fac.getScriptEngine(new ClassFilter() { + @Override + public boolean exposeToScripts(final String name) { + return true; + } + }); + fail("SecurityException should have been thrown"); + } catch (final SecurityException exp) {} + } + + @Test + public void nashornConfigSecurityTest2() { + if (System.getSecurityManager() == null) { + // pass vacuously + return; + } + + final NashornScriptEngineFactory fac = new NashornScriptEngineFactory(); + try { + fac.getScriptEngine(new String[0], null, new ClassFilter() { + @Override + public boolean exposeToScripts(final String name) { + return true; + } + }); + fail("SecurityException should have been thrown"); + } catch (final SecurityException exp) {} + } } diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java index dae46fd623c..291e8d424c4 100644 --- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java +++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java @@ -629,34 +629,6 @@ public class ScriptEngineTest { assertEquals(enumerable, Boolean.FALSE); } - @Test - public void nashornConfigSecurityTest() { - final NashornScriptEngineFactory fac = new NashornScriptEngineFactory(); - try { - fac.getScriptEngine(new ClassFilter() { - @Override - public boolean exposeToScripts(final String name) { - return true; - } - }); - fail("SecurityException should have been thrown"); - } catch (final SecurityException exp) {} - } - - @Test - public void nashornConfigSecurityTest2() { - final NashornScriptEngineFactory fac = new NashornScriptEngineFactory(); - try { - fac.getScriptEngine(new String[0], null, new ClassFilter() { - @Override - public boolean exposeToScripts(final String name) { - return true; - } - }); - fail("SecurityException should have been thrown"); - } catch (final SecurityException exp) {} - } - private static void checkProperty(final ScriptEngine e, final String name) throws ScriptException { final String value = System.getProperty(name); diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java index 1a21dd39484..dc3474439a8 100644 --- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java +++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java @@ -361,4 +361,26 @@ public class ScriptObjectMirrorTest { final Function func = invocable.getInterface(Function.class); assertFalse((boolean)func.apply(engine.eval("({ x: 2 })"))); } + + // @bug 8055687: Wrong "this" passed to JSObject.eval call + @Test + public void checkThisForJSObjectEval() throws Exception { + final ScriptEngineManager engineManager = new ScriptEngineManager(); + final ScriptEngine e = engineManager.getEngineByName("nashorn"); + final JSObject jsobj = (JSObject)e.eval("({foo: 23, bar: 'hello' })"); + assertEquals(((Number)jsobj.eval("this.foo")).intValue(), 23); + assertEquals(jsobj.eval("this.bar"), "hello"); + assertEquals(jsobj.eval("String(this)"), "[object Object]"); + final Object global = e.eval("this"); + assertFalse(global.equals(jsobj.eval("this"))); + } + + @Test + public void topLevelAnonFuncStatement() throws Exception { + final ScriptEngineManager engineManager = new ScriptEngineManager(); + final ScriptEngine e = engineManager.getEngineByName("nashorn"); + final JSObject func = (JSObject)e.eval("function(x) { return x + ' world' }"); + assertTrue(func.isFunction()); + assertEquals(func.call(e.eval("this"), "hello"), "hello world"); + } } diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java new file mode 100644 index 00000000000..558833ebb22 --- /dev/null +++ b/nashorn/test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.runtime; + + +import jdk.nashorn.api.scripting.ClassFilter; +import jdk.nashorn.api.scripting.NashornScriptEngineFactory; +import jdk.nashorn.api.scripting.URLReader; +import org.testng.annotations.Test; + +import javax.script.ScriptEngine; +import javax.script.ScriptException; +import java.io.File; + +import static org.testng.Assert.fail; + +public class ClassFilterTest { + private static final String NASHORN_CODE_CACHE = "nashorn.persistent.code.cache"; + private static final String CLASSFILTER_CODE_CACHE = "build/classfilter_nashorn_code_cache"; + + // @Test + // This test takes too much time for basic "ant clean test" run. + // Given that "allow-all-java-classes" is equivalent to no java class + // filter and external tests don't access any java, not sure if this + // test contributes much. We need faster "ant clean test" cycle for + // developers. + public void runExternalJsTest() { + String[] paths = new String[]{ + "test/script/basic/compile-octane.js", + "test/script/basic/jquery.js", + "test/script/basic/prototype.js", + "test/script/basic/runsunspider.js", + "test/script/basic/underscore.js", + "test/script/basic/yui.js", + "test/script/basic/run-octane.js" + }; + NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); + for (String path : paths) { + ScriptEngine engine = factory.getScriptEngine(new String[]{"-scripting"}, getClass().getClassLoader(), getClassFilter()); + try { + engine.eval(new URLReader(new File(path).toURI().toURL())); + } catch (Exception e) { + fail("Script " + path + " fails with exception :" + e.getMessage()); + } + } + } + + @Test + public void noJavaOptionTest() { + NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); + ScriptEngine engine = factory.getScriptEngine(new String[]{"--no-java"}, getClass().getClassLoader(), getClassFilter()); + try { + engine.eval("var str = Java.type('java.lang.String');"); + fail("TypeError should have been thrown"); + } catch (ScriptException exc) { + } + } + + @Test + public void securityTest() { + if (System.getSecurityManager() == null) { + return; + } + + NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); + ScriptEngine engine = factory.getScriptEngine(getClassFilter()); + try { + engine.eval("var thread = Java.type('sun.misc.Unsafe')"); + fail("SecurityException should have been thrown"); + } catch (final Exception exc) { + } + try { + engine.eval("var thread = new sun.misc.Unsafe()"); + fail("SecurityException should have been thrown"); + } catch (final Exception exc) { + } + try { + engine.eval("var thread = Java.extend(sun.misc.Unsafe, {})"); + fail("TypeError should have been thrown"); + } catch (final Exception exc) { + } + try { + engine.eval("java.lang.System.exit(0)"); + fail("SecurityException should have been thrown"); + } catch (final Exception exc) { + } + + } + + @Test + public void persistentCacheTest() { + final String oldCodeCache = System.getProperty(NASHORN_CODE_CACHE); + System.setProperty(NASHORN_CODE_CACHE, CLASSFILTER_CODE_CACHE); + try { + persistentCacheTestImpl(); + } finally { + if (oldCodeCache != null) { + System.setProperty(NASHORN_CODE_CACHE, oldCodeCache); + } + } + } + + private void persistentCacheTestImpl() { + NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); + ScriptEngine engine = factory.getScriptEngine( + new String[]{"--persistent-code-cache"}, + getClass().getClassLoader(), + getClassFilter() + ); + String testScript = "var a = Java.type('java.lang.String');" + generateCodeForPersistentStore(); + try { + engine.eval(testScript); + } catch (final ScriptException exc) { + fail(exc.getMessage()); + } + ScriptEngine engineSafe = factory.getScriptEngine( + new String[]{"--persistent-code-cache"}, + getClass().getClassLoader(), + new ClassFilter() { + @Override + public boolean exposeToScripts(String s) { + return false; + } + } + ); + try { + engineSafe.eval(testScript); + fail("ClassNotFoundException should have been thrown"); + } catch (final Exception exc) { + if (!(exc.getCause() instanceof ClassNotFoundException)) { + fail("ClassNotFoundException expected"); + } + } + } + + private String generateCodeForPersistentStore() { + StringBuilder stringBuilder = new StringBuilder(); + for (int i=0; i < 100; i++) { + stringBuilder.append("function i") + .append(i) + .append("(y, z) { var x") + .append(i) + .append(" = ") + .append(i) + .append(";}"); + } + return stringBuilder.toString(); + } + + private ClassFilter getClassFilter() { + return new ClassFilter() { + @Override + public boolean exposeToScripts(String s) { + return true; + } + }; + } +} diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/SourceTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/SourceTest.java index c4e747a5be2..eb837fb2633 100644 --- a/nashorn/test/src/jdk/nashorn/internal/runtime/SourceTest.java +++ b/nashorn/test/src/jdk/nashorn/internal/runtime/SourceTest.java @@ -117,9 +117,6 @@ public class SourceTest { assertEquals(str1, str2); assertEquals(source1.hashCode(), source2.hashCode()); assertTrue(source1.equals(source2)); - // Test for immutability - Arrays.fill(source1.getContent(), (char)0); - Arrays.fill(source2.getContent(), (char)1); assertTrue(Arrays.equals(source1.getContent(), str1.toCharArray())); assertTrue(Arrays.equals(source1.getContent(), chars1)); assertTrue(Arrays.equals(source1.getContent(), source2.getContent()));